// Initialize this animation controller from given object builder. // param forceReloadMwm: (Re)load MWM files even if they are in cache. // Returns true on success. public static bool InitFromDefinition(this VRage.Game.Components.MyAnimationControllerComponent thisController, MyAnimationControllerDefinition animControllerDefinition, bool forceReloadMwm = false) { bool result = true; thisController.Clear(); thisController.SourceId = animControllerDefinition.Id; foreach (var objBuilderLayer in animControllerDefinition.Layers) { var layer = thisController.Controller.CreateLayer(objBuilderLayer.Name); if (layer == null) { continue; } switch (objBuilderLayer.Mode) { case VRage.Game.ObjectBuilders.MyObjectBuilder_AnimationLayer.MyLayerMode.Add: layer.Mode = VRageRender.Animations.MyAnimationStateMachine.MyBlendingMode.Add; break; case VRage.Game.ObjectBuilders.MyObjectBuilder_AnimationLayer.MyLayerMode.Replace: layer.Mode = VRageRender.Animations.MyAnimationStateMachine.MyBlendingMode.Replace; break; default: Debug.Fail("Unknown layer mode."); layer.Mode = VRageRender.Animations.MyAnimationStateMachine.MyBlendingMode.Replace; break; } if (objBuilderLayer.BoneMask != null) { string[] boneMaskArray = objBuilderLayer.BoneMask.Split(m_boneListSeparators); foreach (string s in boneMaskArray) layer.BoneMaskStrIds.Add(MyStringId.GetOrCompute(s)); } else { layer.BoneMaskStrIds.Clear(); } layer.BoneMask = null; // this will build itself in animation controller when we know all character bones MyAnimationVirtualNodes virtualNodes = new MyAnimationVirtualNodes(); result = InitLayerNodes(layer, objBuilderLayer.StateMachine, animControllerDefinition, thisController.Controller, layer.Name + "/", virtualNodes, forceReloadMwm) && result; layer.SetState(layer.Name + "/" + objBuilderLayer.InitialSMNode); layer.SortTransitions(); } foreach (var footIkChain in animControllerDefinition.FootIkChains) thisController.InverseKinematics.RegisterFootBone(footIkChain.FootBone, footIkChain.ChainLength, footIkChain.AlignBoneWithTerrain); foreach (var ignoredBone in animControllerDefinition.IkIgnoredBones) thisController.InverseKinematics.RegisterIgnoredBone(ignoredBone); if (result) thisController.MarkAsValid(); return result; }
// Initialize this animation controller from given object builder. // Returns true on success. public static bool InitFromDefinition(this VRage.Game.Components.MyAnimationControllerComponent thisController, MyAnimationControllerDefinition animControllerDefinition) { bool result = true; thisController.Clear(); thisController.SourceId = animControllerDefinition.Id; foreach (var objBuilderLayer in animControllerDefinition.Layers) { var layer = thisController.Controller.CreateLayer(objBuilderLayer.Name); if (layer == null) { continue; } switch (objBuilderLayer.Mode) { case VRage.Game.ObjectBuilders.MyObjectBuilder_AnimationLayer.MyLayerMode.Add: layer.Mode = VRage.Animations.MyAnimationStateMachine.MyBlendingMode.Add; break; case VRage.Game.ObjectBuilders.MyObjectBuilder_AnimationLayer.MyLayerMode.Replace: layer.Mode = VRage.Animations.MyAnimationStateMachine.MyBlendingMode.Replace; break; default: Debug.Fail("Unknown layer mode."); layer.Mode = VRage.Animations.MyAnimationStateMachine.MyBlendingMode.Replace; break; } if (objBuilderLayer.BoneMask != null) { string[] boneMaskArray = objBuilderLayer.BoneMask.Split(m_boneListSeparators); foreach (string s in boneMaskArray) { layer.BoneMaskStrIds.Add(MyStringId.GetOrCompute(s)); } } else { layer.BoneMaskStrIds.Clear(); } layer.BoneMask = null; // this will build itself in animation controller when we know all character bones MyAnimationVirtualNodes virtualNodes = new MyAnimationVirtualNodes(); result = InitLayerNodes(layer, objBuilderLayer.StateMachine, animControllerDefinition, thisController.Controller, layer.Name + "/", virtualNodes) && result; layer.SetState(layer.Name + "/" + objBuilderLayer.InitialSMNode); layer.SortTransitions(); } if (result) { thisController.MarkAsValid(); } return(result); }
// 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; }
// Initialize state machine of one layer. private static bool InitLayerNodes(MyAnimationStateMachine layer, string stateMachineName, MyAnimationControllerDefinition animControllerDefinition, MyAnimationController animationController, string currentNodeNamePrefix, MyAnimationVirtualNodes virtualNodes) { 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)) { result = false; } } else { var smNode = new VRage.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); 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); }