private void LoadAnimations(BinaryReader reader) { var bones = ReadArrayOf <M2Bone>(reader, mHeader.OfsBones, mHeader.NBones); Bones = bones.Select(b => new M2AnimationBone(this, ref b, reader)).ToArray(); if (Bones.Any(b => b.IsBillboarded)) { NeedsPerInstanceAnimation = true; } AnimationLookup = ReadArrayOf <short>(reader, mHeader.OfsAnimLookup, mHeader.NAnimLookup); Animations = ReadArrayOf <AnimationEntry>(reader, mHeader.OfsAnimations, mHeader.NAnimations); AnimationIds = Animations.Select(x => x.animationID).ToArray(); var uvAnims = ReadArrayOf <M2TexAnim>(reader, mHeader.OfsUvAnimation, mHeader.NUvAnimation); UvAnimations = uvAnims.Select(uv => new M2UVAnimation(this, ref uv, reader)).ToArray(); var colorAnims = ReadArrayOf <M2ColorAnim>(reader, mHeader.OfsSubmeshAnimations, mHeader.NSubmeshAnimations); ColorAnimations = colorAnims.Select(c => new M2TexColorAnimation(this, ref c, reader)).ToArray(); var transparencies = ReadArrayOf <AnimationBlock>(reader, mHeader.OfsTransparencies, mHeader.NTransparencies); Transparencies = transparencies.Select(t => new M2AlphaAnimation(this, ref t, reader)).ToArray(); }
internal void Write(EndianBinaryWriter writer) { writer.ScheduleWriteOffset(16, AlignmentMode.Center, () => { foreach (var bone in Bones) { writer.Write(bone.ID); } }); writer.ScheduleWriteOffset(16, AlignmentMode.Center, () => { foreach (var bone in Bones) { writer.Write(bone.Matrix); } }); writer.ScheduleWriteOffset(16, AlignmentMode.Center, () => { foreach (var bone in Bones) { writer.AddStringToStringTable(bone.Name); } }); writer.ScheduleWriteOffsetIf(ExData != null, 16, AlignmentMode.Center, () => ExData.Write(writer)); writer.Write(Bones.Count); writer.ScheduleWriteOffsetIf(Bones.Any(x => x.ParentID != -1), 16, AlignmentMode.Center, () => { foreach (var bone in Bones) { writer.Write(bone.ParentID); } }); writer.WriteNulls(writer.AddressSpace == AddressSpace.Int64 ? 32 : 40); }
internal override void WriteBody(EndianBinaryWriter writer, StringSet stringSet) { writer.Write(StartIndex); writer.Write(Bones.Count); stringSet.WriteString(writer, ExternalName); stringSet.WriteString(writer, Name); bool hasAnyRotation = Bones.Any(x => Math.Abs(x.Rotation.X) > 0 || Math.Abs(x.Rotation.Y) > 0 || Math.Abs(x.Rotation.Z) > 0); writer.ScheduleWriteOffsetIf(hasAnyRotation, 4, AlignmentMode.Left, () => { foreach (var bone in Bones) { bone.WriteOsgBlockInfo(writer, stringSet); } }); if (writer.AddressSpace == AddressSpace.Int64) { writer.WriteNulls(4 * sizeof(ulong)); } else { writer.WriteNulls(5 * sizeof(uint)); } }
void StepSecond() { Assert.IsTrue(Bones.Any(), "Bones.Any()"); var bone = Bones.Dequeue(); Debug.Log($"{nameof(StepSecond)}: {bone.gameObject} looks {_parent.gameObject}", bone); bone.LookAt(_parent.Start.position); bone.MoveToTouch(_parent.Start.position); _parent = bone; BackingStack.Push(bone); if (!Bones.Any()) { _state = IkState.Last; } }
internal void Write(EndianBinaryWriter writer, BinaryFormat format) { var stringSet = new StringSet(this); writer.ScheduleWriteOffset(16, AlignmentMode.Center, () => { foreach (var bone in Bones) { if (bone.IsEx) { bone.Id = stringSet.GetStringId(bone.Name); } writer.Write(bone.Id); } }); writer.ScheduleWriteOffset(16, AlignmentMode.Center, () => { foreach (var bone in Bones) { writer.Write(bone.InverseBindPoseMatrix); } }); writer.ScheduleWriteOffset(16, AlignmentMode.Center, () => { foreach (var bone in Bones) { writer.AddStringToStringTable(bone.Name); } writer.WriteNulls(writer.AddressSpace.GetByteSize()); }); writer.ScheduleWriteOffsetIf(stringSet.Strings.Count > 0 || Blocks.Count > 0, 16, AlignmentMode.Center, () => { var osageNames = new List <string>(Blocks.Count / 2); var osageNodes = new List <OsageNode>(Blocks.Count / 2); var clothNames = new List <string>(Blocks.Count / 8); foreach (var block in Blocks) { switch (block) { case OsageBlock osageBlock: osageBlock.StartIndex = osageNodes.Count; osageNodes.AddRange(osageBlock.Nodes); osageNames.Add(osageBlock.ExternalName); break; case ClothBlock clothBlock: clothNames.Add(clothBlock.Name); break; } } writer.Write(osageNames.Count); writer.Write(osageNodes.Count); writer.WriteNulls(sizeof(uint)); writer.ScheduleWriteOffset(4, AlignmentMode.Left, () => { foreach (var osageNode in osageNodes) { osageNode.Write(writer, stringSet); } writer.WriteNulls(3 * sizeof(uint)); }); writer.ScheduleWriteOffset(16, AlignmentMode.Left, () => { foreach (string value in osageNames) { writer.AddStringToStringTable(value); } foreach (string value in clothNames) { writer.AddStringToStringTable(value); } writer.WriteNulls(writer.AddressSpace.GetByteSize()); }); writer.ScheduleWriteOffset(16, AlignmentMode.Left, () => { foreach (var block in Blocks) { writer.AddStringToStringTable(block.Signature); writer.ScheduleWriteOffset(8, AlignmentMode.Left, () => block.Write(writer, stringSet, format)); } writer.WriteNulls(writer.AddressSpace.GetByteSize() * 2); }); writer.Write(stringSet.Strings.Count); writer.ScheduleWriteOffset(16, AlignmentMode.Left, () => { foreach (string value in stringSet.Strings) { writer.AddStringToStringTable(value); } writer.WriteNulls(writer.AddressSpace.GetByteSize()); }); writer.ScheduleWriteOffset(16, AlignmentMode.Left, () => { foreach (var osageNode in osageNodes) { if (string.IsNullOrEmpty(osageNode.SiblingName)) { continue; } stringSet.WriteString(writer, osageNode.Name); stringSet.WriteString(writer, osageNode.SiblingName); writer.Write(osageNode.SiblingMaxDistance); } writer.WriteNulls(3 * sizeof(uint)); }); writer.Write(clothNames.Count); if (writer.AddressSpace == AddressSpace.Int64) { writer.WriteNulls(4); } writer.WriteNulls(7 * writer.AddressSpace.GetByteSize()); }); writer.Write(Bones.Count); writer.ScheduleWriteOffsetIf(Bones.Any(x => x.Parent != null), 16, AlignmentMode.Center, () => { foreach (var bone in Bones) { writer.Write(bone.Parent?.Id ?? 0xFFFFFFFF); } }); writer.WriteNulls(3 * writer.AddressSpace.GetByteSize()); }