// 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); }
// -------------------------------------------------------------------------------------------- /// <summary> /// Reload all mwm tracks while in-game. Mwms from cache are not used. /// </summary> public void ReloadMwmTracks() { foreach (var component in m_skinnedEntityComponents) { MyAnimationControllerDefinition animationControllerDefinition = MyDefinitionManagerBase.Static.GetDefinition <MyAnimationControllerDefinition>(MyStringHash.GetOrCompute(component.SourceId.SubtypeName)); if (animationControllerDefinition != null) { component.Clear(); component.InitFromDefinition(animationControllerDefinition, forceReloadMwm: true); // reload from original def that was modified by postprocessor if (component.ReloadBonesNeeded != null) { component.ReloadBonesNeeded(); } } } }
private void ReceivedMessageHandler(MyExternalDebugStructures.CommonMsgHeader messageHeader, IntPtr messageData) { MyExternalDebugStructures.ACReloadInGameMsg msgReload; if (MyExternalDebugStructures.ReadMessageFromPtr(ref messageHeader, messageData, out msgReload)) { try { string acAddress = msgReload.ACAddress; string acName = msgReload.ACName; MyObjectBuilder_Definitions allDefinitions; // = null; // load animation controller definition from SBC file if (MyObjectBuilderSerializer.DeserializeXML(acAddress, out allDefinitions) && allDefinitions.Definitions != null && allDefinitions.Definitions.Length > 0) { var firstDef = allDefinitions.Definitions[0]; MyModContext context = new MyModContext(); context.Init("AnimationControllerDefinition", Path.GetFileName(acAddress)); MyAnimationControllerDefinition animationControllerDefinition = new MyAnimationControllerDefinition(); animationControllerDefinition.Init(firstDef, context); // swap animation controller for each entity foreach (MyEntity entity in MyEntities.GetEntities()) { MyCharacter character = entity as MyCharacter; if (character != null && character.Definition.AnimationController == acName) { character.AnimationController.InitFromDefinition(animationControllerDefinition); character.ObtainBones(); } } // update in def. manager MyStringHash animSubtypeNameHash = MyStringHash.GetOrCompute(acName); MyAnimationControllerDefinition animControllerDefInManager = MyDefinitionManager.Static.GetDefinition <MyAnimationControllerDefinition>(animSubtypeNameHash); animControllerDefInManager.Init(firstDef, context); } } catch (Exception e) { MyLog.Default.WriteLine(e); } } }
// receiving messages private void LiveDebugging_ReceivedMessageHandler(MyExternalDebugStructures.CommonMsgHeader messageHeader, IntPtr messageData) { MyExternalDebugStructures.ACReloadInGameMsg msgReload; if (MyExternalDebugStructures.ReadMessageFromPtr(ref messageHeader, messageData, out msgReload)) { try { string acContentPath = msgReload.ACContentAddress; string acAddress = msgReload.ACAddress; string acName = msgReload.ACName; MyObjectBuilder_Definitions allDefinitions; // = null; // load animation controller definition from SBC file if (MyObjectBuilderSerializer.DeserializeXML(acAddress, out allDefinitions) && allDefinitions.Definitions != null && allDefinitions.Definitions.Length > 0) { var firstDef = allDefinitions.Definitions[0]; MyModContext context = new MyModContext(); context.Init("AnimationControllerDefinition", acAddress, acContentPath); MyAnimationControllerDefinition animationControllerDefinition = new MyAnimationControllerDefinition(); animationControllerDefinition.Init(firstDef, context); MyStringHash animSubtypeNameHash = MyStringHash.GetOrCompute(acName); // post process and update in def. manager MyAnimationControllerDefinition originalAnimationControllerDefinition = MyDefinitionManagerBase.Static.GetDefinition <MyAnimationControllerDefinition>( animSubtypeNameHash); var postprocessor = MyDefinitionManagerBase.GetPostProcessor(typeof(MyObjectBuilder_AnimationControllerDefinition)); if (postprocessor != null) { MyDefinitionPostprocessor.Bundle originalBundle = new MyDefinitionPostprocessor.Bundle { Context = MyModContext.BaseGame, Definitions = new Dictionary <MyStringHash, MyDefinitionBase> { { animSubtypeNameHash, originalAnimationControllerDefinition } }, Set = new MyDefinitionSet() }; originalBundle.Set.AddDefinition(originalAnimationControllerDefinition); MyDefinitionPostprocessor.Bundle overridingBundle = new MyDefinitionPostprocessor.Bundle { Context = context, Definitions = new Dictionary <MyStringHash, MyDefinitionBase> { { animSubtypeNameHash, animationControllerDefinition } }, Set = new MyDefinitionSet() }; overridingBundle.Set.AddDefinition(animationControllerDefinition); // postprocess -> override existing definition in memory postprocessor.AfterLoaded(ref overridingBundle); postprocessor.OverrideBy(ref originalBundle, ref overridingBundle); } // swap animation controller for each entity foreach (var component in m_skinnedEntityComponents) { if (component != null && component.SourceId.SubtypeName == acName) { component.Clear(); component.InitFromDefinition(originalAnimationControllerDefinition, forceReloadMwm: true); // reload from original def that was modified by postprocessor if (component.ReloadBonesNeeded != null) { component.ReloadBonesNeeded(); } } } } } catch (Exception e) { MyLog.Default.WriteLine(e); } } }
// 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); }
// Initialize state machine of one layer. private static bool InitLayerNodes(VRage.Animations.MyAnimationStateMachine layer, string stateMachineName, MyAnimationControllerDefinition animControllerDefinition, VRage.Animations.MyAnimationController animationController, string currentNodeNamePrefix = "") { 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 + "/")) { result = false; } } else { if (objBuilderNode.AnimationTree == null) { // no animation tree, just skip continue; } var smNode = new VRage.Animations.MyAnimationStateMachineNode(absoluteNodeName); layer.AddNode(smNode); var smNodeAnimTree = InitNodeAnimationTree(objBuilderNode.AnimationTree.Child); smNode.RootAnimationNode = smNodeAnimTree; } } } // 2nd step: generate transitions if (objBuilderStateMachine.Transitions != null) { foreach (var objBuilderTransition in objBuilderStateMachine.Transitions) { int conditionConjunctionIndex = 0; do { // generate transition for each condition conjunction var transition = layer.AddTransition(objBuilderTransition.From, objBuilderTransition.To, new VRage.Animations.MyAnimationStateMachineTransition()) as VRage.Animations.MyAnimationStateMachineTransition; // if ok, fill in conditions if (transition != null) { transition.Name = MyStringId.GetOrCompute(objBuilderTransition.Name); transition.TransitionTimeInSec = objBuilderTransition.TimeInSec; transition.Sync = objBuilderTransition.Sync; 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); } } return(result); }