// Initialize state machine of one layer. private static bool InitLayerNodes(MyAnimationStateMachine layer, string stateMachineName, MyAnimationControllerDefinition animControllerDefinition, MyAnimationController animationController, string currentNodeNamePrefix, MyAnimationVirtualNodes virtualNodes, bool forceReloadMwm) { var objBuilderStateMachine = animControllerDefinition.StateMachines.FirstOrDefault(x => x.Name == stateMachineName); if (objBuilderStateMachine == null) { Debug.Fail("Animation state machine " + stateMachineName + " was not found."); return false; } bool result = true; // 1st step: generate nodes if (objBuilderStateMachine.Nodes != null) foreach (var objBuilderNode in objBuilderStateMachine.Nodes) { string absoluteNodeName = currentNodeNamePrefix + objBuilderNode.Name; if (objBuilderNode.StateMachineName != null) { // embedded state machine, copy its nodes if (!InitLayerNodes(layer, objBuilderNode.StateMachineName, animControllerDefinition, animationController, absoluteNodeName + "/", virtualNodes, forceReloadMwm)) result = false; } else { var smNode = new VRageRender.Animations.MyAnimationStateMachineNode(absoluteNodeName); if (objBuilderNode.Type == MyObjectBuilder_AnimationSMNode.MySMNodeType.PassThrough || objBuilderNode.Type == MyObjectBuilder_AnimationSMNode.MySMNodeType.Any || objBuilderNode.Type == MyObjectBuilder_AnimationSMNode.MySMNodeType.AnyExceptTarget) { smNode.PassThrough = true; } else { smNode.PassThrough = false; } if (objBuilderNode.Type == MyObjectBuilder_AnimationSMNode.MySMNodeType.Any || objBuilderNode.Type == MyObjectBuilder_AnimationSMNode.MySMNodeType.AnyExceptTarget) { virtualNodes.NodesAny.Add(absoluteNodeName, new MyAnimationVirtualNodeData() { AnyNodePrefix = currentNodeNamePrefix, ExceptTarget = (objBuilderNode.Type == MyObjectBuilder_AnimationSMNode.MySMNodeType.AnyExceptTarget) }); } layer.AddNode(smNode); if (objBuilderNode.AnimationTree != null) { var smNodeAnimTree = InitNodeAnimationTree(objBuilderNode.AnimationTree.Child, forceReloadMwm); smNode.RootAnimationNode = smNodeAnimTree; } else { smNode.RootAnimationNode = new MyAnimationTreeNodeDummy(); } } } // 2nd step: generate transitions if (objBuilderStateMachine.Transitions != null) foreach (var objBuilderTransition in objBuilderStateMachine.Transitions) { string absoluteNameNodeFrom = currentNodeNamePrefix + objBuilderTransition.From; string absoluteNameNodeTo = currentNodeNamePrefix + objBuilderTransition.To; MyAnimationVirtualNodeData virtualNodeData; if (virtualNodes.NodesAny.TryGetValue(absoluteNameNodeFrom, out virtualNodeData)) { // nodes of type "any": // "any" node is source: we create transitions directly from all nodes // "any" node is target: we will use "any" node as pass through foreach (var nodeFromCandidate in layer.AllNodes) { if (nodeFromCandidate.Key.StartsWith(virtualNodeData.AnyNodePrefix) // select nodes in the same SM && nodeFromCandidate.Key != absoluteNameNodeFrom) // disallow from "any" to the same "any" { // create transition if target is different from source or when we don't care about it if (!virtualNodeData.ExceptTarget || absoluteNameNodeTo != nodeFromCandidate.Key) CreateTransition(layer, animationController, nodeFromCandidate.Key, absoluteNameNodeTo, objBuilderTransition); } } } CreateTransition(layer, animationController, absoluteNameNodeFrom, absoluteNameNodeTo, objBuilderTransition); } return result; }
private static void CreateTransition(MyAnimationStateMachine layer, MyAnimationController animationController, string absoluteNameNodeFrom, string absoluteNameNodeTo, MyObjectBuilder_AnimationSMTransition objBuilderTransition) { int conditionConjunctionIndex = 0; do { // generate transition for each condition conjunction var transition = layer.AddTransition(absoluteNameNodeFrom, absoluteNameNodeTo, new VRageRender.Animations.MyAnimationStateMachineTransition()) as VRageRender.Animations.MyAnimationStateMachineTransition; // if ok, fill in conditions if (transition != null) { transition.Name = MyStringId.GetOrCompute(objBuilderTransition.Name != null ? objBuilderTransition.Name.ToLower() : null); transition.TransitionTimeInSec = objBuilderTransition.TimeInSec; transition.Sync = objBuilderTransition.Sync; transition.Priority = objBuilderTransition.Priority; if (objBuilderTransition.Conditions != null && objBuilderTransition.Conditions[conditionConjunctionIndex] != null) { var conjunctionOfConditions = objBuilderTransition.Conditions[conditionConjunctionIndex].Conditions; foreach (var objBuilderCondition in conjunctionOfConditions) { var condition = ParseOneCondition(animationController, objBuilderCondition); if (condition != null) transition.Conditions.Add(condition); } } } conditionConjunctionIndex++; } while (objBuilderTransition.Conditions != null && conditionConjunctionIndex < objBuilderTransition.Conditions.Length); }
// Convert one condition from object builder to in-game representation. private static MyCondition<float> ParseOneCondition(MyAnimationController animationController, MyObjectBuilder_AnimationSMCondition objBuilderCondition) { MyCondition<float> condition; objBuilderCondition.ValueLeft = objBuilderCondition.ValueLeft != null ? objBuilderCondition.ValueLeft.ToLower() : "0"; objBuilderCondition.ValueRight = objBuilderCondition.ValueRight != null ? objBuilderCondition.ValueRight.ToLower() : "0"; double lhs, rhs; if (Double.TryParse(objBuilderCondition.ValueLeft, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out lhs)) { if (Double.TryParse(objBuilderCondition.ValueRight, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out rhs)) { condition = new VRage.Generics.StateMachine.MyCondition<float>( animationController.Variables, ConvertOperation(objBuilderCondition.Operation), (float) lhs, (float) rhs); } else { condition = new VRage.Generics.StateMachine.MyCondition<float>( animationController.Variables, ConvertOperation(objBuilderCondition.Operation), (float) lhs, objBuilderCondition.ValueRight); } } else { if (Double.TryParse(objBuilderCondition.ValueRight, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out rhs)) { condition = new VRage.Generics.StateMachine.MyCondition<float>( animationController.Variables, ConvertOperation(objBuilderCondition.Operation), objBuilderCondition.ValueLeft, (float) rhs); } else { condition = new VRage.Generics.StateMachine.MyCondition<float>( animationController.Variables, ConvertOperation(objBuilderCondition.Operation), objBuilderCondition.ValueLeft, objBuilderCondition.ValueRight); } } return condition; }
private void LiveDebugging_SendAnimationStateChangesToEditor(MyAnimationController animController) { if (animController == null) return; int layerCount = animController.GetLayerCount(); if (layerCount != m_debuggingAnimControllerCurrentNodes.Count) { m_debuggingAnimControllerCurrentNodes.Clear(); for (int i = 0; i < layerCount; i++) m_debuggingAnimControllerCurrentNodes.Add(null); m_debuggingAnimControllerTreePath.Clear(); for (int i = 0; i < layerCount; i++) { m_debuggingAnimControllerTreePath.Add(new int[animController.GetLayerByIndex(i).VisitedTreeNodesPath.Length]); } } for (int i = 0; i < layerCount; i++) { var layerVisitedTreeNodesPath = animController.GetLayerByIndex(i).VisitedTreeNodesPath; if (animController.GetLayerByIndex(i).CurrentNode != m_debuggingAnimControllerCurrentNodes[i] || !LiveDebugging_CompareAnimTreePathSeqs(layerVisitedTreeNodesPath, m_debuggingAnimControllerTreePath[i])) { Array.Copy(layerVisitedTreeNodesPath, m_debuggingAnimControllerTreePath[i], layerVisitedTreeNodesPath.Length); // local copy m_debuggingAnimControllerCurrentNodes[i] = animController.GetLayerByIndex(i).CurrentNode; if (m_debuggingAnimControllerCurrentNodes[i] != null) { var msg = MyExternalDebugStructures.ACSendStateToEditorMsg.Create(m_debuggingAnimControllerCurrentNodes[i].Name, m_debuggingAnimControllerTreePath[i]); MySessionComponentExtDebug.Static.SendMessageToClients(msg); } } } }