public override void OnInspectorGUI() { bool rebuildTrack = false; base.OnInspectorGUI(); serializedObject.Update(); if (_animationClip.objectReferenceValue == null) { EditorGUILayout.HelpBox("There's no Animation Clip", MessageType.Warning); Rect helpBoxRect = GUILayoutUtility.GetLastRect(); float yCenter = helpBoxRect.center.y; helpBoxRect.xMax -= 3; helpBoxRect.xMin = helpBoxRect.xMax - 50; helpBoxRect.yMin = yCenter - 12.5f; helpBoxRect.height = 25f; FAnimationTrack animTrack = (FAnimationTrack)_animEvent.Track; if (animTrack.AnimatorController == null || animTrack.LayerId == -1) { GUI.enabled = false; } if (GUI.Button(helpBoxRect, "Create")) { CreateAnimationClip(_animEvent); } GUI.enabled = true; } EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_animationClip); Rect animationClipRect = GUILayoutUtility.GetLastRect(); if (Event.current.type == EventType.DragUpdated && animationClipRect.Contains(Event.current.mousePosition)) { int numAnimations = NumAnimationsDragAndDrop(_animEvent.Sequence.FrameRate); if (numAnimations > 0) { DragAndDrop.visualMode = DragAndDropVisualMode.Link; } } else if (Event.current.type == EventType.DragPerform && animationClipRect.Contains(Event.current.mousePosition)) { if (NumAnimationsDragAndDrop(_animEvent.Sequence.FrameRate) > 0) { DragAndDrop.AcceptDrag(); AnimationClip clip = GetAnimationClipDragAndDrop(_animEvent.Sequence.FrameRate); if (clip != null) { _animationClip.objectReferenceValue = clip; } } } if (EditorGUI.EndChangeCheck()) { AnimationClip clip = (AnimationClip)_animationClip.objectReferenceValue; if (clip) { if (clip.frameRate != _animEvent.Track.Timeline.Sequence.FrameRate) { Debug.LogError(string.Format("Can't add animation, it has a different frame rate from the sequence ({0} vs {1})", clip.frameRate, _animEvent.Track.Timeline.Sequence.FrameRate)); _animationClip.objectReferenceValue = null; } else { SerializedProperty frameRangeEnd = _frameRange.FindPropertyRelative("_end"); FrameRange maxFrameRange = _animEvent.GetMaxFrameRange(); frameRangeEnd.intValue = Mathf.Min(_animEvent.FrameRange.Start + Mathf.RoundToInt(clip.length * clip.frameRate), maxFrameRange.End); } rebuildTrack = true; } else { CheckDeleteAnimation(_animEvent); } } bool isAnimationEditable = Flux.FUtility.IsAnimationEditable(_animEvent._animationClip); if (isAnimationEditable) { EditorGUILayout.PropertyField(_controlsAnimation); } else { if (_controlsAnimation.boolValue) { _controlsAnimation.boolValue = false; } } if (!_controlsAnimation.boolValue) { if (_animEvent.IsBlending()) { float offset = _startOffset.intValue / _animEvent._animationClip.frameRate; float blendFinish = offset + (_blendLength.intValue / _animEvent._animationClip.frameRate); EditorGUILayout.BeginHorizontal(); EditorGUILayout.BeginHorizontal(GUILayout.Width(EditorGUIUtility.labelWidth - 5)); // hack to get around some layout issue with imgui _showBlendAndOffsetContent = EditorGUILayout.Foldout(_showBlendAndOffsetContent, new GUIContent("Offset+Blend")); EditorGUILayout.EndHorizontal(); EditorGUI.BeginChangeCheck(); EditorGUILayout.MinMaxSlider(ref offset, ref blendFinish, 0, _animEvent.GetMaxStartOffset() / _animEvent._animationClip.frameRate + _animEvent.LengthTime); if (EditorGUI.EndChangeCheck()) { _startOffset.intValue = Mathf.Clamp(Mathf.RoundToInt(offset * _animEvent.Sequence.FrameRate), 0, _animEvent.GetMaxStartOffset()); _blendLength.intValue = Mathf.Clamp(Mathf.RoundToInt((blendFinish - offset) * _animEvent.Sequence.FrameRate), 0, _animEvent.Length); rebuildTrack = true; } EditorGUILayout.EndHorizontal(); if (_showBlendAndOffsetContent) { EditorGUI.BeginChangeCheck(); ++EditorGUI.indentLevel; if (!isAnimationEditable) { EditorGUILayout.IntSlider(_startOffset, 0, _animEvent.GetMaxStartOffset()); } // if( _animEvent.IsBlending() ) { EditorGUILayout.IntSlider(_blendLength, 0, _animEvent.Length); } --EditorGUI.indentLevel; if (EditorGUI.EndChangeCheck()) { rebuildTrack = true; } } } else { EditorGUI.BeginChangeCheck(); EditorGUILayout.IntSlider(_startOffset, 0, _animEvent.GetMaxStartOffset()); if (EditorGUI.EndChangeCheck()) { rebuildTrack = true; } } } serializedObject.ApplyModifiedProperties(); if (rebuildTrack) { FAnimationTrackInspector.RebuildStateMachine((FAnimationTrack)_animEvent.Track); } }
private void UpdateEventFromController() { bool isBlending = _animEvt.IsBlending(); if (isBlending) { // FPlayAnimationEvent prevAnimEvt = (FPlayAnimationEvent)_animTrack.GetEvents()[_animEvt.GetId() - 1]; if (_transitionToState == null) { _transitionToState = FAnimationTrackInspector.GetTransitionTo(_animEvt); if (_transitionToState == null) { // if( animTrackEditor.PreviewInSceneView ) // animTrackEditor.ClearPreview(); FAnimationTrackInspector.RebuildStateMachine((FAnimationTrack)_trackEditor._track); _transitionToState = FAnimationTrackInspector.GetTransitionTo(_animEvt); } } if (_transitionSO == null) { if (_transitionToState != null) { _transitionSO = new SerializedObject(_transitionToState); // SerializedProperty p = _transitionSO.GetIterator(); // // while( p.Next( true ) ) // Debug.Log (p.propertyPath ); _transitionDuration = _transitionSO.FindProperty("m_TransitionDuration"); _transitionOffset = _transitionSO.FindProperty("m_TransitionOffset"); _transitionConditions = _transitionSO.FindProperty("m_Conditions"); } } else if (_transitionSO.targetObject == null) { _transitionDuration = null; _transitionOffset = null; _transitionConditions = null; _transitionSO = null; } } else { if (_transitionToState != null || _transitionSO != null) { _transitionToState = null; _transitionSO = null; _transitionOffset = null; _transitionDuration = null; _transitionConditions = null; } } if (_transitionSO != null) { _transitionSO.Update(); _animEvtSO.Update(); FPlayAnimationEvent prevAnimEvt = (FPlayAnimationEvent)_animTrack.GetEvents()[_animEvt.GetId() - 1]; AnimationClip prevAnimEvtClip = prevAnimEvt._animationClip; if (prevAnimEvtClip != null) { float exitTimeNormalized = (prevAnimEvt.Length / prevAnimEvtClip.frameRate) / prevAnimEvtClip.length; SerializedProperty exitTime = _transitionConditions.GetArrayElementAtIndex(0).FindPropertyRelative("m_ExitTime"); if (!Mathf.Approximately(exitTimeNormalized, exitTime.floatValue)) { exitTime.floatValue = exitTimeNormalized; } float blendNormalized = (_blendLength.intValue / prevAnimEvtClip.frameRate) / prevAnimEvtClip.length; if (!Mathf.Approximately(blendNormalized, _transitionDuration.floatValue)) { _blendLength.intValue = Mathf.Clamp(Mathf.RoundToInt(_transitionDuration.floatValue * prevAnimEvtClip.length * prevAnimEvtClip.frameRate), 0, _animEvt.Length); _transitionDuration.floatValue = (_blendLength.intValue / prevAnimEvtClip.frameRate) / prevAnimEvtClip.length; _animEvtSO.ApplyModifiedProperties(); } } _transitionSO.ApplyModifiedProperties(); } }
public static void RebuildStateMachine(FAnimationTrack track) { if (track.AnimatorController == null || track.LayerId == -1) { return; } bool isPreviewing = track.HasCache; if (isPreviewing) { track.ClearCache(); } Animator animator = track.Owner.GetComponent <Animator>(); animator.runtimeAnimatorController = null; AnimatorController controller = (AnimatorController)track.AnimatorController; track.UpdateEventIds(); AnimatorControllerLayer layer = FindLayer(controller, track.LayerName); if (layer == null) { controller.AddLayer(track.LayerName); layer = FindLayer(controller, track.LayerName); } AnimatorStateMachine fluxSM = FindStateMachine(layer.stateMachine, FLUX_STATE_MACHINE_NAME); if (fluxSM == null) { fluxSM = layer.stateMachine.AddStateMachine(FLUX_STATE_MACHINE_NAME); ChildAnimatorStateMachine[] stateMachines = layer.stateMachine.stateMachines; for (int i = 0; i != stateMachines.Length; ++i) { if (stateMachines[i].stateMachine == fluxSM) { stateMachines[i].position = layer.stateMachine.entryPosition + new Vector3(300, 0, 0); break; } } layer.stateMachine.stateMachines = stateMachines; } List <FEvent> events = track.Events; if (fluxSM.states.Length > events.Count) { for (int i = events.Count; i < fluxSM.states.Length; ++i) { fluxSM.RemoveState(fluxSM.states[i].state); } } else if (fluxSM.states.Length < events.Count) { for (int i = fluxSM.states.Length; i < events.Count; ++i) { fluxSM.AddState(i.ToString()); } } AnimatorState lastState = null; Vector3 pos = fluxSM.entryPosition + new Vector3(300, 0, 0); Vector3 statePosDelta = new Vector3(0, 80, 0); ChildAnimatorState[] states = fluxSM.states; for (int i = 0; i != events.Count; ++i) { FPlayAnimationEvent animEvent = (FPlayAnimationEvent)events[i]; if (animEvent._animationClip == null) // dump events without animations { continue; } states[i].position = pos; AnimatorState state = states[i].state; state.name = i.ToString(); pos += statePosDelta; state.motion = animEvent._animationClip; animEvent._stateHash = Animator.StringToHash(state.name); if (lastState) { AnimatorStateTransition[] lastStateTransitions = lastState.transitions; if (animEvent.IsBlending()) { AnimatorStateTransition transition = null; for (int j = lastStateTransitions.Length - 1; j > 0; --j) { lastState.RemoveTransition(lastStateTransitions[j]); } transition = lastStateTransitions.Length == 1 ? lastStateTransitions[0] : lastState.AddTransition(state); transition.offset = (animEvent._startOffset / animEvent._animationClip.frameRate) / animEvent._animationClip.length; FPlayAnimationEvent prevAnimEvent = (FPlayAnimationEvent)events[i - 1]; int offsetFrame = Mathf.RoundToInt(transition.offset * animEvent._animationClip.length * animEvent._animationClip.frameRate); animEvent._startOffset = Mathf.Clamp(offsetFrame, 0, animEvent.GetMaxStartOffset()); transition.offset = (animEvent._startOffset / animEvent._animationClip.frameRate) / animEvent._animationClip.length; EditorUtility.SetDirty(animEvent); float blendSeconds = animEvent._blendLength / prevAnimEvent._animationClip.frameRate; transition.duration = blendSeconds; transition.hasExitTime = true; float p = blendSeconds / prevAnimEvent._animationClip.length; transition.exitTime = p > 1f ? 1f : 1f - Mathf.Clamp01(blendSeconds / prevAnimEvent._animationClip.length); for (int j = transition.conditions.Length - 1; j >= 0; --j) { transition.RemoveCondition(transition.conditions[j]); } // AnimatorCondition condition = transition.conditions[0]; // condition.threshold = 0; } else // animations not blending, needs hack for animation previewing { for (int j = lastStateTransitions.Length - 1; j >= 0; --j) { lastState.RemoveTransition(lastStateTransitions[j]); } } } lastState = state; } fluxSM.states = states; if (fluxSM.states.Length > 0) { layer.stateMachine.defaultState = fluxSM.states[0].state; } animator.runtimeAnimatorController = controller; if (isPreviewing) { track.CreateCache(); } }
public override void OnInspectorGUI() { bool rebuildTrack = false; base.OnInspectorGUI(); serializedObject.Update(); if (_animationClip.objectReferenceValue == null) { EditorGUILayout.HelpBox("无动画剪辑Clip", MessageType.Warning); } EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(_animationClip, _animationClipUI); Rect animationClipRect = GUILayoutUtility.GetLastRect(); if (Event.current.type == EventType.DragUpdated && animationClipRect.Contains(Event.current.mousePosition)) { int numAnimations = NumAnimationsDragAndDrop(_animEvent.Sequence.FrameRate); if (numAnimations > 0) { DragAndDrop.visualMode = DragAndDropVisualMode.Link; } } else if (Event.current.type == EventType.DragPerform && animationClipRect.Contains(Event.current.mousePosition)) { if (NumAnimationsDragAndDrop(_animEvent.Sequence.FrameRate) > 0) { DragAndDrop.AcceptDrag(); AnimationClip clip = GetAnimationClipDragAndDrop(_animEvent.Sequence.FrameRate); if (clip != null) { _animationClip.objectReferenceValue = clip; } } } if (EditorGUI.EndChangeCheck()) { AnimationClip clip = (AnimationClip)_animationClip.objectReferenceValue; if (clip) { if (clip.frameRate != _animEvent.Track.Container.Sequence.FrameRate) { Debug.LogError(string.Format("Can't add animation, it has a different frame rate from the sequence ({0} vs {1})", clip.frameRate, _animEvent.Track.Container.Sequence.FrameRate)); _animationClip.objectReferenceValue = null; } else { SerializedProperty frameRangeEnd = _frameRange.FindPropertyRelative("_end"); FrameRange maxFrameRange = _animEvent.GetMaxFrameRange(); frameRangeEnd.intValue = Mathf.Min(_animEvent.FrameRange.Start + Mathf.RoundToInt(clip.length * clip.frameRate), maxFrameRange.End); } rebuildTrack = true; } else { CheckDeleteAnimation(_animEvent); } } if (_animEvent.IsBlending()) { int id = _animEvent.GetId(); FPlayAnimationEvent preAnimEvt = _animEvent.Track.Events[id - 1] as FPlayAnimationEvent; if (id > 0) { EditorGUI.BeginChangeCheck(); EditorGUILayout.IntSlider(_startOffset, 0, _animEvent.GetMaxStartOffset(), _startOffsetUI); EditorGUILayout.IntSlider(_blendLength, 0, preAnimEvt.Length > _animEvent.Length ? _animEvent.Length : preAnimEvt.Length, _blendLengthUI); if (EditorGUI.EndChangeCheck()) { rebuildTrack = true; } } } else { EditorGUI.BeginChangeCheck(); EditorGUILayout.IntSlider(_startOffset, 0, _animEvent.GetMaxStartOffset(), _startOffsetUI); if (EditorGUI.EndChangeCheck()) { rebuildTrack = true; } } serializedObject.ApplyModifiedProperties(); if (rebuildTrack) { FAnimationTrackInspector.RebuildStateMachine((FAnimationTrack)_animEvent.Track); } }