示例#1
0
 private void BuildNodeList()
 {
     NJS_OBJECT[] objs = editedHierarchy.GetObjects();
     for (int i = 0; i < objs.Length; i++)
     {
         comboBoxNode.Items.Add(i.ToString() + ": " + objs[i].Name.ToString());
     }
 }
示例#2
0
        private static string GetModel(byte[] fc, int address, uint key, string fn, List <string> nodenames, Dictionary <string, KeyValuePair <string, NJS_OBJECT> > modelfiles)
        {
            string name = null;
            int    ptr3 = fc.GetPointer(address, key);

            if (ptr3 != 0)
            {
                name = $"object_{ptr3:X8}";
                if (!nodenames.Contains(name))
                {
                    NJS_OBJECT obj = new NJS_OBJECT(fc, ptr3, key, ModelFormat.Chunk);
                    name = obj.Name;
                    List <string> names = new List <string>(obj.GetObjects().Select((o) => o.Name));
                    foreach (string s in names)
                    {
                        if (modelfiles.ContainsKey(s))
                        {
                            modelfiles.Remove(s);
                        }
                    }
                    nodenames.AddRange(names);
                    modelfiles.Add(obj.Name, new KeyValuePair <string, NJS_OBJECT>(fn, obj));
                }
            }

            return(name);
        }
示例#3
0
        public StartPosItem(NJS_OBJECT model, string textures, float offset, Vertex position, int yrot, Device dev, EditorItemSelection selectionManager, bool Weight = false)
            : base(selectionManager)
        {
            Model     = model;
            hasWeight = Weight;

            model.ProcessVertexData();

            if (hasWeight)
            {
                Meshes = model.ProcessWeightedModel().ToArray();
            }
            else
            {
                NJS_OBJECT[] models = model.GetObjects();
                Meshes = new Mesh[models.Length];
                for (int i = 0; i < models.Length; i++)
                {
                    if (models[i].Attach != null)
                    {
                        Meshes[i] = models[i].Attach.CreateD3DMesh();
                    }
                }
            }

            texture     = textures;
            this.offset = offset;
            Position    = position;
            YRotation   = yrot;
        }
示例#4
0
 public static Mesh[] GetMeshes(NJS_OBJECT model, Device dev)
 {
     model.ProcessVertexData();
     NJS_OBJECT[] models = model.GetObjects();
     Mesh[] Meshes = new Mesh[models.Length];
     for (int i = 0; i < models.Length; i++)
         if (models[i].Attach != null)
             Meshes[i] = models[i].Attach.CreateD3DMesh(dev);
     return Meshes;
 }
示例#5
0
 public static Mesh[] GetMeshes(NJS_OBJECT model)
 {
     model.ProcessVertexData();
     NJS_OBJECT[] models = model.GetObjects();
     Mesh[]       Meshes = new Mesh[models.Length];
     for (int i = 0; i < models.Length; i++)
     {
         if (models[i].Attach != null)
         {
             Meshes[i] = models[i].Attach.CreateD3DMesh();
         }
     }
     return(Meshes);
 }
示例#6
0
 public StartPosItem(NJS_OBJECT model, string textures, float offset, Vertex position, int yrot, Device dev, EditorItemSelection selectionManager)
     : base(selectionManager)
 {
     Model = model;
     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)
             Meshes[i] = models[i].Attach.CreateD3DMesh(dev);
     texture = textures;
     this.offset = offset;
     Position = position;
     YRotation = yrot;
 }
示例#7
0
        public static NJS_OBJECT GetModel(byte[] file, int address, uint imageBase, Dictionary <string, NJS_OBJECT> models)
        {
            NJS_OBJECT result = null;
            int        ptr    = file.GetPointer(address, imageBase);

            if (ptr != 0)
            {
                result = new NJS_OBJECT(file, ptr, imageBase, ModelFormat.Chunk);
                if (models.ContainsKey(result.Name))
                {
                    result = models[result.Name];
                }
                else
                {
                    foreach (NJS_OBJECT obj in result.GetObjects())
                    {
                        models[obj.Name] = obj;
                    }
                }
            }
            return(result);
        }
示例#8
0
        static void Main(string[] args)
        {
            string dir = Environment.CurrentDirectory;

            try
            {
                Queue <string> argq = new Queue <string>(args);
                if (argq.Count > 0 && argq.Peek().Equals("/be", StringComparison.OrdinalIgnoreCase))
                {
                    ByteConverter.BigEndian = true;
                    argq.Dequeue();
                }
                string mdlfilename;
                if (argq.Count > 0)
                {
                    mdlfilename = argq.Dequeue();
                    Console.WriteLine("File: {0}", mdlfilename);
                }
                else
                {
                    Console.Write("File: ");
                    mdlfilename = Console.ReadLine();
                }
                mdlfilename = Path.GetFullPath(mdlfilename);
                string[] anifilenames = new string[argq.Count];
                for (int j = 0; j < anifilenames.Length; j++)
                {
                    Console.WriteLine("Animations: {0}", argq.Peek());
                    anifilenames[j] = Path.GetFullPath(argq.Dequeue());
                }
                Environment.CurrentDirectory = 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));
                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);
                }
                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);
                    }
                }
                Dictionary <int, string>    animfns = new Dictionary <int, string>();
                Dictionary <int, Animation> anims   = new Dictionary <int, Animation>();
                foreach (string anifilename in anifilenames)
                {
                    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)
                    {
                        anims[i]   = new Animation(anifile, ByteConverter.ToInt32(anifile, address + 4), 0, ByteConverter.ToInt16(anifile, address + 2));
                        animfns[i] = Path.Combine(Path.GetFileNameWithoutExtension(anifilename), i.ToString(NumberFormatInfo.InvariantInfo) + ".saanim");
                        address   += 8;
                        i          = ByteConverter.ToInt16(anifile, address);
                    }
                }
                foreach (KeyValuePair <int, NJS_OBJECT> model in models)
                {
                    List <string> animlist = new List <string>();
                    foreach (KeyValuePair <int, Animation> anim in anims)
                    {
                        if (model.Value.CountAnimated() == anim.Value.ModelParts)
                        {
                            animlist.Add("../" + animfns[anim.Key]);
                        }
                    }
                    ModelFile.CreateFile(Path.Combine(Path.GetFileNameWithoutExtension(mdlfilename),
                                                      model.Key.ToString(NumberFormatInfo.InvariantInfo) + ".sa2mdl"), model.Value, animlist.ToArray(),
                                         null, null, null, "splitMDL", null, ModelFormat.Chunk);
                }
                IniSerializer.Serialize(modelnames, new IniCollectionSettings(IniCollectionMode.IndexOnly),
                                        Path.Combine(Path.GetFileNameWithoutExtension(mdlfilename), Path.GetFileNameWithoutExtension(mdlfilename) + ".ini"));
                foreach (KeyValuePair <int, Animation> anim in anims)
                {
                    anim.Value.Save(animfns[anim.Key]);
                }
            }
            finally
            {
                Environment.CurrentDirectory = dir;
            }
        }
示例#9
0
        static byte[] GetSections(NJS_OBJECT mdl)
        {
            List <byte> result = new List <byte>();

            NJS_OBJECT[] objs        = mdl.GetObjects();
            int[]        modeladdr   = new int[objs.Length];
            int[]        objaddr     = new int[objs.Length];
            int[]        mataddr     = new int[objs.Length];
            int[]        meshaddr    = new int[objs.Length];
            List <int>[] polyaddr    = new List <int> [objs.Length];
            List <int>[] uvaddr      = new List <int> [objs.Length];
            int[]        vertaddr    = new int[objs.Length];
            int[]        normaddr    = new int[objs.Length];
            int          currentaddr = 0;
            // Write all polys
            int polysection = currentaddr;

            currentaddr += 8;
            short polycount = 0;

            for (int m = objs.Length - 1; m > -1; m--)
            {
                polyaddr[m] = new List <int>();
                if (objs[m].Attach != null)
                {
                    BasicAttach att = (BasicAttach)objs[m].Attach;
                    if (att.Mesh != null)
                    {
                        foreach (NJS_MESHSET mesh in att.Mesh)
                        {
                            polyaddr[m].Add(result.Count);
                            //Console.WriteLine("Polyaddr in model {0} : {1}", m, currentaddr.ToString("X"));
                            foreach (Strip poly in mesh.Poly)
                            {
                                if (poly.Reversed)
                                {
                                    result.AddRange(BitConverter.GetBytes((short)(0x8000 | (poly.Indexes.Length & 0x7FFF))));
                                }
                                else
                                {
                                    result.AddRange(BitConverter.GetBytes((short)(poly.Indexes.Length & 0x7FFF)));
                                }
                                polycount++;
                                for (int ind = 0; ind < poly.Indexes.Length; ind++)
                                {
                                    result.AddRange(BitConverter.GetBytes(poly.Indexes[ind]));
                                    polycount++;
                                }
                            }
                            currentaddr = result.Count;
                        }
                    }
                }
            }
            if ((polycount * 2) % 4 != 0)
            {
                int res = polycount * 2;
                do
                {
                    result.Add(0xCD);
                    res++;
                }while (res % 4 != 0);
            }
            currentaddr = result.Count;
            result.InsertRange(polysection, BitConverter.GetBytes((uint)0));
            result.InsertRange(polysection + 4, BitConverter.GetBytes((uint)polycount * 2));
            // Write all vertices
            int vertsection = currentaddr;

            currentaddr += 8;
            short vertexcount = 0;

            for (int m = objs.Length - 1; m > -1; m--)
            {
                if (objs[m].Attach != null)
                {
                    BasicAttach att = (BasicAttach)objs[m].Attach;
                    vertaddr[m] = currentaddr;
                    if (att.Vertex != null)
                    {
                        for (int v = 0; v < att.Vertex.Length; v++)
                        {
                            result.AddRange(BitConverter.GetBytes(att.Vertex[v].X));
                            result.AddRange(BitConverter.GetBytes(att.Vertex[v].Y));
                            result.AddRange(BitConverter.GetBytes(att.Vertex[v].Z));
                            vertexcount++;
                        }
                    }
                    currentaddr = result.Count;
                }
            }
            result.InsertRange(vertsection + 8, BitConverter.GetBytes((uint)1));
            result.InsertRange(vertsection + 4 + 8, BitConverter.GetBytes((uint)vertexcount * 12));
            // Write all normals
            int normsection = currentaddr;

            currentaddr += 8;
            short normalcount = 0;

            for (int m = objs.Length - 1; m > -1; m--)
            {
                if (objs[m].Attach != null)
                {
                    BasicAttach att = (BasicAttach)objs[m].Attach;
                    normaddr[m] = currentaddr;
                    if (att.Vertex != null)
                    {
                        for (int v = 0; v < att.Vertex.Length; v++)
                        {
                            result.AddRange(BitConverter.GetBytes(att.Normal[v].X));
                            result.AddRange(BitConverter.GetBytes(att.Normal[v].Y));
                            result.AddRange(BitConverter.GetBytes(att.Normal[v].Z));
                            normalcount++;
                        }
                    }
                    currentaddr = result.Count;
                }
            }
            result.InsertRange(normsection + 8, BitConverter.GetBytes((uint)2));
            result.InsertRange(normsection + 4 + 8, BitConverter.GetBytes((uint)normalcount * 12));
            // Write all UVs
            int uvsection = currentaddr;

            currentaddr += 8;
            short uvcount = 0;

            for (int m = objs.Length - 1; m > -1; m--)
            {
                uvaddr[m] = new List <int>();
                if (objs[m].Attach != null)
                {
                    BasicAttach att = (BasicAttach)objs[m].Attach;
                    foreach (NJS_MESHSET mesh in att.Mesh)
                    {
                        uvaddr[m].Add(currentaddr);
                        if (mesh.UV != null)
                        {
                            for (int uv = 0; uv < mesh.UV.Length; uv++)
                            {
                                result.AddRange(BitConverter.GetBytes((short)(mesh.UV[uv].U * 255f)));
                                result.AddRange(BitConverter.GetBytes((short)(mesh.UV[uv].V * 255f)));
                                uvcount++;
                            }
                        }
                        currentaddr = result.Count;
                    }
                }
            }
            result.InsertRange(uvsection + 8, BitConverter.GetBytes((uint)3));
            result.InsertRange(uvsection + 4 + 8, BitConverter.GetBytes((uint)uvcount * 4));
            // Write materials
            int matsection = currentaddr;

            currentaddr += 8;
            short matcount = 0;

            for (int m = objs.Length - 1; m > -1; m--)
            {
                if (objs[m].Attach != null)
                {
                    BasicAttach att = (BasicAttach)objs[m].Attach;
                    if (att.Material != null && att.Material.Count > 0)
                    {
                        mataddr[m] = result.Count;
                        foreach (NJS_MATERIAL mat in att.Material)
                        {
                            result.AddRange(BitConverter.GetBytes(mat.DiffuseColor.ToArgb()));
                            result.AddRange(BitConverter.GetBytes(mat.SpecularColor.ToArgb()));
                            result.AddRange(BitConverter.GetBytes(mat.Exponent));
                            result.AddRange(BitConverter.GetBytes(mat.TextureID));
                            result.AddRange(BitConverter.GetBytes(mat.Flags));
                            matcount++;
                            currentaddr = result.Count;
                        }
                    }
                }
            }
            result.InsertRange(matsection + 8, BitConverter.GetBytes((short)4));
            result.InsertRange(matsection + 2 + 8, BitConverter.GetBytes(matcount));
            result.InsertRange(matsection + 4 + 8, BitConverter.GetBytes((uint)matcount * 20));
            // Write meshsets
            short meshcount   = 0;
            int   meshsection = currentaddr;

            currentaddr += 8;
            for (int m = objs.Length - 1; m > -1; m--)
            {
                if (objs[m].Attach != null)
                {
                    BasicAttach att = (BasicAttach)objs[m].Attach;
                    if (att.Material != null && att.Material.Count > 0)
                    {
                        int[] polys = polyaddr[m].ToArray();
                        int[] uvs   = uvaddr[m].ToArray();
                        meshaddr[m] = result.Count;
                        NJS_MESHSET[] meshes = att.Mesh.ToArray();
                        for (int mesh = 0; mesh < meshes.Length; mesh++)
                        {
                            result.AddRange(BitConverter.GetBytes((ushort)((meshes[mesh].MaterialID & 0x3FFF) | ((int)meshes[mesh].PolyType << 0xE))));
                            result.AddRange(BitConverter.GetBytes((ushort)meshes[mesh].Poly.Count));
                            result.AddRange(BitConverter.GetBytes((uint)polys[mesh] + 8));
                            result.AddRange(BitConverter.GetBytes((uint)0));                             //polyattr
                            result.AddRange(BitConverter.GetBytes((uint)0));                             //polynormal pointer
                            result.AddRange(BitConverter.GetBytes((uint)0));                             //vcolor pointer
                            if (meshes[mesh].UV != null && meshes[mesh].UV.Length > 0)
                            {
                                result.AddRange(BitConverter.GetBytes((uint)uvs[mesh] + 8));
                            }
                            else
                            {
                                result.AddRange(BitConverter.GetBytes((uint)0));
                            }
                            meshcount++;
                        }
                    }
                    currentaddr = result.Count;
                }
            }
            result.InsertRange(meshsection + 8, BitConverter.GetBytes((ushort)5));
            result.InsertRange(meshsection + 2 + 8, BitConverter.GetBytes(meshcount));
            result.InsertRange(meshsection + 4 + 8, BitConverter.GetBytes((uint)meshcount * 24));
            // Write models
            short modelcount   = 0;
            int   modelsection = currentaddr;

            currentaddr += 8;
            for (int m = objs.Length - 1; m > -1; m--)
            {
                if (objs[m].Attach != null)
                {
                    modeladdr[m] = currentaddr;
                    BasicAttach att = (BasicAttach)objs[m].Attach;
                    result.AddRange(BitConverter.GetBytes((uint)vertaddr[m] + 8));
                    result.AddRange(BitConverter.GetBytes((uint)normaddr[m] + 8));
                    result.AddRange(BitConverter.GetBytes((uint)att.Vertex.Length));
                    result.AddRange(BitConverter.GetBytes((uint)meshaddr[m] + 8));
                    result.AddRange(BitConverter.GetBytes((uint)mataddr[m] + 8));
                    result.AddRange(BitConverter.GetBytes((ushort)att.Mesh.Count));
                    result.AddRange(BitConverter.GetBytes((ushort)att.Material.Count));
                    result.AddRange(BitConverter.GetBytes(att.Bounds.Center.X));
                    result.AddRange(BitConverter.GetBytes(att.Bounds.Center.Y));
                    result.AddRange(BitConverter.GetBytes(att.Bounds.Center.Z));
                    result.AddRange(BitConverter.GetBytes(att.Bounds.Radius));
                    modelcount++;
                    currentaddr = result.Count;
                }
            }
            result.InsertRange(modelsection + 8, BitConverter.GetBytes((ushort)6));
            result.InsertRange(modelsection + 2 + 8, BitConverter.GetBytes((ushort)modelcount));
            result.InsertRange(modelsection + 4 + 8, BitConverter.GetBytes((uint)(40 * modelcount)));
            // Write objects
            int objectsection = currentaddr;

            currentaddr += 8;
            for (int m = objs.Length - 1; m > -1; m--)
            {
                objaddr[m] = currentaddr;
                result.AddRange(BitConverter.GetBytes((int)objs[m].GetFlags()));
                if (objs[m].Attach != null)
                {
                    result.AddRange(BitConverter.GetBytes((uint)modeladdr[m] + 8));
                }
                else
                {
                    result.AddRange(BitConverter.GetBytes((uint)0));
                }
                result.AddRange(BitConverter.GetBytes(objs[m].Position.X));
                result.AddRange(BitConverter.GetBytes(objs[m].Position.Y));
                result.AddRange(BitConverter.GetBytes(objs[m].Position.Z));
                result.AddRange(BitConverter.GetBytes(objs[m].Rotation.X));
                result.AddRange(BitConverter.GetBytes(objs[m].Rotation.Y));
                result.AddRange(BitConverter.GetBytes(objs[m].Rotation.Z));
                result.AddRange(BitConverter.GetBytes(objs[m].Scale.X));
                result.AddRange(BitConverter.GetBytes(objs[m].Scale.Y));
                result.AddRange(BitConverter.GetBytes(objs[m].Scale.Z));
                if (objs[m].Children != null && objs[m].Children.Count > 0)
                {
                    result.AddRange(BitConverter.GetBytes((uint)(objaddr[FindModelIndex(objs[m].Children[0], objs)]) + 8));                     //child
                }
                else
                {
                    result.AddRange(BitConverter.GetBytes((uint)0));
                }
                if (objs[m].Sibling != null)
                {
                    result.AddRange(BitConverter.GetBytes((uint)(objaddr[FindModelIndex(objs[m].Sibling, objs)]) + 8));                     //sibling
                }
                else
                {
                    result.AddRange(BitConverter.GetBytes((uint)0));
                }
                currentaddr = result.Count;
            }
            result.InsertRange(objectsection + 8, BitConverter.GetBytes((ushort)7));
            result.InsertRange(objectsection + 2 + 8, BitConverter.GetBytes((ushort)objs.Length));
            result.InsertRange(objectsection + 4 + 8, BitConverter.GetBytes((uint)objs.Length * 52));
            return(result.ToArray());
        }
示例#10
0
        static void Main(string[] args)
        {
            string basemdlname;

            if (args.Length > 0)
            {
                basemdlname = args[0];
            }
            else
            {
                Console.Write("Base Model: ");
                basemdlname = Console.ReadLine().Trim('"');
            }
            string      fext      = Path.GetExtension(basemdlname);
            ModelFile   modelFile = new ModelFile(basemdlname);
            ModelFormat fmt       = modelFile.Format;
            NJS_OBJECT  basemdl   = modelFile.Model;
            string      mtnname;

            if (args.Length > 1)
            {
                mtnname = args[1];
            }
            else
            {
                Console.Write("Motion: ");
                mtnname = Console.ReadLine().Trim('"');
            }
            NJS_MOTION mtn = NJS_MOTION.Load(mtnname, basemdl.CountMorph());
            string     outdir;

            if (args.Length > 2)
            {
                outdir = args[2];
            }
            else
            {
                outdir = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(mtnname)), Path.GetFileNameWithoutExtension(mtnname));
            }
            Directory.CreateDirectory(outdir);
            MTNInfo inf = new MTNInfo()
            {
                ModelFormat = fmt, Name = mtn.Name, Frames = mtn.Frames, InterpolationMode = mtn.InterpolationMode
            };

            IniSerializer.Serialize(inf, Path.Combine(outdir, Path.ChangeExtension(Path.GetFileName(mtnname), ".ini")));
            NJS_OBJECT[] objs = basemdl.GetObjects().Where(a => a.Morph).ToArray();
            for (int frame = 0; frame < mtn.Frames; frame++)
            {
                if (!mtn.Models.Any(a => a.Value.Vertex.ContainsKey(frame)))
                {
                    continue;
                }
                foreach ((int idx, AnimModelData amd) in mtn.Models)
                {
                    if (amd.Vertex.ContainsKey(frame))
                    {
                        Vertex[] verts = amd.Vertex[frame];
                        amd.Normal.TryGetValue(frame, out Vertex[] norms);
                        switch (objs[idx].Attach)
                        {
                        case BasicAttach batt:
                            for (int i = 0; i < Math.Min(verts.Length, batt.Vertex.Length); i++)
                            {
                                batt.Vertex[i] = verts[i];
                                if (norms != null && batt.Normal != null)
                                {
                                    batt.Normal[i] = norms[i];
                                }
                            }
                            break;

                        case ChunkAttach catt:
                            if (catt.Vertex == null)
                            {
                                continue;
                            }
                            int vcnt = catt.Vertex.Sum(a => a.VertexCount);
                            int ci   = 0;
                            int vi   = 0;
                            for (int i = 0; i < Math.Min(verts.Length, vcnt); i++)
                            {
                                catt.Vertex[ci].Vertices[vi] = verts[i];
                                if (norms != null && catt.Vertex[ci].Normals != null)
                                {
                                    catt.Vertex[ci].Normals[vi] = norms[i];
                                }
                                if (++vi >= catt.Vertex[ci].VertexCount)
                                {
                                    ++ci;
                                    vi = 0;
                                }
                            }
                            break;
                        }
                    }
                }
                ModelFile.CreateFile(Path.Combine(outdir, $"{frame}{fext}"), basemdl, null, null, null, null, fmt);
            }
        }
示例#11
0
 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
     {
         byte[] file = File.ReadAllBytes(filename);
         if (Path.GetExtension(filename).Equals(".prs", StringComparison.OrdinalIgnoreCase))
         {
             file = FraGag.Compression.Prs.Decompress(file);
         }
         SA_Tools.ByteConverter.BigEndian = false;
         uint?baseaddr = SA_Tools.HelperFunctions.SetupEXE(ref file);
         if (baseaddr.HasValue)
         {
             modelinfo.numericUpDown2.Value   = baseaddr.Value;
             modelinfo.numericUpDown2.Enabled = false;
             modelinfo.ComboBox1.Enabled      = false;
             modelinfo.checkBox2.Checked      = modelinfo.checkBox2.Enabled = false;
             LoadBinFile(file);
         }
         else if (Path.GetExtension(filename).Equals(".rel", StringComparison.OrdinalIgnoreCase))
         {
             SA_Tools.ByteConverter.BigEndian = true;
             SA_Tools.HelperFunctions.FixRELPointers(file);
             modelinfo.numericUpDown2.Value   = 0;
             modelinfo.numericUpDown2.Enabled = false;
             modelinfo.ComboBox1.Enabled      = false;
             modelinfo.checkBox2.Enabled      = false;
             modelinfo.checkBox2.Checked      = true;
             LoadBinFile(file);
         }
         else
         {
             using (FileTypeDialog ftd = new FileTypeDialog())
             {
                 if (ftd.ShowDialog(this) != DialogResult.OK)
                 {
                     return;
                 }
                 if (ftd.typBinary.Checked)
                 {
                     modelinfo.numericUpDown2.Enabled = true;
                     modelinfo.ComboBox1.Enabled      = true;
                     modelinfo.checkBox2.Enabled      = true;
                     LoadBinFile(file);
                 }
                 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();
 }
示例#12
0
        static void Main(string[] args)
        {
            string path;

            if (args.Length > 0)
            {
                path = args[0];
            }
            else
            {
                Console.Write("Path: ");
                path = Console.ReadLine().Trim('"');
            }
            path = Path.GetFullPath(path);
            if (path.EndsWith(".ini"))
            {
                path = Path.GetDirectoryName(path);
            }
            string  mtnfn = new DirectoryInfo(path).Name;
            MTNInfo info  = IniSerializer.Deserialize <MTNInfo>(Path.Combine(path, mtnfn + ".ini"));
            string  fext  = null;

            switch (info.ModelFormat)
            {
            case ModelFormat.Basic:
            case ModelFormat.BasicDX:
                fext = "*.sa1mdl";
                break;

            case ModelFormat.Chunk:
                fext = "*.sa2mdl";
                break;

            case ModelFormat.GC:
                fext = "*.sa2bmdl";
                break;
            }
            SortedDictionary <int, NJS_OBJECT> mdls = new SortedDictionary <int, NJS_OBJECT>();

            foreach (string fn in Directory.EnumerateFiles(path, fext))
            {
                if (int.TryParse(Path.GetFileNameWithoutExtension(fn), out int i) && i >= 0 && i < info.Frames)
                {
                    mdls[i] = new ModelFile(fn).Model;
                }
            }
            NJS_OBJECT first   = mdls.First().Value;
            int        nodecnt = first.CountMorph();

            int[]        vcnt  = new int[nodecnt];
            ushort[][]   polys = new ushort[nodecnt][];
            NJS_OBJECT[] nodes = first.GetObjects().Where(a => a.Morph).ToArray();
            for (int i = 0; i < nodecnt; i++)
            {
                switch (nodes[i].Attach)
                {
                case BasicAttach batt:
                    vcnt[i] = batt.Vertex.Length;
                    List <ushort> plist = new List <ushort>();
                    foreach (NJS_MESHSET mesh in batt.Mesh)
                    {
                        foreach (Poly p in mesh.Poly)
                        {
                            plist.AddRange(p.Indexes);
                        }
                    }
                    polys[i] = plist.ToArray();
                    break;

                case ChunkAttach catt:
                    if (catt.Vertex != null)
                    {
                        vcnt[i] = catt.Vertex.Sum(a => a.VertexCount);
                    }
                    plist = new List <ushort>();
                    foreach (PolyChunkStrip pcs in catt.Poly.OfType <PolyChunkStrip>())
                    {
                        foreach (PolyChunkStrip.Strip s in pcs.Strips)
                        {
                            plist.AddRange(s.Indexes);
                        }
                    }
                    polys[i] = plist.ToArray();
                    break;
                }
            }
            NJS_MOTION mtn = new NJS_MOTION()
            {
                Name = info.Name, Frames = info.Frames, InterpolationMode = info.InterpolationMode, ModelParts = nodecnt
            };

            foreach ((int frame, NJS_OBJECT mdl) in mdls)
            {
                NJS_OBJECT[] nodes2 = mdl.GetObjects().Where(a => a.Morph).ToArray();
                if (nodes2.Length != nodecnt)
                {
                    Console.WriteLine("Warning: Model {0} skeleton does not match first file!", frame);
                    if (nodes2.Length > mtn.ModelParts)
                    {
                        mtn.ModelParts = nodes2.Length;
                    }
                }
                for (int i = 0; i < nodes2.Length; i++)
                {
                    switch (nodes2[i].Attach)
                    {
                    case BasicAttach batt:
                        if (batt.Vertex.Length != vcnt[i])
                        {
                            Console.WriteLine("Warning: Model {0} node {1} vertex count does not match first file!", frame, i);
                        }
                        AnimModelData amd;
                        if (!mtn.Models.TryGetValue(i, out amd))
                        {
                            amd = new AnimModelData()
                            {
                                VertexName = mtn.MdataName + "_vtx_" + i, NormalName = mtn.MdataName + "_nor_" + i
                            };
                            mtn.Models[i] = amd;
                        }
                        amd.Vertex[frame] = batt.Vertex;
                        if (batt.Normal != null)
                        {
                            amd.Normal[frame] = batt.Normal;
                        }
                        List <ushort> plist = new List <ushort>();
                        foreach (NJS_MESHSET mesh in batt.Mesh)
                        {
                            foreach (Poly p in mesh.Poly)
                            {
                                plist.AddRange(p.Indexes);
                            }
                        }
                        if (!polys[i].SequenceEqual(plist))
                        {
                            Console.WriteLine("Warning: Model {0} node {1} poly data does not match first file!", frame, i);
                        }
                        break;

                    case ChunkAttach catt:
                        if (catt.Vertex != null)
                        {
                            if (catt.Vertex.Sum(a => a.VertexCount) != vcnt[i])
                            {
                                Console.WriteLine("Warning: Model {0} node {1} vertex count does not match first file!", frame, i);
                            }
                            if (!mtn.Models.TryGetValue(i, out amd))
                            {
                                amd = new AnimModelData()
                                {
                                    VertexName = mtn.MdataName + "_vtx_" + i, NormalName = mtn.MdataName + "_nor_" + i
                                };
                                mtn.Models[i] = amd;
                            }
                            amd.Vertex[frame] = catt.Vertex.SelectMany(a => a.Vertices).ToArray();
                            if (catt.Vertex.All(a => a.Normals != null))
                            {
                                amd.Normal[frame] = catt.Vertex.SelectMany(a => a.Normals).ToArray();
                            }
                        }
                        plist = new List <ushort>();
                        foreach (PolyChunkStrip pcs in catt.Poly.OfType <PolyChunkStrip>())
                        {
                            foreach (PolyChunkStrip.Strip s in pcs.Strips)
                            {
                                plist.AddRange(s.Indexes);
                            }
                        }
                        polys[i] = plist.ToArray();
                        break;
                    }
                }
            }
            foreach ((int _, AnimModelData amd) in mtn.Models)
            {
                amd.VertexItemName = Enumerable.Range(0, amd.Vertex.Count).Select(a => amd.VertexName + "_" + a).ToArray();
                if (amd.Normal.Count > 0)
                {
                    amd.NormalItemName = Enumerable.Range(0, amd.Normal.Count).Select(a => amd.NormalName + "_" + a).ToArray();
                }
            }
            mtn.Save(Path.Combine(path, $"{mtnfn}.saanim"));
        }
示例#13
0
        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;
            }
        }