Example #1
0
        protected override void OnReplace(object oldData)
        {
            Model oldDataT = ( Model )oldData;

            // Replace the mesh name with the one we replaced.
            if (oldDataT.Meshes.Count == Data.Meshes.Count)
            {
                Data.Meshes[0].Name = oldDataT.Meshes[0].Name;
                Data.Meshes[0].ID   = oldDataT.Meshes[0].ID;
            }

            // Pass the ex data to meshes if they don't have them.
            // Game crashes without the ex data if it tries to make use of them.
            // SMH sega, can't even do a null check!!
            foreach (var mesh in Data.Meshes)
            {
                var oldMesh = oldDataT.Meshes.FirstOrDefault(x => x.Name.Equals(mesh.Name, StringComparison.OrdinalIgnoreCase));
                if (oldMesh != null)
                {
                    if (mesh.Skin != null && mesh.Skin.ExData == null)
                    {
                        mesh.Skin.ExData = oldMesh.Skin?.ExData;
                    }

                    mesh.Name = oldMesh.Name;
                    mesh.ID   = oldMesh.ID;
                }
            }

            // Pass the format/endianness
            Data.Format     = oldDataT.Format;
            Data.Endianness = oldDataT.Endianness;

            // Randomize texture IDs if we are modern
            if (BinaryFormatUtilities.IsModern(Data.Format) && Data.TextureSet != null)
            {
                var newIDs = new List <int>(Data.TextureSet.Textures.Count);

                var random = new Random();
                for (int i = 0; i < Data.TextureSet.Textures.Count; i++)
                {
                    int currentID;
                    do
                    {
                        currentID = random.Next(int.MinValue, int.MaxValue);
                    } while (newIDs.Contains(currentID));

                    newIDs.Add(currentID);
                }

                TextureUtilities.ReAssignTextureIDs(Data, newIDs);
            }

            Textures?.Replace(Data.TextureSet);

            base.OnReplace(oldData);
        }
Example #2
0
        public void Save(Stream destination, ObjectDatabase objectDatabase, TextureDatabase textureDatabase, BoneDatabase boneDatabase, bool leaveOpen = false)
        {
            if (objectDatabase != null)
            {
                foreach (var mesh in Meshes)
                {
                    mesh.ID = objectDatabase.GetMesh(mesh.Name)?.ID ?? mesh.ID;
                }
            }

            if (boneDatabase != null)
            {
                string fileName = (destination is FileStream fileStream) ? Path.GetFileName(fileStream.Name) : string.Empty;

                // Assume we are exporting in game's style
                var skeleton = boneDatabase.Skeletons.FirstOrDefault(x => fileName.StartsWith(x.Name, StringComparison.OrdinalIgnoreCase));

                // If we couldn't find it, default to CMN skeleton
                if (skeleton == null)
                {
                    skeleton = boneDatabase.Skeletons.FirstOrDefault(x => x.Name.Equals("CMN", StringComparison.OrdinalIgnoreCase));
                }

                // Still?? Then default to the first skeleton (this is unlikely to happen though)
                if (skeleton == null)
                {
                    skeleton = boneDatabase.Skeletons[0];
                }

                // Pretty much impossible to miss
                if (skeleton != null)
                {
                    foreach (var skin in Meshes.Where(x => x.Skin != null).Select(x => x.Skin))
                    {
                        foreach (var bone in skin.Bones)
                        {
                            int index = skin.ExData?.BoneNames?.FindIndex(x => x.Equals(bone.Name, StringComparison.OrdinalIgnoreCase)) ?? -1;
                            if (index == -1)
                            {
                                index = skeleton.BoneNames1.FindIndex(x => x.Equals(bone.Name, StringComparison.OrdinalIgnoreCase));
                            }
                            else
                            {
                                index = 0x8000 | index;
                            }

                            if (index != -1)
                            {
                                // Before we do this, fix the child bones
                                foreach (var childBone in skin.Bones.Where(x => x.ParentID.Equals(bone.ID)))
                                {
                                    childBone.ParentID = index;
                                }

                                // Now replace the ID
                                bone.ID = index;
                            }
                            else
                            {
                                Debug.WriteLine($"Model.Save: Bone wasn't found in bone database or ex-data: {bone.Name}");
                            }
                        }
                    }
                }
            }

            if (textureDatabase != null && TextureSet != null)
            {
                var newIDs    = new List <int>(TextureSet.Textures.Count);
                int currentID = textureDatabase.Textures.Max(x => x.ID) + 1;
                foreach (var texture in TextureSet.Textures)
                {
                    var textureEntry = !string.IsNullOrEmpty(texture.Name) ?
                                       textureDatabase.GetTexture(texture.Name) : textureDatabase.GetTexture(texture.ID);

                    if (textureEntry == null)
                    {
                        textureDatabase.Textures.Add(textureEntry = new TextureEntry
                        {
                            ID   = currentID++,
                            Name = texture.Name ?? $"Texture{currentID}",
                        });
                    }

                    newIDs.Add(textureEntry.ID);
                }

                if (!newIDs.SequenceEqual(TextureIDs))
                {
                    TextureUtilities.ReAssignTextureIDs(this, newIDs);
                }
            }

            Save(destination, leaveOpen);
        }