Пример #1
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));
        }
Пример #2
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);
            }
        }
Пример #3
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));
            }
            }
        }