using System; using Oni.Motoko; namespace Oni.Totoro { internal static class BodyDatReader { public static Body Read(InstanceDescriptor source) { InstanceDescriptor trcm = ReadTRCM(source); InstanceDescriptor trga; InstanceDescriptor trta; InstanceDescriptor tria; using (var reader = trcm.OpenRead(84)) { trga = reader.ReadInstance(); trta = reader.ReadInstance(); tria = reader.ReadInstance(); } var geometries = ReadTRGA(trga); var translations = ReadTRTA(trta); var indices = ReadTRIA(tria); var nodes = new BodyNode[geometries.Length]; for (int i = 0; i < nodes.Length; i++) { nodes[i] = new BodyNode { Name = BodyNode.Names[i], Index = i, Geometry = geometries[i], Translation = translations[i], }; } for (int i = 0; i < nodes.Length; i++) { var node = nodes[i]; for (int j = indices[i].FirstChildIndex; j != 0; j = indices[j].SiblingIndex) { nodes[j].Parent = node; node.Nodes.Add(nodes[j]); } } var body = new Body(); body.Nodes.AddRange(nodes); return body; } private static InstanceDescriptor ReadTRCM(InstanceDescriptor source) { if (source.Template.Tag == TemplateTag.TRCM) return source; if (source.Template.Tag == TemplateTag.ONCC) source = Game.CharacterClass.Read(source).Body; if (source.Template.Tag != TemplateTag.TRBS) throw new InvalidOperationException(string.Format("Invalid body source type {0}", source.Template.Tag)); return ReadTRBS(source).Last(); } private static InstanceDescriptor[] ReadTRBS(InstanceDescriptor trbs) { using (var reader = trbs.OpenRead()) return reader.ReadInstanceArray(5); } private static Geometry[] ReadTRGA(InstanceDescriptor trga) { InstanceDescriptor[] descriptors; using (var reader = trga.OpenRead(22)) descriptors = reader.ReadInstanceArray(reader.ReadInt16()); var geometries = new Geometry[descriptors.Length]; for (int i = 0; i < descriptors.Length; i++) geometries[i] = GeometryDatReader.Read(descriptors[i]); return geometries; } private static Vector3[] ReadTRTA(InstanceDescriptor trta) { using (var reader = trta.OpenRead(22)) return reader.ReadVector3Array(reader.ReadInt16()); } private struct NodeIndices { public byte ParentIndex; public byte FirstChildIndex; public byte SiblingIndex; } private static NodeIndices[] ReadTRIA(InstanceDescriptor tria) { using (var reader = tria.OpenRead(22)) { var indices = new NodeIndices[reader.ReadInt16()]; for (int i = 0; i < indices.Length; i++) { indices[i].ParentIndex = reader.ReadByte(); indices[i].FirstChildIndex = reader.ReadByte(); indices[i].SiblingIndex = reader.ReadByte(); reader.Skip(1); } return indices; } } } }