/// <summary> /// /// </summary> /// <param name="n"></param> /// <param name="externalID"></param> /// <param name="stride"></param> /// <param name="count"></param> private static void RemoveMatAnim(HSD_TexAnim texAnim, int externalID, int stride, int count) { var fobjs = texAnim.AnimationObject.FObjDesc.List; List <int> toRem = new List <int>(); for (int i = count - 1; i >= 0; i--) { var frame = externalID + stride * i; foreach (var f in fobjs) { var key = RemoveKey(f, frame); if (key != null && key.Value != 0 && !toRem.Contains((int)key.Value)) { toRem.Add((int)key.Value); } } } toRem.Sort(); toRem.Reverse(); foreach (var r in toRem) { texAnim.RemoveImageAt(r); } }
/// <summary> /// /// </summary> /// <param name="n"></param> /// <param name="tobjs"></param> /// <param name="externalID"></param> /// <param name="stride"></param> /// <param name="count"></param> public static void InjectIntoMatTexAnim(HSD_TexAnim texAnim, HSD_TOBJ[] tobjs, int externalID, int stride, int count, int defaultValue = 0) { var fobjs = texAnim.AnimationObject.FObjDesc.List; int cspIndex = 0; for (int i = 0; i < count; i++) { var tindex = defaultValue; if (i < tobjs.Length && tobjs[i] != null) { tindex = texAnim.AddImage(tobjs[i]); } foreach (var f in fobjs) { f.InsertKey(new HSDRaw.Tools.FOBJKey() { Frame = externalID + stride * cspIndex, Value = tindex, InterpolationType = HSDRaw.Common.Animation.GXInterpolationType.HSD_A_OP_CON }); } cspIndex++; } }
/// <summary> /// /// </summary> public void SaveStockNode() { // set meta data StockNode.Reserved = (short)ReservedItems.Length; StockNode.Stride = (short)Items.Length; List <FOBJKey> keys = new List <FOBJKey>(); List <HSD_TOBJ> tobjs = new List <HSD_TOBJ>(); // reserved for (int i = 0; i < ReservedItems.Length; i++) { if (ReservedItems[i].TOBJS.Length > 0) { keys.Add(new FOBJKey() { Frame = i, InterpolationType = GXInterpolationType.HSD_A_OP_CON, Value = tobjs.Count }); tobjs.Add(ReservedItems[i].TOBJS[0].TOBJ); } } // get fighter stock icons for (int i = 0; i < Items.Length; i++) { for (int j = 0; j < Items[i].TOBJS.Length; j++) { keys.Add(new FOBJKey() { Frame = ReservedItems.Length + j * Items.Length + i, InterpolationType = GXInterpolationType.HSD_A_OP_CON, Value = tobjs.Count }); tobjs.Add(Items[i].TOBJS[j].TOBJ); } } // order keys keys = keys.OrderBy(e => e.Frame).ToList(); // generate new tex anim var newTexAnim = new HSD_TexAnim(); newTexAnim.AnimationObject = new HSD_AOBJ(); newTexAnim.AnimationObject.FObjDesc = new HSD_FOBJDesc(); newTexAnim.AnimationObject.FObjDesc.SetKeys(keys, (byte)TexTrackType.HSD_A_T_TIMG); newTexAnim.AnimationObject.FObjDesc.Next = new HSD_FOBJDesc(); newTexAnim.AnimationObject.FObjDesc.Next.SetKeys(keys, (byte)TexTrackType.HSD_A_T_TCLT); newTexAnim.FromTOBJs(tobjs, false); newTexAnim.Optimize(); StockNode.MatAnimJoint = new HSD_MatAnimJoint(); StockNode.MatAnimJoint.MaterialAnimation = new HSD_MatAnim(); StockNode.MatAnimJoint.MaterialAnimation.TextureAnimation = newTexAnim; // done MessageBox.Show("Stock Icon Symbol has been rebuilt"); }
/// <summary> /// /// </summary> /// <param name="stage"></param> /// <param name="icons"></param> public static MEX_mexMapData GenerateMexMap(SBM_MnSelectStageDataTable stage, IEnumerable <MEXStageIconEntry> icons) { MEX_mexMapData mapData = new MEX_mexMapData(); var nameTexAnim = new HSD_TexAnim(); var nameKeys = new List <FOBJKey>(); var iconTexAnim = new HSD_TexAnim(); var iconKeys = new List <FOBJKey>(); HSD_JOBJ root = new HSD_JOBJ() { SX = 1, SY = 1, SZ = 1, Flags = JOBJ_FLAG.CLASSICAL_SCALING }; HSD_AnimJoint animRoot = new HSD_AnimJoint(); // extra { var tobjs = stage.IconLargeMatAnimJoint.Child.MaterialAnimation.Next.TextureAnimation.ToTOBJs(); var index = iconTexAnim.AddImage(tobjs[0]); iconKeys.Add(new FOBJKey() { Frame = index, Value = index, InterpolationType = GXInterpolationType.HSD_A_OP_CON }); index = iconTexAnim.AddImage(tobjs[1]); iconKeys.Add(new FOBJKey() { Frame = index, Value = index, InterpolationType = GXInterpolationType.HSD_A_OP_CON }); } foreach (var v in icons) { var index = iconTexAnim.AddImage(v.IconTOBJ); if (index == -1) { index = 0; } iconKeys.Add(new FOBJKey() { Frame = index, Value = index, InterpolationType = GXInterpolationType.HSD_A_OP_CON }); index = nameTexAnim.AddImage(v.NameTOBJ); if (index == -1) { index = 0; } nameKeys.Add(new FOBJKey() { Frame = index, Value = index, InterpolationType = GXInterpolationType.HSD_A_OP_CON }); v.Joint.Next = null; v.Joint.Child = null; v.AnimJoint.Next = null; v.AnimJoint.Child = null; root.AddChild(v.Joint); animRoot.AddChild(v.AnimJoint); } iconKeys.Add(new FOBJKey() { Frame = 1600, Value = 0, InterpolationType = GXInterpolationType.HSD_A_OP_CON }); iconTexAnim.GXTexMapID = HSDRaw.GX.GXTexMapID.GX_TEXMAP0; iconTexAnim.AnimationObject = new HSD_AOBJ(); iconTexAnim.AnimationObject.EndFrame = 1600; iconTexAnim.AnimationObject.FObjDesc = new HSD_FOBJDesc(); iconTexAnim.AnimationObject.FObjDesc.SetKeys(iconKeys, (byte)TexTrackType.HSD_A_T_TIMG); iconTexAnim.AnimationObject.FObjDesc.Next = new HSD_FOBJDesc(); iconTexAnim.AnimationObject.FObjDesc.Next.SetKeys(iconKeys, (byte)TexTrackType.HSD_A_T_TCLT); var iconJOBJ = HSDAccessor.DeepClone <HSD_JOBJ>(stage.IconDoubleModel); iconJOBJ.Child = iconJOBJ.Child.Next; var iconAnimJoint = HSDAccessor.DeepClone <HSD_AnimJoint>(stage.IconDoubleAnimJoint); iconAnimJoint.Child = iconAnimJoint.Child.Next; var iconMatAnimJoint = HSDAccessor.DeepClone <HSD_MatAnimJoint>(stage.IconDoubleMatAnimJoint); iconMatAnimJoint.Child = iconMatAnimJoint.Child.Next; iconMatAnimJoint.Child.MaterialAnimation.Next.TextureAnimation = iconTexAnim; var iconNameAnim = HSDAccessor.DeepClone <HSD_MatAnimJoint>(stage.StageNameMatAnimJoint); nameTexAnim.AnimationObject = new HSD_AOBJ(); nameTexAnim.AnimationObject.EndFrame = 1600; nameTexAnim.AnimationObject.FObjDesc = new HSD_FOBJDesc(); nameTexAnim.AnimationObject.FObjDesc.SetKeys(nameKeys, (byte)TexTrackType.HSD_A_T_TIMG); iconNameAnim.Child.Child.MaterialAnimation.TextureAnimation = nameTexAnim; mapData.IconModel = iconJOBJ; mapData.IconAnimJoint = iconAnimJoint; mapData.IconMatAnimJoint = iconMatAnimJoint; mapData.PositionModel = root; mapData.PositionAnimJoint = animRoot; mapData.StageNameMaterialAnimation = iconNameAnim; return(mapData); }
/// <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 }); } } }
/// <summary> /// /// </summary> /// <param name="file"></param> /// <returns></returns> public static MEX_Stock GenerateStockIconNodeFromVanilla(HSD_TexAnim texanim) { // extract tex anim assets var tobjs = texanim.ToTOBJs(); var keys = texanim.AnimationObject.FObjDesc.GetDecodedKeys(); FOBJ_Player player = new FOBJ_Player(); player.Keys = keys; // generate stock node var stockNode = new MEX_Stock(); stockNode.Reserved = 10; stockNode.Stride = 26; var newTobjs = new List <HSD_TOBJ>(); var newKeys = new List <FOBJKey>(); // get hardcoded images /* * 0 - blank * 1 - smash ball * 2 - master hand * 3 - crazy hand * 4 - target * 5 - giga bowser * 6 - sandbag * 7 - red dot * 8 - furby */ int[] hardcoded = new[] { 250, 26, 27, 28, 57, 58, 59, 185, 185 }; for (int i = 0; i < hardcoded.Length; i++) { newKeys.Add(new FOBJKey() { Frame = i, InterpolationType = GXInterpolationType.HSD_A_OP_CON, Value = newTobjs.Count }); newTobjs.Add(tobjs[(int)player.GetValue(hardcoded[i])]); } // get fighter stock icons for (int i = 0; i < 27; i++) { int color = 0; while (true) { var key = keys.Find(e => e.Frame == color * 30 + (i == 26 ? 29 : i)); if (key != null) { newKeys.Add(new FOBJKey() { Frame = 10 + color * 26 + i, InterpolationType = GXInterpolationType.HSD_A_OP_CON, Value = newTobjs.Count }); newTobjs.Add(tobjs[(int)key.Value]); color++; } else { break; } } } // order keys newKeys = newKeys.OrderBy(e => e.Frame).ToList(); foreach (var k in newKeys) { Console.WriteLine(k.Frame + " " + k.Value); } // generate new tex anim var newTexAnim = new HSD_TexAnim(); newTexAnim.AnimationObject = new HSD_AOBJ(); newTexAnim.AnimationObject.FObjDesc = new HSD_FOBJDesc(); newTexAnim.AnimationObject.FObjDesc.SetKeys(newKeys, (byte)TexTrackType.HSD_A_T_TIMG); newTexAnim.AnimationObject.FObjDesc.Next = new HSD_FOBJDesc(); newTexAnim.AnimationObject.FObjDesc.Next.SetKeys(newKeys, (byte)TexTrackType.HSD_A_T_TCLT); newTexAnim.FromTOBJs(newTobjs, false); stockNode.MatAnimJoint = new HSD_MatAnimJoint(); stockNode.MatAnimJoint.MaterialAnimation = new HSD_MatAnim(); stockNode.MatAnimJoint.MaterialAnimation.TextureAnimation = newTexAnim; return(stockNode); }