Ejemplo n.º 1
0
        /// <summary>
        /// Replace textures on a Kerbal model.
        /// </summary>
        private void PersonaliseKerbal(Component component, ProtoCrewMember kerbal, bool isEva, bool useEvaSuit)
        {
            Transform transform = component.transform;

            // Prefabricated Vintage & Future IVA models are missing so they are instantiated anew every time. Hence, we have
            // to apply fixes to them and set fallback default textures.
            bool isPrefabMissing = !isEva && kerbal.suit != KerbalSuit.Default;

            Appearance appearance = mapper.GetAppearance(kerbal);

            Skin skin        = mapper.GetKerbalSkin(kerbal, appearance);
            Suit suit        = mapper.GetKerbalSuit(kerbal, appearance);
            Skin defaultSkin = mapper.GetDefault(kerbal.gender);
            Suit defaultSuit = mapper.GetDefault(kerbal.suit);

            Transform modelTransform = (isEva, kerbal.suit, kerbal.gender) switch {
                (false, KerbalSuit.Default, _) => transform.Find("model01"),
                (false, KerbalSuit.Vintage, _) => transform.Find("kbIVA@idle/model01"),
                (false, KerbalSuit.Future, Gender.Male) => transform.Find("serenityMaleIVA/model01"),
                (false, KerbalSuit.Future, Gender.Female) => transform.Find("serenityFemaleIVA/model01"),
                _ => transform.Find("model01")
            };

            // Sometimes when we switch between suits (e.g. with clothes hanger) suit kind and model get out of sync.
            // Just try all possible nodes in such cases.
            modelTransform ??= transform.Find("model01") ?? transform.Find("kbIVA@idle/model01") ??
            transform.Find("serenityMaleIVA/model01") ?? transform.Find("serenityFemaleIVA/model01");

            // We determine body and helmet texture here to avoid code duplication between suit and helmet cases in the
            // following switch.
            // Setting the suit explicitly -- even when default -- is necessary for two reasons: to fix IVA suits after KSP
            // resetting them to the stock ones all the time and to fix the switch to default texture on start of EVA walk or
            // EVA suit toggle.
            Texture2D suitTexture   = suit.GetSuit(useEvaSuit, kerbal) ?? defaultSuit.GetSuit(useEvaSuit, kerbal);
            Texture2D suitNormalMap = suit.GetSuitNRM(useEvaSuit) ?? defaultSuit.GetSuitNRM(useEvaSuit);

            foreach (Renderer renderer in modelTransform.GetComponentsInChildren <Renderer>())
            {
                var smr = renderer as SkinnedMeshRenderer;

                // Headlight flares and thruster jets.
                if (smr == null)
                {
                    continue;
                }

                Material material = smr.material;

                Texture2D newTexture   = null;
                Texture2D newNormalMap = null;
                Texture2D newEmissive  = null;

                switch (smr.name)
                {
                case "eyeballLeft":
                case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_eyeballLeft": {
                    if (skin.Eyeless)
                    {
                        smr.sharedMesh = null;
                        break;
                    }

                    newTexture = skin.EyeballLeft;

                    if (isPrefabMissing)
                    {
                        newTexture ??= defaultSkin.EyeballLeft;
                        material.shader = Replacer.EyeShader;
                    }
                    break;
                }

                case "eyeballRight":
                case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_eyeballRight": {
                    if (skin.Eyeless)
                    {
                        smr.sharedMesh = null;
                        break;
                    }

                    newTexture = skin.EyeballRight;

                    if (isPrefabMissing)
                    {
                        newTexture ??= defaultSkin.EyeballRight;
                        material.shader = Replacer.EyeShader;
                    }
                    break;
                }

                case "pupilLeft":
                case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_pupilLeft": {
                    if (skin.Eyeless)
                    {
                        smr.sharedMesh = null;
                        break;
                    }

                    newTexture = skin.PupilLeft;

                    if (isPrefabMissing)
                    {
                        newTexture ??= defaultSkin.PupilLeft;
                        material.shader = Replacer.EyeShader;
                    }

                    if (newTexture != null)
                    {
                        material.color = Color.white;
                    }
                    break;
                }

                case "pupilRight":
                case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_pupilRight": {
                    if (skin.Eyeless)
                    {
                        smr.sharedMesh = null;
                        break;
                    }

                    newTexture = skin.PupilRight;

                    if (isPrefabMissing)
                    {
                        newTexture ??= defaultSkin.PupilRight;
                        material.shader = Replacer.EyeShader;
                    }

                    if (newTexture != null)
                    {
                        material.color = Color.white;
                    }
                    break;
                }

                case "headMesh01":
                case "headMesh02":
                case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_pCube1":
                case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_polySurface51": {
                    newTexture   = skin.Head;
                    newNormalMap = skin.HeadNRM;

                    if (isPrefabMissing)
                    {
                        newTexture ??= defaultSkin.Head;
                        newNormalMap ??= defaultSkin.HeadNRM;
                        material.shader = newNormalMap == null ? Replacer.HeadShader : Replacer.BumpedHeadShader;
                    }
                    else if (newNormalMap != null)
                    {
                        material.shader = Replacer.BumpedHeadShader;
                    }
                    break;
                }

                case "tongue":
                case "upTeeth01":
                case "upTeeth02":
                case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_upTeeth01":
                case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_downTeeth01": {
                    if (isPrefabMissing)
                    {
                        smr.material = Replacer.Instance.TeethMaterial;
                    }
                    break;
                }

                case "body01":
                case "mesh_female_kerbalAstronaut01_body01": {
                    newTexture   = suitTexture;
                    newNormalMap = suitNormalMap;
                    if (isEva)
                    {
                        newEmissive = suit.EvaSuitEmissive;
                    }

                    // Update textures in Kerbal IVA object since KSP resets them to these values a few frames later.
                    var kerbalIva = component as Kerbal;
                    if (kerbalIva != null)
                    {
                        kerbalIva.textureStandard = newTexture;
                        kerbalIva.textureVeteran  = newTexture;
                    }
                    break;
                }

                case "neckRing": {
                    if (isEva)
                    {
                        newTexture   = suitTexture;
                        newNormalMap = suitNormalMap;
                    }
                    else
                    {
                        smr.gameObject.DestroyGameObjectImmediate();
                    }
                    break;
                }

                case "helmet":
                case "mesh_female_kerbalAstronaut01_helmet": {
                    newTexture   = suitTexture;
                    newNormalMap = suitNormalMap;
                    break;
                }

                case "visor":
                case "mesh_female_kerbalAstronaut01_visor": {
                    // Visor texture has to be replaced every time.
                    newTexture = suit.GetVisor(useEvaSuit);
                    if (newTexture != null)
                    {
                        material.color = Color.white;
                    }
                    break;
                }

                default: { // Jetpack.
                    if (isEva)
                    {
                        smr.enabled = useEvaSuit;
                        if (useEvaSuit)
                        {
                            newTexture   = suit.Jetpack;
                            newNormalMap = suit.JetpackNRM;
                            newEmissive  = suit.JetpackEmissive;
                        }
                    }
                    break;
                }
                }

                if (newTexture != null)
                {
                    material.mainTexture = newTexture;
                }
                if (newNormalMap != null)
                {
                    material.SetTexture(Util.BumpMapProperty, newNormalMap);
                }
                if (newEmissive != null)
                {
                    material.SetTexture(Util.EmissiveProperty, newEmissive);
                }
            }

            // Backpacks and parachute are positioned on another node in model hierarchy.
            if (isEva)
            {
                bool showJetpack  = useEvaSuit;
                bool showBackpack = showJetpack && !mapper.HideBackpack;

                Transform flagTransform      = transform.Find("model/kbEVA_flagDecals");
                Transform cargoPackTransform = transform.Find("model/EVABackpack/kerbalCargoContainerPack/base") ??
                                               transform.Find("model/kerbalCargoContainerPack/base");
                Transform parachutePackTransform   = transform.Find("model/EVAparachute/base");
                Transform parachuteCanopyTransform = transform.Find("model/EVAparachute/canopyrot/canopy");

                var flag            = flagTransform.GetComponent <Renderer>();
                var cargoPack       = cargoPackTransform.GetComponent <Renderer>();
                var parachutePack   = parachutePackTransform.GetComponent <Renderer>();
                var parachuteCanopy = parachuteCanopyTransform.GetComponent <Renderer>();

                flag.enabled          = showJetpack;
                cargoPack.enabled     = showBackpack;
                parachutePack.enabled = showBackpack;

                if (showBackpack)
                {
                    if (suit.CargoPack != null)
                    {
                        cargoPack.material.mainTexture = suit.CargoPack;
                    }
                    if (suit.CargoPackNRM != null)
                    {
                        cargoPack.material.SetTexture(Util.BumpMapProperty, suit.CargoPackNRM);
                    }
                    if (suit.CargoPackEmissive != null)
                    {
                        cargoPack.material.SetTexture(Util.EmissiveProperty, suit.CargoPackEmissive);
                    }

                    if (suit.ParachutePack != null)
                    {
                        parachutePack.material.mainTexture = suit.ParachutePack;
                    }
                    if (suit.ParachutePackNRM != null)
                    {
                        parachutePack.material.SetTexture(Util.BumpMapProperty, suit.ParachutePackNRM);
                    }
                }

                if (suit.ParachuteCanopy != null)
                {
                    parachuteCanopy.material.mainTexture = suit.ParachuteCanopy;
                }
                if (suit.ParachuteCanopyNRM != null)
                {
                    parachuteCanopy.material.SetTexture(Util.BumpMapProperty, suit.ParachuteCanopyNRM);
                }
            }
        }