예제 #1
0
        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;
        }
예제 #2
0
        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();
        }
예제 #3
0
        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
        }