public string GetFullSubtypeDescription(PartSubtype subtype) { lock (lockObject) { try { GetFullSubtypeDescriptionInternal(subtype); string result = stringBuilder.ToString(); int leadingWhitespace = result.Length - result.TrimStart().Length; int trailingWhitespace = result.Length - result.TrimEnd().Length; if (leadingWhitespace != 0) { Log.error("[SwitcherSubtypeDescriptionGenerator] decription has leading whitespace: {0}", leadingWhitespace); } if (trailingWhitespace != 0) { Log.error("[SwitcherSubtypeDescriptionGenerator] decription has trailing whitespace: {0}", trailingWhitespace); } return(result); } catch (Exception ex) { Log.error(ex, ex.Message); return("<color=orange><b>error generating description</b></color>\n\nhere's some placeholder text instead"); } finally { stringBuilder.Clear(); } } }
public override void Setup(UIPartActionWindow window, Part part, PartModule partModule, UI_Scene scene, UI_Control control, BaseField field) { base.Setup(window, part, partModule, scene, control, field); ModuleB9PartSwitch switcherModule = (ModuleB9PartSwitch)partModule; SwitcherSubtypeDescriptionGenerator subtypeDescriptionGenerator = new SwitcherSubtypeDescriptionGenerator(switcherModule); subtypeButtons = new List <UIPartActionSubtypeButton>(switcherModule.subtypes.Count); for (int i = 0; i < switcherModule.subtypes.Count; i++) { PartSubtype subtype = switcherModule.subtypes[i]; if (!subtype.IsUnlocked()) { continue; } GameObject buttonGameObject = Instantiate(prefabVariantButton, scrollMain.content); UIPartActionSubtypeButton subtypeButton = buttonGameObject.GetComponent <UIPartActionSubtypeButton>(); // prevent capturing in closures int index = i; subtypeButton.Setup( subtype.title, subtypeDescriptionGenerator.GetFullSubtypeDescription(subtype), subtype.PrimaryColor, subtype.SecondaryColor, () => SetSubtype(index) ); subtypeButtons.Add(subtypeButton); } subtypeButtons[0].previousItem = subtypeButtons[subtypeButtons.Count - 1]; subtypeButtons[0].nextItem = subtypeButtons[1]; for (int i = 1; i < subtypeButtons.Count - 1; i++) { subtypeButtons[i].previousItem = subtypeButtons[i - 1]; subtypeButtons[i].nextItem = subtypeButtons[i + 1]; } subtypeButtons[subtypeButtons.Count - 1].previousItem = subtypeButtons[subtypeButtons.Count - 2]; subtypeButtons[subtypeButtons.Count - 1].nextItem = subtypeButtons[0]; switcherDescriptionText.text = switcherModule.switcherDescription; TooltipHelper.SetupSubtypeInfoTooltip(buttonPreviousTooltipController, "", ""); TooltipHelper.SetupSubtypeInfoTooltip(buttonNextTooltipController, "", ""); SetTooltips(switcherModule.currentSubtypeIndex); buttonPrevious.onClick.AddListener(PreviousSubtype); buttonNext.onClick.AddListener(NextSubtype); subtypeTitleText.text = switcherModule.CurrentSubtype.title; subtypeButtons[switcherModule.currentSubtypeIndex].Activate(); }
public void TestFindBestSubtype__FirstWhenNoManagedResourcesAndNoStructural() { PartSubtype subtype0 = CreateSubtype(0, "SomeResource1"); PartSubtype subtype1 = CreateSubtype(1, "SomeResource1"); PartSubtype subtype2 = CreateSubtype(1, "SomeResource2"); PartSubtype[] subtypes = { subtype0, subtype1, subtype2 }; string[] resourceNamesOnPart = { "SomeResource0" }; Assert.Same(subtype1, determinator.FindBestSubtype(subtypes, resourceNamesOnPart)); }
public void TestFindBestSubtype__CantDetermineFromResources__First() { PartSubtype subtype0 = CreateSubtype(0, "SomeResource1"); PartSubtype subtype1 = CreateSubtype(1, "SomeResource1"); PartSubtype subtype2 = CreateSubtype(1, "SomeResource2"); PartSubtype subtype3 = CreateSubtype(1, "SomeResource3"); PartSubtype[] subtypes = { subtype0, subtype1, subtype2, subtype3 }; string[] resourceNamesOnPart = { "SomeResource0", "SomeResource2", "SomeResource3" }; Assert.Same(subtype1, determinator.FindBestSubtype(subtypes, resourceNamesOnPart)); }
public void TestFindBestSubtype__PreferStructuralWhenNoManagedResources() { PartSubtype subtype0 = CreateSubtype(1, "SomeResource1"); PartSubtype subtype1 = CreateSubtype(0); PartSubtype subtype2 = CreateSubtype(1); PartSubtype subtype3 = CreateSubtype(1); PartSubtype[] subtypes = { subtype0, subtype1, subtype2, subtype3 }; string[] resourceNamesOnPart = { "SomeResource0" }; Assert.Same(subtype2, determinator.FindBestSubtype(subtypes, resourceNamesOnPart)); }
public void TestFindBestSubtype__FirstWhenNoTanks() { PartSubtype subtype0 = new PartSubtype { defaultSubtypePriority = 0 }; PartSubtype subtype1 = new PartSubtype { defaultSubtypePriority = 1 }; PartSubtype subtype2 = new PartSubtype { defaultSubtypePriority = 1 }; PartSubtype[] subtypes = { subtype0, subtype1, subtype2 }; string[] resourceNamesOnPart = { "SomeResource" }; Assert.Same(subtype1, determinator.FindBestSubtype(subtypes, resourceNamesOnPart)); }
public override void TestStartUp() { base.TestStartUp(); part.partInfo = new AvailablePart(); // So that it thinks it's loading from a save module.baseVolume = 1; resourceDef1 = new PartResourceDefinition("resource1"); resourceDef2 = new PartResourceDefinition("resource2"); resourceDef3 = new PartResourceDefinition("resource3"); TankResource tankResource1 = new TankResource(); tankResource1.resourceDefinition = resourceDef1; TankResource tankResource2 = new TankResource(); tankResource2.resourceDefinition = resourceDef1; TankResource tankResource3 = new TankResource(); tankResource3.resourceDefinition = resourceDef2; TankType tankType1 = new TankType(); tankType1.resources.Add(tankResource1); TankType tankType2 = new TankType(); tankType2.resources.Add(tankResource2); tankType2.resources.Add(tankResource3); subtype1 = new PartSubtype(); subtype1.subtypeName = "subtype1"; subtype1.tankType = tankType1; module.subtypes.Add(subtype1); subtype2 = new PartSubtype(); subtype2.subtypeName = "subtype2"; subtype2.tankType = tankType2; module.subtypes.Add(subtype2); subtype3 = new PartSubtype(); subtype3.subtypeName = "subtype3"; subtype3.tankType = B9TankSettings.StructuralTankType; module.subtypes.Add(subtype3); }
private PartSubtype CreateSubtype(int defaultSubtypePriority, params string[] resourceNames) { PartSubtype subtype = new PartSubtype() { defaultSubtypePriority = defaultSubtypePriority, tankType = new TankType(), }; foreach (string resourceName in resourceNames) { subtype.tankType.resources.Add(new TankResource() { resourceDefinition = new PartResourceDefinition(resourceName) }); } return(subtype); }
public void TestFindBestSubtype() { PartSubtype subtype1 = new PartSubtype(); subtype1.subtypeName = "subtype1"; subtype1.tankType = B9TankSettings.StructuralTankType; module.subtypes.Add(subtype1); PartSubtype subtype2 = new PartSubtype(); subtype2.subtypeName = "subtype2"; subtype2.tankType = B9TankSettings.StructuralTankType; module.subtypes.Add(subtype2); PartSubtype subtype3 = new PartSubtype(); subtype3.subtypeName = "subtype3"; subtype3.tankType = B9TankSettings.StructuralTankType; module.subtypes.Add(subtype3); module.currentSubtypeName = "subtype2"; module.OnStart(PartModule.StartState.Editor); assertEquals("Should identify the subtype by name", module.CurrentSubtype, subtype2); module.currentSubtypeName = null; module.currentSubtypeIndex = 2; module.OnStart(PartModule.StartState.Editor); assertEquals("Should identify the subtype by index", module.CurrentSubtype, subtype3); PartResourceDefinition resourceDef1 = new PartResourceDefinition("resource1"); PartResourceDefinition resourceDef2 = new PartResourceDefinition("resource2"); PartResourceDefinition resourceDef3 = new PartResourceDefinition("resource3"); TankResource tankResource1 = new TankResource(); tankResource1.resourceDefinition = resourceDef1; TankResource tankResource2 = new TankResource(); tankResource2.resourceDefinition = resourceDef1; TankResource tankResource3 = new TankResource(); tankResource3.resourceDefinition = resourceDef2; TankType tankType1 = new TankType(); tankType1.resources.Add(tankResource1); subtype1.tankType = tankType1; TankType tankType2 = new TankType(); tankType2.resources.Add(tankResource2); tankType2.resources.Add(tankResource3); subtype2.tankType = tankType2; module.currentSubtypeName = null; module.currentSubtypeIndex = -1; module.baseVolume = 1f; module.OnStart(PartModule.StartState.Editor); assertEquals("It identifies a structural subtype when no resources present", module.CurrentSubtype, subtype3); PartResource partResource1 = part.AddResource(resourceDef3, 1f, 1f); module.currentSubtypeName = null; module.currentSubtypeIndex = -1; module.OnStart(PartModule.StartState.Editor); assertEquals("It identifies a structural subtype when only an unmanaged resource present", module.CurrentSubtype, subtype3); PartResource partResource2 = part.AddResource(resourceDef1, 1f, 1f); PartResource partResource3 = part.AddResource(resourceDef2, 1f, 1f); module.currentSubtypeName = null; module.currentSubtypeIndex = -1; module.OnStart(PartModule.StartState.Editor); assertEquals("It identifies the correct subtype by resources when present", module.CurrentSubtype, subtype2); part.RemoveResource(partResource2); module.currentSubtypeName = null; module.currentSubtypeIndex = -1; module.OnStart(PartModule.StartState.Editor); assertEquals("It identifies the first subtype when subtype can't be determined from resources", module.CurrentSubtype, subtype1); }
public PartSubtypeContext(Part part, ModuleB9PartSwitch module, PartSubtype subtype) { Part = part; Module = module; Subtype = subtype; }
private void GetFullSubtypeDescriptionInternal(PartSubtype subtype) { if (!subtype.descriptionSummary.IsNullOrEmpty()) { stringBuilder.AppendLine(subtype.descriptionSummary); } stringBuilder.BeginGroup(); if (subtype.tankType.resources.Count > 0 || parentResources.Length > 0) { stringBuilder.AppendLine("<b>{0}:</b>", SwitcherSubtypeDescriptionGenerator_Resources); foreach (TankResource resource in subtype.tankType) { stringBuilder.AppendLine(" <color=#bfff3f>- {0}</color>: {1:0.#}", resource.resourceDefinition.displayName, resource.unitsPerVolume * module.GetTotalVolume(subtype)); } float parentVolume = baseParentVolume + (subtype.volumeAddedToParent * module.VolumeScale); foreach (KeyValuePair <TankResource, float> resourceAndAmount in parentResources) { float amount = resourceAndAmount.Key.unitsPerVolume * parentVolume; float difference = amount - resourceAndAmount.Value; stringBuilder.Append(" <color=#bfff3f>- {0}</color>: {1:0.#}", resourceAndAmount.Key.resourceDefinition.displayName, amount); if (!ApproximatelyZero(difference)) { stringBuilder.Append(FormatResourceDifference(difference)); } stringBuilder.AppendLine(); } } float dryMass = baseDryMass + module.GetDryMass(subtype) + module.GetParentDryMass(subtype); float wetMass = baseWetMass + module.GetWetMass(subtype) + module.GetParentWetMass(subtype); float dryMassDifference = dryMass - partDryMass; float wetMassDifference = wetMass - partWetMass; float dryCost = baseDryCost + module.GetDryCost(subtype) + module.GetParentDryCost(subtype); float wetCost = baseWetCost + module.GetWetCost(subtype) + module.GetParentWetCost(subtype); float dryCostDifference = dryCost - partDryCost; float wetCostDifference = wetCost - partWetCost; stringBuilder.BeginGroup(); if (showWetMass) { stringBuilder.Append("<b>{0}:</b> {1} {2}", SwitcherSubtypeDescriptionGenerator_Mass, SwitcherSubypeDescriptionGenerator_MassTons(dryMass, "0.###"), SwitcherSubtypeDescriptionGenerator_TankEmpty); if (!ApproximatelyZero(dryMassDifference) && !ApproximatelyEqual(dryMassDifference, wetMassDifference)) { stringBuilder.Append(FormatMassDifference(dryMassDifference)); } stringBuilder.Append(" / {0} {1}", SwitcherSubypeDescriptionGenerator_MassTons(wetMass, "0.###"), SwitcherSubtypeDescriptionGenerator_TankFull); if (!ApproximatelyZero(wetMassDifference)) { stringBuilder.Append(FormatMassDifference(wetMassDifference)); } stringBuilder.AppendLine(); } else if (showDryMass) { stringBuilder.Append("<b>{0}:</b> {1}", SwitcherSubtypeDescriptionGenerator_Mass, SwitcherSubypeDescriptionGenerator_MassTons(dryMass, "0.###")); if (!ApproximatelyZero(dryMassDifference)) { stringBuilder.Append(FormatMassDifference(dryMassDifference)); } stringBuilder.AppendLine(); } if (showWetCost) { stringBuilder.Append("<b>{0}:</b> <sprite=\"CurrencySpriteAsset\" name=\"Funds\" tint=1> {1:0.#} {2}", SwitcherSubtypeDescriptionGenerator_Cost, dryCost, SwitcherSubtypeDescriptionGenerator_TankEmpty); if (!ApproximatelyZero(dryCostDifference) && !ApproximatelyEqual(dryCostDifference, wetCostDifference)) { stringBuilder.Append(FormatCostDifference(dryCostDifference)); } stringBuilder.Append(" / <sprite=\"CurrencySpriteAsset\" name=\"Funds\" tint=1> {0:0.#} {1}", wetCost, SwitcherSubtypeDescriptionGenerator_TankFull); if (!ApproximatelyZero(wetCostDifference)) { stringBuilder.Append(FormatCostDifference(wetCostDifference)); } stringBuilder.AppendLine(); } else if (showDryCost) { stringBuilder.Append("<b>{0}:</b> <sprite=\"CurrencySpriteAsset\" name=\"Funds\" tint=1> {1:#.#}", SwitcherSubtypeDescriptionGenerator_Cost, dryCost); if (!ApproximatelyZero(dryCostDifference)) { stringBuilder.Append(FormatCostDifference(dryCostDifference)); } stringBuilder.AppendLine(); } if (showMaxTemp) { float maxTemp = subtype.maxTemp > 0 ? subtype.maxTemp : prefabMaxTemp; stringBuilder.Append("<b>{0}:</b> {1}", SwitcherSubtypeDescriptionGenerator_MaxTemp, SwitcherSubypeDescriptionGenerator_TemperatureKelvins(maxTemp, "#")); if (!ApproximatelyEqual(maxTemp, currentMaxTemp)) { stringBuilder.Append(FormatTemperatureDifference(maxTemp - currentMaxTemp)); } stringBuilder.AppendLine(); } if (showSkinMaxTemp) { float skinMaxTemp = subtype.skinMaxTemp > 0 ? subtype.skinMaxTemp : prefabSkinMaxTemp; stringBuilder.Append("<b>{0}:</b> {1}", SwitcherSubtypeDescriptionGenerator_MaxSkinTemp, SwitcherSubypeDescriptionGenerator_TemperatureKelvins(skinMaxTemp, "#")); if (!ApproximatelyEqual(skinMaxTemp, currentSkinMaxTemp)) { stringBuilder.Append(FormatTemperatureDifference(skinMaxTemp - currentSkinMaxTemp)); } stringBuilder.AppendLine(); } if (showCrashTolerance) { float crashTolerance = subtype.crashTolerance > 0 ? subtype.crashTolerance : prefabCrashTolerance; stringBuilder.Append("<b>{0}:</b> {1}", SwitcherSubtypeDescriptionGenerator_CrashTolerance, SwitcherSubypeDescriptionGenerator_SpeedMetersPerSecond(crashTolerance, "#")); if (!ApproximatelyEqual(crashTolerance, currentCrashTolerance)) { stringBuilder.Append(FormatSpeedDifference(crashTolerance - currentCrashTolerance)); } stringBuilder.AppendLine(); } stringBuilder.BeginGroup(); if (!subtype.descriptionDetail.IsNullOrEmpty()) { stringBuilder.AppendLine(subtype.descriptionDetail); } }