/// <summary> /// /// </summary> /// <param name="node"></param> /// <returns></returns> private static HSD_MatAnimJoint GenerateMatAnimJointFromJOBJ(HSD_JOBJ node) { HSD_MatAnimJoint joint = new HSD_MatAnimJoint(); if (node.Dobj != null) { foreach (var v in node.Dobj.List) { if (joint.MaterialAnimation == null) { joint.MaterialAnimation = new HSD_MatAnim(); } else { joint.MaterialAnimation.Add(new HSD_MatAnim() { }); } } } foreach (var v in node.Children) { joint.AddChild(GenerateMatAnimJointFromJOBJ(v)); } return(joint); }
public override void Open(HSDReader Reader) { Type = Reader.ReadInt32(); if (Type == -1) { MatAnimJoint = Reader.ReadObject <HSD_MatAnimJoint>(Reader.ReadUInt32()); } else { Reader.ReadInt32(); // nothing } FrameCount = Reader.ReadSingle(); uint TrackCountOffset = Reader.ReadUInt32(); uint TrackOffset = Reader.ReadUInt32(); Reader.Seek(TrackCountOffset); List <byte> TrackCounts = new List <byte>(); byte TrackCount; while ((TrackCount = Reader.ReadByte()) != 0xFF) { TrackCounts.Add(TrackCount); } int track = 0; for (int i = 0; i < TrackCounts.Count; i++) { HSD_AnimNode Node = new HSD_AnimNode(); Nodes.Add(Node); for (int j = 0; j < TrackCounts[i]; j++) { Reader.Seek((uint)(TrackOffset + 0xC * track++)); HSD_Track t = new HSD_Track(); t.Open(Reader); Node.Tracks.Add(t); } } }
/// <summary> /// /// </summary> /// <param name="icons"></param> /// <returns></returns> public static Tuple <HSD_JOBJ, HSD_AnimJoint, HSD_MatAnimJoint> GenerateIconModel(MEX_CSSIconEntry[] icons) { HSD_JOBJ position_joint = new HSD_JOBJ(); position_joint.Flags = JOBJ_FLAG.CLASSICAL_SCALING | JOBJ_FLAG.ROOT_XLU; position_joint.SX = 1; position_joint.SY = 1; position_joint.SZ = 1; HSD_AnimJoint anim_joint = new HSD_AnimJoint(); HSD_MatAnimJoint matanim_joint = new HSD_MatAnimJoint(); foreach (var ico in icons) { ico.Joint.Next = null; ico.AnimJoint.Next = null; ico.MatAnimJoint.Next = null; position_joint.AddChild(ico.Joint); anim_joint.AddChild(ico.AnimJoint); matanim_joint.AddChild(ico.MatAnimJoint); } return(new Tuple <HSD_JOBJ, HSD_AnimJoint, HSD_MatAnimJoint>(position_joint, anim_joint, matanim_joint)); }
/// <summary> /// /// </summary> /// <param name="table"></param> /// <param name="icons"></param> /// <returns></returns> private static MEX_mexSelectChr GenerateMexSelectChrSymbol(SBM_SelectChrDataTable table, MEX_CSSIcon[] cssIcons) { // create mexSelectChr struct MEX_mexSelectChr mex = new MEX_mexSelectChr(); // generate icon model var icon_joint = HSDAccessor.DeepClone <HSD_JOBJ>(table.MenuModel.Children[2].Child); icon_joint.TX = 0; icon_joint.TY = 0; icon_joint.TZ = 0; icon_joint.Next = null; var center = RegenerateIcon(icon_joint); // generate material_anim_joint var icon_matanim_joint = HSDAccessor.DeepClone <HSD_MatAnimJoint>(table.MenuMaterialAnimation.Children[2].Child); icon_matanim_joint.Next = null; // general base models HSD_JOBJ position_joint = new HSD_JOBJ(); position_joint.Flags = JOBJ_FLAG.CLASSICAL_SCALING | JOBJ_FLAG.ROOT_XLU; position_joint.SX = 1; position_joint.SY = 1; position_joint.SZ = 1; HSD_AnimJoint anim_joint = new HSD_AnimJoint(); HSD_MatAnimJoint matanim_joint = new HSD_MatAnimJoint(); // create icon data var joints = table.MenuModel.BreathFirstList; var matanims = table.MenuAnimation.BreathFirstList; foreach (var ico in cssIcons) { if (joints[ico.JointID].Dobj == null) { continue; } HSD_JOBJ joint = HSDAccessor.DeepClone <HSD_JOBJ>(icon_joint); joint.Dobj.Pobj.Attributes = icon_joint.Dobj.Pobj.Attributes; joint.Dobj.Next.Pobj.Attributes = icon_joint.Dobj.Pobj.Attributes; joint.Dobj.Next.Mobj.Textures = HSDAccessor.DeepClone <HSD_TOBJ>(joints[ico.JointID].Dobj.Next.Mobj.Textures); var worldPosition = new GXVector3(joints[ico.JointID].TX, joints[ico.JointID].TY, joints[ico.JointID].TZ); // get anim var anim = matanims[ico.JointID].AOBJ; // if it's a clone get parent location if (ico.JointID < 15) { worldPosition = new GXVector3(joints[ico.JointID - 1].TX, joints[ico.JointID - 1].TY, joints[ico.JointID - 1].TZ); anim = matanims[ico.JointID - 1].AOBJ; } // check animation for world position if (anim != null) { foreach (var v in anim.FObjDesc.List) { System.Diagnostics.Debug.WriteLine(v.JointTrackType); if (v.JointTrackType == JointTrackType.HSD_A_J_TRAX) { var keys = v.GetDecodedKeys(); worldPosition.X = keys[keys.Count - 1].Value; } } } joint.TX = worldPosition.X + center.X; joint.TY = worldPosition.Y + center.Y; joint.TZ = worldPosition.Z + center.Z; position_joint.AddChild(joint); anim_joint.AddChild(new HSD_AnimJoint()); matanim_joint.AddChild(HSDAccessor.DeepClone <HSD_MatAnimJoint>(icon_matanim_joint)); } mex.IconModel = position_joint; mex.IconAnimJoint = anim_joint; mex.IconMatAnimJoint = matanim_joint; mex.CSPMatAnim = HSDAccessor.DeepClone <HSD_MatAnim>(table.MenuMaterialAnimation.Children[6].Child.MaterialAnimation); var cspkeys = mex.CSPMatAnim.TextureAnimation.AnimationObject.FObjDesc.GetDecodedKeys(); foreach (var k in cspkeys) { if ((k.Frame % 30) >= 19) { k.Frame++; } } mex.CSPMatAnim.TextureAnimation.AnimationObject.FObjDesc.SetKeys(cspkeys, (byte)TexTrackType.HSD_A_T_TIMG); mex.CSPMatAnim.TextureAnimation.AnimationObject.FObjDesc.Next.SetKeys(cspkeys, (byte)TexTrackType.HSD_A_T_TCLT); mex.CSPStride = 30; return(mex); }
/// <summary> /// /// </summary> public void FromMatAnim(HSD_MatAnimJoint joint) { Nodes.Clear(); FrameCount = 0; if (joint == null) { return; } foreach (var j in joint.BreathFirstList) { MatAnimJoint matjoint = new MatAnimJoint(); if (j.MaterialAnimation != null) { foreach (var a in j.MaterialAnimation.List) { MatAnim anm = new MatAnim(); if (a.AnimationObject != null) { FrameCount = (int)Math.Max(FrameCount, a.AnimationObject.EndFrame); foreach (var fdesc in a.AnimationObject.FObjDesc.List) { anm.Tracks.Add(new FOBJ_Player(fdesc)); } } if (a.TextureAnimation != null) { foreach (var t in a.TextureAnimation.List) { MatAnimTexture tex = new MatAnimTexture(); tex.Textures.AddRange(t.ToTOBJs()); tex.TextureID = t.GXTexMapID; if (t.AnimationObject != null) { if (t.AnimationObject != null) { FrameCount = (int)Math.Max(FrameCount, t.AnimationObject.EndFrame); foreach (var fdesc in t.AnimationObject.FObjDesc.List) { tex.Tracks.Add(new FOBJ_Player(fdesc)); } } } anm.TextureAnims.Add(tex); } } matjoint.Nodes.Add(anm); } } Nodes.Add(matjoint); } }
/// <summary> /// Opens dat file from stream /// </summary> /// <param name="stream"></param> public void Open(Stream stream) { using (BinaryReaderExt r = new BinaryReaderExt(stream)) { r.BigEndian = true; // Parse Header ----------------------------- var fsize = r.ReadInt32(); // dat size int relocOffset = r.ReadInt32() + 0x20; int relocCount = r.ReadInt32(); int rootCount = r.ReadInt32(); int refCount = r.ReadInt32(); VersionChars = r.ReadChars(4); // Parse Relocation Table ----------------------------- List <int> Offsets = new List <int>(); HashSet <int> OffsetContain = new HashSet <int>(); Dictionary <int, int> relocOffsets = new Dictionary <int, int>(); Offsets.Add(relocOffset); r.BaseStream.Position = relocOffset; for (int i = 0; i < relocCount; i++) { int offset = r.ReadInt32() + 0x20; var temp = r.BaseStream.Position; r.BaseStream.Position = offset; var objectOff = r.ReadInt32() + 0x20; // if we need to read past end of file then we need to include filesize as an offset // this fixes files that had previously been manually relocated to end of file if (objectOff > relocOffset && !Offsets.Contains(fsize)) { Offsets.Add(fsize); } // if (objectOff < 0) { r.BaseStream.Position = temp; continue; } relocOffsets.Add(offset, objectOff); if (!OffsetContain.Contains(objectOff)) { OffsetContain.Add(objectOff); Offsets.Add(objectOff); } r.BaseStream.Position = temp; } // Parse Roots--------------------------------- List <int> rootOffsets = new List <int>(); List <string> rootStrings = new List <string>(); List <int> refOffsets = new List <int>(); List <string> refStrings = new List <string>(); var stringStart = r.BaseStream.Position + (refCount + rootCount) * 8; for (int i = 0; i < rootCount; i++) { rootOffsets.Add(r.ReadInt32() + 0x20); rootStrings.Add(r.ReadString((int)stringStart + r.ReadInt32(), -1)); } for (int i = 0; i < refCount; i++) { var refp = r.ReadInt32() + 0x20; refOffsets.Add(refp); refStrings.Add(r.ReadString((int)stringStart + r.ReadInt32(), -1)); var temp = r.Position; var special = refp; while (true) { r.Seek((uint)special); special = r.ReadInt32(); if (special == 0 || special == -1) { break; } special += 0x20; relocOffsets.Add(refp, special); refp = special; if (!OffsetContain.Contains(special)) { OffsetContain.Add(special); Offsets.Add(special); } } r.Seek(temp); } foreach (var v in rootOffsets) { if (!OffsetContain.Contains(v)) { OffsetContain.Add(v); Offsets.Add(v); } } foreach (var v in refOffsets) { if (!OffsetContain.Contains(v)) { OffsetContain.Add(v); Offsets.Add(v); } } // Split Raw Struct Data-------------------------- Offsets.Sort(); Dictionary <int, HSDStruct> offsetToStruct = new Dictionary <int, HSDStruct>(); Dictionary <int, List <int> > offsetToOffsets = new Dictionary <int, List <int> >(); Dictionary <int, List <int> > offsetToInnerOffsets = new Dictionary <int, List <int> >(); var relockeys = relocOffsets.Keys.ToList(); for (int i = 0; i < Offsets.Count - 1; i++) { r.BaseStream.Position = Offsets[i]; byte[] data = r.ReadBytes(Offsets[i + 1] - Offsets[i]); if (!offsetToOffsets.ContainsKey(Offsets[i])) { var relocKets = relockeys.FindAll(e => e >= Offsets[i] && e < Offsets[i + 1]); var list = new List <int>(); foreach (var k in relocKets) { list.Add(relocOffsets[k]); } offsetToOffsets.Add(Offsets[i], list); offsetToInnerOffsets.Add(Offsets[i], relocKets); } if (!offsetToStruct.ContainsKey(Offsets[i])) { var struture = new HSDStruct(data); offsetToStruct.Add(Offsets[i], struture); } } // set references------------------------- foreach (var str in offsetToStruct) { var offsets = offsetToOffsets[str.Key]; var innerOffsets = offsetToInnerOffsets[str.Key]; for (int i = 0; i < offsets.Count; i++) { if (offsetToStruct.ContainsKey(offsets[i]) && str.Value.Length >= innerOffsets[i] - str.Key + 4) { str.Value.SetReferenceStruct(innerOffsets[i] - str.Key, offsetToStruct[offsets[i]]); } } _structCache.Add(str.Value); _structCacheToOffset.Add(str.Value, str.Key); } // set roots for (int i = 0; i < rootOffsets.Count; i++) { HSDStruct str = offsetToStruct[rootOffsets[i]]; HSDAccessor a = new HSDAccessor(); a._s = str; if (rootStrings[i].EndsWith("shapeanim_joint")) { var acc = new HSDAccessor(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("matanim_joint")) { var acc = new HSD_MatAnimJoint(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("_joint")) { var jobj = new HSD_JOBJ(); jobj._s = str; a = jobj; } else if (rootStrings[i].EndsWith("_animjoint")) { var jobj = new HSD_AnimJoint(); jobj._s = str; a = jobj; } else if (rootStrings[i].EndsWith("_texanim")) { var jobj = new HSD_TexAnim(); jobj._s = str; a = jobj; } else if (rootStrings[i].EndsWith("_figatree")) { var jobj = new HSD_FigaTree(); jobj._s = str; a = jobj; } else if (rootStrings[i].EndsWith("_scene_models") || rootStrings[i].Equals("Stc_rarwmdls") || rootStrings[i].Equals("Stc_scemdls") || rootStrings[i].Equals("lupe") || rootStrings[i].Equals("tdsce")) { var jobj = new HSDNullPointerArrayAccessor <HSD_JOBJDesc>(); jobj._s = str; a = jobj; } else if (rootStrings[i].StartsWith("ftData")) { var acc = new SBM_PlayerData(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("MnSelectChrDataTable")) { var acc = new SBM_SelectChrDataTable(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("MnSelectStageDataTable")) { var acc = new SBM_MnSelectStageDataTable(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("coll_data")) { var acc = new SBM_Coll_Data(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("scene_data") || rootStrings[i].Equals("pnlsce") || rootStrings[i].Equals("flmsce") || (rootStrings[i].StartsWith("Sc") && str.Length == 0x10)) { var acc = new HSD_SOBJ(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("map_plit")) { var acc = new HSDNullPointerArrayAccessor <HSD_Light>(); acc._s = str; a = acc; } /*else * if (rootStrings[i].StartsWith("grGroundParam")) * { * var acc = new SBM_GroundParam(); * acc._s = str; * a = acc; * }*/ else if (rootStrings[i].StartsWith("map_head")) { var acc = new SBM_Map_Head(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("grGroundParam")) { var acc = new SBM_GroundParam(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("vcDataStar")) { var acc = new KAR_vcDataStar(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("vcDataWheel")) { var acc = new KAR_vcDataWheel(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("grModelMotion")) { var acc = new KAR_grModelMotion(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("grModel")) { var acc = new KAR_grModel(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("grData")) { var acc = new KAR_grData(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("_texg")) { var acc = new HSD_TEXGraphicBank(); acc._s = str; a = acc; } else if (rootStrings[i].EndsWith("_ptcl")) { var acc = new HSD_ParticleGroup(); acc._s = str; a = acc; } else if (rootStrings[i].StartsWith("eff")) { var acc = new SBM_EffectTable(); acc._s = str; a = acc; } Roots.Add(new HSDRootNode() { Name = rootStrings[i], Data = a }); } // set references for (int i = 0; i < refOffsets.Count; i++) { HSDStruct str = offsetToStruct[refOffsets[i]]; HSDAccessor a = new HSDAccessor(); a._s = str; References.Add(new HSDRootNode() { Name = refStrings[i], Data = a }); } } }