/* * [MenuItem("Assets/Export Mecanim Animation Controller", false, 301)] * private static void CreateAnimatorFile() { * var animatorController = Selection.activeObject as AnimatorController; * if (animatorController == null) { * return; * } * * CreateAsset(animatorController); * } * * [MenuItem("Assets/Export Mecanim Animation Controller", true)] * private static bool CreateAnimatorController() { * return Selection.activeObject is AnimatorController; * } */ // public static AnimatorGraphAsset Fetch(string name) { // AnimatorGraphAsset output = null; //#if UNITY_EDITOR // string pathToAnimationResource = "Assets/Resources/DB/Animator/"; // string animationFilePath = pathToAnimationResource + name + ".asset"; // output = UnityEditor.AssetDatabase.LoadAssetAtPath(animationFilePath, typeof(AnimatorGraphAsset)) as AnimatorGraphAsset; // if (output == null) { // output = CreateInstance<AnimatorGraphAsset>(); // animationFilePath = UnityEditor.AssetDatabase.GenerateUniqueAssetPath(animationFilePath); // UnityEditor.AssetDatabase.CreateAsset(output, animationFilePath); // UnityEditor.AssetDatabase.SaveAssets(); // UnityEditor.AssetDatabase.Refresh(); // } //#endif // if (output != null) { // if (output.Settings == null) // output.Settings = new AnimatorGraph(); // } // return output; // } public static void CreateAsset(AnimatorGraphAsset dataAsset, AnimatorController controller) { if (!controller) { return; } if (!dataAsset) { return; } QuantumRunner.Init();//make sure we can get debug calls from Quantum dataAsset.controller = controller; int weightTableResolution = (int)dataAsset.weight_table_resolution; int variableCount = controller.parameters.Length; dataAsset.Settings.variables = new AnimatorVariable[variableCount]; //Mecanim Parameters/Variables //make a dictionary of paramets by name for use when extracting conditions for transitions Dictionary <string, AnimatorControllerParameter> parameterDic = new Dictionary <string, AnimatorControllerParameter>(); for (int v = 0; v < variableCount; v++) { AnimatorControllerParameter parameter = controller.parameters[v]; parameterDic.Add(parameter.name, parameter); AnimatorVariable newVariable = new AnimatorVariable(); newVariable.name = parameter.name; newVariable.index = v; switch (parameter.type) { case AnimatorControllerParameterType.Bool: newVariable.type = AnimatorVariable.VariableType.Bool; newVariable.defaultBool = parameter.defaultBool; break; case AnimatorControllerParameterType.Float: newVariable.type = AnimatorVariable.VariableType.FP; newVariable.defaultFp = FP.FromFloat_UNSAFE(parameter.defaultFloat); break; case AnimatorControllerParameterType.Int: newVariable.type = AnimatorVariable.VariableType.Int; newVariable.defaultInt = parameter.defaultInt; break; case AnimatorControllerParameterType.Trigger: newVariable.type = AnimatorVariable.VariableType.Trigger; break; } dataAsset.Settings.variables[v] = newVariable; } //Mecanim State Graph int layerCount = controller.layers.Length; dataAsset.clips.Clear(); dataAsset.Settings.layers = new AnimatorLayer[layerCount]; for (int l = 0; l < layerCount; l++) { AnimatorLayer newLayer = new AnimatorLayer(); newLayer.name = controller.layers[l].name; newLayer.id = l; int stateCount = controller.layers[l].stateMachine.states.Length; newLayer.states = new Quantum.AnimatorState[stateCount + 1];//additional element for the any state Dictionary <UnityEditor.Animations.AnimatorState, Quantum.AnimatorState> stateDictionary = new Dictionary <AnimatorState, Quantum.AnimatorState>(); for (int s = 0; s < stateCount; s++) { UnityEditor.Animations.AnimatorState state = controller.layers[l].stateMachine.states[s].state; Quantum.AnimatorState newState = new Quantum.AnimatorState(); newState.name = state.name; newState.id = state.nameHash; newState.isDefault = controller.layers[l].stateMachine.defaultState == state; newState.speed = FP.FromFloat_UNSAFE(state.speed); newState.cycleOffset = FP.FromFloat_UNSAFE(state.cycleOffset); if (state.motion != null) { AnimationClip clip = state.motion as AnimationClip; if (clip != null) { dataAsset.clips.Add(clip); AnimatorClip newClip = new AnimatorClip(); newClip.name = state.motion.name; newClip.data = Extract(clip); newState.motion = newClip; } else { BlendTree tree = state.motion as BlendTree; if (tree != null) { int childCount = tree.children.Length; AnimatorBlendTree newBlendTree = new AnimatorBlendTree(); newBlendTree.name = state.motion.name; newBlendTree.motionCount = childCount; newBlendTree.motions = new AnimatorMotion[childCount]; newBlendTree.positions = new FPVector2[childCount]; newBlendTree.weights = new FP[childCount]; string parameterXname = tree.blendParameter; string parameterYname = tree.blendParameterY; for (int v = 0; v < variableCount; v++) { if (controller.parameters[v].name == parameterXname) { newBlendTree.blendParameterIndex = v; } if (controller.parameters[v].name == parameterYname) { newBlendTree.blendParameterIndexY = v; } } for (int c = 0; c < childCount; c++) { ChildMotion cMotion = tree.children[c]; AnimationClip cClip = cMotion.motion as AnimationClip; newBlendTree.positions[c] = new FPVector2(FP.FromFloat_UNSAFE(cMotion.position.x), FP.FromFloat_UNSAFE(cMotion.position.y)); if (cClip != null) { dataAsset.clips.Add(cClip); AnimatorClip newClip = new AnimatorClip(); newClip.data = Extract(cClip); newClip.name = newClip.clipName; newBlendTree.motions[c] = newClip; } } FP val = FP._0 / 21; newBlendTree.CalculateWeightTable(weightTableResolution); newState.motion = newBlendTree; } } } newLayer.states[s] = newState; stateDictionary.Add(state, newState); } //State Transistions //once the states have all been created //we'll hook up the transitions for (int s = 0; s < stateCount; s++) { UnityEditor.Animations.AnimatorState state = controller.layers[l].stateMachine.states[s].state; Quantum.AnimatorState newState = newLayer.states[s]; int transitionCount = state.transitions.Length; newState.transitions = new Quantum.AnimatorTransition[transitionCount]; for (int t = 0; t < transitionCount; t++) { AnimatorStateTransition transition = state.transitions[t]; if (!stateDictionary.ContainsKey(transition.destinationState)) { continue; } Quantum.AnimatorTransition newTransition = new Quantum.AnimatorTransition(); newTransition.index = t; newTransition.name = string.Format("{0} to {1}", state.name, transition.destinationState.name); newTransition.duration = FP.FromFloat_UNSAFE(transition.duration * state.motion.averageDuration); newTransition.hasExitTime = transition.hasExitTime; newTransition.exitTime = FP.FromFloat_UNSAFE(transition.exitTime * state.motion.averageDuration); newTransition.offset = FP.FromFloat_UNSAFE(transition.offset * transition.destinationState.motion.averageDuration); newTransition.destinationStateId = stateDictionary[transition.destinationState].id; newTransition.destinationStateName = stateDictionary[transition.destinationState].name; newTransition.canTransitionToSelf = transition.canTransitionToSelf; int conditionCount = transition.conditions.Length; newTransition.conditions = new Quantum.AnimatorCondition[conditionCount]; for (int c = 0; c < conditionCount; c++) { UnityEditor.Animations.AnimatorCondition condition = state.transitions[t].conditions[c]; if (!parameterDic.ContainsKey(condition.parameter)) { continue; } AnimatorControllerParameter parameter = parameterDic[condition.parameter]; Quantum.AnimatorCondition newCondition = new Quantum.AnimatorCondition(); newCondition.variableName = condition.parameter; newCondition.mode = (Quantum.AnimatorCondition.Modes)condition.mode; switch (parameter.type) { case AnimatorControllerParameterType.Float: newCondition.thresholdFp = FP.FromFloat_UNSAFE(condition.threshold); break; case AnimatorControllerParameterType.Int: newCondition.thresholdInt = Mathf.RoundToInt(condition.threshold); break; } newTransition.conditions[c] = newCondition; } newState.transitions[t] = newTransition; } } //Create Any State Quantum.AnimatorState anyState = new Quantum.AnimatorState(); anyState.name = "Any State"; anyState.id = anyState.name.GetHashCode(); anyState.isAny = true;//important for this one AnimatorStateTransition[] anyStateTransitions = controller.layers[l].stateMachine.anyStateTransitions; int anyStateTransitionCount = anyStateTransitions.Length; anyState.transitions = new Quantum.AnimatorTransition[anyStateTransitionCount]; for (int t = 0; t < anyStateTransitionCount; t++) { AnimatorStateTransition transition = anyStateTransitions[t]; if (!stateDictionary.ContainsKey(transition.destinationState)) { continue; } Quantum.AnimatorTransition newTransition = new Quantum.AnimatorTransition(); newTransition.index = t; newTransition.name = string.Format("Any State to {0}", transition.destinationState.name); newTransition.duration = FP.FromFloat_UNSAFE(transition.duration); newTransition.hasExitTime = transition.hasExitTime; newTransition.exitTime = FP._1; newTransition.offset = FP.FromFloat_UNSAFE(transition.offset * transition.destinationState.motion.averageDuration); newTransition.destinationStateId = stateDictionary[transition.destinationState].id; newTransition.destinationStateName = stateDictionary[transition.destinationState].name; newTransition.canTransitionToSelf = transition.canTransitionToSelf; int conditionCount = transition.conditions.Length; newTransition.conditions = new Quantum.AnimatorCondition[conditionCount]; for (int c = 0; c < conditionCount; c++) { UnityEditor.Animations.AnimatorCondition condition = anyStateTransitions[t].conditions[c]; if (!parameterDic.ContainsKey(condition.parameter)) { continue; } AnimatorControllerParameter parameter = parameterDic[condition.parameter]; Quantum.AnimatorCondition newCondition = new Quantum.AnimatorCondition(); newCondition.variableName = condition.parameter; newCondition.mode = (Quantum.AnimatorCondition.Modes)condition.mode; switch (parameter.type) { case AnimatorControllerParameterType.Float: newCondition.thresholdFp = FP.FromFloat_UNSAFE(condition.threshold); break; case AnimatorControllerParameterType.Int: newCondition.thresholdInt = Mathf.RoundToInt(condition.threshold); break; } newTransition.conditions[c] = newCondition; } anyState.transitions[t] = newTransition; } newLayer.states[stateCount] = anyState; dataAsset.Settings.layers[l] = newLayer; } EditorUtility.SetDirty(dataAsset); }
public override void OnInspectorGUI() { var graph = asset.Settings; if (GUILayout.Button("Import Mecanim Controller")) { ExportAnimations.CreateAsset(asset, (UnityEditor.Animations.AnimatorController)asset.controller); EditorUtility.SetDirty(asset); AssetDatabase.Refresh(); } if (graph != null && graph.layers != null) { int layerCount = graph.layers.Length; if (layerCount > 0) { string[] layerNames = new string[layerCount]; for (int l = 0; l < layerCount; l++) { layerNames[l] = graph.layers[l].name; } selectedLayer = GUILayout.Toolbar(selectedLayer, layerNames); AnimatorLayer layer = graph.layers[selectedLayer]; if (layer != null) { int stateCount = layer.states.Length; if (stateCount > 0) { string[] stateNames = new string[stateCount]; for (int s = 0; s < stateCount; s++) { stateNames[s] = layer.states[s].name; } selectedState = GUILayout.Toolbar(selectedState, stateNames); AnimatorState state = layer.states[selectedState]; if (state != null) { EditorGUILayout.BeginVertical("box"); EditorGUILayout.LabelField("State"); EditorGUILayout.LabelField(state.name); EditorGUILayout.LabelField(string.Format("Is Default: {0}", state.isDefault)); if (state.motion != null) { EditorGUILayout.LabelField(string.Format("Is Blend Tree: {0}", state.motion.isTree)); if (!state.motion.isTree) { AnimatorClip motion = state.motion as AnimatorClip; AnimationClipGui(motion); } else { AnimatorBlendTree motion = state.motion as AnimatorBlendTree; string[] blends = new string[motion.motionCount]; for (int b = 0; b < motion.motionCount; b++) { blends[b] = motion.motions[b].name; } selectedBlend = SelectionField(blends, selectedBlend, 2); AnimatorClip clip = motion.motions[selectedBlend] as AnimatorClip; AnimationClipGui(clip); } } else { EditorGUILayout.LabelField("No Motion Set"); } EditorGUILayout.Space(); EditorGUILayout.LabelField("Transitions"); int transitionCount = state.transitions.Length; for (int t = 0; t < transitionCount; t++) { EditorGUILayout.BeginVertical("Box"); AnimatorTransition transition = state.transitions[t]; EditorGUILayout.LabelField(string.Format("{0}. {1}", transition.index, transition.name)); EditorGUILayout.LabelField(string.Format("Duration: {0} sec", transition.duration.AsFloat)); EditorGUILayout.LabelField(string.Format("Has Exit Time: {0}", transition.hasExitTime)); EditorGUILayout.LabelField(string.Format("Exit Time: {0} sec", transition.exitTime.AsFloat)); EditorGUILayout.LabelField(string.Format("Destination State (Hash): {0} ({1})", transition.destinationStateName, transition.destinationStateId)); EditorGUILayout.LabelField(string.Format("Offset: {0} sec", transition.offset.AsFloat)); int conditionCount = transition.conditions.Length; for (int c = 0; c < conditionCount; c++) { EditorGUILayout.BeginVertical("Box"); AnimatorCondition condition = transition.conditions[c]; AnimatorVariable variable = graph.variables[graph.VariableIndex(condition.variableName)]; string conditionMode = ""; switch (condition.mode) { case AnimatorCondition.Modes.Equals: conditionMode = "=="; break; case AnimatorCondition.Modes.Greater: conditionMode = ">"; break; case AnimatorCondition.Modes.If: conditionMode = "is true"; break; case AnimatorCondition.Modes.IfNot: conditionMode = "is false"; break; case AnimatorCondition.Modes.Less: conditionMode = "<"; break; case AnimatorCondition.Modes.NotEqual: conditionMode = "!="; break; } string threshold = ""; switch (variable.type) { case AnimatorVariable.VariableType.FP: threshold = condition.thresholdFp.AsFloat.ToString(); break; case AnimatorVariable.VariableType.Int: threshold = condition.thresholdInt.ToString(); break; } EditorGUILayout.LabelField(string.Format("\"{0}\" - {1} - {2}", condition.variableName, conditionMode, threshold)); EditorGUILayout.EndVertical(); } EditorGUILayout.EndVertical(); } EditorGUILayout.EndVertical(); } } } } } base.OnInspectorGUI(); }
public AnimatorData(Animator v) { animatorVal = v; animatorRef = null; }