/// <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); } }
public unsafe void Cache() { if (this.m_Loop) { int length = this.curve.length; if (length >= 2) { this.m_InternalLoopingCurve ??= new AnimationCurve(); Keyframe key = this.curve[length - 1]; Keyframe *keyframePtr1 = &key; keyframePtr1.time -= this.m_Range; Keyframe keyframe2 = this.curve[0]; Keyframe *keyframePtr2 = &keyframe2; keyframePtr2.time += this.m_Range; this.m_InternalLoopingCurve.keys = this.curve.keys; this.m_InternalLoopingCurve.AddKey(key); this.m_InternalLoopingCurve.AddKey(keyframe2); } } }
/// <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)); } } }