// // Methods // /// <summary> /// Handles the onGUI event. /// </summary> /// <param name="property">Property.</param> /// <param name="node">Node.</param> /// <param name="guiContent">GUI content.</param> public override void OnGUI(SerializedNodeProperty property, ActionNode node, GUIContent guiContent) { //if (animatorSerialized == null || aniController == null) { if (aniController == null) { //!!! Serialization never serialized Animator cos its initialized in Reset after // NodePropertyIterator iter= property.serializedNode.GetIterator(); // iter.Find(attribute.animatorFieldName); // animatorSerialized=iter.current; // // if(animatorSerialized==null || animatorSerialized.value==null){ // Debug.LogError("AnimatorStateNodePropertyDrawer> No Animator component set on node parent GameObject"); // return; // } //runtimeContoller =( (Animator)animatorSerialized.value).runtimeAnimatorController; Animator animator = node.GetType().GetField(attribute.animatorFieldName).GetValue(node) as Animator; RuntimeAnimatorController runtimeContoller; runtimeContoller = animator.runtimeAnimatorController; if (runtimeContoller is AnimatorOverrideController) { aniController = ((AnimatorOverrideController)runtimeContoller).runtimeAnimatorController as UnityEditor.Animations.AnimatorController; } else { aniController = runtimeContoller as UnityEditor.Animations.AnimatorController; } } animatorStateDisplayOptions = MecanimUtility.GetDisplayOptions(aniController); animatorStateValues = MecanimUtility.GetAnimatorStates(aniController); if (property.value != null) { if (animatorStateValues.Length > 0) { animatorStateSelectedPrev = animatorStateSelected = animatorStateValues.FirstOrDefault((itm) => itm.nameHash == ((ws.winx.unity.AnimatorState)property.value).nameHash); } } animatorStateSelected = EditorGUILayoutEx.CustomObjectPopup(guiContent, animatorStateSelected, animatorStateDisplayOptions, animatorStateValues); //,compare); //TODO try Begin/End Check if (animatorStateSelectedPrev != animatorStateSelected) { NodePropertyIterator iter = property.serializedNode.GetIterator(); iter.Find(attribute.layerIndexFieldName); SerializedNodeProperty layerIndexSerialized = iter.current; layerIndexSerialized.value = MecanimUtility.GetLayerIndex(aniController, animatorStateSelected); layerIndexSerialized.ApplyModifiedValue(); ws.winx.unity.AnimatorState state = property.value as ws.winx.unity.AnimatorState; if (state == null) { state = ScriptableObject.CreateInstance <ws.winx.unity.AnimatorState>(); } state.motion = animatorStateSelected.motion; state.nameHash = animatorStateSelected.nameHash; state.layer = (int)layerIndexSerialized.value; if (state.motion is UnityEditor.Animations.BlendTree) { BlendTree tree = (BlendTree)state.motion; int blendParamsNum = tree.GetRecursiveBlendParamCount(); state.blendParamsHashes = new int[blendParamsNum]; for (int i = 0; i < blendParamsNum; i++) { state.blendParamsHashes[i] = Animator.StringToHash(tree.GetRecursiveBlendParam(i)); } } else { state.blendParamsHashes = null; } //property.value=state; property.ValueChanged(); property.ApplyModifiedValue(); animatorStateSelectedPrev = animatorStateSelected; } if (animatorStateSelected.motion == null) { Debug.LogError("Selected state doesn't have Motion set"); } }
public override void OnGUI(SerializedNodeProperty property, BehaviourMachine.ActionNode node, GUIContent guiContent) { // Now draw the property as a Slider or an IntSlider based on whether it’s a float or integer. if (property.type != typeof(MinMaxRangeSO)) { Debug.LogWarning("Use only with MinMaxRange type"); } else { var range = attribute as MinMaxRangeSAttribute; var so = (MinMaxRangeSO)property.value; //set or reset to default full range if (so.rangeStart == so.rangeEnd) { so.rangeStart = range.minLimit; so.rangeEnd = range.maxLimit; } var newMin = so.rangeStart; var newMax = so.rangeEnd; Rect position = GUILayoutUtility.GetRect(Screen.width - 32f, 32f); var xDivision = position.width * 0.33f; var yDivision = position.height * 0.5f; EditorGUI.LabelField(new Rect(position.x, position.y, xDivision, yDivision) , guiContent); EditorGUI.LabelField(new Rect(position.x, position.y + yDivision, position.width, yDivision) , range.minLimit.ToString("0.##")); EditorGUI.LabelField(new Rect(position.x + position.width - 28f, position.y + yDivision, position.width, yDivision) , range.maxLimit.ToString("0.##")); EditorGUI.MinMaxSlider(new Rect(position.x + 24f, position.y + yDivision, position.width - 48f, yDivision) , ref newMin, ref newMax, range.minLimit, range.maxLimit); EditorGUI.LabelField(new Rect(position.x + xDivision, position.y, xDivision, yDivision) , "From: "); newMin = Mathf.Clamp(EditorGUI.FloatField(new Rect(position.x + xDivision + 30, position.y, xDivision - 30, yDivision) , newMin) , range.minLimit, newMax); EditorGUI.LabelField(new Rect(position.x + xDivision * 2f, position.y, xDivision, yDivision) , "To: "); newMax = Mathf.Clamp(EditorGUI.FloatField(new Rect(position.x + xDivision * 2f + 24, position.y, xDivision - 24, yDivision) , newMax) , newMin, range.maxLimit); so.rangeStart = newMin; so.rangeEnd = newMax; property.ValueChanged(); property.ApplyModifiedValue(); property.serializedNode.ApplyModifiedProperties(); } }
/// <summary> /// Handles the GUI event. /// </summary> void OnGUI() { if (_keyframeMarker == null) { _keyframeMarker = new GUIContent(EditorGUILayoutEx.ANIMATION_STYLES.pointIcon); } if (!Application.isPlaying && __gameObjectClipList != null) { _curvesEditorShow = EditorGUILayout.Foldout(_curvesEditorShow, "Curves"); //int indentLevel = 0; Rect curveEditorRect = new Rect(0, 0, 0, 0); int i = 0; if (_curvesEditorShow) { //This makes layout to work (Reserving space) curveEditorRect = GUILayoutUtility.GetRect(Screen.width - 16f, 200); /////// CURVE EDITOR //////// curveEditorRect.width = curveEditorRect.width - 32f; curveEditorRect.x = 16f; if (curveEditor == null) { CurveWrapperW[] curveWrappers; int numCurves = curves.Length; curveWrappers = new CurveWrapperW[numCurves]; CurveWrapperW curveWrapperNew; for (i = 0; i < numCurves; i++) { curveWrapperNew = new CurveWrapperW(); curveWrapperNew.curve = curves [i]; curveWrapperNew.color = curveColors [i]; curveWrappers [i] = curveWrapperNew; } curveEditor = new CurveEditorW(curveEditorRect, curveWrappers, false); curveEditor.FrameSelected(true, true); curveEditor.scaleWithWindow = true; curveEditor.hSlider = false; curveEditor.hRangeMin = 0f; curveEditor.hRangeMax = 1f; curveEditor.hRangeLocked = true; curveEditor.onSelect += onCurveSelect; } else { curveEditor.rect = curveEditorRect; curveEditor.FrameSelected(false, false); } curveEditor.DoEditor(); /////////////////////////////////////////////////////////////////////////////// ///////////// ADD/REMOVE CURVE BINDED TO OBJECT PROP OR GLOBAL VARIABLE ///////////// /// // EditorGUILayout.BeginHorizontal(); //if curve is selected display curve properties if (_curveIndexSelected > -1 && _curveIndexSelected < variablesBindedToCurves.Length) { UnityVariable variableSelected = variablesBindedToCurves [_curveIndexSelected]; try { bindingCurvesGUIContent.text = variableSelected.instanceBinded.name + "." + variableSelected.memberPath; EditorGUILayout.LabelField(bindingCurvesGUIContent, new GUILayoutOption[] {}); EditorGUI.BeginChangeCheck(); Color colorNew = EditorGUILayout.ColorField(curveColors [_curveIndexSelected]); if (EditorGUI.EndChangeCheck()) { curveEditor.animationCurves [_curveIndexSelected].color = colorNew; curveColors [_curveIndexSelected] = colorNew; curvesColorsSerialized.ValueChanged(); curvesColorsSerialized.ApplyModifiedValue(); } } catch (MissingReferenceException ex) { bindingCurvesGUIContent.text = "Invalid UVariable " + ex.Message; } } else { bindingCurvesGUIContent.text = "Curve binding:"; List <UnityVariable> blackboardLocalList = (MecanimNodeEditorWindow.__serializedNode.target.blackboard as BlackboardCustom).GetVariableBy(typeof(float)); List <GUIContent> displayOptionsList = blackboardLocalList.Select((item) => new GUIContent("Local/" + item.name)).ToList(); __variableSelected = EditorGUILayoutEx.UnityVariablePopup(bindingCurvesGUIContent, __variableSelected, typeof(float), displayOptionsList, blackboardLocalList); _colorSelected = EditorGUILayout.ColorField(_colorSelected); } /////////////// ADD CURVE(+) ///////// if (GUILayout.Button("Add") && __variableSelected != null) { List <UnityVariable> vList = variablesBindedToCurves.ToList(); vList.Add(__variableSelected); variablesBindedToCurvesSerialized.value = variablesBindedToCurves = vList.ToArray(); variablesBindedToCurvesSerialized.ValueChanged(); //variablesBindedToCurvesSerialized.ApplyModifiedValue (); List <Color> cList = curveColors.ToList(); _colorSelected.a = 1; cList.Add(_colorSelected); curvesColorsSerialized.value = curveColors = cList.ToArray(); curvesColorsSerialized.ValueChanged(); //curvesColorsSerialized.ApplyModifiedValue (); AnimationCurve curveAnimationNew; List <AnimationCurve> crList = curves.ToList(); curveAnimationNew = new AnimationCurve(new Keyframe[] { new Keyframe(0f, (float)__variableSelected.Value), new Keyframe(1f, 1f) }); //TODO add from preset crList.Add(curveAnimationNew); curvesSerialized.value = curves = crList.ToArray(); curvesSerialized.ValueChanged(); //curvesColorsSerialized.ApplyModifiedValue (); ///add curve wrapped to CurveEditor CurveWrapperW curveWrapperW = new CurveWrapperW(); curveWrapperW.color = _colorSelected; curveWrapperW.curve = curveAnimationNew; curveEditor.AddCurve(curveWrapperW); curveEditor.FrameSelected(true, true); __serializedNode.Update(); __serializedNode.ApplyModifiedProperties(); __variableSelected = null; } ///////////// DELETE CURVE //////////// if (GUILayout.Button("Del") || Event.current.keyCode == KeyCode.Delete) { curveEditor.RemoveCurveAt(_curveIndexSelected); List <UnityVariable> vList = variablesBindedToCurves.ToList(); vList.RemoveAt(_curveIndexSelected); variablesBindedToCurvesSerialized.value = variablesBindedToCurves = vList.ToArray(); variablesBindedToCurvesSerialized.ValueChanged(); List <Color> cList = curveColors.ToList(); cList.RemoveAt(_curveIndexSelected); curvesColorsSerialized.value = curveColors = cList.ToArray(); curvesColorsSerialized.ValueChanged(); List <AnimationCurve> crList = curves.ToList(); crList.RemoveAt(_curveIndexSelected); curvesSerialized.value = curves = crList.ToArray(); curvesSerialized.ValueChanged(); _curveIndexSelected = -1; __variableSelected = null; __serializedNode.ApplyModifiedProperties(); } EditorGUILayout.EndHorizontal(); } else //NOT CURVE EDITOR ///////////// GAMEOBJECT - CLIP BINDINGS ////////// { __gameObjectClipList.DoLayoutList(); ////////////////////////////////////////////// } EditorGUILayout.Space(); __mecanimNodeClipBinding.clip = __spaceGameObjectAnimationClip; ///////////// TIME CONTROL OF ANIMATION (SLIDER) ///////// Rect timeControlRect = GUILayoutUtility.GetRect(Screen.width, 26f); timeControlRect.xMax = 32f; ///////////// PLAY ANIMATION TOGGLE ///////// __isPlaying = GUI.Toggle(timeControlRect, __isPlaying, !__isPlaying ? EditorGUILayoutEx.ANIMATION_STYLES.playIcon : EditorGUILayoutEx.ANIMATION_STYLES.pauseIcon, EditorGUILayoutEx.ANIMATION_STYLES.playButton); if (__isPlaying) { } else { } timeControlRect.xMin = timeControlRect.xMax + 1f; timeControlRect.xMax = timeControlRect.xMin + 21f; timeControlRect.yMin += 2f; EditorGUI.BeginChangeCheck(); Color color = GUI.color; //save color if (AnimationMode.InAnimationMode()) { GUI.color = AnimationMode.animatedPropertyColor; //change color of record button to red } ///////////// RECORD ANIMATION TOGGLE ///////// __isRecording = GUI.Toggle(timeControlRect, __isRecording, EditorGUILayoutEx.ANIMATION_STYLES.recordIcon, EditorStyles.toolbarButton); GUI.color = color; //restore color if (EditorGUI.EndChangeCheck()) { if (__isRecording) { if (!AnimationMode.InAnimationMode()) { List <EditorClipBinding> list = (clipBindingsSerialized.value as EditorClipBinding[]).ToList(); list.Add(__mecanimNodeClipBinding); __clipBindingsToBeAnimated = list.ToArray(); AnimationMode.StartAnimationMode(); Undo.postprocessModifications += PostprocessAnimationRecordingModifications; //calculate offset of boonRoot position before animation from boonRoot position at time=0s. AnimationModeUtility.SaveBindingsOffset(clipBindingsSerialized.value as EditorClipBinding[]); AnimationModeUtility.SaveBindingOffset(__mecanimNodeClipBinding); //calculate time in seconds from the current postion of time scrubber __timeCurrent = __timeNormalized * __spaceGameObjectAnimationClip.length; //apply clip animaiton at __timeCurrent AnimationModeUtility.SampleClipBindingAt(__clipBindingsToBeAnimated , __timeCurrent); LockRootGameObject(true); SceneView.RepaintAll(); } } else { //Remove Undo property modificaiton handlers Undo.postprocessModifications -= PostprocessAnimationRecordingModifications; AnimationMode.StopAnimationMode(); //reset gameobject with bones to state before animation AnimationModeUtility.ResetBindingsTransformPropertyModification(clipBindingsSerialized.value as EditorClipBinding[]); //reset Node.self gameObject AnimationModeUtility.ResetBindingTransformPropertyModification(__mecanimNodeClipBinding); LockRootGameObject(false); } } timeControlRect.xMin = 40f + 16f; timeControlRect.xMax = Screen.width - 68f; timeControlRect.yMin -= 2f; EditorGUI.BeginChangeCheck(); /// TIMELINE SLIDER /// __timeNormalized = EditorGUILayoutEx.CustomHSlider(timeControlRect, __timeNormalized, 0f, 1f, EditorGUILayoutEx.ANIMATION_STYLES.timeScrubber); if (EditorGUI.EndChangeCheck() || __timeNormalizedUpdate) { __timeCurrent = __timeNormalized * __spaceGameObjectAnimationClip.length; __timeNormalizedUpdate = false; if (!AnimationMode.InAnimationMode()) { AnimationMode.StartAnimationMode(); //calculate offset of boonRoot position before animation from boonRoot position at time=0s. AnimationModeUtility.SaveBindingsOffset(clipBindingsSerialized.value as EditorClipBinding[]); AnimationModeUtility.SaveBindingOffset(__mecanimNodeClipBinding); LockRootGameObject(true); } if (!__isRecording) { __isRecording = true; //add recording Undo events handlers Undo.postprocessModifications += PostprocessAnimationRecordingModifications; List <EditorClipBinding> list = (clipBindingsSerialized.value as EditorClipBinding[]).ToList(); list.Add(__mecanimNodeClipBinding); __clipBindingsToBeAnimated = list.ToArray(); } //moves clip to time: __timeCurrent AnimationModeUtility.SampleClipBindingAt(__clipBindingsToBeAnimated, __timeCurrent); } ///////////// ROTATION/SCALE KEYFRAMES ///////////////////////// Rect keyframesRect = GUILayoutUtility.GetRect(Screen.width - 16f, 16f); keyframesRect.xMax = timeControlRect.xMax + _keyframeMarker.image.width * 0.5f; keyframesRect.xMin = timeControlRect.xMin - _keyframeMarker.image.width * 0.5f; //Show rotation or scale keyframes if Rotation or Scale tools are selected if (Selection.activeGameObject != null) { if (Tools.current == Tool.Rotate) { EditorClipBinding clipBindingCurrent = (clipBindingsSerialized.value as EditorClipBinding[]).FirstOrDefault((itm) => itm.gameObject != null && itm.gameObject.transform.childCount > 0 && itm.gameObject.transform.GetChild(0).gameObject == Selection.activeGameObject); if (clipBindingCurrent != null && clipBindingCurrent.visible && clipBindingCurrent.clip != null) { EditorCurveBinding curveBinding = AnimationUtilityEx.EditorCurveBinding_RotX; curveBinding.path = AnimationUtility.CalculateTransformPath(clipBindingCurrent.gameObject.transform.GetChild(0), clipBindingCurrent.gameObject.transform.root); keyframeTimeValues = AnimationUtilityEx.GetTimesNormalized(clipBindingCurrent.clip, curveBinding, __spaceGameObjectAnimationClip.length); } else { keyframeTimeValues = new float[0]; } } else if (Tools.current == Tool.Scale) { EditorClipBinding clipBindingCurrent = (clipBindingsSerialized.value as EditorClipBinding[]).FirstOrDefault((itm) => itm.gameObject != null && itm.gameObject.transform.childCount > 0 && itm.gameObject.transform.GetChild(0).gameObject == Selection.activeGameObject); if (clipBindingCurrent != null && clipBindingCurrent.visible && clipBindingCurrent.clip != null) { EditorCurveBinding curveBinding = AnimationUtilityEx.EditorCurveBinding_SclX; curveBinding.path = AnimationUtility.CalculateTransformPath(clipBindingCurrent.gameObject.transform.GetChild(0), clipBindingCurrent.gameObject.transform.root); keyframeTimeValues = AnimationUtilityEx.GetTimesNormalized(clipBindingCurrent.clip, curveBinding, __spaceGameObjectAnimationClip.length); } else { keyframeTimeValues = new float[0]; } } else { keyframeTimeValues = new float[0]; } } else { keyframeTimeValues = new float[0]; } keyframesDisplayNames = keyframeTimeValues.Select((itm) => { return(Decimal.Round(Convert.ToDecimal(itm * __spaceGameObjectAnimationClip.length), 2).ToString() + ".s"); }).ToArray(); keyframeTimeValuesSelected = new bool[keyframeTimeValues.Length]; //used for multiselection option not used here //create custom timeline showing rotation or scale keyframes EditorGUILayoutEx.CustomTimeLine(ref keyframesRect, _keyframeMarker, ref keyframeTimeValues, ref eventTimeValuesPrev, ref keyframesDisplayNames, ref keyframeTimeValuesSelected, -1f, null, onKeyframeDelete, null, onKeyframeEdit, null ); // DISPLAY TIME in [s] and in [%] EditorGUILayout.LabelField("Time: " + Decimal.Round(Convert.ToDecimal(__timeCurrent), 2).ToString() + "s (" + Mathf.FloorToInt(__timeNormalized * 100) + "%) Frame:" + Mathf.FloorToInt(__timeCurrent * __spaceGameObjectAnimationClip.frameRate).ToString()); /////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////// /// /// Draw red time scrubber line on top of Curve Editor /// ////////////////////////////////////////////////////////////// if (_curvesEditorShow) { Handles.color = Color.red; float leftrightMargin = 39f; // 40f; float effectiveWidth = curveEditorRect.width - 2 * leftrightMargin - curveEditorRect.xMin; float timeLineX = curveEditorRect.xMin + leftrightMargin + effectiveWidth * __timeNormalized; Handles.DrawLine(new Vector2(timeLineX, curveEditorRect.y), new Vector2(timeLineX, curveEditorRect.y + curveEditorRect.height)); } ////////// EVALUATE CURVES ////////// int variablesNum = variablesBindedToCurves.Length; for (int varriableCurrentinx = 0; varriableCurrentinx < variablesNum; varriableCurrentinx++) { try { variablesBindedToCurves [varriableCurrentinx].Value = curves [varriableCurrentinx].Evaluate(__timeNormalized); } catch (Exception ex) { variablesBindedToCurves [varriableCurrentinx].name = "Invalid UVariable" + ex.Message; } } } }