| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- using UnityEngine;
- using UnityEditor;
- using UnityEditor.Animations;
- //using UnityEditorInternal;
- using System.Collections.Generic;
- using Flux;
- using FluxEditor;
- namespace FluxEditor
- {
- [CustomEditor(typeof(FAnimationTrack))]
- public class FAnimationTrackInspector : FTrackInspector {
- // private const string ADVANCE_TRIGGER = "FAdvanceTrigger";
- private const string FLUX_STATE_MACHINE_NAME = "FluxStateMachine";
- private FAnimationTrack _animTrack = null;
-
- private SerializedProperty _animatorController = null;
- private SerializedProperty _layerName = null;
- private SerializedProperty _layerId = null;
- public override void OnEnable()
- {
- base.OnEnable();
- if( target == null )
- {
- DestroyImmediate( this );
- return;
- }
- _animTrack = (FAnimationTrack)target;
- _animatorController = serializedObject.FindProperty("_animatorController");
- _layerName = serializedObject.FindProperty("_layerName");
- _layerId = serializedObject.FindProperty( "_layerId" );
- }
-
- public override void OnInspectorGUI()
- {
- base.OnInspectorGUI();
- serializedObject.Update();
- if( _animatorController.objectReferenceValue == null )
- {
- EditorGUILayout.HelpBox("There's no Animator Controller", 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;
- if( GUI.Button( helpBoxRect, "Create" ) )
- {
- AnimatorController newController = CreateAnimatorController( _animTrack );
- if( newController )
- _animatorController.objectReferenceValue = newController;
- UpdateLayer( newController == null ? null : newController.layers[0] );
- }
- }
- AnimatorController prevAnimatorController = (AnimatorController)_animatorController.objectReferenceValue;
- EditorGUILayout.PropertyField( _animatorController );
- AnimatorController controller = (AnimatorController)_animatorController.objectReferenceValue;
- if( controller != prevAnimatorController )
- {
- AnimatorControllerLayer layer = controller == null ? null : controller.layers[0];
- if( layer != null && (layer.stateMachine.states.Length > 0 || layer.stateMachine.stateMachines.Length > 0) )
- layer = null;
- UpdateLayer( layer );
- }
- if( controller != null )
- {
- string[] layers = new string[controller.layers.Length];
- int layerIndex = -1;
- for( int i = 0; i != controller.layers.Length; ++i )
- {
- layers[i] = controller.layers[i].name;
- if( layers[i] == _layerName.stringValue )
- layerIndex = i;
- }
- // doesn't have layer
- if( layerIndex == -1 )
- {
- EditorGUILayout.HelpBox("No Layer Selected!", MessageType.Error);
- }
- else if( layerIndex != _layerId.intValue ) // has it, but it got moved
- {
- UpdateLayer( controller.layers[layerIndex] );
- }
- EditorGUI.BeginChangeCheck();
- layerIndex = EditorGUILayout.Popup( "State Machine Layer", layerIndex, layers );
- if( EditorGUI.EndChangeCheck() )
- {
- // choosing existing one
- if( layerIndex > -1 )
- {
- if( VerifyUseAnimatorControllerLayer( controller.layers[layerIndex] ) )
- {
- UpdateLayer( controller.layers[layerIndex] );
- }
- }
- }
- }
- serializedObject.ApplyModifiedProperties();
- }
- public void UpdateLayer( AnimatorControllerLayer layer )
- {
- if( layer == null )
- {
- _layerName.stringValue = null;
- _layerId.intValue = -1;
- }
- else
- {
- AnimatorController controller = (AnimatorController)_animatorController.objectReferenceValue;
- for( int i = 0; i != controller.layers.Length; ++i )
- {
- if( controller.layers[i].name == layer.name )
- {
- _layerName.stringValue = layer.name;
- _layerId.intValue = i;
- return;
- }
- }
- // shouldn't get here..
- Debug.LogError("Trying to set a layer that doesn't belong to the controller");
- UpdateLayer( null );
- }
- }
- 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];
- animEvent._startOffset = Mathf.Clamp( Mathf.RoundToInt(transition.offset * animEvent._animationClip.length * animEvent._animationClip.frameRate), 0, animEvent._animationClip.isLooping ? animEvent.Length : Mathf.RoundToInt( animEvent._animationClip.length * animEvent._animationClip.frameRate ) - animEvent.Length );
- transition.offset = (animEvent._startOffset / animEvent._animationClip.frameRate) / animEvent._animationClip.length;
- EditorUtility.SetDirty( animEvent );
- transition.duration = (animEvent._blendLength / prevAnimEvent._animationClip.frameRate) / prevAnimEvent._animationClip.length;
- transition.hasExitTime = true;
- transition.exitTime = (prevAnimEvent.Length + prevAnimEvent._startOffset) / (prevAnimEvent._animationClip.length*prevAnimEvent._animationClip.frameRate);
- 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 static AnimatorStateTransition GetTransitionTo( FPlayAnimationEvent animEvt )
- {
- FAnimationTrack animTrack = (FAnimationTrack)animEvt.Track;
- if( animTrack.AnimatorController == null )
- return null;
- AnimatorController controller = (AnimatorController)animTrack.AnimatorController;
- AnimatorState animState = null;
- AnimatorControllerLayer layer = FindLayer( controller, ((FAnimationTrack)animEvt.Track).LayerName );
- if( layer == null )
- return null;
- if( layer.stateMachine.stateMachines.Length == 0 )
- return null;
- ChildAnimatorStateMachine fluxSM = layer.stateMachine.stateMachines[0];
- AnimatorStateMachine stateMachine = fluxSM.stateMachine;
- for( int i = 0; i != stateMachine.states.Length; ++i )
- {
- if( stateMachine.states[i].state.nameHash == animEvt._stateHash )
- {
- animState = stateMachine.states[i].state;
- break;
- }
- }
-
- if( animState == null )
- {
- // Debug.LogError("Couldn't find state " + animEvt._animationClip );
- return null;
- }
-
- for( int i = 0; i != stateMachine.states.Length; ++i )
- {
- AnimatorState state = stateMachine.states[i].state;
- AnimatorStateTransition[] transitions = state.transitions;
- for( int j = 0; j != transitions.Length; ++j )
- {
- if( transitions[j].destinationState == animState )
- {
- return transitions[j];
- }
- }
- }
-
- return null;
- }
- public static AnimatorController CreateAnimatorController( FAnimationTrack animTrack )
- {
- string defaultFolder = "Assets/";
- string defaultFileName = string.Format( "{0}_{1}.controller", animTrack.Timeline.Sequence.name, animTrack.Owner.name );
- string defaultFilePath = AssetDatabase.GenerateUniqueAssetPath( defaultFolder+defaultFileName );
- defaultFileName = System.IO.Path.GetFileNameWithoutExtension( defaultFilePath );
-
- string filePath = EditorUtility.SaveFilePanel( "Create new AnimatorController...", defaultFolder, defaultFileName, "controller" );
-
- if( string.IsNullOrEmpty( filePath ) )
- return null;
-
- // transform the path into a local path
- if( !filePath.StartsWith( Application.dataPath ) )
- {
- Debug.LogError("Cannot save controller outside of the project");
- return null;
- }
-
- string fileLocalPath = "Assets"+filePath.Substring(Application.dataPath.Length, filePath.Length-Application.dataPath.Length);
-
- // AnimatorController animatorAtPath = (AnimatorController)AssetDatabase.LoadAssetAtPath( fileLocalPath, typeof(AnimatorController) );
- return AnimatorController.CreateAnimatorControllerAtPath( fileLocalPath );
- }
- private static bool VerifyUseAnimatorControllerLayer( AnimatorControllerLayer layer )
- {
- if( layer == null || (layer.stateMachine.states.Length == 0 && layer.stateMachine.stateMachines.Length == 0) )
- return true;
- return EditorUtility.DisplayDialog( "Animator Controller's Layer isn't empty!",
- "Layer '" + layer.name + "' is not empty, and Flux will change it.\n"
- + "Are you sure you want to use this layer?", "Use", "Cancel" );
- }
- private static AnimatorControllerParameter FindParameter( AnimatorController controller, string paramName )
- {
- foreach( AnimatorControllerParameter p in controller.parameters )
- {
- if( p.name == paramName )
- return p;
- }
- return null;
- }
- private static AnimatorControllerLayer FindLayer( AnimatorController controller, string layerName )
- {
- foreach( AnimatorControllerLayer layer in controller.layers )
- {
- if( layer.name == layerName )
- return layer;
- }
- return null;
- }
- private static AnimatorStateMachine FindStateMachine( AnimatorStateMachine stateMachine, string stateMachineName )
- {
- foreach( ChildAnimatorStateMachine sm in stateMachine.stateMachines )
- {
- if( sm.stateMachine.name == stateMachineName )
- return sm.stateMachine;
- }
- return null;
- }
- }
- }
|