public State(string name) : base(ResourceType, ResourceTag) { this.mStateMachine = null; this.mName = name; if (name == null) { this.mNameHash = 0; this.bNameIsHash = true; } else if (!name.StartsWith("0x") || !uint.TryParse(name.Substring(2), System.Globalization.NumberStyles.HexNumber, null, out this.mNameHash)) { this.mNameHash = FNVHash.HashString32(name); this.bNameIsHash = false; } else { this.bNameIsHash = true; } this.mFlags = JazzState.Flags.None; this.mDecisionGraph = null; this.mTransitions = new List <State>(); this.mAwarenessOverlayLevel = JazzChunk.AwarenessLevel.Unset; }
public DGRootNode(DecisionGraph dg, StateNode state) : base(null, state) { if (dg == null) { throw new ArgumentNullException("dg"); } this.mDecisionGraph = dg; this.mEntryAnchor.SetPosition(sRad, 0); this.mEntryAnchor.SetDirection(1, 0); this.UpdateVisualization(); }
public StateMachine(GenericRCOLResource jazzResource) : this("") { if (jazzResource == null) { throw new ArgumentNullException("jazzResource"); } GenericRCOLResource.ChunkEntryList chunkEntries = jazzResource.ChunkEntries; if (chunkEntries == null || chunkEntries.Count == 0) { throw new ArgumentException( "RCOL Resource is empty", "jazzResource"); } KeyNameReg.RefreshKeyNameMaps(); uint hash; string name; int i, j, index = -1; State state; ActorDefinition ad; ParamDefinition pd; DecisionGraphNode dgn; JazzStateMachine jazzSM = null; GenericRCOLResource.ChunkEntry ce; AChunkObject[] chunks = new AChunkObject[chunkEntries.Count]; List<ActorDefinition> actorDefs = new List<ActorDefinition>(); List<ParamDefinition> paramDefs = new List<ParamDefinition>(); #region Phase 1: Instantiate Chunks and Copy over value fields for (i = 0; i < chunkEntries.Count; i++) { ce = chunkEntries[i]; hash = ce.TGIBlock.ResourceType; switch (hash) { case PlayAnimationNode.ResourceType: JazzPlayAnimationNode jpan = ce.RCOLBlock as JazzPlayAnimationNode; PlayAnimationNode lan = new PlayAnimationNode(); lan.ClipKey = new RK(jpan.ClipResource); lan.TrackMaskKey = new RK(jpan.TkmkResource); // lan.SlotSetup copied over later lan.AdditiveClipKey = new RK(jpan.AdditiveClipResource); lan.ClipPattern = jpan.Animation; lan.AdditiveClipPattern = jpan.AdditiveAnimation; lan.Flags = jpan.AnimationNodeFlags; lan.Priority = jpan.AnimationPriority1; lan.BlendInTime = jpan.BlendInTime; lan.BlendOutTime = jpan.BlendOutTime; lan.Speed = jpan.Speed; // lan.Actor set later lan.TimingPriority = jpan.TimingPriority; chunks[i] = lan; break; case StopAnimationNode.ResourceType: JazzStopAnimationNode jsan = ce.RCOLBlock as JazzStopAnimationNode; StopAnimationNode san = new StopAnimationNode(); san.Flags = jsan.AnimationFlags; san.Priority = jsan.AnimationPriority1; san.BlendInTime = jsan.BlendInTime; san.BlendOutTime = jsan.BlendOutTime; san.Speed = jsan.Speed; // san.Actor set later san.TimingPriority = jsan.TimingPriority; chunks[i] = san; break; case ActorOperationNode.ResourceType: JazzActorOperationNode jaon = ce.RCOLBlock as JazzActorOperationNode; ActorOperationNode aon = new ActorOperationNode(jaon.ActorOp); // aon.Target set later aon.Operand = jaon.Operand != 0; chunks[i] = aon; break; case CreatePropNode.ResourceType: JazzCreatePropNode jcpn = ce.RCOLBlock as JazzCreatePropNode; CreatePropNode cpn = new CreatePropNode(); // cpn.PropActor set later // cpn.PropParameter set later cpn.PropKey = new RK(jcpn.PropResource); chunks[i] = cpn; break; case RandomNode.ResourceType: JazzRandomNode jrand = ce.RCOLBlock as JazzRandomNode; RandomNode rand = new RandomNode(); // rand.Slices set later rand.Flags = jrand.Properties; chunks[i] = rand; break; case SelectOnParameterNode.ResourceType: // sopn.Parameter set later // sopn.Cases set later chunks[i] = new SelectOnParameterNode(); break; case SelectOnDestinationNode.ResourceType: // sodn.Cases set later chunks[i] = new SelectOnDestinationNode(); break; case NextStateNode.ResourceType: // nsn.NextState set later chunks[i] = new NextStateNode(); break; case DecisionGraph.ResourceType: // dg.State set later // dg.DecisionMakers set later // dg.EntryPoints set later chunks[i] = new DecisionGraph(); break; case State.ResourceType: JazzState js = ce.RCOLBlock as JazzState; hash = js.NameHash; if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); state = new State(name); state.Flags = js.Properties; // state.DecisionGraph set later // state.Transitions set later state.AwarenessOverlayLevel = js.AwarenessOverlayLevel; chunks[i] = state; break; case ParamDefinition.ResourceType: JazzParameterDefinition jpd = ce.RCOLBlock as JazzParameterDefinition; hash = jpd.NameHash; if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); pd = new ParamDefinition(name); hash = jpd.DefaultValue; if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); pd.DefaultValue = name; chunks[i] = pd; paramDefs.Add(pd); break; case ActorDefinition.ResourceType: JazzActorDefinition jad = ce.RCOLBlock as JazzActorDefinition; hash = jad.NameHash; if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); ad = new ActorDefinition(name); chunks[i] = ad; actorDefs.Add(ad); break; case StateMachine.ResourceType: if (index != -1) { throw new Exception( "More than one State Machine in RCOL"); } index = i; jazzSM = ce.RCOLBlock as JazzStateMachine; hash = jazzSM.NameHash; if (hash == 0) { name = null; this.bNameIsHash = true; } else if (!KeyNameReg.TryFindName(hash, out name)) { name = KeyNameReg.UnhashName(hash); this.bNameIsHash = true; } else { this.bNameIsHash = false; } this.mName = name; this.mNameHash = hash; // this.mActorDefinitions set later // this.mParameterDefinitions set later // this.mStates set later this.mFlags = jazzSM.Properties; this.mDefaultPriority = jazzSM.AutomationPriority; this.mAwarenessOverlayLevel = jazzSM.AwarenessOverlayLevel; chunks[i] = this; break; } } if (index == -1) { throw new Exception("RCOL does not contain a Jazz Graph"); } #endregion #region Phase 2: Copy over fields referencing other chunks for (i = 0; i < chunkEntries.Count; i++) { ce = chunkEntries[i]; switch (ce.TGIBlock.ResourceType) { case PlayAnimationNode.ResourceType: JazzPlayAnimationNode jpan = ce.RCOLBlock as JazzPlayAnimationNode; PlayAnimationNode lan = chunks[i] as PlayAnimationNode; index = jpan.ActorDefinitionIndex.TGIBlockIndex; lan.Actor = index < 0 ? null : chunks[index + 1] as ActorDefinition; break; case StopAnimationNode.ResourceType: JazzStopAnimationNode jsan = ce.RCOLBlock as JazzStopAnimationNode; StopAnimationNode san = chunks[i] as StopAnimationNode; index = jsan.ActorDefinitionIndex.TGIBlockIndex; san.Actor = index < 0 ? null : chunks[index + 1] as ActorDefinition; break; case ActorOperationNode.ResourceType: JazzActorOperationNode jaon = ce.RCOLBlock as JazzActorOperationNode; ActorOperationNode aon = chunks[i] as ActorOperationNode; index = jaon.ActorDefinitionIndex.TGIBlockIndex; aon.Actor = index < 0 ? null : chunks[index + 1] as ActorDefinition; break; case CreatePropNode.ResourceType: JazzCreatePropNode jcpn = ce.RCOLBlock as JazzCreatePropNode; CreatePropNode cpn = chunks[i] as CreatePropNode; index = jcpn.ActorDefinitionIndex.TGIBlockIndex; cpn.PropActor = index < 0 ? null : chunks[index + 1] as ActorDefinition; index = jcpn.ParameterDefinitionIndex.TGIBlockIndex; cpn.PropParam = index < 0 ? null : chunks[index + 1] as ParamDefinition; break; case RandomNode.ResourceType: JazzRandomNode jrand = ce.RCOLBlock as JazzRandomNode; RandomNode rand = chunks[i] as RandomNode; RandomNode.Slice slice; List<RandomNode.Slice> slices = rand.Slices; foreach (JazzRandomNode.Outcome oc in jrand.Outcomes) { slice = new RandomNode.Slice(oc.Weight); foreach (GenericRCOLResource.ChunkReference cr in oc.DecisionGraphIndexes) { index = cr.TGIBlockIndex; dgn = index < 0 ? null : chunks[index + 1] as DecisionGraphNode; slice.Targets.Add(dgn); } slices.Add(slice); } break; case SelectOnParameterNode.ResourceType: JazzSelectOnParameterNode jsopn = ce.RCOLBlock as JazzSelectOnParameterNode; SelectOnParameterNode sopn = chunks[i] as SelectOnParameterNode; index = jsopn.ParameterDefinitionIndex.TGIBlockIndex; sopn.Parameter = index < 0 ? null : chunks[index + 1] as ParamDefinition; foreach (JazzSelectOnParameterNode.Match mp in jsopn.Matches) { hash = mp.TestValue; if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); foreach (GenericRCOLResource.ChunkReference cr in mp.DecisionGraphIndexes) { index = cr.TGIBlockIndex; dgn = index < 0 ? null : chunks[index + 1] as DecisionGraphNode; sopn.AddCaseTarget(name, dgn); } } break; case SelectOnDestinationNode.ResourceType: JazzSelectOnDestinationNode jsodn = ce.RCOLBlock as JazzSelectOnDestinationNode; SelectOnDestinationNode sodn = chunks[i] as SelectOnDestinationNode; foreach (JazzSelectOnDestinationNode.Match md in jsodn.Matches) { index = md.StateIndex.TGIBlockIndex; state = index < 0 ? null : chunks[index + 1] as State; foreach (GenericRCOLResource.ChunkReference cr in md.DecisionGraphIndexes) { index = cr.TGIBlockIndex; dgn = index < 0 ? null : chunks[index + 1] as DecisionGraphNode; sodn.AddCaseTarget(state, dgn); } } break; case NextStateNode.ResourceType: JazzNextStateNode jnsn = ce.RCOLBlock as JazzNextStateNode; NextStateNode nsn = chunks[i] as NextStateNode; index = jnsn.StateIndex.TGIBlockIndex; nsn.NextState = index < 0 ? null : chunks[index + 1] as State; break; case DecisionGraph.ResourceType: JazzDecisionGraph jdg = ce.RCOLBlock as JazzDecisionGraph; DecisionGraph dg = chunks[i] as DecisionGraph; foreach (GenericRCOLResource.ChunkReference dm in jdg.OutboundDecisionGraphIndexes) { index = dm.TGIBlockIndex; dgn = index < 0 ? null : chunks[index + 1] as DecisionGraphNode; dg.AddDecisionMaker(dgn); } foreach (GenericRCOLResource.ChunkReference ep in jdg.InboundDecisionGraphIndexes) { index = ep.TGIBlockIndex; dgn = index < 0 ? null : chunks[index + 1] as DecisionGraphNode; dg.AddEntryPoint(dgn); } break; case State.ResourceType: State transition; JazzState js = ce.RCOLBlock as JazzState; state = chunks[i] as State; index = js.DecisionGraphIndex.TGIBlockIndex; state.DecisionGraph = index < 0 ? null : chunks[index + 1] as DecisionGraph; foreach (GenericRCOLResource.ChunkReference trans in js.OutboundStateIndexes) { index = trans.TGIBlockIndex; transition = index < 0 ? null : chunks[index + 1] as State; state.AddTransition(transition); } break; case ParamDefinition.ResourceType: case ActorDefinition.ResourceType: break; case StateMachine.ResourceType: jazzSM = ce.RCOLBlock as JazzStateMachine; foreach (GenericRCOLResource.ChunkReference jad in jazzSM.ActorDefinitionIndexes) { index = jad.TGIBlockIndex; ad = index < 0 ? null : chunks[index + 1] as ActorDefinition; this.AddActorDefinition(ad); } foreach (GenericRCOLResource.ChunkReference jpd in jazzSM.PropertyDefinitionIndexes) { index = jpd.TGIBlockIndex; pd = index < 0 ? null : chunks[index + 1] as ParamDefinition; this.AddParamDefinition(pd); } foreach (GenericRCOLResource.ChunkReference jst in jazzSM.StateIndexes) { index = jst.TGIBlockIndex; state = index < 0 ? null : chunks[index + 1] as State; this.AddState(state); } break; } } #endregion #region Phase 3: Copy over animation slots and Find "Extras" for (i = 0; i < chunkEntries.Count; i++) { ce = chunkEntries[i]; switch (ce.TGIBlock.ResourceType) { case PlayAnimationNode.ResourceType: JazzPlayAnimationNode jpan = ce.RCOLBlock as JazzPlayAnimationNode; PlayAnimationNode lan = chunks[i] as PlayAnimationNode; SlotSetupBuilder ssb = lan.SlotSetup; foreach (JazzPlayAnimationNode.ActorSlot slot in jpan.ActorSlots) { ssb.AddSlotAssignment(slot.ChainId, slot.SlotId, slot.ActorNameHash, slot.SlotNameHash); } foreach (JazzPlayAnimationNode.ActorSuffix suffix in jpan.ActorSuffixes) { hash = suffix.ActorNameHash; ad = null; if (hash != 0) { index = -1; for (i = actorDefs.Count - 1; i >= 0 && index == -1; i--) { ad = actorDefs[i]; if (ad.NameHash == hash) { index = i; } } if (index < 0) { if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); ad = new ActorDefinition(name); actorDefs.Add(ad); this.mExtraActors.Add(ad); } } hash = suffix.SuffixHash; pd = null; if (hash != 0) { index = -1; for (i = paramDefs.Count - 1; i >= 0 && index == -1; i--) { pd = paramDefs[i]; if (pd.NameHash == hash) { index = i; } } if (index < 0) { if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); pd = new ParamDefinition(name); paramDefs.Add(pd); this.mExtraParams.Add(pd); } } ssb.AddNamespaceSlotSuffix(ad, pd); } break; case State.ResourceType: state = chunks[i] as State; index = this.mStates.IndexOf(state); if (index < 0) { this.mExtraStates.Add(state); } break; case ParamDefinition.ResourceType: pd = chunks[i] as ParamDefinition; index = this.mParamDefinitions.IndexOf(pd); if (index < 0) { this.mExtraParams.Add(pd); } break; case ActorDefinition.ResourceType: ad = chunks[i] as ActorDefinition; index = this.mActorDefinitions.IndexOf(ad); if (index < 0) { this.mExtraActors.Add(ad); } break; } } #endregion #region Phase 4: Copy over Animation CLIP Namespace Map RK rk; List<RK> rks = this.SlurpReferencedRKs(); List<uint> foldedClipInstances = new List<uint>(rks.Count); for (i = rks.Count - 1; i >= 0; i--) { rk = rks[i]; if (rk.TID == 0x6b20c4f3) { hash = (uint)((rk.IID >> 0x20) ^ (rk.IID & 0xffffffff)); foldedClipInstances.Add(hash); } else { rks.RemoveAt(i); } } index = 0; Anim animation; Anim[] animations = new Anim[jazzSM.Animations.Count]; foreach (JazzStateMachine.Animation anim in jazzSM.Animations) { hash = anim.NameHash; if (!foldedClipInstances.Contains(hash)) { animation = new Anim(); animation.SrcFileHash = hash; if (KeyNameReg.TryFindName(hash, out name)) { animation.SrcFileName = name; animation.SrcFileIsValid = true; } else { animation.SrcFileName = KeyNameReg.UnhashName(hash); animation.SrcFileIsValid = false; } hash = anim.Actor1Hash; if (KeyNameReg.TryFindName(hash, out name)) { animation.Namespace = name; } else { animation.Namespace = string.Concat("0x", hash.ToString("X8")); } hash = anim.Actor2Hash; ad = null; if (hash != 0) { j = -1; for (i = actorDefs.Count - 1; i >= 0 && j < 0; i--) { ad = actorDefs[i]; if (ad.NameHash == hash) { j = i; } } if (j < 0) { if (!KeyNameReg.TryFindName(hash, out name)) name = KeyNameReg.UnhashName(hash); ad = new ActorDefinition(name); actorDefs.Add(ad); this.mExtraActors.Add(ad); } } animation.Actor = ad; animations[index++] = animation; } } ulong clipHash; Dictionary<ulong, string> keyNameMap = new Dictionary<ulong, string>(); for (i = index - 1; i >= 0; i--) { animation = animations[i]; this.mNamespaceMap.SetNamespaceMap( animation.SrcFileName, animation.Namespace, animation.Actor); if (animation.SrcFileIsValid) { clipHash = FNVHash.HashString64(animation.SrcFileName); keyNameMap[clipHash] = animation.SrcFileName; } } // Update the Key to Filename Map of the Namespace Map SortedDictionary<RK, string> k2fn = this.mNamespaceMap.KeyToFilenameMap; k2fn.Clear(); for (i = rks.Count - 1; i >= 0; i--) { rk = rks[i]; if (keyNameMap.TryGetValue(rk.IID, out name) || KeyNameReg.TryFindName(rk.IID, out name)) { k2fn[rk] = name; } } #endregion }