Пример #1
0
        /// <summary>
        /// Gets the size of this keyframe, in bytes.
        /// </summary>
        /// <param name="keyframe">The keyframe for which to get the size for.</param>
        /// <param name="layer">The layer in question.</param>
        /// <param name="header">The header.</param>
        /// <returns></returns>
        public static unsafe int GetKeyframeSize(Keyframe *keyframe, Layer *layer, MetadataHeader *header)
        {
            switch ((keyframe->KeyframeType & (KeyframeType)0x7FFF))
            {
            default:
            case KeyframeType.HalfByteCount:
                return(layer->NumBytes + sizeof(Keyframe));    // +8 may be an error here, but parses existing files.

            case KeyframeType.SizeFromHeader:
                return(header->AnimationType1Offset * 4);    // Typically 0x14 * 4

            case KeyframeType.SizeFromSameStructSimpleHeader:
            case KeyframeType.SizeFromSameStructComplexHeader:
                return(keyframe->NumberOfBytesDivBy4 * 4);
            }
        }
Пример #2
0
        /// <summary>
        /// Initializes this.
        /// Use this if you want to re-initialize the class without creating a new instance.
        /// </summary>
        /// <param name="headerAddress">The address of the menu metadata header.</param>
        /// <param name="isLoaded">True if the metadata is already loaded into the game, else false.</param>
        public void Initialize(MetadataHeader *headerAddress, bool isLoaded)
        {
            Header = headerAddress;

            var entryHeaderPtr = (byte *)(headerAddress + 1);

            ObjectSectionHeader = (ObjectSectionHeader *)entryHeaderPtr;

            InitializeOrClear(ref Objects, ObjectSectionHeader->NumObjects);
            InitializeOrClear(ref Layers, ObjectSectionHeader->NumObjects);
            InitializeOrClear(ref ActionLayers, ObjectSectionHeader->NumObjects);

            // Add entry
            for (int x = 0; x < ObjectSectionHeader->NumObjects; x++)
            {
                var entryPtr = isLoaded ? ObjectSectionHeader->GetObjectPointer(ObjectSectionHeader, x) : (Object *)(entryHeaderPtr + (uint)ObjectSectionHeader->GetObjectPointer(ObjectSectionHeader, x));
                Objects.Add(entryPtr);

                // Add action layers.
                var actionLayers = GetItemOrDefault(ActionLayers, x);
                InitializeOrClear(ref actionLayers, 1);

                // Add layers
                var layers = GetItemOrDefault(Layers, x);
                InitializeOrClear(ref layers, entryPtr->LayerCount);

                for (int y = 0; y < entryPtr->LayerCount; y++)
                {
                    var subEntryPtr = isLoaded ? entryPtr->GetLayerPointer(entryPtr, y) : (Layer *)((byte *)entryPtr + (uint)entryPtr->GetLayerPointer(entryPtr, y));
                    if (y == 0)
                    {
                        actionLayers.Add((ActionLayer *)subEntryPtr);
                    }
                    else
                    {
                        layers.Add(subEntryPtr);
                    }
                }

                ActionLayers.Add(actionLayers);
                Layers.Add(layers);
            }

            // Add final section.
            TextureIdHeader = isLoaded ? Header->TextureIndicesPtr : (TextureSectionHeader *)((byte *)headerAddress + (uint)Header->TextureIndicesPtr);
        }
Пример #3
0
 /// <summary/>
 /// <param name="headerAddress">The address of the menu metadata header.</param>
 /// <param name="isLoaded">True if the metadata is already loaded into the game, else false.</param>
 public InMemoryMenuMetadata(MetadataHeader *headerAddress, bool isLoaded)
 {
     Initialize(headerAddress, isLoaded);
 }
Пример #4
0
        /// <summary>
        /// Returns a list of all keyframe data belonging to this specific layer.
        /// </summary>
        /// <param name="layer">The layer to get the keyframes for.</param>
        /// <param name="header">Header of the file from which the keyframes are sourced.</param>
        /// <param name="keySpan">The buffer to place the keyframes in.</param>
        /// <returns>The supplied buffer, sliced.</returns>
        public static unsafe Span <BlittablePointer <Keyframe> > GetKeyFrames(Layer *layer, MetadataHeader *header, Span <BlittablePointer <Keyframe> > keySpan)
        {
            int remainingFrames = layer->NumKeyframes;
            var currentPointer  = (byte *)(layer + 1);
            int numItems        = 0;

            if (layer->MaybeAnimationDurationFrames <= 0 && remainingFrames <= 0)
            {
                return(keySpan.Slice(0, numItems));
            }

            while (remainingFrames > 1)
            {
                var keyFramePtr    = (Keyframe *)currentPointer;
                var keyFrameLength = Keyframe.GetKeyframeSize(keyFramePtr, layer, header);
                var keyFrameType   = (short)(keyFramePtr->KeyframeType & (KeyframeType)0x7FFF);
                keySpan[numItems++] = keyFramePtr;

                // Animation ends if no duration, unless keyframes type 0/1
                if (keyFramePtr->AnimationActivationPointFrames < 1 && keyFrameType != 0 && keyFrameType != 1)
                {
                    break;
                }

                remainingFrames--;
                currentPointer += keyFrameLength;
            }

            return(keySpan.Slice(0, numItems));
        }
Пример #5
0
        /// <summary>
        /// Gets the individual data items for a given keyframe.
        /// </summary>
        /// <param name="keyframe">Pointer to the keyframe in question.</param>
        /// <param name="layer">Pointer to the layer in question.</param>
        /// <param name="header">Pointer to the archive header.</param>
        /// <param name="stack">Preallocated stack memory. Recommend 32 items.</param>
        /// <returns></returns>
        public unsafe Span <DataHeaderWrapper> GetData(Keyframe *keyframe, Layer *layer, MetadataHeader *header, Span <DataHeaderWrapper> stack)
        {
            // Invalid.
            if (keyframe->NumberOfChangedProperties < 0)
            {
                return(stack.Slice(0, 0));
            }

            var keyframeType = (keyframe->KeyframeType & (KeyframeType)0x7FFF);

            switch (keyframeType)
            {
            default:
            case KeyframeType.HalfByteCount:     // 0
            {
                var result = new DataHeaderWrapper()
                {
                    DataType = DataHeaderWrapper.InvalidDataType,
                    NumBytes = layer->NumBytes,
                    DataPtr  = (byte *)(keyframe + 1)
                };
                stack[0] = result;
                return(stack.Slice(0, 1));
            }

            case KeyframeType.SizeFromHeader:     // 1
            {
                var result = new DataHeaderWrapper()
                {
                    DataType = DataHeaderWrapper.InvalidDataType,
                    NumBytes = (short)(header->AnimationType1Offset * 4),
                    DataPtr  = (byte *)(keyframe + 1)
                };
                stack[0] = result;
                return(stack.Slice(0, 1));
            }

            case KeyframeType.SizeFromSameStructSimpleHeader:     // 2
            {
                var headersPtr   = (Type2DataHeader *)(keyframe + 1);
                var valuesOffset = ((keyframe->NumberOfBytesDivBy4 - keyframe->NumberOfChangedProperties) * 4);
                var valuesPtr    = (int *)((byte *)keyframe + valuesOffset);

                for (int x = 0; x < keyframe->NumberOfChangedProperties; x++)
                {
                    stack[x] = new DataHeaderWrapper()
                    {
                        DataType = headersPtr->DataType,
                        NumBytes = sizeof(int),
                        DataPtr  = (byte *)valuesPtr,
                    };

                    valuesPtr++;
                    headersPtr++;
                }

                return(stack.Slice(0, keyframe->NumberOfChangedProperties));
            }

            case KeyframeType.SizeFromSameStructComplexHeader:     // 3
            {
                var headersPtr   = (Type3DataHeader *)(keyframe + 1);
                var valuesOffset = (keyframe->NumberOfChangedProperties * sizeof(Type3DataHeader));
                var valuesPtr    = (byte *)headersPtr + valuesOffset;

                for (int x = 0; x < keyframe->NumberOfChangedProperties; x++)
                {
                    stack[x] = new DataHeaderWrapper()
                    {
                        DataType = headersPtr->DataType,
                        NumBytes = headersPtr->NumBytes,
                        DataPtr  = valuesPtr,
                    };

                    valuesPtr += headersPtr->NumBytes;
                    headersPtr++;
                }

                return(stack.Slice(0, keyframe->NumberOfChangedProperties));
            }
            }
        }