示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
        public static ChunkAttach ToChunk(this BasicAttach basatt)
        {
            ChunkAttach cnkatt = new ChunkAttach(true, true)
            {
                Name = basatt.Name + "_cnk", Bounds = basatt.Bounds
            };
            VertexChunk vcnk;
            bool        hasnormal = basatt.Normal?.Length > 0;
            bool        hasvcolor = basatt.Mesh.Any(a => a.VColor != null);

            if (hasvcolor)
            {
                vcnk      = new VertexChunk(ChunkType.Vertex_VertexDiffuse8);
                hasnormal = false;
            }
            else if (hasnormal)
            {
                vcnk = new VertexChunk(ChunkType.Vertex_VertexNormal);
            }
            else
            {
                vcnk = new VertexChunk(ChunkType.Vertex_Vertex);
            }
            List <CachedVertex>       cache  = new List <CachedVertex>(basatt.Vertex.Length);
            List <List <Strip> >      strips = new List <List <Strip> >();
            List <List <List <UV> > > uvs    = new List <List <List <UV> > >();

            foreach (NJS_MESHSET mesh in basatt.Mesh)
            {
                List <Strip>      polys = new List <Strip>();
                List <List <UV> > us    = null;
                bool hasUV             = mesh.UV != null;
                bool hasVColor         = mesh.VColor != null;
                int  currentstriptotal = 0;
                switch (mesh.PolyType)
                {
                case Basic_PolyType.Triangles:
                {
                    List <ushort>           tris  = new List <ushort>();
                    Dictionary <ushort, UV> uvmap = new Dictionary <ushort, UV>();
                    foreach (Poly poly in mesh.Poly)
                    {
                        for (int i = 0; i < 3; i++)
                        {
                            ushort ind = (ushort)cache.AddUnique(new CachedVertex(
                                                                     basatt.Vertex[poly.Indexes[i]],
                                                                     basatt.Normal[poly.Indexes[i]],
                                                                     hasVColor ? mesh.VColor[currentstriptotal] : Color.White,
                                                                     mesh.UV?[currentstriptotal]));
                            if (hasUV)
                            {
                                uvmap[ind] = mesh.UV[currentstriptotal];
                            }
                            ++currentstriptotal;
                            tris.Add(ind);
                        }
                    }

                    if (hasUV)
                    {
                        us = new List <List <UV> >();
                    }

                    nvStripifier.GenerateStrips(tris.ToArray(), out var primitiveGroups);

                    // Add strips
                    for (var i = 0; i < primitiveGroups.Length; i++)
                    {
                        var primitiveGroup = primitiveGroups[i];
                        System.Diagnostics.Debug.Assert(primitiveGroup.Type == PrimitiveType.TriangleStrip);

                        var       stripIndices = new ushort[primitiveGroup.Indices.Length];
                        List <UV> stripuv      = new List <UV>();
                        for (var j = 0; j < primitiveGroup.Indices.Length; j++)
                        {
                            var vertexIndex = primitiveGroup.Indices[j];
                            stripIndices[j] = vertexIndex;
                            if (hasUV)
                            {
                                stripuv.Add(uvmap[vertexIndex]);
                            }
                        }

                        polys.Add(new Strip(stripIndices, false));
                        if (hasUV)
                        {
                            us.Add(stripuv);
                        }
                    }
                }
                break;

                case Basic_PolyType.Quads:
                {
                    List <ushort>           tris  = new List <ushort>();
                    Dictionary <ushort, UV> uvmap = new Dictionary <ushort, UV>();
                    foreach (Poly poly in mesh.Poly)
                    {
                        ushort[] quad = new ushort[4];
                        for (int i = 0; i < 4; i++)
                        {
                            ushort ind = (ushort)cache.AddUnique(new CachedVertex(
                                                                     basatt.Vertex[poly.Indexes[i]],
                                                                     basatt.Normal[poly.Indexes[i]],
                                                                     hasVColor ? mesh.VColor[currentstriptotal] : Color.White,
                                                                     mesh.UV?[currentstriptotal]));
                            if (hasUV)
                            {
                                uvmap[ind] = mesh.UV[currentstriptotal];
                            }
                            ++currentstriptotal;
                            quad[i] = ind;
                        }
                        tris.Add(quad[0]);
                        tris.Add(quad[1]);
                        tris.Add(quad[2]);
                        tris.Add(quad[2]);
                        tris.Add(quad[1]);
                        tris.Add(quad[3]);
                    }

                    if (hasUV)
                    {
                        us = new List <List <UV> >();
                    }

                    nvStripifier.GenerateStrips(tris.ToArray(), out var primitiveGroups);

                    // Add strips
                    for (var i = 0; i < primitiveGroups.Length; i++)
                    {
                        var primitiveGroup = primitiveGroups[i];
                        System.Diagnostics.Debug.Assert(primitiveGroup.Type == PrimitiveType.TriangleStrip);

                        var       stripIndices = new ushort[primitiveGroup.Indices.Length];
                        List <UV> stripuv      = new List <UV>();
                        for (var j = 0; j < primitiveGroup.Indices.Length; j++)
                        {
                            var vertexIndex = primitiveGroup.Indices[j];
                            stripIndices[j] = vertexIndex;
                            if (hasUV)
                            {
                                stripuv.Add(uvmap[vertexIndex]);
                            }
                        }

                        polys.Add(new Strip(stripIndices, false));
                        if (hasUV)
                        {
                            us.Add(stripuv);
                        }
                    }
                }
                break;

                case Basic_PolyType.NPoly:
                case Basic_PolyType.Strips:
                    if (hasUV)
                    {
                        us = new List <List <UV> >();
                    }
                    foreach (Strip poly in mesh.Poly.Cast <Strip>())
                    {
                        List <UV> stripuv = new List <UV>();
                        ushort[]  inds    = (ushort[])poly.Indexes.Clone();
                        for (int i = 0; i < poly.Indexes.Length; i++)
                        {
                            inds[i] = (ushort)cache.AddUnique(new CachedVertex(
                                                                  basatt.Vertex[poly.Indexes[i]],
                                                                  basatt.Normal[poly.Indexes[i]],
                                                                  hasVColor ? mesh.VColor[currentstriptotal] : Color.White));
                            if (hasUV)
                            {
                                stripuv.Add(mesh.UV[currentstriptotal]);
                            }
                            ++currentstriptotal;
                        }

                        polys.Add(new Strip(inds, poly.Reversed));
                        if (hasUV)
                        {
                            us.Add(stripuv);
                        }
                    }
                    break;
                }
                strips.Add(polys);
                uvs.Add(us);
            }
            foreach (var item in cache)
            {
                vcnk.Vertices.Add(item.vertex);
                if (hasnormal)
                {
                    vcnk.Normals.Add(item.normal);
                }
                if (hasvcolor)
                {
                    vcnk.Diffuse.Add(item.color);
                }
            }
            cnkatt.Vertex.Add(vcnk);
            for (int i = 0; i < basatt.Mesh.Count; i++)
            {
                NJS_MESHSET  mesh = basatt.Mesh[i];
                NJS_MATERIAL mat  = null;
                if (basatt.Material != null && mesh.MaterialID < basatt.Material.Count)
                {
                    mat = basatt.Material[mesh.MaterialID];
                    cnkatt.Poly.Add(new PolyChunkTinyTextureID()
                    {
                        ClampU      = mat.ClampU,
                        ClampV      = mat.ClampV,
                        FilterMode  = mat.FilterMode,
                        FlipU       = mat.FlipU,
                        FlipV       = mat.FlipV,
                        SuperSample = mat.SuperSample,
                        TextureID   = (ushort)mat.TextureID
                    });
                    cnkatt.Poly.Add(new PolyChunkMaterial()
                    {
                        SourceAlpha      = mat.SourceAlpha,
                        DestinationAlpha = mat.DestinationAlpha,
                        Diffuse          = mat.DiffuseColor,
                        Specular         = mat.SpecularColor,
                        SpecularExponent = (byte)mat.Exponent
                    });
                }
                PolyChunkStrip strip;
                if (mesh.UV != null)
                {
                    strip = new PolyChunkStrip(ChunkType.Strip_StripUVN);
                }
                else
                {
                    strip = new PolyChunkStrip(ChunkType.Strip_Strip);
                }
                if (mat != null)
                {
                    strip.IgnoreLight        = mat.IgnoreLighting;
                    strip.IgnoreSpecular     = mat.IgnoreSpecular;
                    strip.UseAlpha           = mat.UseAlpha;
                    strip.DoubleSide         = mat.DoubleSided;
                    strip.FlatShading        = mat.FlatShading;
                    strip.EnvironmentMapping = mat.EnvironmentMap;
                }
                for (int i1 = 0; i1 < strips[i].Count; i1++)
                {
                    Strip item = strips[i][i1];
                    UV[]  uv2  = null;
                    if (mesh.UV != null)
                    {
                        uv2 = uvs[i][i1].ToArray();
                    }
                    strip.Strips.Add(new PolyChunkStrip.Strip(item.Reversed, item.Indexes, uv2, null));
                }
                cnkatt.Poly.Add(strip);
            }

            return(cnkatt);
        }
示例#5
0
        public static BasicAttach ToBasic(this ChunkAttach cnkatt)
        {
            BasicAttach basatt = new BasicAttach()
            {
                Name = cnkatt.Name, Bounds = cnkatt.Bounds
            };

            if (cnkatt.Vertex != null)
            {
                foreach (VertexChunk chunk in cnkatt.Vertex)
                {
                    if (VertexBuffer.Length < chunk.IndexOffset + chunk.VertexCount)
                    {
                        Array.Resize(ref VertexBuffer, chunk.IndexOffset + chunk.VertexCount);
                        Array.Resize(ref NormalBuffer, chunk.IndexOffset + chunk.VertexCount);
                        Array.Resize(ref ColorBuffer, chunk.IndexOffset + chunk.VertexCount);
                    }
                    Array.Copy(chunk.Vertices.ToArray(), 0, VertexBuffer, chunk.IndexOffset, chunk.Vertices.Count);
                    Array.Copy(chunk.Normals.ToArray(), 0, NormalBuffer, chunk.IndexOffset, chunk.Normals.Count);
                    if (chunk.Diffuse.Count > 0)
                    {
                        Array.Copy(chunk.Diffuse.Cast <Color?>().ToArray(), 0, ColorBuffer, chunk.IndexOffset, chunk.Diffuse.Count);
                    }
                }
            }
            NJS_MATERIAL material = new NJS_MATERIAL()
            {
                UseTexture = true
            };
            int minVtx = int.MaxValue;
            int maxVtx = int.MinValue;

            foreach (PolyChunk chunk in cnkatt.Poly)
            {
                switch (chunk.Type)
                {
                case ChunkType.Bits_BlendAlpha:
                {
                    PolyChunkBitsBlendAlpha c2 = (PolyChunkBitsBlendAlpha)chunk;
                    material.SourceAlpha      = c2.SourceAlpha;
                    material.DestinationAlpha = c2.DestinationAlpha;
                }
                break;

                case ChunkType.Bits_MipmapDAdjust:
                    break;

                case ChunkType.Bits_SpecularExponent:
                    material.Exponent = ((PolyChunkBitsSpecularExponent)chunk).SpecularExponent;
                    break;

                case ChunkType.Tiny_TextureID:
                case ChunkType.Tiny_TextureID2:
                {
                    PolyChunkTinyTextureID c2 = (PolyChunkTinyTextureID)chunk;
                    material.ClampU      = c2.ClampU;
                    material.ClampV      = c2.ClampV;
                    material.FilterMode  = c2.FilterMode;
                    material.FlipU       = c2.FlipU;
                    material.FlipV       = c2.FlipV;
                    material.SuperSample = c2.SuperSample;
                    material.TextureID   = c2.TextureID;
                }
                break;

                case ChunkType.Material_Diffuse:
                case ChunkType.Material_Ambient:
                case ChunkType.Material_DiffuseAmbient:
                case ChunkType.Material_Specular:
                case ChunkType.Material_DiffuseSpecular:
                case ChunkType.Material_AmbientSpecular:
                case ChunkType.Material_DiffuseAmbientSpecular:
                case ChunkType.Material_Diffuse2:
                case ChunkType.Material_Ambient2:
                case ChunkType.Material_DiffuseAmbient2:
                case ChunkType.Material_Specular2:
                case ChunkType.Material_DiffuseSpecular2:
                case ChunkType.Material_AmbientSpecular2:
                case ChunkType.Material_DiffuseAmbientSpecular2:
                {
                    PolyChunkMaterial c2 = (PolyChunkMaterial)chunk;
                    material.SourceAlpha      = c2.SourceAlpha;
                    material.DestinationAlpha = c2.DestinationAlpha;
                    if (c2.Diffuse.HasValue)
                    {
                        material.DiffuseColor = c2.Diffuse.Value;
                    }
                    if (c2.Specular.HasValue)
                    {
                        material.SpecularColor = c2.Specular.Value;
                        material.Exponent      = c2.SpecularExponent;
                    }
                }
                break;

                case ChunkType.Strip_Strip:
                case ChunkType.Strip_StripUVN:
                case ChunkType.Strip_StripUVH:
                case ChunkType.Strip_StripNormal:
                case ChunkType.Strip_StripUVNNormal:
                case ChunkType.Strip_StripUVHNormal:
                case ChunkType.Strip_StripColor:
                case ChunkType.Strip_StripUVNColor:
                case ChunkType.Strip_StripUVHColor:
                case ChunkType.Strip_Strip2:
                case ChunkType.Strip_StripUVN2:
                case ChunkType.Strip_StripUVH2:
                {
                    PolyChunkStrip c2 = (PolyChunkStrip)chunk;
                    material.DoubleSided    = c2.DoubleSide;
                    material.EnvironmentMap = c2.EnvironmentMapping;
                    material.FlatShading    = c2.FlatShading;
                    material.IgnoreLighting = c2.IgnoreLight;
                    material.IgnoreSpecular = c2.IgnoreSpecular;
                    material.UseAlpha       = c2.UseAlpha;
                    bool hasStripVColor = false;
                    switch (chunk.Type)
                    {
                    case ChunkType.Strip_StripColor:
                    case ChunkType.Strip_StripUVNColor:
                    case ChunkType.Strip_StripUVHColor:
                        hasStripVColor = true;
                        break;
                    }
                    bool hasUV = false;
                    switch (chunk.Type)
                    {
                    case ChunkType.Strip_StripUVN:
                    case ChunkType.Strip_StripUVH:
                    case ChunkType.Strip_StripUVNColor:
                    case ChunkType.Strip_StripUVHColor:
                    case ChunkType.Strip_StripUVN2:
                    case ChunkType.Strip_StripUVH2:
                        hasUV = true;
                        break;
                    }
                    bool hasVertVColor = false;
                    if (!hasStripVColor && c2.Strips.All(a => a.Indexes.All(b => ColorBuffer[b].HasValue)))
                    {
                        hasVertVColor = true;
                    }
                    bool         hasVColor = hasStripVColor || hasVertVColor;
                    List <Strip> strips    = new List <Strip>(c2.StripCount);
                    List <UV>    uvs       = hasUV ? new List <UV>() : null;
                    List <Color> vcolors   = hasVColor ? new List <Color>() : null;
                    foreach (PolyChunkStrip.Strip strip in c2.Strips)
                    {
                        minVtx = Math.Min(minVtx, strip.Indexes.Min());
                        maxVtx = Math.Max(maxVtx, strip.Indexes.Max());
                        strips.Add(new Strip((ushort[])strip.Indexes.Clone(), strip.Reversed));
                        if (hasUV)
                        {
                            uvs.AddRange(strip.UVs);
                        }
                        if (hasStripVColor)
                        {
                            vcolors.AddRange(strip.VColors);
                        }
                        else if (hasVertVColor)
                        {
                            foreach (short i in strip.Indexes)
                            {
                                vcolors.Add(ColorBuffer[i].Value);
                            }
                        }
                    }
                    NJS_MESHSET mesh = new NJS_MESHSET(strips.ToArray(), false, hasUV, hasVColor);
                    if (hasUV)
                    {
                        uvs.CopyTo(mesh.UV);
                    }
                    if (hasVColor)
                    {
                        vcolors.CopyTo(mesh.VColor);
                    }
                    mesh.MaterialID = (ushort)basatt.Material.Count;
                    basatt.Mesh.Add(mesh);
                    basatt.Material.Add(material);
                    material = new NJS_MATERIAL(material.GetBytes(), 0);
                }
                break;
                }
            }
            int numVtx = maxVtx - minVtx + 1;

            basatt.ResizeVertexes(numVtx);
            Array.Copy(VertexBuffer, minVtx, basatt.Vertex, 0, numVtx);
            Array.Copy(NormalBuffer, minVtx, basatt.Normal, 0, numVtx);
            foreach (NJS_MESHSET mesh in basatt.Mesh)
            {
                foreach (Poly poly in mesh.Poly)
                {
                    for (int i = 0; i < poly.Indexes.Length; i++)
                    {
                        poly.Indexes[i] = (ushort)(poly.Indexes[i] - minVtx);
                    }
                }
            }
            return(basatt);
        }
示例#6
0
        static void Main(string[] args)
        {
            string filename;

            if (args.Length > 0)
            {
                filename = args[0];
                Console.WriteLine("File: {0}", filename);
            }
            else
            {
                Console.Write("File: ");
                filename = Console.ReadLine().Trim('"');
            }
            LandTable level = LandTable.LoadFromFile(filename);
            Dictionary <string, Attach> visitedAttaches = new Dictionary <string, Attach>();

            switch (level.Format)
            {
            case LandTableFormat.SA1:
            {
                List <COL> newcollist = new List <COL>();
                foreach (COL col in level.COL.Where((col) => col.Model != null && col.Model.Attach != null))
                {
                    if ((col.SurfaceFlags & SA1SurfaceFlags.Visible) == SA1SurfaceFlags.Visible)
                    {
                        COL newcol = new COL()
                        {
                            Bounds = col.Bounds
                        };
                        newcol.SurfaceFlags = SA1SurfaceFlags.Visible;
                        newcol.Model        = new NJS_OBJECT()
                        {
                            Name = col.Model.Name + "_cnk"
                        };
                        newcol.Model.Position = col.Model.Position;
                        newcol.Model.Rotation = col.Model.Rotation;
                        newcol.Model.Scale    = col.Model.Scale;
                        BasicAttach basatt  = (BasicAttach)col.Model.Attach;
                        string      newname = basatt.Name + "_cnk";
                        if (visitedAttaches.ContainsKey(newname))
                        {
                            newcol.Model.Attach = visitedAttaches[newname];
                        }
                        else
                        {
                            ChunkAttach cnkatt = basatt.ToChunk();
                            visitedAttaches[newname] = cnkatt;
                            newcol.Model.Attach      = cnkatt;
                        }
                        newcollist.Add(newcol);
                    }
                    if ((col.SurfaceFlags & ~SA1SurfaceFlags.Visible) != 0)
                    {
                        col.SurfaceFlags &= ~SA1SurfaceFlags.Visible;
                        newcollist.Add(col);
                    }
                }
                level.COL = newcollist;
            }
                level.Anim = new List <GeoAnimData>();
                level.SaveToFile(System.IO.Path.ChangeExtension(filename, "sa2lvl"), LandTableFormat.SA2);
                break;

            case LandTableFormat.SA2:
                foreach (COL col in level.COL.Where((col) => col.Model != null && col.Model.Attach is ChunkAttach))
                {
                    col.Model.Attach = col.Model.Attach.ToBasic();
                }
                level.Anim       = new List <GeoAnimData>();
                level.Attributes = 8;                         // set LandTable to use PVM/GVM
                level.SaveToFile(System.IO.Path.ChangeExtension(filename, "sa1lvl"), LandTableFormat.SA1);
                break;
            }
        }