public static void Split(string filename) { nodenames.Clear(); modelfiles.Clear(); motionfiles.Clear(); Console.WriteLine("Splitting file {0}...", filename); byte[] fc; if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) { fc = Prs.Decompress(filename); } else { fc = File.ReadAllBytes(filename); } MiniEventIniData ini = new MiniEventIniData() { Name = Path.GetFileNameWithoutExtension(filename) }; string path = Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename))).FullName; uint key; List <NJS_MOTION> motions = null; if (fc[4] == 0x81) { Console.WriteLine("File is in GC/PC format."); ByteConverter.BigEndian = true; key = 0x816DFE60; ini.Game = Game.SA2B; } else { Console.WriteLine("File is in DC format."); ByteConverter.BigEndian = false; key = 0xCB00000; ini.Game = Game.SA2; } int ptr = fc.GetPointer(8, key); if (ptr != 0) { Console.WriteLine("Sonic is in this Mini-Event"); Directory.CreateDirectory(Path.Combine(path, "Sonic")); MiniEventChars data = new MiniEventChars(); data.BodyAnims = GetMotion(fc, ptr, key, $"Sonic\\Body.saanim", motions, 62); int ptr2 = fc.GetPointer(ptr + 4, key); if (ptr2 != 0) { data.HeadPart = GetModel(fc, ptr + 4, key, $"Sonic\\Head.sa2mdl"); } if (data.HeadPart != null) { data.HeadAnims = GetMotion(fc, ptr + 8, key, $"Sonic\\Head.saanim", motions, modelfiles[data.HeadPart].Model.CountAnimated()); if (data.HeadAnims != null) { modelfiles[data.HeadPart].Motions.Add($"Head.saanim"); } data.HeadShapeMotions = GetMotion(fc, ptr + 0xC, key, $"Sonic\\HeadShape.saanim", motions, modelfiles[data.HeadPart].Model.CountMorph()); if (data.HeadShapeMotions != null) { modelfiles[data.HeadPart].Motions.Add($"HeadShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x10, key); if (ptr2 != 0) { data.MouthPart = GetModel(fc, ptr + 0x10, key, $"Sonic\\Mouth.sa2mdl"); } if (data.MouthPart != null) { data.MouthAnims = GetMotion(fc, ptr + 0x14, key, $"Sonic\\Mouth.saanim", motions, modelfiles[data.MouthPart].Model.CountAnimated()); if (data.MouthAnims != null) { modelfiles[data.MouthPart].Motions.Add($"Mouth.saanim"); } data.MouthShapeMotions = GetMotion(fc, ptr + 0x18, key, $"Sonic\\MouthShape.saanim", motions, modelfiles[data.MouthPart].Model.CountMorph()); if (data.MouthShapeMotions != null) { modelfiles[data.MouthPart].Motions.Add($"MouthShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x1C, key); if (ptr2 != 0) { data.LHandPart = GetModel(fc, ptr + 0x1C, key, $"Sonic\\LeftHand.sa2mdl"); } if (data.LHandPart != null) { data.LHandAnims = GetMotion(fc, ptr + 0x20, key, $"Sonic\\LeftHand.saanim", motions, modelfiles[data.LHandPart].Model.CountAnimated()); if (data.LHandAnims != null) { modelfiles[data.LHandPart].Motions.Add($"LeftHand.saanim"); } data.LHandShapeMotions = GetMotion(fc, ptr + 0x24, key, $"Sonic\\LeftHandShape.saanim", motions, modelfiles[data.LHandPart].Model.CountMorph()); if (data.LHandShapeMotions != null) { modelfiles[data.LHandPart].Motions.Add($"LeftHandShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x28, key); if (ptr2 != 0) { data.RHandPart = GetModel(fc, ptr + 0x28, key, $"Sonic\\RightHand.sa2mdl"); } if (data.RHandPart != null) { data.RHandAnims = GetMotion(fc, ptr + 0x2C, key, $"Sonic\\RightHand.saanim", motions, modelfiles[data.RHandPart].Model.CountAnimated()); if (data.RHandAnims != null) { modelfiles[data.RHandPart].Motions.Add($"RightHand.saanim"); } data.RHandShapeMotions = GetMotion(fc, ptr + 0x30, key, $"Sonic\\RightHandShape.saanim", motions, modelfiles[data.RHandPart].Model.CountMorph()); if (data.RHandShapeMotions != null) { modelfiles[data.RHandPart].Motions.Add($"RightHandShape.saanim"); } } ini.Sonic.Add(data); } ptr = fc.GetPointer(0xC, key); if (ptr != 0) { Console.WriteLine("Shadow is in this Mini-Event"); Directory.CreateDirectory(Path.Combine(path, "Shadow")); MiniEventChars data = new MiniEventChars(); data.BodyAnims = GetMotion(fc, ptr, key, $"Shadow\\Body.saanim", motions, 62); int ptr2 = fc.GetPointer(ptr + 4, key); if (ptr2 != 0) { data.HeadPart = GetModel(fc, ptr + 4, key, $"Shadow\\Head.sa2mdl"); } if (data.HeadPart != null) { data.HeadAnims = GetMotion(fc, ptr + 8, key, $"Shadow\\Head.saanim", motions, modelfiles[data.HeadPart].Model.CountAnimated()); if (data.HeadAnims != null) { modelfiles[data.HeadPart].Motions.Add($"Head.saanim"); } data.HeadShapeMotions = GetMotion(fc, ptr + 0xC, key, $"Shadow\\HeadShape.saanim", motions, modelfiles[data.HeadPart].Model.CountMorph()); if (data.HeadShapeMotions != null) { modelfiles[data.HeadPart].Motions.Add($"HeadShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x10, key); if (ptr2 != 0) { data.MouthPart = GetModel(fc, ptr + 0x10, key, $"Shadow\\Mouth.sa2mdl"); } if (data.MouthPart != null) { data.MouthAnims = GetMotion(fc, ptr + 0x14, key, $"Shadow\\Mouth.saanim", motions, modelfiles[data.MouthPart].Model.CountAnimated()); if (data.MouthAnims != null) { modelfiles[data.MouthPart].Motions.Add($"Mouth.saanim"); } data.MouthShapeMotions = GetMotion(fc, ptr + 0x18, key, $"Shadow\\MouthShape.saanim", motions, modelfiles[data.MouthPart].Model.CountMorph()); if (data.MouthShapeMotions != null) { modelfiles[data.MouthPart].Motions.Add($"MouthShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x1C, key); if (ptr2 != 0) { data.LHandPart = GetModel(fc, ptr + 0x1C, key, $"Shadow\\LeftHand.sa2mdl"); } if (data.LHandPart != null) { data.LHandAnims = GetMotion(fc, ptr + 0x20, key, $"Shadow\\LeftHand.saanim", motions, modelfiles[data.LHandPart].Model.CountAnimated()); if (data.LHandAnims != null) { modelfiles[data.LHandPart].Motions.Add($"LeftHand.saanim"); } data.LHandShapeMotions = GetMotion(fc, ptr + 0x24, key, $"Shadow\\LeftHandShape.saanim", motions, modelfiles[data.LHandPart].Model.CountMorph()); if (data.LHandShapeMotions != null) { modelfiles[data.LHandPart].Motions.Add($"LeftHandShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x28, key); if (ptr2 != 0) { data.RHandPart = GetModel(fc, ptr + 0x28, key, $"Shadow\\RightHand.sa2mdl"); } if (data.RHandPart != null) { data.RHandAnims = GetMotion(fc, ptr + 0x2C, key, $"Shadow\\RightHand.saanim", motions, modelfiles[data.RHandPart].Model.CountAnimated()); if (data.RHandAnims != null) { modelfiles[data.RHandPart].Motions.Add($"RightHand.saanim"); } data.RHandShapeMotions = GetMotion(fc, ptr + 0x30, key, $"Shadow\\RightHandShape.saanim", motions, modelfiles[data.RHandPart].Model.CountMorph()); if (data.RHandShapeMotions != null) { modelfiles[data.RHandPart].Motions.Add($"RightHandShape.saanim"); } } ini.Shadow.Add(data); } ptr = fc.GetPointer(0x18, key); if (ptr != 0) { Console.WriteLine("Knuckles is in this Mini-Event"); Directory.CreateDirectory(Path.Combine(path, "Knuckles")); MiniEventChars data = new MiniEventChars(); data.BodyAnims = GetMotion(fc, ptr, key, $"Knuckles\\Body.saanim", motions, 62); int ptr2 = fc.GetPointer(ptr + 4, key); if (ptr2 != 0) { data.HeadPart = GetModel(fc, ptr + 4, key, $"Knuckles\\Head.sa2mdl"); } if (data.HeadPart != null) { data.HeadAnims = GetMotion(fc, ptr + 8, key, $"Knuckles\\Head.saanim", motions, modelfiles[data.HeadPart].Model.CountAnimated()); if (data.HeadAnims != null) { modelfiles[data.HeadPart].Motions.Add($"Head.saanim"); } data.HeadShapeMotions = GetMotion(fc, ptr + 0xC, key, $"Knuckles\\HeadShape.saanim", motions, modelfiles[data.HeadPart].Model.CountMorph()); if (data.HeadShapeMotions != null) { modelfiles[data.HeadPart].Motions.Add($"HeadShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x10, key); if (ptr2 != 0) { data.MouthPart = GetModel(fc, ptr + 0x10, key, $"Knuckles\\Mouth.sa2mdl"); } if (data.MouthPart != null) { data.MouthAnims = GetMotion(fc, ptr + 0x14, key, $"Knuckles\\Mouth.saanim", motions, modelfiles[data.MouthPart].Model.CountAnimated()); if (data.MouthAnims != null) { modelfiles[data.MouthPart].Motions.Add($"Mouth.saanim"); } data.MouthShapeMotions = GetMotion(fc, ptr + 0x18, key, $"Knuckles\\MouthShape.saanim", motions, modelfiles[data.MouthPart].Model.CountMorph()); if (data.MouthShapeMotions != null) { modelfiles[data.MouthPart].Motions.Add($"MouthShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x1C, key); if (ptr2 != 0) { data.LHandPart = GetModel(fc, ptr + 0x1C, key, $"Knuckles\\LeftHand.sa2mdl"); } if (data.LHandPart != null) { data.LHandAnims = GetMotion(fc, ptr + 0x20, key, $"Knuckles\\LeftHand.saanim", motions, modelfiles[data.LHandPart].Model.CountAnimated()); if (data.LHandAnims != null) { modelfiles[data.LHandPart].Motions.Add($"LeftHand.saanim"); } data.LHandShapeMotions = GetMotion(fc, ptr + 0x24, key, $"Knuckles\\LeftHandShape.saanim", motions, modelfiles[data.LHandPart].Model.CountMorph()); if (data.LHandShapeMotions != null) { modelfiles[data.LHandPart].Motions.Add($"LeftHandShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x28, key); if (ptr2 != 0) { data.RHandPart = GetModel(fc, ptr + 0x28, key, $"Knuckles\\RightHand.sa2mdl"); } if (data.RHandPart != null) { data.RHandAnims = GetMotion(fc, ptr + 0x2C, key, $"Knuckles\\RightHand.saanim", motions, modelfiles[data.RHandPart].Model.CountAnimated()); if (data.RHandAnims != null) { modelfiles[data.RHandPart].Motions.Add($"RightHand.saanim"); } data.RHandShapeMotions = GetMotion(fc, ptr + 0x30, key, $"Knuckles\\RightHandShape.saanim", motions, modelfiles[data.RHandPart].Model.CountMorph()); if (data.RHandShapeMotions != null) { modelfiles[data.RHandPart].Motions.Add($"RightHandShape.saanim"); } } ini.Knuckles.Add(data); } ptr = fc.GetPointer(0x1C, key); if (ptr != 0) { Console.WriteLine("Rouge is in this Mini-Event"); Directory.CreateDirectory(Path.Combine(path, "Rouge")); MiniEventChars data = new MiniEventChars(); data.BodyAnims = GetMotion(fc, ptr, key, $"Rouge\\Body.saanim", motions, 62); int ptr2 = fc.GetPointer(ptr + 4, key); if (ptr2 != 0) { data.HeadPart = GetModel(fc, ptr + 4, key, $"Rouge\\Head.sa2mdl"); } if (data.HeadPart != null) { data.HeadAnims = GetMotion(fc, ptr + 8, key, $"Rouge\\Head.saanim", motions, modelfiles[data.HeadPart].Model.CountAnimated()); if (data.HeadAnims != null) { modelfiles[data.HeadPart].Motions.Add($"Head.saanim"); } data.HeadShapeMotions = GetMotion(fc, ptr + 0xC, key, $"Rouge\\HeadShape.saanim", motions, modelfiles[data.HeadPart].Model.CountMorph()); if (data.HeadShapeMotions != null) { modelfiles[data.HeadPart].Motions.Add($"HeadShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x10, key); if (ptr2 != 0) { data.MouthPart = GetModel(fc, ptr + 0x10, key, $"Rouge\\Mouth.sa2mdl"); } if (data.MouthPart != null) { data.MouthAnims = GetMotion(fc, ptr + 0x14, key, $"Rouge\\Mouth.saanim", motions, modelfiles[data.MouthPart].Model.CountAnimated()); if (data.MouthAnims != null) { modelfiles[data.MouthPart].Motions.Add($"Mouth.saanim"); } data.MouthShapeMotions = GetMotion(fc, ptr + 0x18, key, $"Rouge\\MouthShape.saanim", motions, modelfiles[data.MouthPart].Model.CountMorph()); if (data.MouthShapeMotions != null) { modelfiles[data.MouthPart].Motions.Add($"MouthShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x1C, key); if (ptr2 != 0) { data.LHandPart = GetModel(fc, ptr + 0x1C, key, $"Rouge\\LeftHand.sa2mdl"); } if (data.LHandPart != null) { data.LHandAnims = GetMotion(fc, ptr + 0x20, key, $"Rouge\\LeftHand.saanim", motions, modelfiles[data.LHandPart].Model.CountAnimated()); if (data.LHandAnims != null) { modelfiles[data.LHandPart].Motions.Add($"LeftHand.saanim"); } data.LHandShapeMotions = GetMotion(fc, ptr + 0x24, key, $"Rouge\\LeftHandShape.saanim", motions, modelfiles[data.LHandPart].Model.CountMorph()); if (data.LHandShapeMotions != null) { modelfiles[data.LHandPart].Motions.Add($"LeftHandShape.saanim"); } } ptr2 = fc.GetPointer(ptr + 0x28, key); if (ptr2 != 0) { data.RHandPart = GetModel(fc, ptr + 0x28, key, $"Rouge\\RightHand.sa2mdl"); } if (data.RHandPart != null) { data.RHandAnims = GetMotion(fc, ptr + 0x2C, key, $"Rouge\\RightHand.saanim", motions, modelfiles[data.RHandPart].Model.CountAnimated()); if (data.RHandAnims != null) { modelfiles[data.RHandPart].Motions.Add($"RightHand.saanim"); } data.RHandShapeMotions = GetMotion(fc, ptr + 0x30, key, $"Rouge\\RightHandShape.saanim", motions, modelfiles[data.RHandPart].Model.CountMorph()); if (data.RHandShapeMotions != null) { modelfiles[data.RHandPart].Motions.Add($"RightHandShape.saanim"); } } ini.Rouge.Add(data); } ptr = fc.GetPointer(0x24, key); if (ptr != 0) { Console.WriteLine("Mech Eggman is in this Mini-Event"); Directory.CreateDirectory(Path.Combine(path, "Mech Eggman")); ini.MechEggmanBodyAnims = GetMotion(fc, ptr, key, $"Mech Eggman\\Body.saanim", motions, 33); } ptr = fc.GetPointer(4, key); if (ptr != 0) { ini.Camera = GetMotion(fc, ptr + 0x10, key, $"Camera.saanim", motions, 1); ini.CamFrames = ByteConverter.ToInt32(fc, ptr + 4); } else { Console.WriteLine("Mini-Event does not contain a camera."); } foreach (var item in motionfiles.Values) { string fn = item.Filename; string fp = Path.Combine(path, fn); item.Motion.Save(fp); ini.Files.Add(fn, HelperFunctions.FileHash(fp)); } foreach (var item in modelfiles.Values) { string fp = Path.Combine(path, item.Filename); ModelFile.CreateFile(fp, item.Model, item.Motions.ToArray(), null, null, null, item.Format); ini.Files.Add(item.Filename, HelperFunctions.FileHash(fp)); } JsonSerializer js = new JsonSerializer { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore }; using (var tw = File.CreateText(Path.Combine(path, Path.ChangeExtension(Path.GetFileName(filename), ".json")))) js.Serialize(tw, ini); }
static void Main(string[] args) { string filename_src; string filename_dst; if (args.Length == 1) { string[] filenames = File.ReadAllLines(args[0]); for (int f = 0; f < filenames.Length; f++) { Console.WriteLine("Sorting file {0}", filenames[f]); ModelFile model = new ModelFile(filenames[f]); SortModel(model.Model, true); model.SaveToFile(filenames[f]); } return; } string filename_out = "Result.ini"; if (args.Length > 1) { filename_src = Path.GetFullPath(args[0]); filename_dst = Path.GetFullPath(args[1]); Console.WriteLine("Source file: {0}", filename_src); Console.WriteLine("Destination file: {0}", filename_dst); for (int a = 0; a < args.Length; a++) { if (args[a] == "-s") { savediff = true; } if (args[a] == "-a") { overwrite = false; } if (args[a] == "-o") { filename_out = Path.GetFullPath(args[a + 1]); } } if (savediff) { Console.Write("Output file: {0}, ", filename_out); Console.Write("mode: " + (overwrite ? "Overwrite" : "Append") + "\n"); } } else { Console.WriteLine("This tool compares two levels or models and outputs a list of differences between them.\n"); Console.WriteLine("Usage:"); Console.WriteLine("CompareTool <file1> <file2> [-s] [-a] [-o outputfile]\n"); Console.WriteLine("Arguments:"); Console.WriteLine("file1: Source level or model"); Console.WriteLine("file2: Destination level or model"); //Console.WriteLine("-s: Save the list of differences to an INI file"); Console.WriteLine("-a: Append to the list of differences instead of overwriting it"); Console.WriteLine("-o: Output filename (default is Result.ini)\n"); Console.WriteLine("Example:"); Console.WriteLine("CompareTool Level_PC.sa1lvl Level_Gamecube.sa1lvl\n"); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } if (!File.Exists(filename_src) || !File.Exists(filename_dst)) { Console.WriteLine("File {0} or {1} doesn't exist.", filename_src, filename_dst); Console.ReadLine(); return; } string ext = Path.GetExtension(filename_src).ToLowerInvariant(); //biglist = new Dictionary<int, List<DiffData>>(); switch (ext) { case ".sa1lvl": LandTable land_src = LandTable.LoadFromFile(filename_src); LandTable land_dst = LandTable.LoadFromFile(filename_dst); COL[] arr_src = land_src.COL.ToArray(); COL[] arr_dst = land_dst.COL.ToArray(); bool same = true; for (int co = 0; co < arr_src.Length; co++) { if (same && !CompareCOL(arr_src[co], arr_dst[co])) { Console.WriteLine("COL order different at item {0} ({1} / {2} / {3})! Trying manual match.", co, arr_src[co].Bounds.Center.X, arr_src[co].Bounds.Center.Y, arr_src[co].Bounds.Center.Z); same = false; } } //Compare using identical order if (same) { for (int c = 0; c < arr_src.Length; c++) { if (arr_src[c].Model.Attach != null) { CompareAttach((BasicAttach)arr_src[c].Model.Attach, (BasicAttach)arr_dst[c].Model.Attach); } } } //Compare using different order else { if (arr_dst.Length != arr_src.Length) { Console.WriteLine("COL count different: {0} vs {1}", arr_src.Length, arr_dst.Length); } Dictionary <int, int> matches = new Dictionary <int, int>(); for (int c1 = 0; c1 < arr_dst.Length; c1++) { bool found = false; for (int c2 = 0; c2 < arr_dst.Length; c2++) { if (arr_src[c1].Model.Attach != null && CompareCOL(arr_src[c1], arr_dst[c2], 0)) { if (!matches.ContainsKey(c2) && !matches.ContainsValue(c1)) { matches.Add(c2, c1); found = true; Console.WriteLine("COL item {0} matched with {1}", c1, c2); CompareAttach((BasicAttach)arr_src[c1].Model.Attach, (BasicAttach)arr_dst[c2].Model.Attach); } } } //Try again but less strict if (!found) { for (int c2 = 0; c2 < arr_dst.Length; c2++) { if (arr_src[c1].Model.Attach != null && CompareCOL(arr_src[c1], arr_dst[c2], 1)) { if (!matches.ContainsKey(c2) && !matches.ContainsValue(c1)) { matches.Add(c2, c1); Console.WriteLine("COL item {0} partially matched with {1}", c1, c2); CompareAttach((BasicAttach)arr_src[c1].Model.Attach, (BasicAttach)arr_dst[c2].Model.Attach); } } } } } Console.WriteLine("Total COL items in landtables: {0} vs {1}, matches: {2}", arr_src.Length, arr_dst.Length, matches.Count); } //if (savediff) SerializeDiffList(filename_out); break; case ".sa1mdl": NJS_OBJECT mdl_src = new ModelFile(filename_src).Model; NJS_OBJECT mdl_dst = new ModelFile(filename_dst).Model; if (mdl_src.Attach != null) { CompareAttach((BasicAttach)mdl_src.Attach, (BasicAttach)mdl_dst.Attach); } if (mdl_src.Children.Count > 0) { for (int id = 0; id < mdl_src.Children.Count; id++) { if (mdl_src.Children[id].Attach != null) { CompareAttach((BasicAttach)mdl_src.Children[id].Attach, (BasicAttach)mdl_dst.Children[id].Attach); } } } if (mdl_src.Sibling != null && mdl_src.Sibling.Attach != null) { CompareAttach((BasicAttach)mdl_src.Sibling.Attach, (BasicAttach)mdl_dst.Sibling.Attach); } //if (savediff) SerializeDiffList(filename_out); break; default: break; } if (savediff) { Console.WriteLine("Total UV array differences: {0}", uvcount); } }
public static void ExportCPP(DllIniData IniData, Dictionary <string, bool> itemsToExport, string fileName) { using (TextWriter writer = File.CreateText(fileName)) { bool SA2 = IniData.Game == SA_Tools.SplitDLL.Game.SA2B; ModelFormat modelfmt = SA2 ? ModelFormat.Chunk : ModelFormat.BasicDX; LandTableFormat landfmt = SA2 ? LandTableFormat.SA2 : LandTableFormat.SADX; writer.WriteLine("// Generated by SA Tools DLL Mod Generator"); writer.WriteLine(); if (SA2) { writer.WriteLine("#include \"SA2ModLoader.h\""); } else { writer.WriteLine("#include \"SADXModLoader.h\""); } writer.WriteLine(); List <string> labels = new List <string>(); Dictionary <string, uint> texlists = new Dictionary <string, uint>(); foreach (KeyValuePair <string, FileTypeHash> item in IniData.Files.Where(i => itemsToExport[i.Key])) { switch (item.Value.Type) { case "landtable": LandTable tbl = LandTable.LoadFromFile(item.Key); texlists.Add(tbl.Name, tbl.TextureList); tbl.ToStructVariables(writer, landfmt, new List <string>()); labels.AddRange(tbl.GetLabels()); break; case "model": NJS_OBJECT mdl = new ModelFile(item.Key).Model; mdl.ToStructVariables(writer, modelfmt == ModelFormat.BasicDX, new List <string>()); labels.AddRange(mdl.GetLabels()); break; case "basicmodel": case "chunkmodel": mdl = new ModelFile(item.Key).Model; mdl.ToStructVariables(writer, false, new List <string>()); labels.AddRange(mdl.GetLabels()); break; case "basicdxmodel": mdl = new ModelFile(item.Key).Model; mdl.ToStructVariables(writer, true, new List <string>()); labels.AddRange(mdl.GetLabels()); break; case "animation": NJS_MOTION ani = NJS_MOTION.Load(item.Key); ani.ToStructVariables(writer); labels.Add(ani.Name); break; } writer.WriteLine(); } foreach (var item in IniData.DataItems.Where(i => itemsToExport[i.Filename])) { switch (item.Type) { case "animindexlist": { SortedDictionary <short, NJS_MOTION> anims = new SortedDictionary <short, NJS_MOTION>(); foreach (string file in Directory.GetFiles(item.Filename, "*.saanim")) { if (short.TryParse(Path.GetFileNameWithoutExtension(file), NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out short i)) { anims.Add(i, NJS_MOTION.Load(file)); } } foreach (KeyValuePair <short, NJS_MOTION> obj in anims) { obj.Value.ToStructVariables(writer); writer.WriteLine(); } writer.WriteLine("AnimationIndex {0}[] = {{", item.Export); List <string> objs = new List <string>(anims.Count); foreach (KeyValuePair <short, NJS_MOTION> obj in anims) { objs.Add($"{{ {obj.Key}, {obj.Value.ModelParts}, &{obj.Value.Name} }}"); } objs.Add("{ -1 }"); writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "charaobjectdatalist": { foreach (string file in Directory.GetFiles(item.Filename, "*.sa2mdl")) { new ModelFile(file).Model.ToStructVariables(writer, false, new List <string>()); writer.WriteLine(); } foreach (string file in Directory.GetFiles(item.Filename, "*.saanim")) { NJS_MOTION.Load(file).ToStructVariables(writer); writer.WriteLine(); } var data = IniSerializer.Deserialize <CharaObjectData[]>(Path.Combine(item.Filename, "info.ini")); writer.WriteLine("CharaObjectData {0}[] = {{", item.Export); List <string> objs = new List <string>(data.Length); foreach (var obj in data) { objs.Add(obj.ToStruct()); } writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "kartspecialinfolist": { foreach (string file in Directory.GetFiles(item.Filename, "*.sa2mdl")) { new ModelFile(file).Model.ToStructVariables(writer, false, new List <string>()); writer.WriteLine(); } var data = IniSerializer.Deserialize <KartSpecialInfo[]>(Path.Combine(item.Filename, "info.ini")); writer.WriteLine("KartSpecialInfo {0}[] = {{", item.Export); List <string> objs = new List <string>(data.Length); for (int i = 0; i < data.Length; i++) { KartSpecialInfo obj = data[i]; objs.Add(obj.ToStruct()); texlists.Add($"{item.Export}[{i}]", obj.TexList); } writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; case "chaomotiontable": { foreach (string file in Directory.GetFiles(item.Filename, "*.saanim")) { NJS_MOTION.Load(file).ToStructVariables(writer); writer.WriteLine(); } var data = IniSerializer.Deserialize <ChaoMotionTableEntry[]>(Path.Combine(item.Filename, "info.ini")); writer.WriteLine("ChaoMotionTableEntry {0}[] = {{", item.Export); List <string> objs = new List <string>(data.Length); foreach (var obj in data) { objs.Add(obj.ToStruct()); } writer.WriteLine("\t" + string.Join("," + Environment.NewLine + "\t", objs.ToArray())); writer.WriteLine("};"); } break; } } writer.WriteLine("extern \"C\" __declspec(dllexport) void __cdecl Init(const char *path, const HelperFunctions &helperFunctions)"); writer.WriteLine("{"); writer.WriteLine("\tHMODULE handle = GetModuleHandle(L\"{0}\");", IniData.Name); List <string> exports = new List <string>(IniData.Items.Where(item => labels.Contains(item.Label)).Select(item => item.Export).Distinct()); foreach (KeyValuePair <string, string> item in IniData.Exports.Where(item => exports.Contains(item.Key))) { writer.WriteLine("\t{0}{1} = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Value], item.Key); } foreach (DllItemInfo item in IniData.Items.Where(item => labels.Contains(item.Label))) { if (typemap[IniData.Exports[item.Export]].EndsWith("**")) { writer.WriteLine("\t{0} = &{1};", item.ToString(), item.Label); } else { writer.WriteLine("\t*{0} = {1};", item.ToString(), item.Label); } } foreach (var item in IniData.DataItems.Where(item => itemsToExport[item.Filename])) { switch (item.Type) { case "animindexlist": case "charaobjectdatalist": case "kartspecialinfolist": writer.WriteLine("\tHookExport(handle, \"{0}\", {0});", item.Export); break; default: writer.WriteLine("\t{0}{1}_exp = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Type], item.Export); writer.WriteLine("\t*{0}_exp = {0};", item.Export); break; } } if (texlists.Count > 0 && IniData.TexLists != null && IniData.TexLists.Items != null) { exports = new List <string>(IniData.TexLists.Where(item => texlists.Values.Contains(item.Key)).Select(item => item.Value.Export).Distinct()); foreach (KeyValuePair <string, string> item in IniData.Exports.Where(item => exports.Contains(item.Key))) { writer.WriteLine("\t{0}{1} = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Value], item.Key); } foreach (KeyValuePair <string, uint> item in texlists.Where(item => IniData.TexLists.ContainsKey(item.Value))) { DllTexListInfo tex = IniData.TexLists[item.Value]; string str; if (tex.Index.HasValue) { str = $"{tex.Export}[{tex.Index.Value}]"; } else { str = tex.Export; } writer.WriteLine("\t{0}.TexList = {1};", item.Key, str); } } writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine("extern \"C\" __declspec(dllexport) const ModInfo {0}ModInfo = {{ ModLoaderVer }};", SA2 ? "SA2" : "SADX"); } }
public static int SplitFile(string datafilename, string inifilename, string projectFolderName) { try { byte[] datafile = File.ReadAllBytes(datafilename); IniData inifile = IniSerializer.Deserialize <IniData>(inifilename); if (inifile.MD5 != null && inifile.MD5.Count > 0) { string datahash = HelperFunctions.FileHash(datafile); if (!inifile.MD5.Any(h => h.Equals(datahash, StringComparison.OrdinalIgnoreCase))) { Console.WriteLine("The file {0} is not valid for use with the INI {1}.", datafilename, inifilename); return((int)SplitERRORVALUE.InvalidDataMapping); } } ByteConverter.BigEndian = SonicRetro.SAModel.ByteConverter.BigEndian = inifile.BigEndian; Environment.CurrentDirectory = Path.Combine(Environment.CurrentDirectory, Path.GetDirectoryName(datafilename)); if (inifile.Compressed) { datafile = FraGag.Compression.Prs.Decompress(datafile); } uint imageBase = HelperFunctions.SetupEXE(ref datafile) ?? inifile.ImageBase.Value; if (Path.GetExtension(datafilename).Equals(".rel", StringComparison.OrdinalIgnoreCase)) { HelperFunctions.FixRELPointers(datafile); } bool SA2 = inifile.Game == Game.SA2 | inifile.Game == Game.SA2B; ModelFormat modelfmt = 0; LandTableFormat landfmt = 0; switch (inifile.Game) { case Game.SA1: modelfmt = ModelFormat.Basic; landfmt = LandTableFormat.SA1; break; case Game.SADX: modelfmt = ModelFormat.BasicDX; landfmt = LandTableFormat.SADX; break; case Game.SA2: case Game.SA2B: modelfmt = ModelFormat.Chunk; landfmt = LandTableFormat.SA2; break; } int itemcount = 0; Dictionary <string, MasterObjectListEntry> masterobjlist = new Dictionary <string, MasterObjectListEntry>(); Dictionary <string, Dictionary <string, int> > objnamecounts = new Dictionary <string, Dictionary <string, int> >(); Stopwatch timer = new Stopwatch(); timer.Start(); foreach (KeyValuePair <string, SA_Tools.FileInfo> item in inifile.Files) { if (string.IsNullOrEmpty(item.Key)) { continue; } string filedesc = item.Key; SA_Tools.FileInfo data = item.Value; Dictionary <string, string> customProperties = data.CustomProperties; string type = data.Type; int address = data.Address; bool nohash = false; string fileOutputPath = string.Concat(projectFolderName, data.Filename); Console.WriteLine(item.Key + ": " + data.Address.ToString("X") + " → " + fileOutputPath); Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath)); switch (type) { case "landtable": new LandTable(datafile, address, imageBase, landfmt) { Description = item.Key }.SaveToFile(fileOutputPath, landfmt); break; case "model": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, modelfmt, new Dictionary <int, Attach>()); string[] mdlanis = new string[0]; if (customProperties.ContainsKey("animations")) { mdlanis = customProperties["animations"].Split(','); } string[] mdlmorphs = new string[0]; if (customProperties.ContainsKey("morphs")) { mdlmorphs = customProperties["morphs"].Split(','); } ModelFile.CreateFile(fileOutputPath, mdl, mdlanis, null, item.Key, null, modelfmt); } break; case "basicmodel": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Basic, new Dictionary <int, Attach>()); string[] mdlanis = new string[0]; if (customProperties.ContainsKey("animations")) { mdlanis = customProperties["animations"].Split(','); } string[] mdlmorphs = new string[0]; if (customProperties.ContainsKey("morphs")) { mdlmorphs = customProperties["morphs"].Split(','); } ModelFile.CreateFile(fileOutputPath, mdl, mdlanis, null, item.Key, null, ModelFormat.Basic); } break; case "basicdxmodel": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.BasicDX, new Dictionary <int, Attach>()); string[] mdlanis = new string[0]; if (customProperties.ContainsKey("animations")) { mdlanis = customProperties["animations"].Split(','); } string[] mdlmorphs = new string[0]; if (customProperties.ContainsKey("morphs")) { mdlmorphs = customProperties["morphs"].Split(','); } ModelFile.CreateFile(fileOutputPath, mdl, mdlanis, null, item.Key, null, ModelFormat.BasicDX); } break; case "chunkmodel": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>()); string[] mdlanis = new string[0]; if (customProperties.ContainsKey("animations")) { mdlanis = customProperties["animations"].Split(','); } string[] mdlmorphs = new string[0]; if (customProperties.ContainsKey("morphs")) { mdlmorphs = customProperties["morphs"].Split(','); } ModelFile.CreateFile(fileOutputPath, mdl, mdlanis, null, item.Key, null, ModelFormat.Chunk); } break; case "gcmodel": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.GC, new Dictionary <int, Attach>()); string[] mdlanis = new string[0]; if (customProperties.ContainsKey("animations")) { mdlanis = customProperties["animations"].Split(','); } string[] mdlmorphs = new string[0]; if (customProperties.ContainsKey("morphs")) { mdlmorphs = customProperties["morphs"].Split(','); } ModelFile.CreateFile(fileOutputPath, mdl, mdlanis, null, item.Key, null, ModelFormat.GC); } break; case "action": { NJS_ACTION ani = new NJS_ACTION(datafile, address, imageBase, modelfmt, new Dictionary <int, Attach>()); ani.Animation.Name = filedesc; ani.Animation.Save(fileOutputPath); } break; case "animation": new NJS_MOTION(datafile, address, imageBase, int.Parse(customProperties["numparts"], NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite, NumberFormatInfo.InvariantInfo)) { Name = filedesc } .Save(fileOutputPath); break; case "objlist": { ObjectListEntry[] objs = ObjectList.Load(datafile, address, imageBase, SA2); if (inifile.MasterObjectList != null) { foreach (ObjectListEntry obj in objs) { if (!masterobjlist.ContainsKey(obj.CodeString)) { masterobjlist.Add(obj.CodeString, new MasterObjectListEntry(obj)); } if (!objnamecounts.ContainsKey(obj.CodeString)) { objnamecounts.Add(obj.CodeString, new Dictionary <string, int>() { { obj.Name, 1 } }); } else if (!objnamecounts[obj.CodeString].ContainsKey(obj.Name)) { objnamecounts[obj.CodeString].Add(obj.Name, 1); } else { objnamecounts[obj.CodeString][obj.Name]++; } } } objs.Save(fileOutputPath); } break; case "startpos": if (SA2) { SA2StartPosList.Load(datafile, address).Save(fileOutputPath); } else { SA1StartPosList.Load(datafile, address).Save(fileOutputPath); } break; case "texlist": TextureList.Load(datafile, address, imageBase).Save(fileOutputPath); break; case "leveltexlist": new LevelTextureList(datafile, address, imageBase).Save(fileOutputPath); break; case "triallevellist": TrialLevelList.Save(TrialLevelList.Load(datafile, address, imageBase), fileOutputPath); break; case "bosslevellist": BossLevelList.Save(BossLevelList.Load(datafile, address), fileOutputPath); break; case "fieldstartpos": FieldStartPosList.Load(datafile, address).Save(fileOutputPath); break; case "soundtestlist": SoundTestList.Load(datafile, address, imageBase).Save(fileOutputPath); break; case "musiclist": { int muscnt = int.Parse(customProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo); MusicList.Load(datafile, address, imageBase, muscnt).Save(fileOutputPath); } break; case "soundlist": SoundList.Load(datafile, address, imageBase).Save(fileOutputPath); break; case "stringarray": { int cnt = int.Parse(customProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo); Languages lang = Languages.Japanese; if (data.CustomProperties.ContainsKey("language")) { lang = (Languages)Enum.Parse(typeof(Languages), data.CustomProperties["language"], true); } StringArray.Load(datafile, address, imageBase, cnt, lang).Save(fileOutputPath); } break; case "nextlevellist": NextLevelList.Load(datafile, address).Save(fileOutputPath); break; case "cutscenetext": { int cnt = int.Parse(customProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo); new CutsceneText(datafile, address, imageBase, cnt).Save(fileOutputPath, out string[] hashes); data.MD5Hash = string.Join(",", hashes); nohash = true; } break; case "recapscreen": { int cnt = int.Parse(customProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo); RecapScreenList.Load(datafile, address, imageBase, cnt).Save(fileOutputPath, out string[][] hashes); string[] hash2 = new string[hashes.Length]; for (int i = 0; i < hashes.Length; i++) { hash2[i] = string.Join(",", hashes[i]); } data.MD5Hash = string.Join(":", hash2); nohash = true; } break; case "npctext": { int cnt = int.Parse(customProperties["length"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo); NPCTextList.Load(datafile, address, imageBase, cnt).Save(fileOutputPath, out string[][] hashes); string[] hash2 = new string[hashes.Length]; for (int i = 0; i < hashes.Length; i++) { hash2[i] = string.Join(",", hashes[i]); } data.MD5Hash = string.Join(":", hash2); nohash = true; } break; case "levelclearflags": LevelClearFlagList.Save(LevelClearFlagList.Load(datafile, address), fileOutputPath); break; case "deathzone": { List <DeathZoneFlags> flags = new List <DeathZoneFlags>(); string path = Path.GetDirectoryName(fileOutputPath); List <string> hashes = new List <string>(); int num = 0; while (ByteConverter.ToUInt32(datafile, address + 4) != 0) { flags.Add(new DeathZoneFlags(datafile, address)); string file = Path.Combine(path, num++.ToString(NumberFormatInfo.InvariantInfo) + (modelfmt == ModelFormat.Chunk ? ".sa2mdl" : ".sa1mdl")); ModelFile.CreateFile(file, new NJS_OBJECT(datafile, datafile.GetPointer(address + 4, imageBase), imageBase, modelfmt, new Dictionary <int, Attach>()), null, null, null, null, modelfmt); hashes.Add(HelperFunctions.FileHash(file)); address += 8; } flags.ToArray().Save(fileOutputPath); hashes.Insert(0, HelperFunctions.FileHash(fileOutputPath)); data.MD5Hash = string.Join(",", hashes.ToArray()); nohash = true; } break; case "skyboxscale": { int cnt = int.Parse(customProperties["count"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo); SkyboxScaleList.Load(datafile, address, imageBase, cnt).Save(fileOutputPath); } break; case "stageselectlist": { int cnt = int.Parse(customProperties["count"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo); StageSelectLevelList.Load(datafile, address, cnt).Save(fileOutputPath); } break; case "levelrankscores": LevelRankScoresList.Load(datafile, address).Save(fileOutputPath); break; case "levelranktimes": LevelRankTimesList.Load(datafile, address).Save(fileOutputPath); break; case "endpos": SA2EndPosList.Load(datafile, address).Save(fileOutputPath); break; case "animationlist": { int cnt = int.Parse(customProperties["count"], NumberStyles.Integer, NumberFormatInfo.InvariantInfo); SA2AnimationInfoList.Load(datafile, address, cnt).Save(fileOutputPath); } break; case "levelpathlist": { List <string> hashes = new List <string>(); ushort lvlnum = (ushort)ByteConverter.ToUInt32(datafile, address); while (lvlnum != 0xFFFF) { int ptr = ByteConverter.ToInt32(datafile, address + 4); if (ptr != 0) { ptr = (int)((uint)ptr - imageBase); SA1LevelAct level = new SA1LevelAct(lvlnum); string lvldir = Path.Combine(fileOutputPath, level.ToString()); PathList.Load(datafile, ptr, imageBase).Save(lvldir, out string[] lvlhashes); hashes.Add(level.ToString() + ":" + string.Join(",", lvlhashes)); } address += 8; lvlnum = (ushort)ByteConverter.ToUInt32(datafile, address); } data.MD5Hash = string.Join("|", hashes.ToArray()); nohash = true; } break; case "pathlist": { PathList.Load(datafile, address, imageBase).Save(fileOutputPath, out string[] hashes); data.MD5Hash = string.Join(",", hashes.ToArray()); nohash = true; } break; case "stagelightdatalist": SA1StageLightDataList.Load(datafile, address).Save(fileOutputPath); break; case "weldlist": WeldList.Load(datafile, address, imageBase).Save(fileOutputPath); break; case "bmitemattrlist": BlackMarketItemAttributesList.Load(datafile, address, imageBase).Save(fileOutputPath); break; case "creditstextlist": CreditsTextList.Load(datafile, address, imageBase).Save(fileOutputPath); break; case "animindexlist": { Directory.CreateDirectory(fileOutputPath); List <string> hashes = new List <string>(); int i = ByteConverter.ToInt16(datafile, address); while (i != -1) { new NJS_MOTION(datafile, datafile.GetPointer(address + 4, imageBase), imageBase, ByteConverter.ToInt16(datafile, address + 2)) .Save(fileOutputPath + "/" + i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim"); hashes.Add(i.ToString(NumberFormatInfo.InvariantInfo) + ":" + HelperFunctions.FileHash(fileOutputPath + "/" + i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim")); address += 8; i = ByteConverter.ToInt16(datafile, address); } data.MD5Hash = string.Join("|", hashes.ToArray()); nohash = true; } break; case "storysequence": SA2StoryList.Load(datafile, address).Save(fileOutputPath); break; default: // raw binary { byte[] bin = new byte[int.Parse(customProperties["size"], NumberStyles.HexNumber)]; Array.Copy(datafile, address, bin, 0, bin.Length); File.WriteAllBytes(fileOutputPath, bin); } break; } if (!nohash) { data.MD5Hash = HelperFunctions.FileHash(fileOutputPath); } itemcount++; } if (inifile.MasterObjectList != null) { foreach (KeyValuePair <string, MasterObjectListEntry> obj in masterobjlist) { KeyValuePair <string, int> name = new KeyValuePair <string, int>(); foreach (KeyValuePair <string, int> it in objnamecounts[obj.Key]) { if (it.Value > name.Value) { name = it; } } obj.Value.Name = name.Key; obj.Value.Names = objnamecounts[obj.Key].Select((it) => it.Key).ToArray(); } string masterObjectListOutputPath = string.Concat(projectFolderName, inifile.MasterObjectList); IniSerializer.Serialize(masterobjlist, masterObjectListOutputPath); } IniSerializer.Serialize(inifile, Path.Combine(projectFolderName, Path.GetFileNameWithoutExtension(datafilename) + "_data.ini")); timer.Stop(); Console.WriteLine("Split " + itemcount + " items in " + timer.Elapsed.TotalSeconds + " seconds."); Console.WriteLine(); } catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); Console.WriteLine("Press any key to exit."); Console.ReadLine(); return((int)SplitERRORVALUE.UnhandledException); } return((int)SplitERRORVALUE.Success); }
public ContentModel(Engine engine, ModelVariantIdentifier variant, ModelFile file, ModelQuality quality) : this(engine, variant, file.GetModelDefinition(), quality) { }
static void Main(string[] args) { Queue <string> argq = new Queue <string>(args); string mdlfilename; if (argq.Count > 0) { mdlfilename = argq.Dequeue(); Console.WriteLine("New Model File: {0}", mdlfilename); } else { Console.Write("New Model File: "); mdlfilename = Console.ReadLine().Trim('"'); } ModelFile model = new ModelFile(mdlfilename); NJS_OBJECT[] objects = model.Model.GetObjects(); string repmdlfilename; if (argq.Count > 0) { repmdlfilename = argq.Dequeue(); Console.WriteLine("Old Model File: {0}", repmdlfilename); } else { Console.Write("Old Model File: "); repmdlfilename = Console.ReadLine().Trim('"'); } ModelFile repmodel = new ModelFile(repmdlfilename); NJS_OBJECT[] repobjects = repmodel.Model.GetObjects(); if (model.Format != repmodel.Format) { Console.WriteLine("Format mismatch between files! Most data will be unable to be relabeled."); } if (objects.Length != repobjects.Length) { Console.WriteLine("Models have different structures, the game may crash."); } for (int i = 0; i < Math.Min(objects.Length, repobjects.Length); i++) { objects[i].Name = repobjects[i].Name; if (objects[i].Attach != null && repobjects[i].Attach != null) { objects[i].Attach.Name = repobjects[i].Attach.Name; if (objects[i].Attach is BasicAttach && repobjects[i].Attach is BasicAttach) { BasicAttach attach = (BasicAttach)objects[i].Attach; BasicAttach repattach = (BasicAttach)repobjects[i].Attach; attach.VertexName = repattach.VertexName; if (repattach.NormalName != null) { attach.NormalName = repattach.NormalName; } if (repattach.MaterialName != null) { attach.MaterialName = repattach.MaterialName; } attach.MeshName = repattach.MeshName; for (int j = 0; j < Math.Min(attach.Mesh.Count, repattach.Mesh.Count); j++) { attach.Mesh[j].PolyName = repattach.Mesh[j].PolyName; if (repattach.Mesh[j].PolyNormalName != null) { attach.Mesh[j].PolyNormalName = repattach.Mesh[j].PolyNormalName; } if (repattach.Mesh[j].UVName != null) { attach.Mesh[j].UVName = repattach.Mesh[j].UVName; } if (repattach.Mesh[j].VColorName != null) { attach.Mesh[j].VColorName = repattach.Mesh[j].VColorName; } } } else if (objects[i].Attach is ChunkAttach && repobjects[i].Attach is ChunkAttach) { ChunkAttach attach = (ChunkAttach)objects[i].Attach; ChunkAttach repattach = (ChunkAttach)repobjects[i].Attach; if (repattach.VertexName != null) { attach.VertexName = repattach.VertexName; } if (repattach.PolyName != null) { attach.PolyName = repattach.PolyName; } } } } model.SaveToFile(repmdlfilename); }
public static int SplitDLLFile(string datafilename, string inifilename, string projectFolderName) { #if !DEBUG try #endif { byte[] datafile = File.ReadAllBytes(datafilename); IniData inifile = IniSerializer.Deserialize <IniData>(inifilename); uint imageBase = HelperFunctions.SetupEXE(ref datafile).Value; Dictionary <string, int> exports; { int ptr = BitConverter.ToInt32(datafile, BitConverter.ToInt32(datafile, 0x3c) + 4 + 20 + 96); GCHandle handle = GCHandle.Alloc(datafile, GCHandleType.Pinned); IMAGE_EXPORT_DIRECTORY dir = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure( Marshal.UnsafeAddrOfPinnedArrayElement(datafile, ptr), typeof(IMAGE_EXPORT_DIRECTORY)); handle.Free(); exports = new Dictionary <string, int>(dir.NumberOfFunctions); int nameaddr = dir.AddressOfNames; int ordaddr = dir.AddressOfNameOrdinals; for (int i = 0; i < dir.NumberOfNames; i++) { string name = datafile.GetCString(BitConverter.ToInt32(datafile, nameaddr), System.Text.Encoding.ASCII); int addr = BitConverter.ToInt32(datafile, dir.AddressOfFunctions + (BitConverter.ToInt16(datafile, ordaddr) * 4)); exports.Add(name, addr); nameaddr += 4; ordaddr += 2; } } ModelFormat modelfmt = 0; LandTableFormat landfmt = 0; string modelext = null; string landext = null; switch (inifile.Game) { case Game.SADX: modelfmt = ModelFormat.BasicDX; landfmt = LandTableFormat.SADX; modelext = ".sa1mdl"; landext = ".sa1lvl"; break; case Game.SA2B: modelfmt = ModelFormat.Chunk; landfmt = LandTableFormat.SA2; modelext = ".sa2mdl"; landext = ".sa2lvl"; break; } int itemcount = 0; List <string> labels = new List <string>(); ModelAnimationsDictionary models = new ModelAnimationsDictionary(); DllIniData output = new DllIniData() { Name = inifile.ModuleName, Game = inifile.Game }; Stopwatch timer = new Stopwatch(); timer.Start(); foreach (KeyValuePair <string, FileInfo> item in inifile.Files) { if (string.IsNullOrEmpty(item.Key)) { continue; } FileInfo data = item.Value; string type = data.Type; string name = item.Key; output.Exports[name] = type; int address = exports[name]; string fileOutputPath = ""; if (data.Filename != null) { fileOutputPath = string.Concat(projectFolderName, data.Filename); Console.WriteLine(name + " -> " + fileOutputPath); Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath)); } else { Console.WriteLine(name); } switch (type) { case "landtable": { LandTable land = new LandTable(datafile, address, imageBase, landfmt) { Description = name }; DllItemInfo info = new DllItemInfo() { Export = name, Label = land.Name }; output.Items.Add(info); if (!labels.Contains(land.Name)) { land.SaveToFile(fileOutputPath, landfmt); output.Files[data.Filename] = new FileTypeHash("landtable", HelperFunctions.FileHash(fileOutputPath)); labels.AddRange(land.GetLabels()); } } break; case "battlelandtable": { LandTable land = new LandTable(datafile, address, imageBase, LandTableFormat.SA2B) { Description = name }; DllItemInfo info = new DllItemInfo() { Export = name, Label = land.Name }; output.Items.Add(info); if (!labels.Contains(land.Name)) { land.SaveToFile(fileOutputPath, LandTableFormat.SA2B); output.Files[data.Filename] = new FileTypeHash("landtable", HelperFunctions.FileHash(fileOutputPath)); labels.AddRange(land.GetLabels()); } } break; case "landtablearray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; LandTable land = new LandTable(datafile, ptr, imageBase, landfmt) { Description = idx }; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = land.Name }; output.Items.Add(info); if (!labels.Contains(land.Name)) { string outputFN = Path.Combine(fileOutputPath, i.ToString(NumberFormatInfo.InvariantInfo) + landext); string fileName = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + landext); land.SaveToFile(outputFN, landfmt); output.Files[fileName] = new FileTypeHash("landtable", HelperFunctions.FileHash(outputFN)); labels.AddRange(land.GetLabels()); } } address += 4; } break; case "model": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, modelfmt, new Dictionary <int, Attach>()); DllItemInfo info = new DllItemInfo() { Export = name, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { models.Add(new ModelAnimations(data.Filename, name, mdl, modelfmt)); labels.AddRange(mdl.GetLabels()); } } break; case "morph": { BasicAttach dummy = new BasicAttach(datafile, address, imageBase, modelfmt == ModelFormat.BasicDX); NJS_OBJECT mdl = new NJS_OBJECT() { Attach = dummy }; DllItemInfo info = new DllItemInfo() { Export = name, Label = dummy.Name }; output.Items.Add(info); if (!labels.Contains(dummy.Name)) { models.Add(new ModelAnimations(data.Filename, name, mdl, modelfmt)); labels.AddRange(mdl.GetLabels()); } } break; case "modelarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); NJS_OBJECT mdl = new NJS_OBJECT(datafile, ptr, imageBase, modelfmt, new Dictionary <int, Attach>()); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + modelext); models.Add(new ModelAnimations(fn, idx, mdl, modelfmt)); labels.AddRange(mdl.GetLabels()); } } address += 4; } break; case "modelsarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); BasicAttach dummy = new BasicAttach(datafile, ptr, imageBase, modelfmt == ModelFormat.BasicDX); NJS_OBJECT mdl = new NJS_OBJECT() { Attach = dummy }; string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = dummy.Name }; output.Items.Add(info); if (!labels.Contains(dummy.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + modelext); models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.BasicDX)); labels.AddRange(mdl.GetLabels()); } } address += 4; } break; case "basicmodel": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Basic, new Dictionary <int, Attach>()); DllItemInfo info = new DllItemInfo() { Export = name, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.Basic)); labels.AddRange(mdl.GetLabels()); } } break; case "basicmodelarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); NJS_OBJECT mdl = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.Basic, new Dictionary <int, Attach>()); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa1mdl"); models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.Basic)); labels.AddRange(mdl.GetLabels()); } } address += 4; } break; case "basicdxmodel": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.BasicDX, new Dictionary <int, Attach>()); DllItemInfo info = new DllItemInfo() { Export = name, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.BasicDX)); labels.AddRange(mdl.GetLabels()); } } break; case "basicdxmodelarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); NJS_OBJECT mdl = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.BasicDX, new Dictionary <int, Attach>()); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa1mdl"); models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.BasicDX)); labels.AddRange(mdl.GetLabels()); } } address += 4; } break; case "chunkmodel": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>()); DllItemInfo info = new DllItemInfo() { Export = name, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.Chunk)); labels.AddRange(mdl.GetLabels()); } } break; case "chunkmodelarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); NJS_OBJECT mdl = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>()); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa2mdl"); models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.Chunk)); labels.AddRange(mdl.GetLabels()); } } address += 4; } break; case "actionarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); NJS_ACTION ani = new NJS_ACTION(datafile, ptr, imageBase, modelfmt, new Dictionary <int, Attach>()); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; ani.Animation.Name = item.Key + "_" + i; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = ani.Animation.Name, Field = "motion" }; output.Items.Add(info); info = new DllItemInfo() { Export = name, Index = i, Label = ani.Model.Name, Field = "object" }; output.Items.Add(info); string outputFN = Path.Combine(fileOutputPath, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim"); string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim"); ani.Animation.Save(outputFN); output.Files[fn] = new FileTypeHash("animation", HelperFunctions.FileHash(outputFN)); if (models.Contains(ani.Model.Name)) { ModelAnimations mdl = models[ani.Model.Name]; System.Text.StringBuilder sb = new System.Text.StringBuilder(260); PathRelativePathTo(sb, Path.GetFullPath(Path.Combine(projectFolderName, mdl.Filename)), 0, Path.GetFullPath(outputFN), 0); mdl.Animations.Add(sb.ToString()); // this is where the problem is } else { string mfn = Path.ChangeExtension(fn, modelext); string outputmfn = Path.Combine(projectFolderName, mfn); string animationName = Path.GetFileName(outputFN); ModelFile.CreateFile(outputmfn, ani.Model, new[] { animationName }, null, idx + "->object", null, modelfmt); output.Files[mfn] = new FileTypeHash("model", HelperFunctions.FileHash(outputmfn)); } } address += 4; } break; case "texlist": if (output.TexLists == null) { output.TexLists = new TexListContainer(); } output.TexLists.Add((uint)(address + imageBase), new DllTexListInfo(name, null)); break; case "texlistarray": if (output.TexLists == null) { output.TexLists = new TexListContainer(); } for (int i = 0; i < data.Length; i++) { uint ptr = BitConverter.ToUInt32(datafile, address); if (ptr != 0 && !output.TexLists.ContainsKey(ptr)) { output.TexLists.Add(ptr, new DllTexListInfo(name, i)); } address += 4; } break; case "animindexlist": { Directory.CreateDirectory(fileOutputPath); List <string> hashes = new List <string>(); int i = ByteConverter.ToInt16(datafile, address); while (i != -1) { new NJS_MOTION(datafile, datafile.GetPointer(address + 4, imageBase), imageBase, ByteConverter.ToInt16(datafile, address + 2)) .Save(fileOutputPath + "/" + i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim"); hashes.Add(i.ToString(NumberFormatInfo.InvariantInfo) + ":" + HelperFunctions.FileHash(fileOutputPath + "/" + i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim")); address += 8; i = ByteConverter.ToInt16(datafile, address); } output.DataItems.Add(new DllDataItemInfo() { Type = type, Export = name, Filename = data.Filename, MD5Hash = string.Join("|", hashes.ToArray()) }); } break; case "charaobjectdatalist": { Directory.CreateDirectory(fileOutputPath); List <CharaObjectData> result = new List <CharaObjectData>(); List <string> hashes = new List <string>(); for (int i = 0; i < data.Length; i++) { string chnm = charaobjectnames[i]; CharaObjectData chara = new CharaObjectData(); NJS_OBJECT model = new NJS_OBJECT(datafile, (int)(BitConverter.ToInt32(datafile, address) - imageBase), imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>()); chara.MainModel = model.Name; NJS_MOTION anim = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 4) - imageBase), imageBase, model.CountAnimated()); chara.Animation1 = anim.Name; anim.Save(Path.Combine(fileOutputPath, $"{chnm} Anim 1.saanim")); hashes.Add($"{chnm} Anim 1.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{chnm} Anim 1.saanim"))); anim = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 8) - imageBase), imageBase, model.CountAnimated()); chara.Animation2 = anim.Name; anim.Save(Path.Combine(fileOutputPath, $"{chnm} Anim 2.saanim")); hashes.Add($"{chnm} Anim 2.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{chnm} Anim 2.saanim"))); anim = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 12) - imageBase), imageBase, model.CountAnimated()); chara.Animation3 = anim.Name; anim.Save(Path.Combine(fileOutputPath, $"{chnm} Anim 3.saanim")); hashes.Add($"{chnm} Anim 3.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{chnm} Anim 3.saanim"))); ModelFile.CreateFile(Path.Combine(fileOutputPath, $"{chnm}.sa2mdl"), model, new[] { $"{chnm} Anim 1.saanim", $"{chnm} Anim 2.saanim", $"{chnm} Anim 3.saanim" }, null, null, null, ModelFormat.Chunk); hashes.Add($"{chnm}.sa2mdl:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{chnm}.sa2mdl"))); int ptr = BitConverter.ToInt32(datafile, address + 16); if (ptr != 0) { model = new NJS_OBJECT(datafile, (int)(ptr - imageBase), imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>()); chara.AccessoryModel = model.Name; chara.AccessoryAttachNode = "object_" + (BitConverter.ToInt32(datafile, address + 20) - imageBase).ToString("X8"); ModelFile.CreateFile(Path.Combine(fileOutputPath, $"{chnm} Accessory.sa2mdl"), model, null, null, null, null, ModelFormat.Chunk); hashes.Add($"{chnm} Accessory.sa2mdl:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{chnm} Accessory.sa2mdl"))); } ptr = BitConverter.ToInt32(datafile, address + 24); if (ptr != 0) { model = new NJS_OBJECT(datafile, (int)(ptr - imageBase), imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>()); chara.SuperModel = model.Name; anim = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 28) - imageBase), imageBase, model.CountAnimated()); chara.SuperAnimation1 = anim.Name; anim.Save(Path.Combine(fileOutputPath, $"Super {chnm} Anim 1.saanim")); hashes.Add($"Super {chnm} Anim 1.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"Super {chnm} Anim 1.saanim"))); anim = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 32) - imageBase), imageBase, model.CountAnimated()); chara.SuperAnimation2 = anim.Name; anim.Save(Path.Combine(fileOutputPath, $"Super {chnm} Anim 2.saanim")); hashes.Add($"Super {chnm} Anim 2.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"Super {chnm} Anim 2.saanim"))); anim = new NJS_MOTION(datafile, (int)(BitConverter.ToInt32(datafile, address + 36) - imageBase), imageBase, model.CountAnimated()); chara.SuperAnimation3 = anim.Name; anim.Save(Path.Combine(fileOutputPath, $"Super {chnm} Anim 3.saanim")); hashes.Add($"Super {chnm} Anim 3.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"Super {chnm} Anim 3.saanim"))); ModelFile.CreateFile(Path.Combine(fileOutputPath, $"Super {chnm}.sa2mdl"), model, new[] { $"Super {chnm} Anim 1.saanim", $"Super {chnm} Anim 2.saanim", $"Super {chnm} Anim 3.saanim" }, null, null, null, ModelFormat.Chunk); hashes.Add($"Super {chnm}.sa2mdl:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"Super {chnm}.sa2mdl"))); } chara.Unknown1 = BitConverter.ToInt32(datafile, address + 40); chara.Rating = BitConverter.ToInt32(datafile, address + 44); chara.DescriptionID = BitConverter.ToInt32(datafile, address + 48); chara.TextBackTexture = BitConverter.ToInt32(datafile, address + 52); chara.Unknown5 = BitConverter.ToSingle(datafile, address + 56); result.Add(chara); address += 60; } IniSerializer.Serialize(result, Path.Combine(fileOutputPath, "info.ini")); hashes.Add("info.ini:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, "info.ini"))); output.DataItems.Add(new DllDataItemInfo() { Type = type, Export = name, Filename = data.Filename, MD5Hash = string.Join("|", hashes.ToArray()) }); } break; case "kartspecialinfolist": { Directory.CreateDirectory(fileOutputPath); List <KartSpecialInfo> result = new List <KartSpecialInfo>(); List <string> hashes = new List <string>(); for (int i = 0; i < data.Length; i++) { KartSpecialInfo kart = new KartSpecialInfo { ID = ByteConverter.ToInt32(datafile, address) }; NJS_OBJECT model = new NJS_OBJECT(datafile, (int)(BitConverter.ToInt32(datafile, address + 4) - imageBase), imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>()); kart.Model = model.Name; ModelFile.CreateFile(Path.Combine(fileOutputPath, $"{i}.sa2mdl"), model, null, null, null, null, ModelFormat.Chunk); hashes.Add($"{i}.sa2mdl:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{i}.sa2mdl"))); int ptr = BitConverter.ToInt32(datafile, address + 8); if (ptr != 0) { model = new NJS_OBJECT(datafile, (int)(ptr - imageBase), imageBase, ModelFormat.Chunk, new Dictionary <int, Attach>()); kart.LowModel = model.Name; ModelFile.CreateFile(Path.Combine(fileOutputPath, $"{i} Low.sa2mdl"), model, null, null, null, null, ModelFormat.Chunk); hashes.Add($"{i} Low.sa2mdl:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{i} Low.sa2mdl"))); } kart.TexList = ByteConverter.ToUInt32(datafile, address + 12); kart.Unknown1 = ByteConverter.ToInt32(datafile, address + 16); kart.Unknown2 = ByteConverter.ToInt32(datafile, address + 20); kart.Unknown3 = ByteConverter.ToInt32(datafile, address + 24); result.Add(kart); address += 0x1C; } IniSerializer.Serialize(result, Path.Combine(fileOutputPath, "info.ini")); hashes.Add("info.ini:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, "info.ini"))); output.DataItems.Add(new DllDataItemInfo() { Type = type, Export = name, Filename = data.Filename, MD5Hash = string.Join("|", hashes.ToArray()) }); } break; case "chaomotiontable": { Directory.CreateDirectory(fileOutputPath); List <ChaoMotionTableEntry> result = new List <ChaoMotionTableEntry>(); List <string> hashes = new List <string>(); int nodeCount = int.Parse(data.CustomProperties["nodecount"]); Dictionary <int, string> mtns = new Dictionary <int, string>(); for (int i = 0; i < data.Length; i++) { ChaoMotionTableEntry cmte = new ChaoMotionTableEntry(); int mtnaddr = (int)(ByteConverter.ToInt32(datafile, address) - imageBase); if (!mtns.ContainsKey(mtnaddr)) { NJS_MOTION motion = new NJS_MOTION(datafile, mtnaddr, imageBase, nodeCount, shortrot: true); cmte.Motion = motion.Name; mtns.Add(mtnaddr, motion.Name); motion.Save(Path.Combine(fileOutputPath, $"{i}.saanim")); hashes.Add($"{i}.saanim:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, $"{i}.saanim"))); } else { cmte.Motion = mtns[mtnaddr]; } cmte.Flag1 = ByteConverter.ToUInt16(datafile, address + 4); cmte.Pose = ByteConverter.ToUInt16(datafile, address + 6); cmte.TransitionID = ByteConverter.ToInt32(datafile, address + 8); cmte.Flag2 = ByteConverter.ToUInt32(datafile, address + 12); cmte.StartFrame = ByteConverter.ToSingle(datafile, address + 16); cmte.EndFrame = ByteConverter.ToSingle(datafile, address + 20); cmte.PlaySpeed = ByteConverter.ToSingle(datafile, address + 24); result.Add(cmte); address += 0x1C; } IniSerializer.Serialize(result, Path.Combine(fileOutputPath, "info.ini")); hashes.Add("info.ini:" + HelperFunctions.FileHash(Path.Combine(fileOutputPath, "info.ini"))); output.DataItems.Add(new DllDataItemInfo() { Type = type, Export = name, Filename = data.Filename, MD5Hash = string.Join("|", hashes.ToArray()) }); } break; } itemcount++; } foreach (ModelAnimations item in models) { string modelOutputPath = string.Concat(projectFolderName, item.Filename); //string modelOutputPath = item.Filename; ModelFile.CreateFile(modelOutputPath, item.Model, item.Animations.ToArray(), null, item.Name, null, item.Format); string type = "model"; switch (item.Format) { case ModelFormat.Basic: type = "basicmodel"; break; case ModelFormat.BasicDX: type = "basicdxmodel"; break; case ModelFormat.Chunk: type = "chunkmodel"; break; } output.Files[item.Filename] = new FileTypeHash(type, HelperFunctions.FileHash(modelOutputPath)); } IniSerializer.Serialize(output, Path.Combine(projectFolderName, Path.GetFileNameWithoutExtension(datafilename)) + "_data.ini"); timer.Stop(); Console.WriteLine("Split " + itemcount + " items in " + timer.Elapsed.TotalSeconds + " seconds."); Console.WriteLine(); } #if !DEBUG catch (Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); Console.WriteLine("Press any key to exit."); Console.ReadLine(); return((int)SA_Tools.Split.SplitERRORVALUE.UnhandledException); } #endif return((int)SA_Tools.Split.SplitERRORVALUE.Success); }
/// <summary> /// Lizenz hochladen Service für den Upload der Lizenz /// </summary> /// <exception cref="IO.Swagger.Client.ApiException">Thrown when fails to make API call</exception> /// <param name="adminEMailAdresse">adminEMailAdresse</param> /// <param name="uploadFile">uploadFile</param> /// <returns>Task of LicenseUploadResponseDTO</returns> public async System.Threading.Tasks.Task <LicenseUploadResponseDTO> V1LicenseUploadAsync(string adminEMailAdresse, ModelFile uploadFile) { ApiResponse <LicenseUploadResponseDTO> localVarResponse = await V1LicenseUploadAsyncWithHttpInfo(adminEMailAdresse, uploadFile); return(localVarResponse.Data); }
/// <summary> /// Lizenz hochladen Service für den Upload der Lizenz /// </summary> /// <exception cref="IO.Swagger.Client.ApiException">Thrown when fails to make API call</exception> /// <param name="adminEMailAdresse">adminEMailAdresse</param> /// <param name="uploadFile">uploadFile</param> /// <returns>Task of ApiResponse (LicenseUploadResponseDTO)</returns> public async System.Threading.Tasks.Task <ApiResponse <LicenseUploadResponseDTO> > V1LicenseUploadAsyncWithHttpInfo(string adminEMailAdresse, ModelFile uploadFile) { // verify the required parameter 'adminEMailAdresse' is set if (adminEMailAdresse == null) { throw new ApiException(400, "Missing required parameter 'adminEMailAdresse' when calling LicenseApi->V1LicenseUpload"); } // verify the required parameter 'uploadFile' is set if (uploadFile == null) { throw new ApiException(400, "Missing required parameter 'uploadFile' when calling LicenseApi->V1LicenseUpload"); } var localVarPath = "/v1/license/upload"; var localVarPathParams = new Dictionary <String, String>(); var localVarQueryParams = new List <KeyValuePair <String, String> >(); var localVarHeaderParams = new Dictionary <String, String>(this.Configuration.DefaultHeader); var localVarFormParams = new Dictionary <String, String>(); var localVarFileParams = new Dictionary <String, FileParameter>(); Object localVarPostBody = null; // to determine the Content-Type header String[] localVarHttpContentTypes = new String[] { "multipart/form-data" }; String localVarHttpContentType = this.Configuration.ApiClient.SelectHeaderContentType(localVarHttpContentTypes); // to determine the Accept header String[] localVarHttpHeaderAccepts = new String[] { "application/json" }; String localVarHttpHeaderAccept = this.Configuration.ApiClient.SelectHeaderAccept(localVarHttpHeaderAccepts); if (localVarHttpHeaderAccept != null) { localVarHeaderParams.Add("Accept", localVarHttpHeaderAccept); } if (adminEMailAdresse != null) { localVarQueryParams.AddRange(this.Configuration.ApiClient.ParameterToKeyValuePairs("", "adminEMailAdresse", adminEMailAdresse)); // query parameter } if (uploadFile != null) { localVarFileParams.Add("uploadFile", this.Configuration.ApiClient.ParameterToFile("uploadFile", uploadFile.AbsoluteFile)); } // authentication (bearerToken) required if (!String.IsNullOrEmpty(this.Configuration.GetApiKeyWithPrefix("Authorization"))) { localVarHeaderParams["Authorization"] = this.Configuration.GetApiKeyWithPrefix("Authorization"); } // authentication (oauth2) required // oauth required if (!String.IsNullOrEmpty(this.Configuration.AccessToken)) { localVarHeaderParams["Authorization"] = "Bearer " + this.Configuration.AccessToken; } // make the HTTP request IRestResponse localVarResponse = (IRestResponse)await this.Configuration.ApiClient.CallApiAsync(localVarPath, Method.POST, localVarQueryParams, localVarPostBody, localVarHeaderParams, localVarFormParams, localVarFileParams, localVarPathParams, localVarHttpContentType); int localVarStatusCode = (int)localVarResponse.StatusCode; if (ExceptionFactory != null) { Exception exception = ExceptionFactory("V1LicenseUpload", localVarResponse); if (exception != null) { throw exception; } } return(new ApiResponse <LicenseUploadResponseDTO>(localVarStatusCode, localVarResponse.Headers.ToDictionary(x => x.Name, x => x.Value.ToString()), (LicenseUploadResponseDTO)this.Configuration.ApiClient.Deserialize(localVarResponse, typeof(LicenseUploadResponseDTO)))); }
//private const string URL = "http://*****:*****@myirent.com"; HttpClient client = new HttpClient(); client.BaseAddress = new Uri(URL); var myContent = JsonConvert.SerializeObject(propertyData); var buffer = System.Text.Encoding.UTF8.GetBytes(myContent); var byteContent = new ByteArrayContent(buffer); byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var result = client.PostAsync("", byteContent).Result; var contents = result.Content.ReadAsStringAsync().Result; success = true; } } catch (Exception any) { Console.Write(any.ToString()); MailMessage mailMessage = new MailMessage(); mailMessage.To.Add("*****@*****.**"); mailMessage.From = new MailAddress("*****@*****.**"); mailMessage.Subject = "CoStar XML Feed - Error"; mailMessage.Body = any.ToString(); SmtpClient smtp = new SmtpClient(); smtp.Host = "smtp.myirent.com"; //Or Your SMTP Server Address smtp.Port = 587; smtp.UseDefaultCredentials = false; smtp.Credentials = new System.Net.NetworkCredential ("*****@*****.**", "iRent4Now!"); smtp.Send(mailMessage); success = false; } }
/// <summary> /// Lizenz hochladen Service für den Upload der Lizenz /// </summary> /// <exception cref="IO.Swagger.Client.ApiException">Thrown when fails to make API call</exception> /// <param name="adminEMailAdresse">adminEMailAdresse</param> /// <param name="uploadFile">uploadFile</param> /// <returns>LicenseUploadResponseDTO</returns> public LicenseUploadResponseDTO V1LicenseUpload(string adminEMailAdresse, ModelFile uploadFile) { ApiResponse <LicenseUploadResponseDTO> localVarResponse = V1LicenseUploadWithHttpInfo(adminEMailAdresse, uploadFile); return(localVarResponse.Data); }
private void button2_Click(object sender, EventArgs e) { if (this.textBox3.Text != null && this.textBox3.Text.Trim() != "") { MessageBox.Show("該文件已經上傳請勿重複保存!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } if (this.textBox1.Text == null || this.textBox1.Text.Trim() == "") { MessageBox.Show("請選擇需要上傳的文件!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); this.button1.Focus(); return; } if (this.textBox2.Text == null || this.textBox2.Text.Trim() == "") { MessageBox.Show("文件描述不能為空!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); this.textBox2.Focus(); return; } try { string filePath = this.textBox1.Text; FileInfo fi = new FileInfo(@filePath); //获得文件大小 long fileSize = fi.Length; //提取文件名 int lastIndex = fi.FullName.LastIndexOf(@"\"); string completeName = fi.FullName.Substring(lastIndex + 1); //获得文件扩展名 string fileType = fi.Extension.Replace(".", ""); byte[] files = FileToBytes(filePath); if (fileSize > 0) { string[] type = { "png", "lab" }; bool exists = ((IList)type).Contains(fileType.ToLower()); if (!exists) { MessageBox.Show("文档格式不对!只能为pdf格式。", "提示对话框", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } ModelFile modelFile = new ModelFile(); modelFile.Fileaddress = files; modelFile.Filename = completeName; modelFile.Filedescription = this.textBox2.Text; ModelFile reModelFile = printQ.saveModelFile(modelFile); if (reModelFile != null) { this.textBox3.Text = reModelFile.Fileno; MessageBox.Show("上傳文件成功!", "提示对话框", MessageBoxButtons.OK, MessageBoxIcon.Information); } else { MessageBox.Show("上傳文件失敗!", "提示对话框", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } } else { MessageBox.Show("請確認是否選擇正確的文件上傳!", "提示对话框", MessageBoxButtons.OK, MessageBoxIcon.Information); return; } } catch (Exception ex) { MessageBox.Show("选择文件时候发生了 " + ex.Message); } }
static void Main(string[] args) { bool nometa = false; bool nolabel = false; string mode; string fullpath_out; bool bigendian = false; List <string> mdlanimfiles; if (args.Length == 0) { Console.WriteLine("Split any binary files supported by SA Tools.\n"); Console.WriteLine("Usage:\n"); Console.WriteLine("-Splitting binary files with INI data-"); Console.WriteLine("split binary <file> <inifile> [output path] [-nometa] [-nolabel]\n"); Console.WriteLine("-Splitting SA1/SADX NB files-"); Console.WriteLine("split nb <file> [output path] -ini [split INI file]\n"); Console.WriteLine("-Splitting SA2 MDL files-"); Console.WriteLine("split mdl <file> [output path] -anim [animation files]\n"); Console.WriteLine("-Splitting SA2B MDL files-"); Console.WriteLine("split mdl_b <file> [output path] -anim [animation files]\n"); Console.WriteLine("-Splitting dllexport entries from DLL files-"); Console.WriteLine("split dllexport <file> <type> <name> [output path] [-p numparts]\n"); Console.WriteLine("Press ENTER to exit."); Console.ReadLine(); return; } #if DEBUG if (SplitExtensions(args) == true) { return; } #endif for (int u = 2; u < args.Length; u++) { if (args[u] == "-nometa") { nometa = true; } if (args[u] == "-nolabel") { nolabel = true; } } mode = args[0]; switch (mode.ToLowerInvariant()) { case "binary": string fullpath_bin = Path.GetFullPath(args[1]); if (!File.Exists(fullpath_bin)) { Console.WriteLine("File {0} doesn't exist.", fullpath_bin); return; } Console.WriteLine("File: {0}", fullpath_bin); string fullpath_ini = Path.GetFullPath(args[2]); if (!File.Exists(fullpath_ini)) { Console.WriteLine("File {0} doesn't exist.", fullpath_ini); return; } Console.WriteLine("Data mapping: {0}", fullpath_ini); fullpath_out = Path.GetDirectoryName(fullpath_bin); if (args.Length > 3) { fullpath_out = args[3]; if (fullpath_out[fullpath_out.Length - 1] != '/') { fullpath_out = string.Concat(fullpath_out, '/'); } fullpath_out = Path.GetFullPath(fullpath_out); } Console.WriteLine("Output folder: {0}", fullpath_out); if (nometa) { Console.WriteLine("Labels are disabled"); } if (Path.GetExtension(args[1]).ToLowerInvariant() == ".dll") { SA_Tools.SplitDLL.SplitDLL.SplitDLLFile(fullpath_bin, fullpath_ini, fullpath_out, nometa, nolabel); } else { SA_Tools.Split.Split.SplitFile(fullpath_bin, fullpath_ini, fullpath_out, nometa, nolabel); } break; case "nb": case "nb_b": string fullpath_nb = Path.GetFullPath(args[1]); string path_ini = null; if (args[args.Length - 2].ToLowerInvariant() == "-ini") { path_ini = Path.GetFullPath(args[args.Length - 1]); } if (!File.Exists(fullpath_nb)) { Console.WriteLine("File {0} doesn't exist.", fullpath_nb); return; } Console.WriteLine("File: {0}", fullpath_nb); fullpath_out = Path.GetDirectoryName(fullpath_nb); if (args.Length > 2) { fullpath_out = args[2]; if (fullpath_out[fullpath_out.Length - 1] != '/') { fullpath_out = string.Concat(fullpath_out, '/'); } fullpath_out = Path.GetFullPath(fullpath_out); } Console.WriteLine("Output folder: {0}", fullpath_out); SA_Tools.Split.SplitNB.SplitNBFile(fullpath_nb, false, fullpath_out, 1, path_ini); break; case "mdl": case "mdl_b": string fullpath_mdl = Path.GetFullPath(args[1]); if (!File.Exists(fullpath_mdl)) { Console.WriteLine("File {0} doesn't exist.", fullpath_mdl); return; } Console.Write("File: {0}", fullpath_mdl); if (mode == "mdl_b") { bigendian = true; Console.Write(" (Big Endian)\n"); } else { Console.Write(System.Environment.NewLine); } fullpath_out = Path.GetDirectoryName(fullpath_mdl); if (args.Length > 2) { fullpath_out = args[2]; if (fullpath_out[fullpath_out.Length - 1] != '/') { fullpath_out = string.Concat(fullpath_out, '/'); } fullpath_out = Path.GetFullPath(fullpath_out); } Console.WriteLine("Output path: {0}", fullpath_out); if (args.Length > 3) { mdlanimfiles = new List <string>(); Console.WriteLine("Animation files:"); for (int u = 3; u < args.Length; u++) { string animpath = Path.GetFullPath(args[u]); if (File.Exists(animpath)) { mdlanimfiles.Add(animpath); Console.WriteLine(animpath); } else { Console.WriteLine("File {0} doesn't exist.", animpath); } } SA_Tools.SAArc.sa2MDL.Split(bigendian, fullpath_mdl, fullpath_out, mdlanimfiles.ToArray()); } else { SA_Tools.SAArc.sa2MDL.Split(bigendian, fullpath_mdl, fullpath_out, null); } break; case "dllexport": string fullpath_dllex = Path.GetFullPath(args[1]); string type = args[2]; string name = args[3]; string fileOutputPath = ""; if (args.Length > 4) { fileOutputPath = args[4]; } if (!File.Exists(fullpath_dllex)) { Console.WriteLine("File {0} doesn't exist.", fullpath_dllex); return; } Console.Write("File: {0}", fullpath_dllex); byte[] datafile = File.ReadAllBytes(fullpath_dllex); uint imageBase = SA_Tools.HelperFunctions.SetupEXE(ref datafile).Value; Dictionary <string, int> exports; Dictionary <int, string> labels = new Dictionary <int, string>(); { int ptr = BitConverter.ToInt32(datafile, BitConverter.ToInt32(datafile, 0x3c) + 4 + 20 + 96); GCHandle handle = GCHandle.Alloc(datafile, GCHandleType.Pinned); IMAGE_EXPORT_DIRECTORY dir = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure( Marshal.UnsafeAddrOfPinnedArrayElement(datafile, ptr), typeof(IMAGE_EXPORT_DIRECTORY)); handle.Free(); exports = new Dictionary <string, int>(dir.NumberOfFunctions); int nameaddr = dir.AddressOfNames; int ordaddr = dir.AddressOfNameOrdinals; for (int i = 0; i < dir.NumberOfNames; i++) { string namex = datafile.GetCString(BitConverter.ToInt32(datafile, nameaddr), System.Text.Encoding.ASCII); int addr = BitConverter.ToInt32(datafile, dir.AddressOfFunctions + (BitConverter.ToInt16(datafile, ordaddr) * 4)); exports.Add(namex, addr); labels.Add(addr, namex); nameaddr += 4; ordaddr += 2; } Console.Write(" ({0} exports)\n", exports.Count); } if (!exports.ContainsKey(name)) { Console.WriteLine("The export table has no item named {0}", name); return; } int address = exports[name]; Console.WriteLine("{0} {1}:{2}", type, name, address.ToString("X8")); switch (type) { // Landtables case "landtable": case "sa1landtable": case "sadxlandtable": case "sa2landtable": case "sa2blandtable": case "battlelandtable": LandTableFormat landfmt_cur; string landext; switch (type) { case "sa1landtable": landfmt_cur = LandTableFormat.SA1; landext = ".sa1lvl"; break; case "sadxlandtable": landfmt_cur = LandTableFormat.SADX; landext = ".sa1lvl"; break; case "sa2landtable": landfmt_cur = LandTableFormat.SA2; landext = ".sa2lvl"; break; case "sa2blandtable": case "battlelandtable": landfmt_cur = LandTableFormat.SA2B; landext = ".sa2blvl"; break; case "landtable": default: landfmt_cur = LandTableFormat.SADX; landext = ".sa1lvl"; break; } LandTable land = new LandTable(datafile, address, imageBase, landfmt_cur, labels); if (fileOutputPath == "") { fileOutputPath = land.Name + landext; } if (!Directory.Exists(Path.GetDirectoryName(fileOutputPath))) { Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath)); } land.SaveToFile(fileOutputPath, landfmt_cur, nometa); break; // NJS_OBJECT case "model": case "object": case "basicmodel": case "basicdxmodel": case "chunkmodel": case "gcmodel": { ModelFormat modelfmt_obj; string modelext; switch (type) { case "basicmodel": modelfmt_obj = ModelFormat.Basic; modelext = ".sa1mdl"; break; case "basicdxmodel": modelfmt_obj = ModelFormat.BasicDX; modelext = ".sa1mdl"; break; case "chunkmodel": modelfmt_obj = ModelFormat.Chunk; modelext = ".sa2mdl"; break; case "gcmodel": modelfmt_obj = ModelFormat.GC; modelext = ".sa2bmdl"; break; default: modelfmt_obj = ModelFormat.BasicDX; modelext = ".sa1mdl"; break; } NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, modelfmt_obj, labels, new Dictionary <int, Attach>()); if (fileOutputPath == "") { fileOutputPath = mdl.Name + modelext; } if (!Directory.Exists(Path.GetDirectoryName(fileOutputPath))) { Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath)); } ModelFile.CreateFile(fileOutputPath, mdl, null, null, null, null, modelfmt_obj, nometa); } break; // NJS_MOTION case "animation": case "motion": int numparts = 0; for (int a = 3; a < args.Length; a++) { if (args[a] == "-p") { numparts = int.Parse(args[a + 1], System.Globalization.NumberStyles.Integer); } } NJS_MOTION ani = new NJS_MOTION(datafile, address, imageBase, numparts, labels); if (fileOutputPath == "") { fileOutputPath = ani.Name + "saanim"; } if (!Directory.Exists(Path.GetDirectoryName(fileOutputPath))) { Directory.CreateDirectory(Path.GetDirectoryName(fileOutputPath)); } ani.Save(fileOutputPath, nometa); break; default: Console.WriteLine("Unrecognized export type {0}", type); break; } break; default: Console.WriteLine("Incorrect mode specified. Press ENTER to exit."); Console.ReadLine(); return; } }
public AnimatedModel(Engine engine, Skeleton skeleton, ModelVariantIdentifier variant, ModelFile file, ModelQuality quality) : this(engine, skeleton, variant, file.GetModelDefinition(), quality) { }
static ExportModel ProcessModel(ModelFile mdl, ResourceManager resources) { mdl.Path = mdl.Path.Replace(' ', '_'); var ex = new ExportModel(); for (int midx = 0; midx < mdl.Levels.Length; midx++) { var lvl = mdl.Levels[midx]; var processed = ProcessRef(lvl, resources); var geo = new CL.geometry(); geo.name = geo.id = mdl.Path + "-level" + midx; var mesh = new CL.mesh(); geo.Item = mesh; CL.source positions; CL.source normals = null; CL.source colors = null; CL.source tex1 = null; CL.source tex2 = null; int idxC = 1; positions = CreateSource( geo.name + "-positions", (k) => new Vector4(processed.Vertices[k].Position, 0), 3, processed.Vertices.Length); mesh.vertices = new CL.vertices() { id = geo.name + "-vertices", input = new CL.InputLocal[] { new CL.InputLocal() { semantic = "POSITION", source = "#" + positions.id } } }; var sources = new List <CL.source>() { positions }; if ((processed.FVF & D3DFVF.NORMAL) == D3DFVF.NORMAL) { normals = CreateSource( geo.name + "-normals", (k) => new Vector4(processed.Vertices[k].Normal, 0), 3, processed.Vertices.Length); sources.Add(normals); idxC++; } if ((processed.FVF & D3DFVF.DIFFUSE) == D3DFVF.DIFFUSE) { colors = CreateSource( geo.name + "-color", (k) => { var c = Color4.FromRgba(processed.Vertices[k].Diffuse); return(new Vector4(c.R, c.G, c.B, c.A)); }, 4, processed.Vertices.Length); sources.Add(colors); idxC++; } bool doTex1, doTex2 = false; if ((processed.FVF & D3DFVF.TEX2) == D3DFVF.TEX2) { doTex1 = doTex2 = true; } else if ((processed.FVF & D3DFVF.TEX1) == D3DFVF.TEX1) { doTex1 = true; } else { doTex1 = doTex2 = false; } if (doTex1) { tex1 = CreateSource( geo.name + "-tex1", (k) => new Vector4(processed.Vertices[k].TextureCoordinate, 0, 0), 2, processed.Vertices.Length); sources.Add(tex1); idxC++; } if (doTex2) { tex2 = CreateSource( geo.name + "-tex2", (k) => new Vector4(processed.Vertices[k].TextureCoordinateTwo, 0, 0), 2, processed.Vertices.Length); sources.Add(tex2); idxC++; } mesh.source = sources.ToArray(); var items = new List <object>(); foreach (var dc in processed.Drawcalls) { if (!ex.Materials.Any((x) => x.Name == dc.Material.Name)) { ex.Materials.Add(dc.Material); } var trs = new CL.triangles(); trs.count = (ulong)(dc.Indices.Length / 3); trs.material = dc.Material.Name + "-material"; List <int> pRefs = new List <int>(dc.Indices.Length * idxC); List <CL.InputLocalOffset> inputs = new List <CL.InputLocalOffset>() { new CL.InputLocalOffset() { semantic = "VERTEX", source = "#" + geo.id + "-vertices", offset = 0 } }; ulong off = 1; if (normals != null) { inputs.Add(new CL.InputLocalOffset() { semantic = "NORMAL", source = "#" + normals.id, offset = off++ }); } if (colors != null) { inputs.Add(new CL.InputLocalOffset() { semantic = "COLOR", source = "#" + colors.id, offset = off++ }); } if (tex1 != null) { inputs.Add(new CL.InputLocalOffset() { semantic = "TEXCOORD", source = "#" + tex1.id, offset = off++ }); } if (tex2 != null) { inputs.Add(new CL.InputLocalOffset() { semantic = "TEXCOORD", source = "#" + tex2.id, offset = off++ }); } trs.input = inputs.ToArray(); for (int i = 0; i < dc.Indices.Length; i++) { for (int j = 0; j < idxC; j++) { pRefs.Add(dc.Indices[i]); } } trs.p = string.Join(" ", pRefs.ToArray()); items.Add(trs); } mesh.Items = items.ToArray(); ex.Geometries.Add(geo); } return(ex); }
void DoModel(ModelFile mdl, AbstractConstruct con) { bool open = ImGui.TreeNode(ImGuiExt.Pad("Hardpoints")); var act = NewHpMenu(mdl.Path); switch (act) { case ContextActions.NewFixed: case ContextActions.NewRevolute: newIsFixed = act == ContextActions.NewFixed; addTo = mdl.Hardpoints; addConstruct = con; newHpBuffer.Clear(); popups.OpenPopup("New Hardpoint"); break; } Theme.RenderTreeIcon("Hardpoints", "hardpoint", Color4.CornflowerBlue); if (open) { foreach (var hp in mdl.Hardpoints) { if (doFilter) { if (hp.Name.IndexOf(currentFilter, StringComparison.OrdinalIgnoreCase) == -1) { continue; } } HardpointGizmo gz = null; foreach (var gizmo in gizmos) { if (gizmo.Definition == hp) { gz = gizmo; break; } } if (hp is RevoluteHardpointDefinition) { Theme.Icon("rev", Color4.LightSeaGreen); } else { Theme.Icon("fix", Color4.Purple); } ImGui.SameLine(); if (Theme.IconButton("visible$" + hp.Name, "eye", gz.Enabled ? Color4.White : Color4.Gray)) { gz.Enabled = !gz.Enabled; } ImGui.SameLine(); ImGui.Selectable(hp.Name); var action = EditDeleteHpMenu(mdl.Path + hp.Name); if (action == ContextActions.Delete) { hpDelete = hp; hpDeleteFrom = mdl.Hardpoints; popups.OpenPopup("Confirm Delete"); } if (action == ContextActions.Edit) { hpEditing = hp; } } ImGui.TreePop(); } }
public void addFile(ModelFile file) { this.files.Add(file); }
private void LoadFile(string filename) { loaded = false; Environment.CurrentDirectory = Path.GetDirectoryName(filename); timer1.Stop(); modelFile = null; animation = null; animations = null; animnum = -1; animframe = 0; if (ModelFile.CheckModelFile(filename)) { modelFile = new ModelFile(filename); outfmt = modelFile.Format; model = modelFile.Model; animations = new Animation[modelFile.Animations.Count]; modelFile.Animations.CopyTo(animations, 0); } else { using (FileTypeDialog ftd = new FileTypeDialog()) { if (ftd.ShowDialog(this) != DialogResult.OK) return; byte[] file = File.ReadAllBytes(filename); if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) file = FraGag.Compression.Prs.Decompress(file); if (ftd.typBinary.Checked) { modelinfo.ShowDialog(this); if (modelinfo.checkBox1.Checked) animations = new Animation[] { Animation.ReadHeader(file, (int)modelinfo.numericUpDown3.Value, (uint)modelinfo.numericUpDown2.Value, (ModelFormat)modelinfo.comboBox2.SelectedIndex) }; model = new NJS_OBJECT(file, (int)modelinfo.NumericUpDown1.Value, (uint)modelinfo.numericUpDown2.Value, (ModelFormat)modelinfo.comboBox2.SelectedIndex); switch ((ModelFormat)modelinfo.comboBox2.SelectedIndex) { case ModelFormat.Basic: case ModelFormat.BasicDX: outfmt = ModelFormat.Basic; break; case ModelFormat.Chunk: outfmt = ModelFormat.Chunk; break; } } else if (ftd.typSA2MDL.Checked | ftd.typSA2BMDL.Checked) { ModelFormat fmt = outfmt = ModelFormat.Chunk; ByteConverter.BigEndian = ftd.typSA2BMDL.Checked; using (SA2MDLDialog dlg = new SA2MDLDialog()) { int address = 0; SortedDictionary<int, NJS_OBJECT> sa2models = new SortedDictionary<int, NJS_OBJECT>(); int i = ByteConverter.ToInt32(file, address); while (i != -1) { sa2models.Add(i, new NJS_OBJECT(file, ByteConverter.ToInt32(file, address + 4), 0, fmt)); address += 8; i = ByteConverter.ToInt32(file, address); } foreach (KeyValuePair<int, NJS_OBJECT> item in sa2models) dlg.modelChoice.Items.Add(item.Key + ": " + item.Value.Name); dlg.ShowDialog(this); i = 0; foreach (KeyValuePair<int, NJS_OBJECT> item in sa2models) { if (i == dlg.modelChoice.SelectedIndex) { model = item.Value; break; } i++; } if (dlg.checkBox1.Checked) { using (OpenFileDialog anidlg = new OpenFileDialog() { DefaultExt = "bin", Filter = "Motion Files|*MTN.BIN;*MTN.PRS|All Files|*.*" }) { if (anidlg.ShowDialog(this) == DialogResult.OK) { byte[] anifile = File.ReadAllBytes(anidlg.FileName); if (Path.GetExtension(anidlg.FileName).Equals(".prs", StringComparison.OrdinalIgnoreCase)) anifile = FraGag.Compression.Prs.Decompress(anifile); address = 0; SortedDictionary<int, Animation> anis = new SortedDictionary<int, Animation>(); i = ByteConverter.ToInt32(file, address); while (i != -1) { anis.Add(i, new Animation(file, ByteConverter.ToInt32(file, address + 4), 0, model.CountAnimated())); address += 8; i = ByteConverter.ToInt32(file, address); } animations = new List<Animation>(anis.Values).ToArray(); } } } } } } } model.ProcessVertexData(); NJS_OBJECT[] models = model.GetObjects(); meshes = new Mesh[models.Length]; for (int i = 0; i < models.Length; i++) if (models[i].Attach != null) try { meshes[i] = models[i].Attach.CreateD3DMesh(d3ddevice); } catch { } treeView1.Nodes.Clear(); nodeDict = new Dictionary<NJS_OBJECT, TreeNode>(); AddTreeNode(model, treeView1.Nodes); loaded = saveToolStripMenuItem.Enabled = exportToolStripMenuItem.Enabled = findToolStripMenuItem.Enabled = true; selectedObject = model; SelectedItemChanged(); }
private void button1_Click(object sender, EventArgs e) { bool success = false; uint address = (uint)numericUpDownBinaryAddress.Value; if (checkBoxBinaryMemory.Checked) { address -= (uint)numericUpDownBinaryKey.Value; } LandTableFormat format = (LandTableFormat)comboBoxBinaryFormat.SelectedIndex; LandTableFormat outfmt = format; if (format == LandTableFormat.SADX) { outfmt = LandTableFormat.SA1; } ByteConverter.BigEndian = checkBoxBinaryBigEndian.Checked; Settings.Author = textBoxBinaryAuthor.Text; Settings.Save(); SaveFileDialog sd = new SaveFileDialog(); switch (comboBoxBinaryItemType.SelectedIndex) { //Level case 0: sd = new SaveFileDialog() { DefaultExt = outfmt.ToString().ToLowerInvariant() + "lvl", Filter = outfmt.ToString().ToUpperInvariant() + "LVL Files|*." + outfmt.ToString().ToLowerInvariant() + "lvl|All Files|*.*" }; if (sd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { new LandTable(file, (int)numericUpDownBinaryAddress.Value, (uint)numericUpDownBinaryKey.Value, format) { Author = textBoxBinaryAuthor.Text, Description = textBoxBinaryDescription.Text }.SaveToFile(sd.FileName, outfmt); if (checkBoxBinaryStructs.Checked) { ConvertToText(sd.FileName); } if (!checkBoxBinarySAModel.Checked) { File.Delete(sd.FileName); } success = true; } break; //Model case 1: sd = new SaveFileDialog() { DefaultExt = outfmt.ToString().ToLowerInvariant() + "mdl", Filter = outfmt.ToString().ToUpperInvariant() + "MDL Files|*." + outfmt.ToString().ToLowerInvariant() + "mdl|All Files|*.*" }; if (sd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { NJS_OBJECT tempmodel = new NJS_OBJECT(file, (int)address, (uint)numericUpDownBinaryKey.Value, (ModelFormat)comboBoxBinaryFormat.SelectedIndex, null); ModelFile.CreateFile(sd.FileName, tempmodel, null, textBoxBinaryAuthor.Text, textBoxBinaryDescription.Text, null, (ModelFormat)comboBoxBinaryFormat.SelectedIndex); ConvertToText(sd.FileName, checkBoxBinaryStructs.Checked, checkBoxBinaryNJA.Checked, false); if (!checkBoxBinarySAModel.Checked) { File.Delete(sd.FileName); } success = true; } break; //Action case 2: sd = new SaveFileDialog() { DefaultExt = outfmt.ToString().ToLowerInvariant() + "mdl", Filter = outfmt.ToString().ToUpperInvariant() + "MDL Files|*." + outfmt.ToString().ToLowerInvariant() + "mdl|All Files|*.*" }; if (sd.ShowDialog() == System.Windows.Forms.DialogResult.OK) { //Model NJS_ACTION tempaction = new NJS_ACTION(file, (int)address, (uint)numericUpDownBinaryKey.Value, (ModelFormat)comboBoxBinaryFormat.SelectedIndex, null); NJS_OBJECT tempmodel = tempaction.Model; ModelFile.CreateFile(sd.FileName, tempmodel, null, textBoxBinaryAuthor.Text, textBoxBinaryDescription.Text, null, (ModelFormat)comboBoxBinaryFormat.SelectedIndex); ConvertToText(sd.FileName, checkBoxBinaryStructs.Checked, checkBoxBinaryNJA.Checked, false); if (!checkBoxBinarySAModel.Checked) { File.Delete(sd.FileName); } //Action string saanimPath = Path.Combine(Path.GetDirectoryName(sd.FileName), Path.GetFileNameWithoutExtension(sd.FileName) + ".saanim"); tempaction.Animation.Save(saanimPath); ConvertToText(saanimPath, checkBoxBinaryStructs.Checked, false, checkBoxBinaryJSON.Checked); if (checkBoxBinarySAModel.Checked) { using (TextWriter twmain = File.CreateText(Path.Combine(Path.GetDirectoryName(sd.FileName), Path.GetFileNameWithoutExtension(sd.FileName) + ".action"))) { twmain.WriteLine(Path.GetFileName(saanimPath)); twmain.Flush(); twmain.Close(); } } else { File.Delete(saanimPath); } success = true; } break; } if (success) { MessageBox.Show("Data extracted!", "Binary Data Extractor", MessageBoxButtons.OK, MessageBoxIcon.Information); } }
private static void ExtractWarpGates(List <string> warpList, int mapId, MapDataFile ifo) { const string warpStb = "./3DDATA/stb/warp.stb"; const string zoneStb = "./3DDATA/stb/list_zone.stb"; const string warpGateModel = "./3DDATA/special/warp_gate01/warp.zms"; var zoneDataFile = new DataFile(); zoneDataFile.Load(zoneStb); var warpDataFile = new DataFile(); warpDataFile.Load(warpStb); var destCoords = Vector3.Zero; ModelFile modelFile = new ModelFile(); modelFile.Load(warpGateModel); var vertices = modelFile.Vertices; foreach (var warpGate in ifo.WarpPoints) { var destMapId = int.Parse(warpDataFile[warpGate.WarpID][2]); if (zoneDataFile[destMapId][2].ToString().Contains(".zon")) { ZoneFile zoneFile = new ZoneFile(); zoneFile.Load(zoneDataFile[destMapId][2].ToString()); // Load the zon file foreach (var spawnPoint in zoneFile.SpawnPoints) { if (spawnPoint.Name != warpDataFile[warpGate.WarpID][3].ToString()) { continue; } // rose is stupid and we need to do this to get the right coords destCoords = new Vector3(((spawnPoint.Position.X + 520000.00f) / 100.0f), ((spawnPoint.Position.Z + 520000.00f) / 100.0f), ((spawnPoint.Position.Y) / 100.0f)); break; } } var position = new Vector3(((warpGate.Position.X + 520000.00f) / 100.0f), ((warpGate.Position.Y + 520000.00f) / 100.0f), ((warpGate.Position.Z) / 100.0f)); var world = Matrix.Identity; var rot = Matrix.RotationQuaternion(warpGate.Rotation); var scale = Matrix.Scaling(warpGate.Scale); var trans = Matrix.Translation(position); var objectWorld = rot * scale * trans; Vector3[] vectorPositions = new Vector3[vertices.Count]; for (int i = 0; i < vertices.Count; i++) { vectorPositions[i] = (Vector3)Vector3.Transform(vertices[i].Position, world * objectWorld); } var boundingBox = BoundingBox.FromPoints(vectorPositions); warpList.Add("warp_gate(\"\", " + warpDataFile[warpGate.WarpID][2].ToString() + ", " + (destCoords.X) + ", " + (destCoords.Y) + ", " + (destCoords.Z) + ", " + mapId.ToString() + ", " + (boundingBox.Minimum.X) + ", " + (boundingBox.Minimum.Y) + ", " + (boundingBox.Minimum.Z) + ", " + (boundingBox.Maximum.X) + ", " + (boundingBox.Maximum.Y) + ", " + (boundingBox.Maximum.Z) + ");\n"); } }
static void Main(string[] args) { if (args.Length == 0) { Console.Write("Filename: "); args = new string[] { Console.ReadLine().Trim('"') }; } foreach (string filename in args) { Console.WriteLine("Splitting file {0}...", filename); byte[] fc; if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) { fc = Prs.Decompress(filename); } else { fc = File.ReadAllBytes(filename); } EventIniData ini = new EventIniData() { Name = Path.GetFileNameWithoutExtension(filename) }; string path = Directory.CreateDirectory(Path.Combine(Path.GetDirectoryName(Path.GetFullPath(filename)), Path.GetFileNameWithoutExtension(filename))).FullName; uint key; List <NJS_MOTION> motions = null; bool battle; if (fc[0] == 0x81) { Console.WriteLine("File is in GC/PC format."); ByteConverter.BigEndian = true; key = 0x8125FE60; ini.Game = Game.SA2B; battle = true; motions = ReadMotionFile(Path.ChangeExtension(filename, null) + "motion.bin"); ini.Motions = motions.Select(a => a?.Name).ToList(); foreach (var mtn in motions.Where(a => a != null)) { motionfiles[mtn.Name] = new MotionInfo(null, mtn); } } else { Console.WriteLine("File is in DC format."); ByteConverter.BigEndian = false; key = 0xC600000; ini.Game = Game.SA2; battle = false; } int ptr = fc.GetPointer(0x20, key); if (ptr != 0) { for (int i = 0; i < (battle ? 18 : 16); i++) { string upnam = upgradenames[i]; string chnam = upnam; switch (i) { case 0: chnam = "Sonic"; break; case 4: chnam = "Shadow"; break; case 6: chnam = "Knuckles"; break; case 12: chnam = "Rouge"; break; case 16: chnam = "Mech Tails"; break; case 17: chnam = "Mech Eggman"; break; } UpgradeInfo info = new UpgradeInfo(); info.RootNode = GetModel(fc, ptr, key, $"{chnam} Root.sa2mdl"); if (info.RootNode != null) { int ptr2 = fc.GetPointer(ptr + 4, key); if (ptr2 != 0) { info.AttachNode1 = $"object_{ptr2:X8}"; } info.Model1 = GetModel(fc, ptr + 8, key, $"{upnam} Model 1.sa2mdl"); ptr2 = fc.GetPointer(ptr + 0xC, key); if (ptr2 != 0) { info.AttachNode2 = $"object_{ptr2:X8}"; } info.Model2 = GetModel(fc, ptr + 0x10, key, $"{upnam} Model 2.sa2mdl"); } ini.Upgrades.Add(info); ptr += 0x14; } } else { Console.WriteLine("Event contains no character upgrades."); } ptr = fc.GetPointer(0x18, key); if (ptr != 0) { for (int i = 0; i < 93; i++) { string name = GetModel(fc, ptr, key, $"Mech Part {i + 1}.sa2mdl"); if (name != null) { ini.MechParts.Add(i, name); } ptr += 4; } } else { Console.WriteLine("Event contains no mech parts."); } int gcnt = ByteConverter.ToInt32(fc, 8); ptr = fc.GetPointer(0, key); if (ptr != 0) { Console.WriteLine("Event contains {0} scene(s).", gcnt + 1); for (int gn = 0; gn <= gcnt; gn++) { Directory.CreateDirectory(Path.Combine(path, $"Scene {gn + 1}")); SceneInfo scn = new SceneInfo(); int ptr2 = fc.GetPointer(ptr, key); int ecnt = ByteConverter.ToInt32(fc, ptr + 4); if (ptr2 != 0) { Console.WriteLine("Scene {0} contains {1} entit{2}.", gn + 1, ecnt, ecnt == 1 ? "y" : "ies"); for (int en = 0; en < ecnt; en++) { EntityInfo ent = new EntityInfo(); ent.Model = GetModel(fc, ptr2, key, $"Scene {gn + 1}\\Entity {en + 1} Model.sa2mdl"); ent.Motion = GetMotion(fc, ptr2 + 4, key, $"Scene {gn + 1}\\Entity {en + 1} Motion.saanim", motions, modelfiles[ent.Model].Model.CountAnimated()); if (ent.Motion != null) { modelfiles[ent.Model].Motions.Add(motionfiles[ent.Motion].Filename); } ent.ShapeMotion = GetMotion(fc, ptr2 + 8, key, $"Scene {gn + 1}\\Entity {en + 1} Shape Motion.saanim", motions, modelfiles[ent.Model].Model.CountMorph()); if (ent.ShapeMotion != null) { modelfiles[ent.Model].Motions.Add(motionfiles[ent.ShapeMotion].Filename); } if (battle) { ent.ShadowModel = GetModel(fc, ptr2 + 16, key, $"Scene {gn + 1}\\Entity {en + 1} Shadow Model.sa2mdl"); ent.Position = new Vertex(fc, ptr2 + 24); ent.Flags = ByteConverter.ToUInt32(fc, ptr2 + 40); } else { ent.Position = new Vertex(fc, ptr2 + 16); ent.Flags = ByteConverter.ToUInt32(fc, ptr2 + 28); } scn.Entities.Add(ent); ptr2 += ini.Game == Game.SA2B ? 0x2C : 0x20; } } else { Console.WriteLine("Scene {0} contains no entities.", gn + 1); } ptr2 = fc.GetPointer(ptr + 8, key); if (ptr2 != 0) { int cnt = ByteConverter.ToInt32(fc, ptr + 12); for (int i = 0; i < cnt; i++) { scn.CameraMotions.Add(GetMotion(fc, ptr2, key, $"Scene {gn + 1}\\Camera Motion {i + 1}.saanim", motions, 1)); ptr2 += sizeof(int); } } ptr2 = fc.GetPointer(ptr + 0x18, key); if (ptr2 != 0) { BigInfo big = new BigInfo(); big.Model = GetModel(fc, ptr2, key, $"Scene {gn + 1}\\Big Model.sa2mdl"); if (big.Model != null) { int anicnt = modelfiles[big.Model].Model.CountAnimated(); int ptr3 = fc.GetPointer(ptr2 + 4, key); if (ptr3 != 0) { int cnt = ByteConverter.ToInt32(fc, ptr2 + 8); for (int i = 0; i < cnt; i++) { big.Motions.Add(new string[] { GetMotion(fc, ptr3, key, $"Scene {gn + 1}\\Big Motion {i + 1}a.saanim", motions, anicnt), GetMotion(fc, ptr3 + 4, key, $"Scene {gn + 1}\\Big Motion {i + 1}b.saanim", motions, anicnt) }); ptr3 += 8; } } } big.Unknown = ByteConverter.ToInt32(fc, ptr2 + 12); scn.Big = big; } scn.FrameCount = ByteConverter.ToInt32(fc, ptr + 28); ini.Scenes.Add(scn); ptr += 0x20; } } else { Console.WriteLine("Event contains no scenes."); } ptr = fc.GetPointer(0x1C, key); if (ptr != 0) { ini.TailsTails = GetModel(fc, ptr, key, $"Tails' tails.sa2mdl"); } else { Console.WriteLine("Event does not contain Tails' tails."); } foreach (var item in motionfiles.Values) { string fn = item.Filename ?? $"Unknown Motion {motions.IndexOf(item.Motion)}.saanim"; string fp = Path.Combine(path, fn); item.Motion.Save(fp); ini.Files.Add(fn, HelperFunctions.FileHash(fp)); } foreach (var item in modelfiles.Values) { string fp = Path.Combine(path, item.Filename); ModelFile.CreateFile(fp, item.Model, item.Motions.ToArray(), null, null, null, ModelFormat.Chunk); ini.Files.Add(item.Filename, HelperFunctions.FileHash(fp)); } JsonSerializer js = new JsonSerializer { Formatting = Formatting.Indented, NullValueHandling = NullValueHandling.Ignore }; using (var tw = File.CreateText(Path.Combine(path, Path.ChangeExtension(Path.GetFileName(filename), ".json")))) js.Serialize(tw, ini); } }
private void button5_Click(object sender, EventArgs e) { using (SaveFileDialog fd = new SaveFileDialog() { DefaultExt = "cpp", Filter = "C++ source files|*.cpp", InitialDirectory = Environment.CurrentDirectory, RestoreDirectory = true }) if (fd.ShowDialog(this) == DialogResult.OK) { using (TextWriter writer = File.CreateText(fd.FileName)) { bool SA2 = IniData.Game == Game.SA2B; ModelFormat modelfmt = SA2 ? ModelFormat.Chunk : ModelFormat.BasicDX; LandTableFormat landfmt = SA2 ? LandTableFormat.SA2 : LandTableFormat.SADX; writer.WriteLine("// Generated by SA Tools DLL Mod Generator"); writer.WriteLine(); if (SA2) { writer.WriteLine("#include \"SA2ModLoader.h\""); } else { writer.WriteLine("#include \"SADXModLoader.h\""); } writer.WriteLine(); List <string> labels = new List <string>(); Dictionary <string, uint> texlists = new Dictionary <string, uint>(); foreach (KeyValuePair <string, FileTypeHash> item in IniData.Files.Where((a, i) => listView1.CheckedIndices.Contains(i))) { switch (item.Value.Type) { case "landtable": LandTable tbl = LandTable.LoadFromFile(item.Key); texlists.Add(tbl.Name, tbl.TextureList); tbl.ToStructVariables(writer, landfmt, new List <string>()); labels.AddRange(tbl.GetLabels()); break; case "model": NJS_OBJECT mdl = new ModelFile(item.Key).Model; mdl.ToStructVariables(writer, modelfmt == ModelFormat.BasicDX, new List <string>()); labels.AddRange(mdl.GetLabels()); break; case "basicmodel": case "chunkmodel": mdl = new ModelFile(item.Key).Model; mdl.ToStructVariables(writer, false, new List <string>()); labels.AddRange(mdl.GetLabels()); break; case "basicdxmodel": mdl = new ModelFile(item.Key).Model; mdl.ToStructVariables(writer, true, new List <string>()); labels.AddRange(mdl.GetLabels()); break; case "animation": Animation ani = Animation.Load(item.Key); ani.ToStructVariables(writer); labels.Add(ani.Name); break; } writer.WriteLine(); } writer.WriteLine("extern \"C\" __declspec(dllexport) void __cdecl Init(const char *path, const HelperFunctions &helperFunctions)"); writer.WriteLine("{"); writer.WriteLine("\tHMODULE handle = GetModuleHandle(L\"{0}\");", IniData.Name); List <string> exports = new List <string>(IniData.Items.Where(item => labels.Contains(item.Label)).Select(item => item.Export).Distinct()); foreach (KeyValuePair <string, string> item in IniData.Exports.Where(item => exports.Contains(item.Key))) { writer.WriteLine("\t{0}{1} = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Value], item.Key); } foreach (DllItemInfo item in IniData.Items.Where(item => labels.Contains(item.Label))) { writer.WriteLine("\t{0} = &{1};", item.ToString(), item.Label); } if (texlists.Count > 0 && IniData.TexLists != null && IniData.TexLists.Items != null) { exports = new List <string>(IniData.TexLists.Where(item => texlists.Values.Contains(item.Key)).Select(item => item.Value.Export).Distinct()); foreach (KeyValuePair <string, string> item in IniData.Exports.Where(item => exports.Contains(item.Key))) { writer.WriteLine("\t{0}{1} = ({0})GetProcAddress(handle, \"{1}\");", typemap[item.Value], item.Key); } foreach (KeyValuePair <string, uint> item in texlists.Where(item => IniData.TexLists.ContainsKey(item.Value))) { DllTexListInfo tex = IniData.TexLists[item.Value]; string str; if (tex.Index.HasValue) { str = $"{tex.Export}[{tex.Index.Value}]"; } else { str = tex.Export; } writer.WriteLine("\t{0}.TexList = {1};", item.Key, str); } } writer.WriteLine("}"); writer.WriteLine(); writer.WriteLine("extern \"C\" __declspec(dllexport) const ModInfo {0}ModInfo = {{ ModLoaderVer }};", SA2 ? "SA2" : "SADX"); } } }
static void Main(string[] args) { string datafilename, inifilename; if (args.Length > 0) { datafilename = args[0]; Console.WriteLine("File: {0}", datafilename); } else { Console.Write("File: "); datafilename = Console.ReadLine(); } if (args.Length > 1) { inifilename = args[1]; Console.WriteLine("INI File: {0}", inifilename); } else { Console.Write("INI File: "); inifilename = Console.ReadLine(); } byte[] datafile = File.ReadAllBytes(datafilename); IniData inifile = IniSerializer.Deserialize <IniData>(inifilename); uint imageBase = HelperFunctions.SetupEXE(ref datafile).Value; Dictionary <string, int> exports; { int ptr = BitConverter.ToInt32(datafile, BitConverter.ToInt32(datafile, 0x3c) + 4 + 20 + 96); GCHandle handle = GCHandle.Alloc(datafile, GCHandleType.Pinned); IMAGE_EXPORT_DIRECTORY dir = (IMAGE_EXPORT_DIRECTORY)Marshal.PtrToStructure( Marshal.UnsafeAddrOfPinnedArrayElement(datafile, ptr), typeof(IMAGE_EXPORT_DIRECTORY)); handle.Free(); exports = new Dictionary <string, int>(dir.NumberOfFunctions); int nameaddr = dir.AddressOfNames; int ordaddr = dir.AddressOfNameOrdinals; for (int i = 0; i < dir.NumberOfNames; i++) { string name = HelperFunctions.GetCString(datafile, BitConverter.ToInt32(datafile, nameaddr), System.Text.Encoding.ASCII); int addr = BitConverter.ToInt32(datafile, dir.AddressOfFunctions + (BitConverter.ToInt16(datafile, ordaddr) * 4)); exports.Add(name, addr); nameaddr += 4; ordaddr += 2; } } ModelFormat modelfmt = 0; LandTableFormat landfmt = 0; string modelext = null; string landext = null; switch (inifile.Game) { case Game.SADX: modelfmt = ModelFormat.BasicDX; landfmt = LandTableFormat.SADX; modelext = ".sa1mdl"; landext = ".sa1lvl"; break; case Game.SA2B: modelfmt = ModelFormat.Chunk; landfmt = LandTableFormat.SA2; modelext = ".sa2mdl"; landext = ".sa2lvl"; break; } int itemcount = 0; List <string> labels = new List <string>(); ModelAnimationsDictionary models = new ModelAnimationsDictionary(); DllIniData output = new DllIniData() { Name = inifile.ModuleName, Game = inifile.Game }; Stopwatch timer = new Stopwatch(); timer.Start(); foreach (KeyValuePair <string, FileInfo> item in inifile.Files) { if (string.IsNullOrEmpty(item.Key)) { continue; } FileInfo data = item.Value; string type = data.Type; string name = item.Key; output.Exports[name] = type; int address = exports[name]; if (data.Filename != null) { Console.WriteLine(name + " -> " + data.Filename); Directory.CreateDirectory(Path.GetDirectoryName(data.Filename)); } else { Console.WriteLine(name); } switch (type) { case "landtable": { LandTable land = new LandTable(datafile, address, imageBase, landfmt) { Description = name, Tool = "splitDLL" }; DllItemInfo info = new DllItemInfo() { Export = name, Label = land.Name }; output.Items.Add(info); if (!labels.Contains(land.Name)) { land.SaveToFile(data.Filename, landfmt); output.Files[data.Filename] = new FileTypeHash("landtable", HelperFunctions.FileHash(data.Filename)); labels.AddRange(land.GetLabels()); } } break; case "landtablearray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; LandTable land = new LandTable(datafile, ptr, imageBase, landfmt) { Description = idx, Tool = "splitDLL" }; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = land.Name }; output.Items.Add(info); if (!labels.Contains(land.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + landext); land.SaveToFile(fn, landfmt); output.Files[fn] = new FileTypeHash("landtable", HelperFunctions.FileHash(fn)); labels.AddRange(land.GetLabels()); } } address += 4; } break; case "model": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, modelfmt); DllItemInfo info = new DllItemInfo() { Export = name, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { models.Add(new ModelAnimations(data.Filename, name, mdl, modelfmt)); labels.AddRange(mdl.GetLabels()); } } break; case "morph": { BasicAttach dummy = new BasicAttach(datafile, address, imageBase, modelfmt == ModelFormat.BasicDX); NJS_OBJECT mdl = new NJS_OBJECT() { Attach = dummy }; DllItemInfo info = new DllItemInfo() { Export = name, Label = dummy.Name }; output.Items.Add(info); if (!labels.Contains(dummy.Name)) { models.Add(new ModelAnimations(data.Filename, name, mdl, modelfmt)); labels.AddRange(mdl.GetLabels()); } } break; case "modelarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); NJS_OBJECT mdl = new NJS_OBJECT(datafile, ptr, imageBase, modelfmt); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + modelext); models.Add(new ModelAnimations(fn, idx, mdl, modelfmt)); labels.AddRange(mdl.GetLabels()); } } address += 4; } break; case "modelsarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); BasicAttach dummy = new BasicAttach(datafile, ptr, imageBase, modelfmt == ModelFormat.BasicDX); NJS_OBJECT mdl = new NJS_OBJECT() { Attach = dummy }; string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = dummy.Name }; output.Items.Add(info); if (!labels.Contains(dummy.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + modelext); models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.BasicDX)); labels.AddRange(mdl.GetLabels()); } } address += 4; } break; case "basicmodel": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Basic); DllItemInfo info = new DllItemInfo() { Export = name, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.Basic)); labels.AddRange(mdl.GetLabels()); } } break; case "basicmodelarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); NJS_OBJECT mdl = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.Basic); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa1mdl"); models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.Basic)); labels.AddRange(mdl.GetLabels()); } } address += 4; } break; case "basicdxmodel": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.BasicDX); DllItemInfo info = new DllItemInfo() { Export = name, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.BasicDX)); labels.AddRange(mdl.GetLabels()); } } break; case "basicdxmodelarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); NJS_OBJECT mdl = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.BasicDX); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa1mdl"); models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.BasicDX)); labels.AddRange(mdl.GetLabels()); } } address += 4; } break; case "chunkmodel": { NJS_OBJECT mdl = new NJS_OBJECT(datafile, address, imageBase, ModelFormat.Chunk); DllItemInfo info = new DllItemInfo() { Export = name, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { models.Add(new ModelAnimations(data.Filename, name, mdl, ModelFormat.Chunk)); labels.AddRange(mdl.GetLabels()); } } break; case "chunkmodelarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); NJS_OBJECT mdl = new NJS_OBJECT(datafile, ptr, imageBase, ModelFormat.Chunk); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = mdl.Name }; output.Items.Add(info); if (!labels.Contains(mdl.Name)) { string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".sa2mdl"); models.Add(new ModelAnimations(fn, idx, mdl, ModelFormat.Chunk)); labels.AddRange(mdl.GetLabels()); } } address += 4; } break; case "actionarray": for (int i = 0; i < data.Length; i++) { int ptr = BitConverter.ToInt32(datafile, address); if (ptr != 0) { ptr = (int)(ptr - imageBase); AnimationHeader ani = new AnimationHeader(datafile, ptr, imageBase, modelfmt); string idx = name + "[" + i.ToString(NumberFormatInfo.InvariantInfo) + "]"; ani.Animation.Name = item.Key + "_" + i; DllItemInfo info = new DllItemInfo() { Export = name, Index = i, Label = ani.Animation.Name, Field = "motion" }; output.Items.Add(info); info = new DllItemInfo() { Export = name, Index = i, Label = ani.Model.Name, Field = "object" }; output.Items.Add(info); string fn = Path.Combine(data.Filename, i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim"); ani.Animation.Save(fn); output.Files[fn] = new FileTypeHash("animation", HelperFunctions.FileHash(fn)); if (models.Contains(ani.Model.Name)) { ModelAnimations mdl = models[ani.Model.Name]; System.Text.StringBuilder sb = new System.Text.StringBuilder(260); PathRelativePathTo(sb, Path.GetFullPath(mdl.Filename), 0, Path.GetFullPath(fn), 0); mdl.Animations.Add(sb.ToString()); } else { string mfn = Path.ChangeExtension(fn, modelext); ModelFile.CreateFile(mfn, ani.Model, new[] { Path.GetFileName(fn) }, null, null, idx + "->object", "splitDLL", null, modelfmt); output.Files[mfn] = new FileTypeHash("model", HelperFunctions.FileHash(mfn)); } } address += 4; } break; case "texlist": if (output.TexLists == null) { output.TexLists = new TexListContainer(); } output.TexLists.Add((uint)(address + imageBase), new DllTexListInfo(name, null)); break; case "texlistarray": if (output.TexLists == null) { output.TexLists = new TexListContainer(); } for (int i = 0; i < data.Length; i++) { uint ptr = BitConverter.ToUInt32(datafile, address); if (ptr != 0 && !output.TexLists.ContainsKey(ptr)) { output.TexLists.Add(ptr, new DllTexListInfo(name, i)); } address += 4; } break; } itemcount++; } foreach (ModelAnimations item in models) { ModelFile.CreateFile(item.Filename, item.Model, item.Animations.ToArray(), null, null, item.Name, "splitDLL", null, item.Format); string type = "model"; switch (item.Format) { case ModelFormat.Basic: type = "basicmodel"; break; case ModelFormat.BasicDX: type = "basicdxmodel"; break; case ModelFormat.Chunk: type = "chunkmodel"; break; } output.Files[item.Filename] = new FileTypeHash(type, HelperFunctions.FileHash(item.Filename)); } IniSerializer.Serialize(output, Path.Combine(Environment.CurrentDirectory, Path.GetFileNameWithoutExtension(datafilename)) + "_data.ini"); timer.Stop(); Console.WriteLine("Split " + itemcount + " items in " + timer.Elapsed.TotalSeconds + " seconds."); Console.WriteLine(); }
internal IEnumerator LoadMap(string s, Action onError = null, Action onLoaded = null) { mapLoading = true; loadMap = null; unityMap = ""; swirl = 0; scale = 1; print(mainSite + s); WWW www = new WWW(mainSite + s); yield return(www); if (!string.IsNullOrEmpty(www.error)) { if (onError != null) { onError(); } yield break; } BinaryReader ms = new BinaryReader(www.bytes); Debug.LogWarning("Loading Map " + ms.Length + " " + s); int version = 0; Dictionary <int, CurvySpline2> saveIds = new Dictionary <int, CurvySpline2>(); //bool ingame = _Game != null; //HashSet<KeyValuePair<Vector3, string>> cells = new HashSet<KeyValuePair<Vector3, string>>(); ModelObject modelObject = null; var enumType = typeof(LevelPackets); //var levelPackets = Enum.GetValues(enumType); LevelPackets P, oldP = LevelPackets.Unknown; while (ms.Position < ms.Length) { try { P = (LevelPackets)ms.ReadInt(); if (!Enum.IsDefined(enumType, P)) { ms.Position++; if (isDebug) { Debug.LogError("wrong Levelpacked " + oldP); } else { Loader.errors++; } P = (LevelPackets)ms.ReadInt(); if (!Enum.IsDefined(enumType, P)) { ms.Position--; continue; } } } catch (Exception e) { Debug.LogError(e); continue; } oldP = P; if (P == LevelPackets.unityMap) { var map = ms.ReadString(); yield return(StartCoroutine(LoadUnityMap(map))); } if (P == LevelPackets.Spline) { yield return(StartCoroutine(CreateSpline())); } if (P == LevelPackets.shape) { yield return(StartCoroutine(CreateSpline(null, true))); spline.CreatePivot(ms.ReadVector()); spline.saveId = ms.ReadInt(); saveIds[spline.saveId] = spline; spline.tunnel = ms.ReadBool(); spline.materialId = ms.ReadInt(); spline.color = ms.readColor(); spline.name = ms.ReadString(); } try { if (P == LevelPackets.flatTerrain) { SetFlatTerrain(true); } if (P == LevelPackets.ClosedSpline) { spline.Closed = true; } if (P == LevelPackets.CheckPoint2) { var t = SetCheckPoint(ms.ReadVector()); t.eulerAngles = ms.ReadVector(); } if (P == LevelPackets.disableTerrain) { hideTerrain = true; } if (P == LevelPackets.Block) { var readString = ms.ReadString(); GameObject go; if (modelLib == null) { Debug.LogWarning("Model lib not loaded"); go = GameObject.CreatePrimitive(PrimitiveType.Cube); } else if (modelLib.dict.ContainsKey(readString) && modelLib.dict[readString].gameObj != null) { ModelFile modelFile = modelLib.dict[readString]; var gameObj = modelFile.gameObj; modelFile.usedCount++; go = (GameObject)Instantiate(gameObj); go.name = gameObj.name; } else { go = GameObject.CreatePrimitive(PrimitiveType.Cube); Debug.LogWarning(readString + " not found "); } go.name = readString; modelObject = InitModel(go, readString); modelObject.transform.position = ms.ReadVector(); modelObject.transform.eulerAngles = ms.ReadVector(); modelObject.transform.localScale = ms.ReadVector(); //if (!cells.Add(new KeyValuePair<Vector3, string>(g.pos, go.name))) //{ // Debug.Log("Destroy duplicate " + go.name, go); // Debug.Log("with " + go.name, go); // if (ingame) // Destroy(go); //} } if (P == LevelPackets.FlyingModel && modelObject != null) { modelObject.flying = true; } if (P == LevelPackets.roadtype) { spline.roadType = (RoadType)ms.ReadByte2(); } if (P == LevelPackets.Wall) { spline.wallTexture = true; } if (P == LevelPackets.shapeMaterial) { string readString = ms.ReadString(); spline.thumb = new Thumbnail() { url = Regex.Replace(readString, @"https?://server.critical-missions.com/tm/|https?://tmrace.net/tm/", "") }; //Debug.LogWarning(readString); } if (P == LevelPackets.textureTile) { spline.thumb.material.mainTextureScale = ms.ReadVector(); } if (P == LevelPackets.AntiFly) { _GameSettings.gravitationAntiFly = ms.ReadFloat(); _GameSettings.gravitationFactor = ms.ReadFloat(); } if (P == LevelPackets.Flying) { segment.flying = ms.ReadBool(); } if (P == LevelPackets.heightOffset) { spline.heightOffset = ms.ReadFloat(); } if (P == LevelPackets.Version) { version = ms.ReadInt(); if (version >= 702) { foreach (var a in shapes.ToArray()) { print("removing default brush " + a.name); Destroy(a.gameObject); } } } if (P == LevelPackets.Nitro) { Debug.Log("Nitro Loaded " + nitro); nitro = ms.ReadFloat(); } if (P == LevelPackets.Point) { var readVector = ms.ReadVector(); AddPoint(readVector); if (version >= 702) { segment.spls = new List <CurvySpline2>(); } else { segment.spls = new List <CurvySpline2>(new[] { brushShapes[0] }); } segment.swirl = ms.ReadFloat(); } if (P == LevelPackets.brush) { segment.spls.Add(saveIds[ms.ReadInt()]); } if (P == LevelPackets.Material) { spline.materialId = ms.ReadInt(); print("Set Material " + spline.materialId); spline.color = ms.readColor(); } if (P == LevelPackets.Finnish) { finnish = true; } if (P == LevelPackets.CheckPoint) { SetCheckPoint(segment); } if (P == LevelPackets.Start) { SetStartPoint(segment); start.transform.parent = segment.transform; } if (P == LevelPackets.StartPos) { SetStartPoint(ms.ReadVector(), ms.ReadVector()); } if (P == LevelPackets.Laps) { laps = ms.ReadInt(); _GameSettings.laps = laps; } if (P == LevelPackets.scale) { segment.scale = ms.ReadFloat(); } if (P == LevelPackets.levelTime) { _GameSettings.levelTime = ms.ReadFloat(); } if (P == LevelPackets.rotateTexture) { spline.rotateTexture = true; } if (P == LevelPackets.disableJump) { _Loader.curSceneDef.disableJump = true; } } catch (Exception e) { Debug.LogError(e); } } print("Map Version " + version); if (onLoaded != null) { onLoaded(); } userMapSucces = true; UpdateTerrain(null, true, _Loader.levelEditor == null); if (!_Loader.levelEditor) { Optimize2(); } mapLoading = false; if (isDebug && modelLib != null) { bool parsed = setting.parsedLevels.Contains(_Loader.mapName); if (!parsed) { setting.parsedLevels.Add(_Loader.mapName); } foreach (var a in modelLib.models) { if (!parsed) { setting.Popularity[a.path] = setting.Popularity.TryGet(a.path, 0) + Mathf.Sqrt(Mathf.Sqrt(a.usedCount)); } //if (a.usedCountSqrt != 0) // print(a.name + ":" + a.usedCountSqrt); a.usedCount = 0; } setting.populartyKeys = new List <string>(setting.Popularity.Keys); setting.populartyValues = new List <float>(setting.Popularity.Values); SetDirty(res); } }
/// <summary> /// Process mesh internals<para/> /// Обработка данных меша /// </summary> public void Process(bool needed) { if (needed) { if (GroupModel != null) { if (GroupTextures != null) { if (GroupModel.State == Model.ReadyState.Complete && GroupTextures.State == TextureDictionary.ReadyState.Complete) { // Surface is ready to render // Поверхность готова к отрисовке Ready = true; Model.SubMesh[] subs = GroupModel.GetAllSubMeshes(); Renderers = new StaticRenderer[subs.Length]; Coords.Position = Coords.Position; for (int i = 0; i < Renderers.Length; i++) { Renderers[i] = new StaticRenderer() { BaseMatrix = Coords.Matrix, SubmeshMatrix = subs[i].Parent.Matrix, SubMesh = subs[i], Textures = GroupTextures, Fading = false, FadingDelta = 1 }; } } else { // Check for model state // Проверка состояния модели if (GroupModel.State != Model.ReadyState.Complete) { if (GroupModel.File.State == Files.RenderWareFile.LoadState.Complete) { if (!ModelManager.IsProcessing(GroupModel)) { ModelManager.ModelProcessQueue.Enqueue(GroupModel); } } } // Check for texture dictionary state // Проверка состояния архива текстур if (GroupTextures.State != TextureDictionary.ReadyState.Complete) { if (GroupTextures.File.State == Files.RenderWareFile.LoadState.Complete) { if (!TextureManager.IsProcessing(GroupTextures)) { TextureManager.TextureProcessQueue.Enqueue(GroupTextures); } } } } } else { // Texture not found - get it // Текстура не найдена - получаем её string tname = ObjectManager.Definitions[Definition.ID].TexDictionary; if (TextureManager.Cached.ContainsKey(tname)) { GroupTextures = TextureManager.Cached[tname]; } else { TextureFile tf = null; if (TextureManager.CachedFiles.ContainsKey(tname)) { tf = TextureManager.CachedFiles[tname]; } else { tf = new TextureFile(ArchiveManager.Get(tname + ".txd"), false); TextureManager.CachedFiles.TryAdd(tname, tf); TextureManager.TextureFileProcessQueue.Enqueue(tf); } GroupTextures = new TextureDictionary(tf); TextureManager.Cached.TryAdd(tname, GroupTextures); } GroupTextures.UseCount++; } } else { // Model not found - get it // Модель не найдена - получаем её string mname = ObjectManager.Definitions[Definition.ID].ModelName; if (ModelManager.Cached.ContainsKey(mname)) { GroupModel = ModelManager.Cached[mname]; } else { ModelFile mf = null; if (ModelManager.CachedFiles.ContainsKey(mname)) { mf = ModelManager.CachedFiles[mname]; } else { mf = new ModelFile(ArchiveManager.Get(mname + ".dff"), false); ModelManager.CachedFiles.TryAdd(mname, mf); ModelManager.ModelFileProcessQueue.Enqueue(mf); } GroupModel = new Model(mf); ModelManager.Cached.TryAdd(mname, GroupModel); } GroupModel.UseCount++; } } else { // Cleaning all the usings // Очистка использований if (GroupModel != null) { if (!GroupModel.Important) { GroupModel.UseCount--; } GroupModel = null; } if (GroupTextures != null) { if (!GroupTextures.Important) { GroupTextures.UseCount--; } GroupTextures = null; } if (Renderers != null) { Renderers = null; } Ready = false; } }
public static List <Item> ImportFromFile(string filePath, EditorCamera camera, out bool errorFlag, out string errorMsg, EditorItemSelection selectionManager, OnScreenDisplay osd, bool multiple = false) { List <Item> createdItems = new List <Item>(); if (!File.Exists(filePath)) { errorFlag = true; errorMsg = "File does not exist!"; return(null); } DirectoryInfo filePathInfo = new DirectoryInfo(filePath); bool importError = false; string importErrorMsg = ""; Vector3 pos = camera.Position + (-20 * camera.Look); switch (filePathInfo.Extension) { case ".sa1mdl": ModelFile mf = new ModelFile(filePath); NJS_OBJECT objm = mf.Model; osd.ClearMessageList(); osd.AddMessage("Importing models, please wait...", 3000); osd.ClearMessageList(); createdItems.AddRange(ImportFromHierarchy(objm, selectionManager, osd, multiple)); osd.AddMessage("Stage import complete!", 100); break; case ".obj": case ".objf": LevelItem item = new LevelItem(filePath, new Vertex(pos.X, pos.Y, pos.Z), new Rotation(), levelItems.Count, selectionManager) { Visible = true }; createdItems.Add(item); break; case ".txt": NodeTable.ImportFromFile(filePath, out importError, out importErrorMsg, selectionManager); break; case ".dae": case ".fbx": Assimp.AssimpContext context = new Assimp.AssimpContext(); Assimp.Configs.FBXPreservePivotsConfig conf = new Assimp.Configs.FBXPreservePivotsConfig(false); context.SetConfig(conf); Assimp.Scene scene = context.ImportFile(filePath, Assimp.PostProcessSteps.Triangulate); for (int i = 0; i < scene.RootNode.ChildCount; i++) { osd.ClearMessageList(); osd.AddMessage("Importing model " + i.ToString() + " of " + scene.RootNode.ChildCount.ToString() + "...", 3000); Assimp.Node child = scene.RootNode.Children[i]; List <Assimp.Mesh> meshes = new List <Assimp.Mesh>(); foreach (int j in child.MeshIndices) { meshes.Add(scene.Meshes[j]); } bool isVisible = true; for (int j = 0; j < child.MeshCount; j++) { if (scene.Materials[meshes[j].MaterialIndex].Name.Contains("Collision")) { isVisible = false; break; } } ModelFormat mfmt = ModelFormat.Basic; if (isVisible) { switch (geo.Format) { case LandTableFormat.SA2: mfmt = ModelFormat.Chunk; break; case LandTableFormat.SA2B: mfmt = ModelFormat.GC; break; } } NJS_OBJECT obj = AssimpStuff.AssimpImport(scene, child, mfmt, TextureBitmaps[leveltexs].Select(a => a.Name).ToArray(), !multiple); { //sa2 collision patch if (obj.Attach.GetType() == typeof(BasicAttach)) { BasicAttach ba = obj.Attach as BasicAttach; foreach (NJS_MATERIAL mats in ba.Material) { mats.DoubleSided = true; } } //cant check for transparent texture so i gotta force alpha for now, temporary else if (obj.Attach.GetType() == typeof(ChunkAttach)) { ChunkAttach ca = obj.Attach as ChunkAttach; foreach (PolyChunk polys in ca.Poly) { if (polys.GetType() == typeof(PolyChunkMaterial)) { PolyChunkMaterial mat = polys as PolyChunkMaterial; mat.SourceAlpha = AlphaInstruction.SourceAlpha; mat.DestinationAlpha = AlphaInstruction.InverseSourceAlpha; } else if (polys.GetType() == typeof(PolyChunkStrip)) { PolyChunkStrip str = polys as PolyChunkStrip; //str.UseAlpha = true; } } } } obj.Attach.ProcessVertexData(); LevelItem newLevelItem = new LevelItem(obj.Attach, new Vertex(obj.Position.X + pos.X, obj.Position.Y + pos.Y, obj.Position.Z + pos.Z), obj.Rotation, levelItems.Count, selectionManager) { Visible = isVisible }; createdItems.Add(newLevelItem); } osd.ClearMessageList(); osd.AddMessage("Stage import complete!", 100); break; default: errorFlag = true; errorMsg = "Invalid file format!"; return(null); } StateChanged(); errorFlag = importError; errorMsg = importErrorMsg; return(createdItems); }
public void ExportModel() { string defaultex; switch (COL.Model.GetModelFormat()) { case ModelFormat.Chunk: defaultex = ".sa2mdl"; break; case ModelFormat.GC: defaultex = ".sa2bmdl"; break; case ModelFormat.Basic: case ModelFormat.BasicDX: default: defaultex = ".sa1mdl"; break; } using (System.Windows.Forms.SaveFileDialog a = new System.Windows.Forms.SaveFileDialog { FileName = Name + defaultex, Filter = "SAModel Files|*.sa?mdl|Collada|*.dae|Wavefront|*.obj" }) { if (a.ShowDialog() == System.Windows.Forms.DialogResult.OK) { string ftype = "collada"; switch (System.IO.Path.GetExtension(a.FileName).ToLowerInvariant()) { case ".sa1mdl": case ".sa2mdl": case ".sa2bmdl": ModelFile.CreateFile(a.FileName, COL.Model, null, null, null, null, COL.Model.GetModelFormat()); return; case ".fbx": ftype = "fbx"; break; case ".obj": ftype = "obj"; break; } Assimp.AssimpContext context = new Assimp.AssimpContext(); Assimp.Scene scene = new Assimp.Scene(); scene.Materials.Add(new Assimp.Material()); Assimp.Node n = new Assimp.Node(); n.Name = "RootNode"; scene.RootNode = n; string rootPath = System.IO.Path.GetDirectoryName(a.FileName); List <string> texturePaths = new List <string>(); int numSteps = 0; if (LevelData.TextureBitmaps != null && LevelData.TextureBitmaps.Count > 0) { numSteps = LevelData.TextureBitmaps[LevelData.leveltexs].Length; } for (int i = 0; i < numSteps; i++) { BMPInfo bmp = LevelData.TextureBitmaps[LevelData.leveltexs][i]; texturePaths.Add(System.IO.Path.Combine(rootPath, bmp.Name + ".png")); bmp.Image.Save(System.IO.Path.Combine(rootPath, bmp.Name + ".png")); } SAEditorCommon.Import.AssimpStuff.AssimpExport(COL.Model, scene, Matrix.Identity, texturePaths.Count > 0 ? texturePaths.ToArray() : null, scene.RootNode); context.ExportFile(scene, a.FileName, ftype, Assimp.PostProcessSteps.ValidateDataStructure | Assimp.PostProcessSteps.Triangulate | Assimp.PostProcessSteps.FlipUVs); // } } }
public static void Split(bool isBigEndian, string filePath, string outputFolder, string[] animationPaths) { string dir = Environment.CurrentDirectory; try { if (outputFolder[outputFolder.Length - 1] != '/') { outputFolder = string.Concat(outputFolder, "/"); } ByteConverter.BigEndian = isBigEndian; // get file name, read it from the console if nothing string mdlfilename = filePath; mdlfilename = Path.GetFullPath(mdlfilename); // look through the argumetns for animationfiles string[] anifilenames = animationPaths; // load model file Environment.CurrentDirectory = (outputFolder.Length != 0) ? outputFolder : Path.GetDirectoryName(mdlfilename); byte[] mdlfile = File.ReadAllBytes(mdlfilename); if (Path.GetExtension(mdlfilename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) { mdlfile = FraGag.Compression.Prs.Decompress(mdlfile); } Directory.CreateDirectory(Path.GetFileNameWithoutExtension(mdlfilename)); // getting model pointers int address = 0; int i = ByteConverter.ToInt32(mdlfile, address); SortedDictionary <int, int> modeladdrs = new SortedDictionary <int, int>(); while (i != -1) { modeladdrs[i] = ByteConverter.ToInt32(mdlfile, address + 4); address += 8; i = ByteConverter.ToInt32(mdlfile, address); } // load models from pointer list Dictionary <int, NJS_OBJECT> models = new Dictionary <int, NJS_OBJECT>(); Dictionary <int, string> modelnames = new Dictionary <int, string>(); List <string> partnames = new List <string>(); foreach (KeyValuePair <int, int> item in modeladdrs) { NJS_OBJECT obj = new NJS_OBJECT(mdlfile, item.Value, 0, ModelFormat.Chunk); modelnames[item.Key] = obj.Name; if (!partnames.Contains(obj.Name)) { List <string> names = new List <string>(obj.GetObjects().Select((o) => o.Name)); foreach (int idx in modelnames.Where(a => names.Contains(a.Value)).Select(a => a.Key)) { models.Remove(idx); } models[item.Key] = obj; partnames.AddRange(names); } } // load animations Dictionary <int, string> animfns = new Dictionary <int, string>(); Dictionary <int, NJS_MOTION> anims = new Dictionary <int, NJS_MOTION>(); foreach (string anifilename in anifilenames) { Dictionary <int, int> processedanims = new Dictionary <int, int>(); Dictionary <int, string> ini = new Dictionary <int, string>(); byte[] anifile = File.ReadAllBytes(anifilename); if (Path.GetExtension(anifilename).Equals(".prs", StringComparison.OrdinalIgnoreCase)) { anifile = FraGag.Compression.Prs.Decompress(anifile); } Directory.CreateDirectory(Path.GetFileNameWithoutExtension(anifilename)); address = 0; i = ByteConverter.ToInt16(anifile, address); while (i != -1) { int aniaddr = ByteConverter.ToInt32(anifile, address + 4); if (!processedanims.ContainsKey(aniaddr)) { anims[i] = new NJS_MOTION(anifile, ByteConverter.ToInt32(anifile, address + 4), 0, ByteConverter.ToInt16(anifile, address + 2)); animfns[i] = Path.Combine(Path.GetFileNameWithoutExtension(anifilename), i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim"); anims[i].Save(animfns[i]); processedanims[aniaddr] = i; } ini[i] = "animation_" + aniaddr.ToString("X8"); address += 8; i = ByteConverter.ToInt16(anifile, address); } IniSerializer.Serialize(ini, new IniCollectionSettings(IniCollectionMode.IndexOnly), Path.Combine(Path.GetFileNameWithoutExtension(anifilename), Path.GetFileNameWithoutExtension(anifilename) + ".ini")); } // save output model files foreach (KeyValuePair <int, NJS_OBJECT> model in models) { List <string> animlist = new List <string>(); foreach (KeyValuePair <int, NJS_MOTION> anim in anims) { if (model.Value.CountAnimated() == anim.Value.ModelParts) { string rel = animfns[anim.Key].Replace(outputFolder, string.Empty); if (rel.Length > 1 && rel[1] != ':') { rel = "../" + rel; } animlist.Add(rel); } } ModelFile.CreateFile(Path.Combine(Path.GetFileNameWithoutExtension(mdlfilename), model.Key.ToString(NumberFormatInfo.InvariantInfo) + ".sa2mdl"), model.Value, animlist.ToArray(), null, null, null, null, ModelFormat.Chunk); } // save ini file IniSerializer.Serialize(modelnames, new IniCollectionSettings(IniCollectionMode.IndexOnly), Path.Combine(Path.GetFileNameWithoutExtension(mdlfilename), Path.GetFileNameWithoutExtension(mdlfilename) + ".ini")); } finally { Environment.CurrentDirectory = dir; } }
public static void InitGizmo(Device d3dDevice) { Attach attach = new ModelFile(Resources.x_null).Model.Attach; attach.ProcessVertexData(); XNullMesh = attach.CreateD3DMesh(); attach = new ModelFile(Resources.y_null).Model.Attach; attach.ProcessVertexData(); YNullMesh = attach.CreateD3DMesh(); attach = new ModelFile(Resources.z_null).Model.Attach; attach.ProcessVertexData(); ZNullMesh = attach.CreateD3DMesh(); attach = new ModelFile(Resources.x_move).Model.Attach; attach.ProcessVertexData(); XMoveMesh = attach.CreateD3DMesh(); XMaterial = ((BasicAttach)attach).Material[0]; attach = new ModelFile(Resources.y_move).Model.Attach; attach.ProcessVertexData(); YMoveMesh = attach.CreateD3DMesh(); YMaterial = ((BasicAttach)attach).Material[0]; attach = new ModelFile(Resources.z_move).Model.Attach; attach.ProcessVertexData(); ZMoveMesh = attach.CreateD3DMesh(); ZMaterial = ((BasicAttach)attach).Material[0]; attach = new ModelFile(Resources.xy_move).Model.Attach; attach.ProcessVertexData(); XYMoveMesh = attach.CreateD3DMesh(); DoubleAxisMaterial = ((BasicAttach)attach).Material[0]; attach = new ModelFile(Resources.zx_move).Model.Attach; attach.ProcessVertexData(); ZXMoveMesh = attach.CreateD3DMesh(); attach = new ModelFile(Resources.zy_move).Model.Attach; attach.ProcessVertexData(); ZYMoveMesh = attach.CreateD3DMesh(); attach = new ModelFile(Resources.x_rotation).Model.Attach; attach.ProcessVertexData(); XRotateMesh = attach.CreateD3DMesh(); attach = new ModelFile(Resources.y_rotation).Model.Attach; attach.ProcessVertexData(); YRotateMesh = attach.CreateD3DMesh(); attach = new ModelFile(Resources.z_rotation).Model.Attach; attach.ProcessVertexData(); ZRotateMesh = attach.CreateD3DMesh(); attach = new ModelFile(Resources.x_scale).Model.Attach; attach.ProcessVertexData(); XScaleMesh = attach.CreateD3DMesh(); attach = new ModelFile(Resources.y_scale).Model.Attach; attach.ProcessVertexData(); YScaleMesh = attach.CreateD3DMesh(); attach = new ModelFile(Resources.z_scale).Model.Attach; attach.ProcessVertexData(); ZScaleMesh = attach.CreateD3DMesh(); BoxMesh = Mesh.Box(1, 1, 1); HighlightMaterial = new NJS_MATERIAL() { DiffuseColor = Color.LightGoldenrodYellow, Exponent = 0f, UseTexture = false, IgnoreLighting = true, IgnoreSpecular = true }; ATexture = Resources.PointATexture.ToTexture(d3dDevice); BTexture = Resources.PointBTexture.ToTexture(d3dDevice); StandardMaterial = new NJS_MATERIAL() { DiffuseColor = Color.Gray, IgnoreLighting = true, IgnoreSpecular = true, UseAlpha = false, UseTexture = true, Exponent = 100f }; }
/// <summary> /// Exports a single level, model or animation file as text. /// </summary> /// <param name="source">Source pathname.</param> /// <param name="type">Type of text conversion.</param> /// <param name="destination">Destination pathname. Leave blank to export in the same folder with a swapped extension.</param> /// <param name="basicDX">Use the SADX2004 format for Basic models.</param> public static void ConvertFileToText(string source, TextType type, string destination = "", bool basicDX = true, bool overwrite = true) { string outext = ".c"; string extension = Path.GetExtension(source); switch (extension.ToLowerInvariant()) { case ".sa2lvl": case ".sa1lvl": if (type == TextType.CStructs || type == TextType.NJA) { if (destination == "") { destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext); } if (!overwrite && File.Exists(destination)) { while (File.Exists(destination)) { destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext); } } LandTable land = LandTable.LoadFromFile(source); List <string> labels = new List <string>() { land.Name }; LandTableFormat fmt = land.Format; using (StreamWriter sw = File.CreateText(destination)) { if (type == TextType.CStructs) { sw.Write("/* Sonic Adventure "); switch (land.Format) { case LandTableFormat.SA1: case LandTableFormat.SADX: if (basicDX) { sw.Write("DX"); fmt = LandTableFormat.SADX; } else { sw.Write("1"); fmt = LandTableFormat.SA1; } break; case LandTableFormat.SA2: sw.Write("2"); fmt = LandTableFormat.SA2; break; case LandTableFormat.SA2B: sw.Write("2 Battle"); fmt = LandTableFormat.SA2B; break; } sw.WriteLine(" LandTable"); sw.WriteLine(" * "); sw.WriteLine(" * Generated by DataToolbox"); sw.WriteLine(" * "); if (!string.IsNullOrEmpty(land.Description)) { sw.Write(" * Description: "); sw.WriteLine(land.Description); sw.WriteLine(" * "); } if (!string.IsNullOrEmpty(land.Author)) { sw.Write(" * Author: "); sw.WriteLine(land.Author); sw.WriteLine(" * "); } sw.WriteLine(" */"); sw.WriteLine(); } land.ToStructVariables(sw, fmt, labels, null, type == TextType.NJA); sw.Flush(); sw.Close(); } } break; case ".sa1mdl": case ".sa2mdl": ModelFile modelFile = new ModelFile(source); NJS_OBJECT model = modelFile.Model; List <NJS_MOTION> animations = new List <NJS_MOTION>(modelFile.Animations); if (type == TextType.CStructs) { outext = ".c"; if (destination == "") { destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext); } if (!overwrite && File.Exists(destination)) { while (File.Exists(destination)) { destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext); } } using (StreamWriter sw = File.CreateText(destination)) { sw.Write("/* NINJA "); switch (modelFile.Format) { case ModelFormat.Basic: case ModelFormat.BasicDX: if (basicDX) { sw.Write("Basic (with Sonic Adventure DX additions)"); } else { sw.Write("Basic"); } break; case ModelFormat.Chunk: sw.Write("Chunk"); break; case ModelFormat.GC: sw.Write("GC"); break; } sw.WriteLine(" model"); sw.WriteLine(" * "); sw.WriteLine(" * Generated by DataToolbox"); sw.WriteLine(" * "); if (modelFile != null) { if (!string.IsNullOrEmpty(modelFile.Description)) { sw.Write(" * Description: "); sw.WriteLine(modelFile.Description); sw.WriteLine(" * "); } if (!string.IsNullOrEmpty(modelFile.Author)) { sw.Write(" * Author: "); sw.WriteLine(modelFile.Author); sw.WriteLine(" * "); } } sw.WriteLine(" */"); sw.WriteLine(); List <string> labels_m = new List <string>() { model.Name }; model.ToStructVariables(sw, basicDX, labels_m, null); foreach (NJS_MOTION anim in animations) { anim.ToStructVariables(sw); } sw.Flush(); sw.Close(); } } else if (type == TextType.NJA) { outext = ".nja"; bool isDup = destination.ToLowerInvariant().Contains(".dup"); if (destination == "") { destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext); } if (!overwrite && File.Exists(destination)) { while (File.Exists(destination)) { destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext); } } using (StreamWriter sw2 = File.CreateText(destination)) { List <string> labels_nj = new List <string>() { model.Name }; model.ToNJA(sw2, labels_nj, null, isDup); sw2.Flush(); sw2.Close(); } } break; case ".saanim": NJS_MOTION animation = NJS_MOTION.Load(source); if (type == TextType.CStructs) { outext = ".c"; if (destination == "") { destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext); } if (!overwrite && File.Exists(destination)) { while (File.Exists(destination)) { destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext); } } using (StreamWriter sw = File.CreateText(destination)) { sw.WriteLine("/* NINJA Motion"); sw.WriteLine(" * "); sw.WriteLine(" * Generated by DataToolbox"); sw.WriteLine(" * "); sw.WriteLine(" */"); sw.WriteLine(); animation.ToStructVariables(sw); sw.Flush(); sw.Close(); } } else if (type == TextType.JSON) { outext = ".json"; if (destination == "") { destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext); } if (!overwrite && File.Exists(destination)) { while (File.Exists(destination)) { destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext); } } JsonSerializer js = new JsonSerializer() { Culture = System.Globalization.CultureInfo.InvariantCulture }; using (TextWriter tw = File.CreateText(destination)) using (JsonTextWriter jtw = new JsonTextWriter(tw) { Formatting = Formatting.Indented }) js.Serialize(jtw, animation); } else if (type == TextType.NJA) { outext = animation.IsShapeMotion() ? ".nas" : ".nam"; bool isDum = destination.ToLowerInvariant().Contains(".dum"); if (destination == "") { destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext); } if (!overwrite && File.Exists(destination)) { while (File.Exists(destination)) { destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext); } } using (StreamWriter sw2 = File.CreateText(destination)) { animation.ToNJA(sw2, null, isDum); sw2.Flush(); sw2.Close(); } } break; case ".satex": SplitTools.NJS_TEXLIST texlist = SplitTools.NJS_TEXLIST.Load(source); if (type == TextType.CStructs) { outext = ".c"; if (destination == "") { destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext); } if (!overwrite && File.Exists(destination)) { while (File.Exists(destination)) { destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext); } } using (StreamWriter sw = File.CreateText(destination)) { sw.WriteLine("/* NINJA Texlist"); sw.WriteLine(" * "); sw.WriteLine(" * Generated by DataToolbox"); sw.WriteLine(" * "); sw.WriteLine(" */"); sw.WriteLine(); texlist.ToStruct(sw); sw.Flush(); sw.Close(); } } else if (type == TextType.NJA) { outext = ".tls"; if (destination == "") { destination = Path.Combine(Path.GetDirectoryName(source), Path.GetFileNameWithoutExtension(source) + outext); } if (!overwrite && File.Exists(destination)) { while (File.Exists(destination)) { destination = destination = Path.Combine(Path.GetDirectoryName(destination), Path.GetFileNameWithoutExtension(destination) + "_" + outext); } } using (StreamWriter sw2 = File.CreateText(destination)) { texlist.ToNJA(sw2); sw2.Flush(); sw2.Close(); } } break; } }
public static void ExportCollada(ModelFile mdl, ResourceManager resources, string output) { var dae = NewCollada(); var mats = new CL.library_materials(); var efx = new CL.library_effects(); var geos = new CL.library_geometries(); var scenes = new CL.library_visual_scenes(); var vscene = new CL.visual_scene(); vscene.name = vscene.id = "main-scene"; scenes.visual_scene = new CL.visual_scene[] { vscene }; dae.scene = new CL.COLLADAScene(); dae.scene.instance_visual_scene = new CL.InstanceWithExtra() { url = "#main-scene" }; var exported = ProcessModel(mdl, resources); geos.geometry = exported.Geometries.ToArray(); mats.material = exported.Materials.Select((x) => new CL.material() { name = x.Name, id = x.Name + "-material", instance_effect = new CL.instance_effect() { url = "#" + x.Name + "-effect" } }).ToArray(); efx.effect = exported.Materials.Select((x) => new CL.effect() { id = x.Name + "-effect", Items = new[] { new CL.effectFx_profile_abstractProfile_COMMON() { technique = new CL.effectFx_profile_abstractProfile_COMMONTechnique() { id = "common", Item = new CL.effectFx_profile_abstractProfile_COMMONTechniquePhong() { ambient = ColladaColor("ambient", Color4.Black), emission = ColladaColor("emmision", Color4.Black), diffuse = ColladaColor("diffuse", x.Dc), specular = ColladaColor("specular", new Color4(0.25f, 0.25f, 0.25f, 1f)), shininess = ColladaFloat("shininess", 50), index_of_refraction = ColladaFloat("index_of_refraction", 1) } } } } }).ToArray(); var nodes = new List <CL.node>(); for (int i = 0; i < exported.Geometries.Count; i++) { nodes.Add(exported.GetNode(i, Matrix4x4.Identity, mdl.Path)); } vscene.node = nodes.ToArray(); dae.Items = new object[] { efx, mats, geos, scenes }; using (var stream = File.Create(output)) ColladaSupport.XML.Serialize(stream, dae); }
private void DrawFile(ModelFile file, bool big = true) { if (gui.Button(new GUIContent(big ? file.name : null, file.thumb), buttonSetup(skin.button, big ? 130 : 65))) { selectedGameObject = file.gameObj; if (sgo) Destroy(sgo.gameObject); recent.Remove(file); recent.Insert(0, file); if (recent.Count > 8) recent.RemoveAt(recent.Count - 1); lastSgo = null; sgo = InitModel((GameObject)Instantiate(selectedGameObject), selectedGameObject.name); if (sgo.collider != null) sgo.collider.enabled = false; sgo.SetColor(Color.white); tool2 = Tool2.Draw; tool = Tool.Models; win.Back(); } }
public void Load(System.IO.Stream stream) { CanSave = false; using (var reader = new FileReader(stream)) { reader.SetByteOrder(true); Text = FileName; while (!reader.EndOfStream) { ChunkHeader chunk = new ChunkHeader(); chunk.Position = reader.Position; chunk.Identifier = reader.ReadUInt32(); uint unk = reader.ReadUInt32(); chunk.ChunkSize = reader.ReadUInt32(); chunk.ChunkId = reader.ReadUInt32(); chunk.NextFilePtr = reader.ReadUInt32(); chunk.FileSize = reader.ReadUInt32(); uint unk2 = reader.ReadUInt32(); uint unk3 = reader.ReadUInt32(); Chunks.Add(chunk); var Identifer = chunk.Identifier.Reverse(); switch (Identifer) { case ChunkTextureFile: SWUTexture texture = new SWUTexture(); reader.SeekBegin(chunk.Position + 72); texture.ImageKey = "texture"; texture.SelectedImageKey = "texture"; texture.ReadChunk(reader); chunk.ChunkData = texture; if (chunk.ChunkSize > 244) { reader.Seek(chunk.Position + 244, System.IO.SeekOrigin.Begin); chunk.FileName = reader.ReadString(Syroot.BinaryData.BinaryStringFormat.ZeroTerminated); texture.Text = chunk.FileName; } Nodes.Add(texture); break; case ChunkMetaInfo: break; case ChunkAnimInfo: if (chunk.ChunkSize > 0xB0) { reader.Seek(chunk.Position + 0xB0, System.IO.SeekOrigin.Begin); chunk.FileName = reader.ReadString(Syroot.BinaryData.BinaryStringFormat.ZeroTerminated); } break; case ChunkAnimData: AnimationFile animFile = new AnimationFile(); animFile.Read(reader); chunk.ChunkData = animFile; break; case ChunkSkeletonData: SkeletonFile skelFile = new SkeletonFile(); skelFile.Read(reader); chunk.ChunkData = skelFile; break; case ChunkModelData: ModelFile modelFile = new ModelFile(); modelFile.Read(reader); chunk.ChunkData = modelFile; break; case ChunkMaterialData: MaterialFile matFile = new MaterialFile(); matFile.Read(reader); chunk.ChunkData = matFile; break; } reader.Seek(chunk.Position + chunk.ChunkSize, System.IO.SeekOrigin.Begin); } ReadGPUFile(FilePath); } TreeHelper.CreateFileDirectory(this); }