public void AddSkin(GameObject gameObject, string SkinFolder, ConfigFile config)
        {
            LoadoutAPI.SkinDefInfo skinDefInfo = new LoadoutAPI.SkinDefInfo();
            skinDefInfo.BaseSkins             = new SkinDef[0];
            skinDefInfo.Icon                  = LoadoutAPI.CreateSkinIcon(config.Bind <Color>("", "IconColorTop", Color.magenta).Value, config.Bind <Color>("", "IconColorRight", Color.black).Value, config.Bind <Color>("", "IconColorBottom", Color.magenta).Value, config.Bind <Color>("", "IconColorLeft", Color.black).Value);
            skinDefInfo.NameToken             = config.Bind <string>("", "SkinName", "DefaultName").Value;
            skinDefInfo.UnlockableName        = config.Bind <string>("", "UnlockableName", "").Value;
            skinDefInfo.RootObject            = gameObject.GetComponentInChildren <ModelLocator>().modelTransform.gameObject;
            skinDefInfo.RendererInfos         = new CharacterModel.RendererInfo[0];
            skinDefInfo.MeshReplacements      = new SkinDef.MeshReplacement[0];
            skinDefInfo.GameObjectActivations = new SkinDef.GameObjectActivation[0];
            skinDefInfo.Name                  = "CUSTOM_" + gameObject.name + "_SKIN";

            base.Logger.LogInfo("Adding new skin to " + gameObject.name + " with name " + skinDefInfo.NameToken);

            int    MeshReplacementIndex = config.Bind <int>("", "MeshReplacementIndex", -1).Value;
            string MeshReplacementKey   = config.Bind <string>("", "SkinMeshToUse", "Default").Value;

            string minionSkinForBody = config.Bind <string>("", "MinionReplacementForBody", "NONE", new ConfigDescription("If this is a minion skin, determines the characterbody for it")).Value;
            string minionSkinForSkin = config.Bind <string>("", "MinionReplacementForSkin", "NONE", new ConfigDescription("If this is a minion skin, determines the characterbody for it")).Value;


            bool isMinionSkin = false;

            if (minionSkinForBody != null)
            {
                isMinionSkin = minionSkinForBody != "NONE";
            }


            if (MeshReplacementKey != "Default" && MeshReplacementKey != "Custom" && MeshReplacementKey != null)
            {
                SkinDef def1 = gameObject.GetComponentInChildren <ModelLocator>().modelTransform.GetComponentInChildren <ModelSkinController>().skins.First(x => x.nameToken == MeshReplacementKey);
                MeshReplacementIndex = Array.IndexOf(gameObject.GetComponentInChildren <ModelLocator>().modelTransform.GetComponentInChildren <ModelSkinController>().skins, def1);
            }

            SkinDef def = gameObject.GetComponentInChildren <ModelLocator>().modelTransform.GetComponentInChildren <ModelSkinController>().skins[MeshReplacementIndex];

            if (def)
            {
                skinDefInfo.MeshReplacements = def.meshReplacements;
                skinDefInfo.RendererInfos    = def.rendererInfos;
            }

            CharacterModel.RendererInfo[] rendererInfos = skinDefInfo.RendererInfos;
            CharacterModel.RendererInfo[] array         = new CharacterModel.RendererInfo[rendererInfos.Length];
            rendererInfos.CopyTo(array, 0);



            foreach (string MaterialFolder in Directory.EnumerateDirectories(SkinFolder))
            {
                //Get name of render from folder name
                string[] MaterialIndexVs = MaterialFolder.Split(new string[] { @"\" }, StringSplitOptions.None);
                string   RendererName    = MaterialIndexVs[MaterialIndexVs.Length - 1];

                //Find the renderer based on the name
                int index = Array.IndexOf(array, array.FirstOrDefault(x => x.renderer.name == RendererName));

                //Get the material of the renderer
                Material defaultMaterial = array[index].defaultMaterial;


                if (defaultMaterial)
                {
                    //Create a clone of the material
                    defaultMaterial = UnityEngine.Object.Instantiate <Material>(defaultMaterial);

                    //Iterate through all files related to this material from the skin folder
                    foreach (string FilePath in Directory.EnumerateFiles(MaterialFolder))
                    {
                        //Loading and applying textures from .png
                        if (FilePath.EndsWith(".PNG") || FilePath.EndsWith(".png"))
                        {
                            //Use File name to get texture name
                            string[] FilePathVs = FilePath.Split(new string[] { @"\" }, StringSplitOptions.None);
                            string   FileName   = FilePathVs[FilePathVs.Length - 1].Replace(".PNG", "");

                            //Create new Texture2d and load image in
                            Texture2D savedTex = new Texture2D(1, 1, TextureFormat.RGBAFloat, false, true);
                            ImageConversion.LoadImage(savedTex, System.IO.File.ReadAllBytes(FilePath));

                            //Apply the loaded image
                            savedTex.Apply();

                            //Attempt to place this image onto the material in the correct property
                            if (defaultMaterial.HasProperty(FileName))
                            {
                                defaultMaterial.enableInstancing = true;
                                defaultMaterial.SetTexture(FileName, GetReadableTextureCopy(savedTex));
                            }
                        }
                        else if (FilePath.EndsWith(".cfg"))
                        {
                            //Load the config at this path
                            BepInEx.Configuration.ConfigFile perMatConfig = new ConfigFile(FilePath, true);

                            //iterate through material properties and apply via config
                            foreach (string value in floatProperties)
                            {
                                if (defaultMaterial.HasProperty(value))
                                {
                                    defaultMaterial.SetFloat(value, perMatConfig.Bind <float>("", value, defaultMaterial.GetFloat(value), new ConfigDescription("Sets the value for " + value)).Value);
                                }
                            }

                            foreach (string value in colorProperties)
                            {
                                if (defaultMaterial.HasProperty(value))
                                {
                                    defaultMaterial.SetColor(value, perMatConfig.Bind <Color>("", value, defaultMaterial.GetColor(value), new ConfigDescription("Sets the value for " + value)).Value);
                                }
                            }

                            foreach (string value in defaultMaterial.shaderKeywords)
                            {
                                bool isEnabled = perMatConfig.Bind <bool>("", value, defaultMaterial.IsKeywordEnabled(value), new ConfigDescription("Sets the value for " + value)).Value;

                                if (isEnabled)
                                {
                                    defaultMaterial.EnableKeyword(value);
                                }
                                else
                                {
                                    defaultMaterial.DisableKeyword(value);
                                }
                            }
                        }
                        else
                        {
                            base.Logger.LogError("Unsupported file found in material folder: " + FilePath);
                        }
                    }


                    array[index].defaultMaterial = defaultMaterial;
                }
            }

            skinDefInfo.RendererInfos = array;
            LoadoutAPI.AddSkinToCharacter(gameObject, skinDefInfo);

            SkinDef[] skins = gameObject.GetComponentInChildren <ModelLocator>().modelTransform.GetComponentInChildren <ModelSkinController>().skins;

            skins[skins.Length - 1].minionSkinReplacements      = new SkinDef.MinionSkinReplacement[0];
            skins[skins.Length - 1].projectileGhostReplacements = new SkinDef.ProjectileGhostReplacement[0];


            if (isMinionSkin)
            {
                base.Logger.LogInfo("Is a minion skin");

                foreach (GameObject body in BodyCatalog.allBodyPrefabs)
                {
                    if (body.name == minionSkinForBody)
                    {
                        base.Logger.LogInfo("Applying minionskinreplacement");

                        SkinDef defForMaster = body.GetComponentInChildren <ModelSkinController>().skins.First(x => x.nameToken == minionSkinForSkin);

                        base.Logger.LogInfo("Size was " + defForMaster.minionSkinReplacements.Length);


                        Array.Resize(ref defForMaster.minionSkinReplacements, defForMaster.minionSkinReplacements.Length + 1);
                        defForMaster.minionSkinReplacements[defForMaster.minionSkinReplacements.Length - 1] = new SkinDef.MinionSkinReplacement()
                        {
                            minionBodyPrefab = gameObject, minionSkin = skins[skins.Length - 1]
                        };

                        base.Logger.LogInfo("Size is now " + defForMaster.minionSkinReplacements.Length);
                    }
                }
            }

            SkinDef[][] newSkins = typeof(BodyCatalog).GetFieldValue <SkinDef[][]>("skins");
            newSkins[BodyCatalog.FindBodyIndex(gameObject)] = skins;
            typeof(BodyCatalog).SetFieldValue <SkinDef[][]>("skins", newSkins);
        }
Beispiel #2
0
        public void AddSkin(SurvivorDef def, string SkinFolder, ConfigFile config)
        {
            GameObject gameObject = def.bodyPrefab;

            LoadoutAPI.SkinDefInfo skinDefInfo = new LoadoutAPI.SkinDefInfo();
            skinDefInfo.BaseSkins             = new SkinDef[0];
            skinDefInfo.Icon                  = LoadoutAPI.CreateSkinIcon(config.Bind <Color>("", "IconColorTop", Color.magenta).Value, config.Bind <Color>("", "IconColorRight", Color.black).Value, config.Bind <Color>("", "IconColorBottom", Color.magenta).Value, config.Bind <Color>("", "IconColorLeft", Color.black).Value);
            skinDefInfo.NameToken             = config.Bind <string>("", "SkinName", "DefaultName").Value;
            skinDefInfo.UnlockableName        = config.Bind <string>("", "UnlockableName", "").Value;
            skinDefInfo.RootObject            = def.bodyPrefab.GetComponent <ModelLocator>().modelTransform.gameObject;
            skinDefInfo.RendererInfos         = new CharacterModel.RendererInfo[0];
            skinDefInfo.MeshReplacements      = new SkinDef.MeshReplacement[0];
            skinDefInfo.GameObjectActivations = new SkinDef.GameObjectActivation[0];
            skinDefInfo.Name                  = "SKIN_" + gameObject.name + "_DEFAULT";



            int MeshReplacementIndex = config.Bind <int>("", "MeshReplacementIndex", 0).Value;

            if (MeshReplacementIndex != -1)
            {
                skinDefInfo.MeshReplacements = gameObject.GetComponent <ModelLocator>().modelTransform.GetComponent <ModelSkinController>().skins[MeshReplacementIndex].meshReplacements;
                skinDefInfo.RendererInfos    = gameObject.GetComponent <ModelLocator>().modelTransform.GetComponent <ModelSkinController>().skins[MeshReplacementIndex].rendererInfos;
            }

            CharacterModel.RendererInfo[] rendererInfos = skinDefInfo.RendererInfos;
            CharacterModel.RendererInfo[] array         = new CharacterModel.RendererInfo[rendererInfos.Length];
            rendererInfos.CopyTo(array, 0);



            foreach (string MaterialFolder in Directory.EnumerateDirectories(SkinFolder))
            {
                string[] MaterialIndexVs = MaterialFolder.Split(new string[] { @"\" }, StringSplitOptions.None);
                string   RendererName    = MaterialIndexVs[MaterialIndexVs.Length - 1];

                int index = Array.IndexOf(array, array.FirstOrDefault(x => x.renderer.name == RendererName));

                Material defaultMaterial = array[index].defaultMaterial;
                if (defaultMaterial)
                {
                    defaultMaterial = UnityEngine.Object.Instantiate <Material>(defaultMaterial);

                    foreach (string FilePath in Directory.EnumerateFiles(MaterialFolder))
                    {
                        if (FilePath.EndsWith(".PNG") || FilePath.EndsWith(".png"))
                        {
                            string[] FilePathVs = FilePath.Split(new string[] { @"\" }, StringSplitOptions.None);
                            string   FileName   = FilePathVs[FilePathVs.Length - 1].Replace(".PNG", "");

                            Texture2D savedTex = new Texture2D(1, 1, TextureFormat.RGBAFloat, false, true);
                            ImageConversion.LoadImage(savedTex, System.IO.File.ReadAllBytes(FilePath));

                            savedTex.Apply();

                            if (defaultMaterial.HasProperty(FileName))
                            {
                                defaultMaterial.enableInstancing = true;
                                defaultMaterial.SetTexture(FileName, GetReadableTextureCopy(savedTex));
                            }
                        }
                        else if (FilePath.EndsWith(".cfg"))
                        {
                            string[] ConfigPathVs = FilePath.Split(new string[] { @"\" }, StringSplitOptions.None);
                            string   ConfigName   = @"BepInEx\skins\" + ConfigPathVs[ConfigPathVs.Length - 4] + @"\" + ConfigPathVs[ConfigPathVs.Length - 3] + @"\" + ConfigPathVs[ConfigPathVs.Length - 2] + @"\" + ConfigPathVs[ConfigPathVs.Length - 1];
                            BepInEx.Configuration.ConfigFile perMatConfig = new ConfigFile(ConfigName, true);

                            {
                                foreach (string value in floatProperties)
                                {
                                    if (defaultMaterial.HasProperty(value))
                                    {
                                        defaultMaterial.SetFloat(value, perMatConfig.Bind <float>("", value, defaultMaterial.GetFloat(value), new ConfigDescription("Sets the value for " + value)).Value);
                                    }
                                }



                                foreach (string value in colorProperties)
                                {
                                    if (defaultMaterial.HasProperty(value))
                                    {
                                        defaultMaterial.SetColor(value, perMatConfig.Bind <Color>("", value, defaultMaterial.GetColor(value), new ConfigDescription("Sets the value for " + value)).Value);
                                    }
                                }

                                foreach (string value in defaultMaterial.shaderKeywords)
                                {
                                    bool isEnabled = perMatConfig.Bind <bool>("", value, defaultMaterial.IsKeywordEnabled(value), new ConfigDescription("Sets the value for " + value)).Value;

                                    if (isEnabled)
                                    {
                                        defaultMaterial.EnableKeyword(value);
                                    }
                                    else
                                    {
                                        defaultMaterial.DisableKeyword(value);
                                    }
                                }
                            }
                        }
                        else if (FilePath.EndsWith(".obj"))
                        {
                            Mesh        holderMesh = new Mesh();
                            ObjImporter newMesh    = new ObjImporter();
                            holderMesh = newMesh.ImportFile(FilePath);

                            if (array[index].renderer.gameObject.GetComponent <MeshFilter>())
                            {
                                Array.Resize(ref skinDefInfo.MeshReplacements, skinDefInfo.MeshReplacements.Length + 1);
                                skinDefInfo.MeshReplacements[skinDefInfo.MeshReplacements.Length - 1].mesh     = holderMesh;
                                skinDefInfo.MeshReplacements[skinDefInfo.MeshReplacements.Length - 1].renderer = array[index].renderer;

                                (skinDefInfo.MeshReplacements[skinDefInfo.MeshReplacements.Length - 1].renderer as SkinnedMeshRenderer).sharedMesh = holderMesh;
                            }
                        }
                        else
                        {
                            base.Logger.LogError("Unsupported file found in material folder: " + FilePath);
                        }
                    }


                    array[index].defaultMaterial = defaultMaterial;
                }
            }

            base.Logger.LogInfo("Added new skin to " + def.bodyPrefab.name + " with name " + skinDefInfo.NameToken);

            skinDefInfo.RendererInfos = array;
            LoadoutAPI.AddSkinToCharacter(def.bodyPrefab, skinDefInfo);

            SkinDef[] skins = def.bodyPrefab.GetComponent <ModelLocator>().modelTransform.GetComponent <ModelSkinController>().skins;

            SkinDef[][] newSkins = typeof(BodyCatalog).GetFieldValue <SkinDef[][]>("skins");
            newSkins[SurvivorCatalog.GetBodyIndexFromSurvivorIndex(def.survivorIndex)] = skins;
            typeof(BodyCatalog).SetFieldValue <SkinDef[][]>("skins", newSkins);
        }