private void ShowKerbalSuitButtons(Appearance appearance, int suitIndex, Suit suit) { var mapper = Mapper.Instance; GUILayout.BeginHorizontal(); GUI.enabled = availableSuits.Count != 0; if (GUILayout.Button("<")) { suitIndex = suitIndex == -1 ? 0 : (suitIndex + availableSuits.Count - 1) % availableSuits.Count; if (selectedKerbal != null) { appearance.Suit = availableSuits[suitIndex]; } else if (selectedClass != null) { mapper.ClassSuits[selectedClass] = availableSuits[suitIndex]; } } if (GUILayout.Button(">")) { suitIndex = suitIndex == -1 ? 0 : (suitIndex + 1) % availableSuits.Count; if (selectedKerbal != null) { appearance.Suit = availableSuits[suitIndex]; } else if (selectedClass != null) { mapper.ClassSuits[selectedClass] = availableSuits[suitIndex]; } } GUI.enabled = true; GUILayout.EndHorizontal(); bool hasKerbalGenericSuit = selectedKerbal != null && appearance.Suit == null; Suit defaultSuit = selectedKerbal == null ? mapper.DefaultSuit : mapper.GetDefault(selectedKerbal.suit); GUI.color = suit == defaultSuit && !hasKerbalGenericSuit ? SelectedColour : Color.white; if (GUILayout.Button("Default")) { if (selectedClass != null) { mapper.ClassSuits[selectedClass] = defaultSuit; } else { appearance.Suit = defaultSuit; } } GUI.color = suit == null || hasKerbalGenericSuit ? SelectedColour : Color.white; if (GUILayout.Button("Unset/Generic")) { if (selectedClass != null) { mapper.ClassSuits[selectedClass] = null; } else { appearance.Suit = null; } } GUI.color = Color.white; // Handle radio button clicks and change to default suit if suit kind changed. if (selectedKerbal != null) { bool isVintage = selectedKerbal.suit == KerbalSuit.Vintage; bool isFuture = selectedKerbal.suit == KerbalSuit.Future; isVintage = GUILayout.Toggle(isVintage, "Vintage"); isFuture = GUILayout.Toggle(isFuture, "Future"); KerbalSuit?newSuit = (selectedKerbal.suit, isVintage, isFuture) switch { (KerbalSuit.Default, true, _) => KerbalSuit.Vintage, (KerbalSuit.Default, _, true) => KerbalSuit.Future, (KerbalSuit.Vintage, false, false) => KerbalSuit.Default, (KerbalSuit.Vintage, _, true) => KerbalSuit.Future, (KerbalSuit.Future, false, false) => KerbalSuit.Default, (KerbalSuit.Future, true, _) => KerbalSuit.Vintage, _ => (KerbalSuit?)null }; if (newSuit.HasValue) { selectedKerbal.suit = newSuit.Value; availableSuits = mapper.GetAvailableSuits(selectedKerbal, true); appearance.Suit = mapper.GetDefault(selectedKerbal.suit); } } }
/// <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); } } }
private void WindowHandler(int id) { var mapper = Mapper.Instance; GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); ShowRoster(); // Textures. Appearance appearance = null; Skin skin = null; Suit suit = null; int suitIndex = -1; if (selectedKerbal != null) { appearance = mapper.GetAppearance(selectedKerbal); skin = mapper.GetKerbalSkin(selectedKerbal, appearance); suit = mapper.GetKerbalSuit(selectedKerbal, appearance); suitIndex = availableSuits.IndexOf(suit); } else if (selectedClass != null) { if (mapper.ClassSuits.TryGetValue(selectedClass, out suit)) { suitIndex = availableSuits.IndexOf(suit); } } GUILayout.BeginVertical(); if (skin != null) { ShowKerbalSkinTextures(skin); } if (suit != null) { ShowKerbalSuitTextures(suit); } GUILayout.EndVertical(); GUILayout.BeginVertical(GUILayout.Width(120)); if (selectedKerbal != null && appearance != null) { ShowKerbalSkinButtons(appearance); } if (selectedKerbal != null || selectedClass != null) { ShowKerbalSuitButtons(appearance, suitIndex, suit); } GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.Space(5); ShowOptions(); ShowDumpTexture(); GUILayout.EndVertical(); GUI.DragWindow(new Rect(0, 0, Screen.width, 30)); }