/// <summary> /// Get appearance of a Kerbal. If the skin or the suit is generic it is set to null. If an appearance does not /// yet exist for that Kerbal it is created. /// </summary> public Appearance GetAppearance(ProtoCrewMember kerbal) { if (gameKerbals.TryGetValue(kerbal.name, out Appearance appearance)) { return(appearance); } appearance = new Appearance { Hash = kerbal.name.GetHashCode() }; gameKerbals.Add(kerbal.name, appearance); return(appearance); }
private void ShowKerbalSkinButtons(Appearance appearance) { var mapper = Mapper.Instance; GUILayout.BeginHorizontal(); GUI.enabled = availableSkins.Count != 0; if (GUILayout.Button("<")) { int skinIndex = availableSkins.IndexOf(mapper.GetKerbalSkin(selectedKerbal, appearance)); skinIndex = skinIndex == -1 ? 0 : (availableSkins.Count + skinIndex - 1) % availableSkins.Count; appearance.Skin = availableSkins[skinIndex]; } if (GUILayout.Button(">")) { int skinIndex = availableSkins.IndexOf(mapper.GetKerbalSkin(selectedKerbal, appearance)); skinIndex = skinIndex == -1 ? 0 : (skinIndex + 1) % availableSkins.Count; appearance.Skin = availableSkins[skinIndex]; } GUI.enabled = true; GUILayout.EndHorizontal(); Skin defaultSkin = mapper.GetDefault(selectedKerbal.gender); GUI.color = appearance.Skin == defaultSkin ? SelectedColour : Color.white; if (GUILayout.Button("Default")) { appearance.Skin = defaultSkin; } GUI.color = appearance.Skin == null ? SelectedColour : Color.white; if (GUILayout.Button("Unset/Generic")) { appearance.Skin = null; } GUI.color = Color.white; selectedKerbal.veteran = GUILayout.Toggle(selectedKerbal.veteran, "Veteran"); GUILayout.Space(110); }
/// <summary> /// Save per-game custom Kerbals mapping. /// </summary> void SaveKerbals(ConfigNode node) { KerbalRoster roster = HighLogic.CurrentGame.CrewRoster; foreach (ProtoCrewMember kerbal in roster.Crew.Concat(roster.Tourist).Concat(roster.Unowned)) { if (kerbal.rosterStatus == ProtoCrewMember.RosterStatus.Dead && kerbal.type != ProtoCrewMember.KerbalType.Unowned) { continue; } Appearance appearance = GetAppearance(kerbal); string skinName = appearance.Skin == null ? "GENERIC" : appearance.Skin.Name; string suitName = appearance.Suit == null ? "GENERIC" : appearance.Suit.Name; node.AddValue(kerbal.name, skinName + " " + suitName); } }
/// <summary> /// Get the actual Kerbal skin. Read from appearance if not null (i.e. not generic) otherwise determined randomly. /// </summary> public Skin GetKerbalSkin(ProtoCrewMember kerbal, Appearance appearance) { if (appearance.Skin != null) { return(appearance.Skin); } List <Skin> genderSkins = kerbalSkins[(int)kerbal.gender]; if (genderSkins.Count == 0) { return(DefaultSkin[(int)kerbal.gender]); } // Hash is multiplied with a large prime to increase randomisation, since hashes returned by `GetHashCode()` are // close together if strings only differ in the last (few) char(s). int number = (appearance.Hash * 4099) & 0x7fffffff; return(genderSkins[number % genderSkins.Count]); }
/// <summary> /// Load per-game custom kerbals mapping. /// </summary> void LoadKerbalsMap(ConfigNode node) { node = node ?? customKerbalsNode; KerbalRoster roster = HighLogic.CurrentGame.CrewRoster; foreach (ProtoCrewMember kerbal in roster.Crew.Concat(roster.Tourist).Concat(roster.Unowned)) { if (kerbal.rosterStatus == ProtoCrewMember.RosterStatus.Dead && kerbal.type != ProtoCrewMember.KerbalType.Unowned) { continue; } Appearance appearance = GetAppearance(kerbal); string value = node.GetValue(kerbal.name); if (value != null) { string[] tokens = Util.SplitConfigValue(value); string skinName = tokens.Length >= 1 ? tokens[0] : null; string suitName = tokens.Length >= 2 ? tokens[1] : null; if (skinName != null && skinName != "GENERIC") { appearance.Skin = skinName == "DEFAULT" ? DefaultSkin[(int)kerbal.gender] : Skins.Find(h => h.Name == skinName); } if (suitName != null && suitName != "GENERIC") { appearance.Suit = suitName == "DEFAULT" ? DefaultSuit : suitName == "VINTAGE" ? VintageSuit : Suits.Find(s => s.Name == suitName); } } } }
/// <summary> /// Get the actual Kerbal suit. Read from appearance if not null (i.e. not generic) otherwise determined either from /// class suits or assigned randomly (based on configuration). /// </summary> public Suit GetKerbalSuit(ProtoCrewMember kerbal, Appearance appearance) { Suit suit = appearance.Suit ?? GetClassSuit(kerbal); if (suit != null) { return(suit); } List <Suit> genderSuits = kerbalSuits[(int)kerbal.gender]; if (genderSuits.Count == 0) { return(kerbal.suit == KerbalSuit.Vintage ? VintageSuit : DefaultSuit); } // We must use a different prime here to increase randomisation so that the same skin is not always combined with // the same suit. int number = (appearance.Hash * 2053) & 0x7fffffff; return(genderSuits[number % genderSuits.Count]); }
/// <summary> /// Set ProtoCrewMembers to have the right suit kinds. On some occasions, e.g. when not changing suit kind through /// TR GUI or on new game initialisation there can appear mismatches between suit texture assignments and Kerbal /// models. We fix those here. /// </summary> private static void UpdateKerbalSuitKinds() { var mapper = Mapper.Instance; foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Crew) { if (kerbal.rosterStatus == ProtoCrewMember.RosterStatus.Dead) { continue; } Appearance appearance = mapper.GetAppearance(kerbal); Suit suit = mapper.GetKerbalSuit(kerbal, appearance); if (suit != null && suit.Kind != kerbal.suit) { kerbal.suit = suit.Kind; } } foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Unowned) { if (kerbal.rosterStatus != ProtoCrewMember.RosterStatus.Dead) { continue; } Appearance appearance = mapper.GetAppearance(kerbal); Suit suit = mapper.GetKerbalSuit(kerbal, appearance); if (suit != null && suit.Kind != kerbal.suit) { kerbal.suit = suit.Kind; } } }
/// <summary> /// Replace textures on a Kerbal model. /// </summary> void PersonaliseKerbal(Component component, ProtoCrewMember kerbal, bool isEva, bool useEvaSuit) { Appearance appearance = GetAppearance(kerbal); bool isVintage = kerbal.suit == KerbalSuit.Vintage; Skin skin = GetKerbalSkin(kerbal, appearance); Suit suit = GetKerbalSuit(kerbal, appearance); Suit defaultSuit = isVintage ? VintageSuit : DefaultSuit; Transform model = isEva || !isVintage?component.transform.Find("model01") : component.transform.Find("kbIVA@idle/model01"); Transform flag = isEva ? component.transform.Find("model/kbEVA_flagDecals") : null; Transform parachute = isEva ? component.transform.Find("model/EVAparachute/base") : null; // 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); if (isEva) { flag.GetComponent <Renderer>().enabled = useEvaSuit; parachute.GetComponent <Renderer>().enabled = useEvaSuit && !HideParachuteBackpack; } // We must include hidden meshes, since flares are hidden when light is turned off. // All other meshes are always visible, so no performance hit here. foreach (Renderer renderer in model.GetComponentsInChildren <Renderer>(true)) { var smr = renderer as SkinnedMeshRenderer; // Headlight flares and thruster jets. if (smr == null) { renderer.enabled = useEvaSuit; continue; } Texture2D newTexture = null; Texture2D newNormalMap = null; switch (smr.name) { case "eyeballLeft": case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_eyeballLeft": if (skin.IsEyeless) { smr.sharedMesh = null; } else { newTexture = skin.EyeballLeft; // Vintage IVA is missing a proto-model so it has to be replaced always. if (!isEva && isVintage) { smr.material.shader = Replacer.EyeShader; newTexture = newTexture ?? DefaultSkin[(int)kerbal.gender].EyeballLeft; } } break; case "eyeballRight": case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_eyeballRight": if (skin.IsEyeless) { smr.sharedMesh = null; } else { newTexture = skin.EyeballRight; // Vintage IVA is missing a proto-model so it has to be replaced always. if (!isEva && isVintage) { smr.material.shader = Replacer.EyeShader; newTexture = newTexture ?? DefaultSkin[(int)kerbal.gender].EyeballRight; } } break; case "pupilLeft": case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_pupilLeft": if (skin.IsEyeless) { smr.sharedMesh = null; } else { newTexture = skin.PupilLeft; // Vintage IVA is missing a proto-model so it has to be replaced always. if (!isEva && isVintage) { smr.material.shader = Replacer.EyeShader; newTexture = newTexture ?? DefaultSkin[(int)kerbal.gender].PupilLeft; } if (newTexture != null) { smr.material.color = Color.white; } } break; case "pupilRight": case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_pupilRight": if (skin.IsEyeless) { smr.sharedMesh = null; } else { newTexture = skin.PupilRight; // Vintage IVA is missing a proto-model so it has to be replaced always. if (!isEva && isVintage) { smr.material.shader = Replacer.EyeShader; newTexture = newTexture ?? DefaultSkin[(int)kerbal.gender].PupilRight; } if (newTexture != null) { smr.material.color = Color.white; } } break; case "headMesh01": case "headMesh02": case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_pCube1": case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_polySurface51": if (!skin.IsDefault) { newTexture = skin.Head; } break; case "tongue": case "upTeeth01": case "upTeeth02": case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_upTeeth01": case "mesh_female_kerbalAstronaut01_kerbalGirl_mesh_downTeeth01": break; case "body01": case "mesh_female_kerbalAstronaut01_body01": newTexture = suitTexture; newNormalMap = suitNormalMap; // 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": newTexture = suitTexture; newNormalMap = suitNormalMap; 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) { smr.material.color = Color.white; } break; default: // Jetpack. if (isEva) { smr.enabled = useEvaSuit; if (useEvaSuit) { newTexture = suit.EvaJetpack; newNormalMap = suit.EvaJetpackNRM; } } break; } if (newTexture != null) { smr.material.mainTexture = newTexture; } if (newNormalMap != null) { smr.material.SetTexture(Util.BumpMapProperty, newNormalMap); } } }
/// <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; 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"); Appearance appearance = mapper.GetAppearance(kerbal); Skin skin = mapper.GetKerbalSkin(kerbal, appearance); Skin defaultSkin = mapper.GetDefault(kerbal.gender); // 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 to fix the switch to the default IVA texture // when on EVA. Suit suit = null; Texture2D suitTexture = null; Texture2D suitNormalMap = null; if (mapper.PersonaliseSuit) { Suit defaultSuit = mapper.GetDefault(kerbal.suit); suit = mapper.GetKerbalSuit(kerbal, appearance); suitTexture = suit.GetSuit(useEvaSuit, kerbal) ?? defaultSuit.GetSuit(useEvaSuit, kerbal); 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": { if (suit == null) { break; } 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. if (component is Kerbal kerbalIva) { kerbalIva.textureStandard = newTexture; kerbalIva.textureVeteran = newTexture; } break; } case "neckRing": { if (suit == null) { break; } newTexture = suitTexture; newNormalMap = suitNormalMap; if (isEva) { newEmissive = suit.EvaSuitEmissive; } break; } case "helmet": case "mesh_female_kerbalAstronaut01_helmet": { if (suit == null) { break; } newTexture = suitTexture; newNormalMap = suitNormalMap; if (isEva) { newEmissive = suit.EvaSuitEmissive; } break; } case "visor": case "mesh_female_kerbalAstronaut01_visor": { if (suit == null) { break; } // 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 (suit == null) { break; } 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 (suit == null) { return; } if (showBackpack) { Material cargoPackMaterial = cargoPack.material; Material parachutePackMaterial = parachutePack.material; if (suit.CargoPack != null) { cargoPackMaterial.mainTexture = suit.CargoPack; } if (suit.CargoPackNRM != null) { cargoPackMaterial.SetTexture(Util.BumpMapProperty, suit.CargoPackNRM); } if (suit.CargoPackEmissive != null) { cargoPackMaterial.SetTexture(Util.EmissiveProperty, suit.CargoPackEmissive); } if (suit.ParachutePack != null) { parachutePackMaterial.mainTexture = suit.ParachutePack; } if (suit.ParachutePackNRM != null) { parachutePackMaterial.SetTexture(Util.BumpMapProperty, suit.ParachutePackNRM); } } Material parachuteCanopyMaterial = parachuteCanopy.material; if (suit.ParachuteCanopy != null) { parachuteCanopyMaterial.mainTexture = suit.ParachuteCanopy; } if (suit.ParachuteCanopyNRM != null) { parachuteCanopyMaterial.SetTexture(Util.BumpMapProperty, suit.ParachuteCanopyNRM); } } }
void WindowHandler(int id) { Reflections reflections = Reflections.Instance; Personaliser personaliser = Personaliser.Instance; GUILayout.BeginVertical(); GUILayout.BeginHorizontal(); GUILayout.BeginVertical(GUILayout.Width(200)); // Roster area. rosterScroll = GUILayout.BeginScrollView(rosterScroll); GUILayout.BeginVertical(); foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Crew) { switch (kerbal.rosterStatus) { case ProtoCrewMember.RosterStatus.Assigned: GUI.contentColor = Color.cyan; break; case ProtoCrewMember.RosterStatus.Dead: continue; case ProtoCrewMember.RosterStatus.Missing: GUI.contentColor = Color.yellow; break; default: GUI.contentColor = Color.white; break; } if (GUILayout.Button(kerbal.name)) { selectedKerbal = kerbal; selectedClass = null; } } foreach (ProtoCrewMember kerbal in HighLogic.CurrentGame.CrewRoster.Unowned) { switch (kerbal.rosterStatus) { case ProtoCrewMember.RosterStatus.Dead: GUI.contentColor = Color.cyan; break; default: continue; } if (GUILayout.Button(kerbal.name)) { selectedKerbal = kerbal; selectedClass = null; } } GUI.contentColor = Color.white; GUI.color = ClassColour; // Class suits. foreach (string clazz in classes) { if (GUILayout.Button(clazz)) { selectedKerbal = null; selectedClass = clazz; } } GUI.color = Color.white; GUILayout.EndVertical(); GUILayout.EndScrollView(); if (GUILayout.Button("Reset to Defaults")) { personaliser.ResetKerbals(); } GUILayout.EndVertical(); // Textures. Skin defaultSkin = personaliser.DefaultSkin[0]; Suit defaultSuit = personaliser.DefaultSuit; Appearance appearance = null; Skin skin = null; Suit suit = null; int skinIndex = -1; int suitIndex = -1; if (selectedKerbal != null) { if (selectedKerbal.suit == KerbalSuit.Vintage) { defaultSuit = personaliser.VintageSuit; } appearance = personaliser.GetAppearance(selectedKerbal); defaultSkin = personaliser.DefaultSkin[(int)selectedKerbal.gender]; skin = personaliser.GetKerbalSkin(selectedKerbal, appearance); suit = personaliser.GetKerbalSuit(selectedKerbal, appearance); skinIndex = personaliser.Skins.IndexOf(skin); suitIndex = personaliser.Suits.IndexOf(suit); } else if (selectedClass != null) { personaliser.ClassSuits.TryGetValue(selectedClass, out suit); if (suit != null) { suitIndex = personaliser.Suits.IndexOf(suit); } } GUILayout.Space(10); GUILayout.BeginVertical(); if (skin != null) { GUILayout.Box(skin.Head, GUILayout.Width(200), GUILayout.Height(200)); GUILayout.Label(skin.Name); } if (suit != null) { Texture2D suitTex = suit == defaultSuit && selectedKerbal != null && selectedKerbal.veteran ? suit.IvaSuitVeteran : suit.IvaSuit[0]; Texture2D evaSuitTex = suit.EvaSuit[0] ?? defaultSuit.EvaSuit[0]; GUILayout.BeginHorizontal(); GUILayout.Box(suitTex, GUILayout.Width(100), GUILayout.Height(100)); GUILayout.Space(10); GUILayout.Box(evaSuitTex, GUILayout.Width(100), GUILayout.Height(100)); GUILayout.EndHorizontal(); GUILayout.Label(suit.Name); } GUILayout.EndVertical(); GUILayout.BeginVertical(GUILayout.Width(120)); bool isKerbalSelected = appearance != null; bool isClassSelected = selectedClass != null; if (isKerbalSelected) { GUILayout.BeginHorizontal(); GUI.enabled = personaliser.Skins.Count != 0; if (GUILayout.Button("<")) { skinIndex = skinIndex == -1 ? 0 : skinIndex; skinIndex = (personaliser.Skins.Count + skinIndex - 1) % personaliser.Skins.Count; appearance.Skin = personaliser.Skins[skinIndex]; } if (GUILayout.Button(">")) { skinIndex = (skinIndex + 1) % personaliser.Skins.Count; appearance.Skin = personaliser.Skins[skinIndex]; } GUI.enabled = true; GUILayout.EndHorizontal(); GUI.color = appearance.Skin == defaultSkin ? SelectedColour : Color.white; if (GUILayout.Button("Default")) { appearance.Skin = defaultSkin; } GUI.color = appearance.Skin == null ? SelectedColour : Color.white; if (GUILayout.Button("Unset/Generic")) { appearance.Skin = null; } GUI.color = Color.white; selectedKerbal.veteran = GUILayout.Toggle(selectedKerbal.veteran, "Veteran"); } if (isKerbalSelected || isClassSelected) { bool isVintage = false; if (isKerbalSelected) { isVintage = selectedKerbal.suit == KerbalSuit.Vintage; GUILayout.Space(100); } GUILayout.BeginHorizontal(); GUI.enabled = personaliser.Suits.Count != 0; if (GUILayout.Button("<")) { suitIndex = suitIndex == -1 ? 0 : suitIndex; suitIndex = (personaliser.Suits.Count + suitIndex - 1) % personaliser.Suits.Count; if (isClassSelected) { personaliser.ClassSuits[selectedClass] = personaliser.Suits[suitIndex]; } else { appearance.Suit = personaliser.Suits[suitIndex]; } } if (GUILayout.Button(">")) { suitIndex = (suitIndex + 1) % personaliser.Suits.Count; if (isClassSelected) { personaliser.ClassSuits[selectedClass] = personaliser.Suits[suitIndex]; } else { appearance.Suit = personaliser.Suits[suitIndex]; } } GUI.enabled = true; GUILayout.EndHorizontal(); bool hasKerbalGenericSuit = isKerbalSelected && appearance.Suit == null; GUI.color = suit == defaultSuit && !hasKerbalGenericSuit ? SelectedColour : Color.white; if (GUILayout.Button("Default")) { if (isClassSelected) { personaliser.ClassSuits[selectedClass] = defaultSuit; } else { appearance.Suit = defaultSuit; } } GUI.color = suit == null || hasKerbalGenericSuit ? SelectedColour : Color.white; if (GUILayout.Button("Unset/Generic")) { if (isClassSelected) { personaliser.ClassSuits[selectedClass] = null; } else { appearance.Suit = null; } } GUI.color = Color.white; if (isKerbalSelected) { isVintage = GUILayout.Toggle(isVintage, "Vintage"); selectedKerbal.suit = isVintage ? KerbalSuit.Vintage : KerbalSuit.Default; // Make sure the right kind of default suit is selected. if (appearance.Suit == personaliser.DefaultSuit || appearance.Suit == personaliser.VintageSuit) { appearance.Suit = defaultSuit; } } } GUILayout.EndVertical(); GUILayout.EndHorizontal(); GUILayout.Space(5); bool enableReflections = reflections.ReflectionType == Reflections.Type.Real; enableReflections = GUILayout.Toggle(enableReflections, "Enable real-time reflections for visors and parts"); reflections.ReflectionType = enableReflections ? Reflections.Type.Real : Reflections.Type.None; bool hideParachuteBackpack = personaliser.HideParachuteBackpack; hideParachuteBackpack = GUILayout.Toggle(hideParachuteBackpack, "Hide parachute backpack"); personaliser.HideParachuteBackpack = hideParachuteBackpack; GUILayout.EndVertical(); GUI.DragWindow(new Rect(0, 0, Screen.width, 30)); }
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, _ => null }; if (newSuit.HasValue) { selectedKerbal.suit = newSuit.Value; availableSuits = mapper.GetAvailableSuits(selectedKerbal, true); appearance.Suit = mapper.GetDefault(selectedKerbal.suit); } } }
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)); }