Example #1
0
        //Animations
        private EAN_Animation ParseAnimation(int offset, int nameOffset, int animIndex)
        {
            List <ESK_BoneNonHierarchal> bonesNonHierachal = eanFile.Skeleton.GetNonHierarchalBoneList();

            EAN_Animation animation = new EAN_Animation();

            byte indexSize  = rawBytes[offset + 2];
            byte floatSize  = rawBytes[offset + 3];
            int  nodeCount  = BitConverter.ToInt32(rawBytes, offset + 8);
            int  nodeOffset = BitConverter.ToInt32(rawBytes, offset + 12) + offset;

            //animation header data
            ValidateFloatAndIntPrecision(indexSize, floatSize);
            animation.I_02 = (EAN_Animation.IntPrecision)indexSize;
            animation.I_03 = (EAN_Animation.FloatPrecision)floatSize;
            animation.I_04 = BitConverter.ToInt32(rawBytes, offset + 4);

            if (nodeCount > 0)
            {
                animation.Nodes = new ObservableCollection <EAN_Node>();
                for (int i = 0; i < nodeCount; i++)
                {
                    int thisNodeOffset = BitConverter.ToInt32(rawBytes, nodeOffset) + offset;
                    animation.Nodes.Add(new EAN_Node()
                    {
                        BoneName = GetBoneName(BitConverter.ToInt16(rawBytes, thisNodeOffset), animIndex, bonesNonHierachal)
                    });
                    int keyframedAnimationsCount  = BitConverter.ToInt16(rawBytes, thisNodeOffset + 2);
                    int keyframedAnimationsOffset = BitConverter.ToInt32(rawBytes, thisNodeOffset + 4) + thisNodeOffset;

                    if (keyframedAnimationsCount > 0)
                    {
                        animation.Nodes[i].AnimationComponents = new ObservableCollection <EAN_AnimationComponent>();
                        for (int a = 0; a < keyframedAnimationsCount; a++)
                        {
                            int thisKeyframedAnimationsOffset = BitConverter.ToInt32(rawBytes, keyframedAnimationsOffset) + thisNodeOffset;
                            animation.Nodes[i].AnimationComponents.Add(new EAN_AnimationComponent());
                            animation.Nodes[i].AnimationComponents[a].I_00 = (EAN_AnimationComponent.ComponentType)rawBytes[thisKeyframedAnimationsOffset + 0];
                            animation.Nodes[i].AnimationComponents[a].I_01 = rawBytes[thisKeyframedAnimationsOffset + 1];
                            animation.Nodes[i].AnimationComponents[a].I_02 = BitConverter.ToInt16(rawBytes, thisKeyframedAnimationsOffset + 2);

                            //Offsets/Count
                            int keyframeCount   = BitConverter.ToInt32(rawBytes, thisKeyframedAnimationsOffset + 4);
                            int IndexListOffset = BitConverter.ToInt32(rawBytes, thisKeyframedAnimationsOffset + 8) + thisKeyframedAnimationsOffset;
                            int MatrixOffset    = BitConverter.ToInt32(rawBytes, thisKeyframedAnimationsOffset + 12) + thisKeyframedAnimationsOffset;

                            animation.Nodes[i].AnimationComponents[a].Keyframes = ParseKeyframes(IndexListOffset, MatrixOffset, keyframeCount, indexSize, floatSize);

                            keyframedAnimationsOffset += 4;
                        }
                    }

                    nodeOffset += 4;
                }
            }

            animation.Name         = Utils.GetString(bytes, nameOffset);
            animation.IndexNumeric = animIndex;

            return(animation);
        }
Example #2
0
        private void WriteAnimation(EAN_Animation animation, int offsetToReplace)
        {
            StartNewLine();

            if (animation.FrameCount <= 0)
            {
                throw new InvalidDataException("EAN Save: FrameCount cannot be 0 or less!");
            }

            bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count()), offsetToReplace);
            int startOffset = bytes.Count();
            int nodeCount   = (animation.Nodes != null) ? animation.Nodes.Count() : 0;

            if (nodeCount > 0)
            {
                nodeCount = 0;
                for (int i = 0; i < animation.Nodes.Count(); i++)
                {
                    if (eanFile.Skeleton.Exists(animation.Nodes[i].BoneName))
                    {
                        nodeCount++;
                    }
                }
            }

            bytes.AddRange(new byte[2]);
            bytes.Add((byte)animation.I_02);
            bytes.Add((byte)animation.I_03);
            bytes.AddRange(BitConverter.GetBytes(animation.FrameCount));
            bytes.AddRange(BitConverter.GetBytes(nodeCount));
            bytes.AddRange(new byte[4]);

            //Nodes
            if (nodeCount > 0)
            {
                bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count - startOffset), startOffset + 12);
                List <int> NodeTable = new List <int>();
                for (int i = 0; i < nodeCount; i++)
                {
                    NodeTable.Add(bytes.Count);
                    bytes.AddRange(new byte[4]);
                }

                for (int i = 0; i < nodeCount; i++)
                {
                    if (eanFile.Skeleton.Exists(animation.Nodes[i].BoneName))
                    {
                        bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count - startOffset), NodeTable[i]);
                        int        NodeOffset = bytes.Count;
                        List <int> AnimationComponentTable = new List <int>();

                        int AnimationComponentCount = (animation.Nodes[i].AnimationComponents != null) ? animation.Nodes[i].AnimationComponents.Count : 0;
                        bytes.AddRange(BitConverter.GetBytes(GetBoneIndex(animation.Nodes[i].BoneName, animation.Name)));
                        bytes.AddRange(BitConverter.GetBytes((short)AnimationComponentCount));
                        bytes.AddRange(BitConverter.GetBytes(8));

                        //Get ESK data for this bone as it will be needed for calculating default keyframes
                        ESK_RelativeTransform eskRelativeTransform = eanFile.Skeleton.GetBone(animation.Nodes[i].BoneName)?.RelativeTransform;

                        if (eskRelativeTransform == null)
                        {
                            throw new ArgumentNullException($"EAN Save: Could not find the RelativeTransform for bone {animation.Nodes[i].BoneName}");
                        }

                        //Table
                        for (int a = 0; a < AnimationComponentCount; a++)
                        {
                            AnimationComponentTable.Add(bytes.Count());
                            bytes.AddRange(new byte[4]);
                        }

                        //Data
                        for (int a = 0; a < AnimationComponentCount; a++)
                        {
                            bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count - NodeOffset), AnimationComponentTable[a]);

                            int KeyframeOffset = bytes.Count;

                            //Can happen if loaded from XML and no keyframes were declared.
                            if (animation.Nodes[i].AnimationComponents[a].Keyframes == null)
                            {
                                animation.Nodes[i].AnimationComponents[a].Keyframes = AsyncObservableCollection <EAN_Keyframe> .Create();
                            }

                            //Handle first and last keyframe
                            bool hasFirstKeyframe = animation.Nodes[i].AnimationComponents[a].Keyframes.Any(x => x.FrameIndex == 0);
                            bool hasFinalKeyframe = animation.Nodes[i].AnimationComponents[a].Keyframes.Any(x => x.FrameIndex == animation.FrameCount - 1);
                            int  KeyframeCount    = animation.Nodes[i].AnimationComponents[a].Keyframes.Count;

                            //If no first or final keyframes were found, increment count to include them
                            if (!hasFinalKeyframe)
                            {
                                KeyframeCount++;
                            }
                            if (!hasFirstKeyframe)
                            {
                                KeyframeCount++;
                            }

                            //Select default keyframe
                            EAN_Keyframe defaultKeyframe = null;

                            switch (animation.Nodes[i].AnimationComponents[a].I_00)
                            {
                            case EAN_AnimationComponent.ComponentType.Position:
                                defaultKeyframe = eskRelativeTransform.ToEanPosKeyframe();
                                break;

                            case EAN_AnimationComponent.ComponentType.Rotation:
                                defaultKeyframe = eskRelativeTransform.ToEanRotKeyframe();
                                break;

                            case EAN_AnimationComponent.ComponentType.Scale:
                                defaultKeyframe = eskRelativeTransform.ToEanScaleKeyframe();
                                break;
                            }

                            //Write
                            bytes.Add((byte)animation.Nodes[i].AnimationComponents[a].I_00);
                            bytes.Add(animation.Nodes[i].AnimationComponents[a].I_01);
                            bytes.AddRange(BitConverter.GetBytes(animation.Nodes[i].AnimationComponents[a].I_02));
                            bytes.AddRange(BitConverter.GetBytes(KeyframeCount));
                            bytes.AddRange(new byte[8]);

                            //Validate
                            if (animation.Nodes[i].AnimationComponents[a].Keyframes.Any(x => x.FrameIndex > (animation.FrameCount - 1)))
                            {
                                throw new Exception($"EAN Save: Keyframe FrameIndex must not exceed the animation duration. (Name: {animation.Name}, ID: {animation.ID_UShort}");
                            }

                            //Write Keyframes
                            if (KeyframeCount > 0)
                            {
                                Sorting.SortEntries2(animation.Nodes[i].AnimationComponents[a].Keyframes);

                                bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count - KeyframeOffset), KeyframeOffset + 8);
                                switch (animation.I_02)
                                {
                                case EAN_Animation.IntPrecision._8Bit:
                                    WriteKeyframeIndex_Int8(animation.Nodes[i].AnimationComponents[a].Keyframes, hasFirstKeyframe, hasFinalKeyframe, animation.FrameCount - 1);
                                    break;

                                case EAN_Animation.IntPrecision._16Bit:
                                    WriteKeyframeIndex_Int16(animation.Nodes[i].AnimationComponents[a].Keyframes, hasFirstKeyframe, hasFinalKeyframe, animation.FrameCount - 1);
                                    break;
                                }

                                StartNewLine();
                                bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count - KeyframeOffset), KeyframeOffset + 12);
                                switch (animation.I_03)
                                {
                                case EAN_Animation.FloatPrecision._16Bit:
                                    WriteKeyframeFloats_Float16(animation.Nodes[i].AnimationComponents[a].Keyframes, hasFirstKeyframe, hasFinalKeyframe, defaultKeyframe);
                                    break;

                                case EAN_Animation.FloatPrecision._32Bit:
                                    WriteKeyframeFloats_Float32(animation.Nodes[i].AnimationComponents[a].Keyframes, hasFirstKeyframe, hasFinalKeyframe, defaultKeyframe);
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            bytes.AddRange(new byte[12]);
        }
Example #3
0
        private void WriteAnimation(EAN_Animation animation, int offsetToReplace)
        {
            StartNewLine();

            bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count()), offsetToReplace);
            int startOffset = bytes.Count();
            int nodeCount   = (animation.Nodes != null) ? animation.Nodes.Count() : 0;

            if (nodeCount > 0)
            {
                nodeCount = 0;
                for (int i = 0; i < animation.Nodes.Count(); i++)
                {
                    if (eanFile.Skeleton.Exists(animation.Nodes[i].BoneName))
                    {
                        nodeCount++;
                    }
                }
            }

            bytes.AddRange(new byte[2]);
            bytes.Add((byte)animation.I_02);
            bytes.Add((byte)animation.I_03);
            bytes.AddRange(BitConverter.GetBytes(animation.I_04));
            bytes.AddRange(BitConverter.GetBytes(nodeCount));
            bytes.AddRange(new byte[4]);

            //Nodes
            if (nodeCount > 0)
            {
                bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count() - startOffset), startOffset + 12);
                List <int> NodeTable = new List <int>();
                for (int i = 0; i < nodeCount; i++)
                {
                    NodeTable.Add(bytes.Count());
                    bytes.AddRange(new byte[4]);
                }

                for (int i = 0; i < nodeCount; i++)
                {
                    if (eanFile.Skeleton.Exists(animation.Nodes[i].BoneName))
                    {
                        bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count() - startOffset), NodeTable[i]);
                        int        NodeOffset = bytes.Count();
                        List <int> AnimationComponentTable = new List <int>();

                        int AnimationComponentCount = (animation.Nodes[i].AnimationComponents != null) ? animation.Nodes[i].AnimationComponents.Count() : 0;
                        bytes.AddRange(BitConverter.GetBytes(GetBoneIndex(animation.Nodes[i].BoneName, animation.Name)));
                        bytes.AddRange(BitConverter.GetBytes((short)AnimationComponentCount));
                        bytes.AddRange(BitConverter.GetBytes(8));

                        //Table
                        for (int a = 0; a < AnimationComponentCount; a++)
                        {
                            AnimationComponentTable.Add(bytes.Count());
                            bytes.AddRange(new byte[4]);
                        }

                        //Data
                        for (int a = 0; a < AnimationComponentCount; a++)
                        {
                            bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count() - NodeOffset), AnimationComponentTable[a]);

                            int KeyframeOffset = bytes.Count();
                            int KeyframeCount  = (animation.Nodes[i].AnimationComponents[a].Keyframes != null) ? animation.Nodes[i].AnimationComponents[a].Keyframes.Count() : 0;

                            bytes.Add((byte)animation.Nodes[i].AnimationComponents[a].I_00);
                            bytes.Add(animation.Nodes[i].AnimationComponents[a].I_01);
                            bytes.AddRange(BitConverter.GetBytes(animation.Nodes[i].AnimationComponents[a].I_02));
                            bytes.AddRange(BitConverter.GetBytes(KeyframeCount));
                            bytes.AddRange(new byte[8]);

                            //Sort Keyframes
                            if (KeyframeCount > 0)
                            {
                                var sortedList = animation.Nodes[i].AnimationComponents[a].Keyframes.ToList();
                                sortedList.Sort((x, y) => x.FrameIndex - y.FrameIndex);
                                animation.Nodes[i].AnimationComponents[a].Keyframes = new ObservableCollection <EAN_Keyframe>(sortedList);
                            }

                            if (KeyframeCount > 0)
                            {
                                bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count() - KeyframeOffset), KeyframeOffset + 8);
                                switch (animation.I_02)
                                {
                                case EAN_Animation.IntPrecision._8Bit:
                                    WriteKeyframeIndex_Int8(animation.Nodes[i].AnimationComponents[a].Keyframes);
                                    break;

                                case EAN_Animation.IntPrecision._16Bit:
                                    WriteKeyframeIndex_Int16(animation.Nodes[i].AnimationComponents[a].Keyframes);
                                    break;
                                }

                                StartNewLine();
                                bytes = Utils.ReplaceRange(bytes, BitConverter.GetBytes(bytes.Count() - KeyframeOffset), KeyframeOffset + 12);
                                switch (animation.I_03)
                                {
                                case EAN_Animation.FloatPrecision._16Bit:
                                    WriteKeyframeFloats_Float16(animation.Nodes[i].AnimationComponents[a].Keyframes);
                                    break;

                                case EAN_Animation.FloatPrecision._32Bit:
                                    WriteKeyframeFloats_Float32(animation.Nodes[i].AnimationComponents[a].Keyframes);
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            bytes.AddRange(new byte[12]);
        }