private static DialogGUIBase[] CreateOptions(ModuleB9PartSwitch module, IList <Callback> afterCreateCallbacks) { List <DialogGUIBase> options = new List <DialogGUIBase>(); SwitcherSubtypeDescriptionGenerator subtypeDescriptionGenerator = new SwitcherSubtypeDescriptionGenerator(module); foreach (PartSubtype subtype in module.subtypes) { if (!subtype.IsUnlocked()) { continue; } if (subtype == module.CurrentSubtype) { string currentSubtypeText = Localization.PartSwitchFlightDialog_CurrentSubtypeLabel(subtype.title); // <<1>> (Current) DialogGUILabel label = new DialogGUILabel(currentSubtypeText, HighLogic.UISkin.button); afterCreateCallbacks.Add(delegate { if (!(label.uiItem.GetComponent <TextMeshProUGUI>() is TextMeshProUGUI textUI)) { throw new Exception("Could not find TextMeshProUGUI"); } else { textUI.raycastTarget = true; } });
public static void Spawn(ModuleB9PartSwitch module) { if (!module.subtypes.Any(subtype => subtype != module.CurrentSubtype && subtype.allowSwitchInFlight)) { return; } MaybeCreateResourceRemovalWarning(module, () => CreateDialogue(module)); }
private bool DisplayInfoOnSwitcher(ModuleB9PartSwitch switcher) { return (switcher.ChangesMass || switcher.ChangesCost || switcher.PartFieldManaged(SubtypePartFields.MaxTemp) || switcher.PartFieldManaged(SubtypePartFields.SkinMaxTemp) || switcher.PartFieldManaged(SubtypePartFields.CrashTolerance)); }
private bool DisplayInfoOnSwitcher(ModuleB9PartSwitch switcher) { return (switcher.ChangesMass || switcher.ChangesCost || switcher.HasPartAspectLock(PartMaxTempModifier.PART_ASPECT_LOCK) || switcher.HasPartAspectLock(PartSkinMaxTempModifier.PART_ASPECT_LOCK) || switcher.HasPartAspectLock(PartCrashToleranceModifier.PART_ASPECT_LOCK)); }
private bool DisplayInfoOnSwitcher(ModuleB9PartSwitch switcher) { return switcher.ChangesMass || switcher.ChangesCost || switcher.PartFieldManaged(SubtypePartFields.MaxTemp) || switcher.PartFieldManaged(SubtypePartFields.SkinMaxTemp) || switcher.PartFieldManaged(SubtypePartFields.CrashTolerance); }
public static void MaybeCreateResourceRemovalWarning(ModuleB9PartSwitch module, Action onConfirm) { if (HighLogic.LoadedSceneIsFlight && module.CurrentTankType.ResourceNames.Any(name => module.part.Resources[name].amount > 0)) { CreateWarning(module, onConfirm); } else { onConfirm(); } }
public static void Spawn(ModuleB9PartSwitch module) { try { MaybeCreateResourceRemovalWarning(module, () => CreateDialogue(module)); } catch (Exception ex) { UnityEngine.Debug.LogException(ex); FatalErrorHandler.HandleFatalError(ex); } }
public static void Spawn(ModuleB9PartSwitch module) { try { MaybeCreateResourceRemovalWarning(module, () => CreateDialogue(module)); } catch (Exception ex) { Log.error(ex, ex.Message); FatalErrorHandler.HandleFatalError(ex); } }
public static void Spawn(ModuleB9PartSwitch module) { bool showWarning = HighLogic.LoadedSceneIsFlight && module.CurrentTankType.ResourceNames.Any(name => module.part.Resources[name].amount > 0); if (showWarning) { CreateWarning(module); } else { CreateDialogue(module); } }
private static void CreateDialogue(ModuleB9PartSwitch module) { PopupDialog.SpawnPopupDialog( new MultiOptionDialog( "B9PartSwitch_SwitchInFlight", Localizer.Format(Localization.PartSwitchFlightDialog_SelectNewSubtypeDialogTitle, module.switcherDescription), // Select <<1>> module.part.partInfo.title, HighLogic.UISkin, CreateOptions(module) ), false, HighLogic.UISkin ); }
public void SetParent(ModuleB9PartSwitch parent) { if (parent == null) { throw new ArgumentNullException("parent cannot be null"); } if (parent.part == null) { throw new ArgumentNullException("parent.part cannot be null"); } this.parent = parent; part = parent.part; }
private static void CreateWarning(ModuleB9PartSwitch module) { PopupDialog.SpawnPopupDialog( new MultiOptionDialog( "B9PartSwitch_SwitchInFlightWarning", Localizer.Format(Localization.PartSwitchFlightDialog_ResourcesWillBeDumpedWarning, module.part.partInfo.title, module.switcherDescription), // <<1>> has resources that will be dumped by switching the <<2>> Localization.PartSwitchFlightDialog_ConfirmResourceRemovalDialogTitle, // Confirm Resource Removal HighLogic.UISkin, new DialogGUIButton(Localization.PartSwitchFlightDialog_AcceptString, () => CreateDialogue(module)), new DialogGUIButton(Localization.PartSwitchFlightDialog_CancelString, delegate { }) ), false, HighLogic.UISkin ); }
public void Setup(ModuleB9PartSwitch parent) { if (parent == null) { throw new ArgumentNullException("parent cannot be null"); } if (parent.part == null) { throw new ArgumentNullException("parent.part cannot be null"); } this.parent = parent; FindObjects(); FindNodes(); }
private static DialogGUIBase[] CreateOptions(ModuleB9PartSwitch module) { List <DialogGUIBase> options = new List <DialogGUIBase>(); foreach (PartSubtype subtype in module.subtypes) { if (subtype == module.CurrentSubtype) { options.Add(new DialogGUILabel(Localizer.Format(Localization.PartSwitchFlightDialog_CurrentSubtypeLabel, subtype.title), HighLogic.UISkin.button)); // <<1>> (Current) } else if (HighLogic.LoadedSceneIsEditor || subtype.allowSwitchInFlight) { options.Add(new DialogGUIButton(subtype.title, () => module.SwitchSubtype(subtype.Name))); } } options.Add(new DialogGUIButton(Localization.PartSwitchFlightDialog_CancelString, delegate { })); return(options.ToArray()); }
private static void CreateDialogue(ModuleB9PartSwitch module) { List <Callback> afterCreateCallbacks = new List <Callback>(); PopupDialog.SpawnPopupDialog( new MultiOptionDialog( "B9PartSwitch_SwitchInFlight", Localization.PartSwitchFlightDialog_SelectNewSubtypeDialogTitle(module.switcherDescription), // Select <<1>> module.part.partInfo.title, HighLogic.UISkin, CreateOptions(module, afterCreateCallbacks) ), false, HighLogic.UISkin ); foreach (Callback callback in afterCreateCallbacks) { callback(); } }
public void Setup(ModuleB9PartSwitch parent, bool displayWarnings = true) { if (parent == null) { throw new ArgumentNullException("parent cannot be null"); } if (parent.part == null) { throw new ArgumentNullException("parent.part cannot be null"); } this.parent = parent; aspectLocks.Clear(); Part part = parent.part; Part partPrefab = part.GetPrefab() ?? part; partModifiers.Clear(); IEnumerable <object> aspectLocksOnOtherModules = parent.PartAspectLocksOnOtherModules; string errorString = null; void OnInitializationError(string message) { LogError(message); if (displayWarnings) { if (errorString == null) { errorString = $"Initialization errors on {parent} subtype '{Name}'"; } errorString += "\n " + message; } } void MaybeAddModifier(IPartModifier modifier) { if (modifier == null) { return; } if (modifier is IPartAspectLock partAspectLockHolder) { object partAspectLock = partAspectLockHolder; if (aspectLocksOnOtherModules.Contains(partAspectLock)) { OnInitializationError($"More than one module can't manage {modifier.Description}"); return; } else { aspectLocks.Add(partAspectLock); } } partModifiers.Add(modifier); } if (maxTemp > 0) { MaybeAddModifier(new PartMaxTempModifier(part, partPrefab.maxTemp, maxTemp)); } if (skinMaxTemp > 0) { MaybeAddModifier(new PartSkinMaxTempModifier(part, partPrefab.skinMaxTemp, skinMaxTemp)); } if (crashTolerance > 0) { MaybeAddModifier(new PartCrashToleranceModifier(part, partPrefab.crashTolerance, crashTolerance)); } if (attachNode.IsNotNull()) { if (part.attachRules.srfAttach) { if (part.srfAttachNode.IsNotNull()) { MaybeAddModifier(new PartAttachNodeModifier(part.srfAttachNode, partPrefab.srfAttachNode, attachNode, parent)); } else { OnInitializationError("attachNode specified but part does not have a surface attach node"); } } else { OnInitializationError("attachNode specified but part does not allow surface attach"); } } if (CoMOffset.IsFinite()) { MaybeAddModifier(new PartCoMOffsetModifier(part, partPrefab.CoMOffset, CoMOffset)); } if (CoPOffset.IsFinite()) { MaybeAddModifier(new PartCoPOffsetModifier(part, partPrefab.CoPOffset, CoPOffset)); } if (CoLOffset.IsFinite()) { MaybeAddModifier(new PartCoLOffsetModifier(part, partPrefab.CoLOffset, CoLOffset)); } if (CenterOfBuoyancy.IsFinite()) { MaybeAddModifier(new PartCenterOfBuoyancyModifier(part, partPrefab.CenterOfBuoyancy, CenterOfBuoyancy)); } if (CenterOfDisplacement.IsFinite()) { MaybeAddModifier(new PartCenterOfDisplacementModifier(part, partPrefab.CenterOfDisplacement, CenterOfDisplacement)); } if (stackSymmetry >= 0) { MaybeAddModifier(new PartStackSymmetryModifier(part, partPrefab.stackSymmetry, stackSymmetry)); } foreach (AttachNodeModifierInfo info in attachNodeModifierInfos) { foreach (IPartModifier partModifier in info.CreatePartModifiers(part, parent, OnInitializationError)) { MaybeAddModifier(partModifier); } } foreach (TextureSwitchInfo info in textureSwitches) { foreach (TextureReplacement replacement in info.CreateTextureReplacements(part, OnInitializationError)) { MaybeAddModifier(replacement); } } foreach (MaterialModifierInfo materialModifierInfo in materialModifierInfos) { foreach (IPartModifier partModifier in materialModifierInfo.CreateModifiers(part.GetModelRoot(), OnInitializationError)) { MaybeAddModifier(partModifier); } } nodes.Clear(); foreach (IStringMatcher nodeName in nodeNames) { bool foundNode = false; foreach (AttachNode node in part.attachNodes) { if (!nodeName.Match(node.id)) { continue; } foundNode = true; if (node.nodeType != AttachNode.NodeType.Stack) { OnInitializationError($"Node {node.id} is not a stack node, and thus cannot be managed by ModuleB9PartSwitch"); continue; } nodes.Add(node); partModifiers.Add(new AttachNodeToggler(node)); } if (!foundNode) { OnInitializationError($"No attach nodes matching '{nodeName}' found"); } } if (HasTank) { foreach (TankResource resource in tankType) { float filledProportion = (resource.percentFilled ?? percentFilled ?? tankType.percentFilled ?? 100f) * 0.01f; bool? tweakable = resourcesTweakable ?? tankType.resourcesTweakable; ResourceModifier resourceModifier = new ResourceModifier(resource, () => parent.GetTotalVolume(this), part, filledProportion, tweakable); MaybeAddModifier(resourceModifier); } } transforms.Clear(); foreach (var transformName in transformNames) { bool foundTransform = false; foreach (Transform transform in part.GetModelRoot().TraverseHierarchy().Where(t => transformName.Match(t.name))) { foundTransform = true; partModifiers.Add(new TransformToggler(transform, part)); transforms.Add(transform); } if (!foundTransform) { OnInitializationError($"No transforms matching '{transformName}' found"); } } foreach (TransformModifierInfo transformModifierInfo in transformModifierInfos) { foreach (IPartModifier partModifier in transformModifierInfo.CreatePartModifiers(part, OnInitializationError)) { MaybeAddModifier(partModifier); } } // Icon setup doesn't set partInfo correctly, so it exists but as a copy without partConfig if ((part.partInfo?.partConfig).IsNotNull()) { foreach (ModuleModifierInfo moduleModifierInfo in moduleModifierInfos) { try { foreach (IPartModifier partModifier in moduleModifierInfo.CreatePartModifiers(part, parent, parent.CreateModuleDataChangedEventDetails())) { MaybeAddModifier(partModifier); } } catch (Exception ex) { OnInitializationError(ex.Message); Debug.LogException(ex); } } } if (!parent.subtypes.Any(subtype => subtype.Name == mirrorSymmetrySubtype)) { OnInitializationError($"Cannot find subtype '{mirrorSymmetrySubtype}' for mirror symmetry subtype"); mirrorSymmetrySubtype = Name; } if (errorString.IsNotNull()) { SeriousWarningHandler.DisplaySeriousWarning(errorString); } }
// This runs after OnStart() so everything should be initalized public void Start() { // Check for incompatible modules bool modifiedSetup = false; List <ModuleB9PartSwitch> otherModules = part.FindModulesImplementing <ModuleB9PartSwitch>(); for (int i = 0; i < otherModules.Count; i++) { ModuleB9PartSwitch otherModule = otherModules[i]; if (otherModule == this) { continue; } bool destroy = false; for (int j = 0; j < managedResourceNames.Count; j++) { if (otherModule.IsManagedResource(managedResourceNames[j])) { LogError("Two ModuleB9PartSwitch modules cannot manage the same resource: " + managedResourceNames[j]); destroy = true; } } for (int j = 0; j < managedTransformNames.Count; j++) { if (otherModule.IsManagedTransform(managedTransformNames[j])) { LogError("Two ModuleB9PartSwitch modules cannot manage the same transform: " + managedTransformNames[j]); destroy = true; } } for (int j = 0; j < managedStackNodeIDs.Count; j++) { if (otherModule.IsManagedNode(managedStackNodeIDs[j])) { LogError("Two ModuleB9PartSwitch modules cannot manage the same attach node: " + managedStackNodeIDs[j]); destroy = true; } } if (otherModule.MaxTempManaged && MaxTempManaged) { LogError("Two ModuleB9PartSwitch modules cannot both manage the part's maxTemp"); destroy = true; } if (otherModule.SkinMaxTempManaged && SkinMaxTempManaged) { LogError("Two ModuleB9PartSwitch modules cannot both manage the part's skinMaxTemp"); destroy = true; } if (otherModule.AttachNodeManaged && AttachNodeManaged) { LogError("Two ModuleB9PartSwitch modules cannot both manage the part's attach node"); destroy = true; } if (destroy) { LogWarning("ModuleB9PartSwitch with moduleID '" + otherModule.moduleID + "' is incomatible, and will be removed."); part.Modules.Remove(otherModule); Destroy(otherModule); modifiedSetup = true; } } for (int i = 0; i < part.Modules.Count; i++) { PartModule m = part.Modules[i]; if (m == null || m is ModuleB9PartSwitch) { continue; } Type mType = m.GetType(); for (int j = 0; j < IncompatibleModuleTypes.Length; j++) { Type testType = IncompatibleModuleTypes[j]; if (mType == testType || mType.IsSubclassOf(testType)) { LogError("ModuleB9PartSwitch and " + m.moduleName + " cannot exist on the same part. " + m.moduleName + " will be removed."); part.Modules.Remove(m); Destroy(m); modifiedSetup = true; break; } } } // If there were incompatible modules, they might have messed with things if (modifiedSetup) { UpdateSubtype(false); } }
public void Setup(ModuleB9PartSwitch parent, bool displayWarnings = true) { if (parent == null) { throw new ArgumentNullException("parent cannot be null"); } if (parent.part == null) { throw new ArgumentNullException("parent.part cannot be null"); } this.parent = parent; aspectLocks.Clear(); Part part = parent.part; Part partPrefab = part.GetPrefab() ?? part; partModifiers.Clear(); IEnumerable <object> aspectLocksOnOtherModules = parent.PartAspectLocksOnOtherModules; string errorString = null; void OnInitializationError(string message) { LogError(message); if (displayWarnings) { if (errorString == null) { errorString = $"Initialization errors on {parent} subtype '{Name}'"; } errorString += "\n " + message; } } void MaybeAddModifier(IPartModifier modifier) { if (modifier == null) { return; } if (aspectLocksOnOtherModules.Contains(modifier.PartAspectLock)) { OnInitializationError($"More than one module can't manage {modifier.Description}"); } else { partModifiers.Add(modifier); aspectLocks.Add(modifier.PartAspectLock); } } if (maxTemp > 0) { MaybeAddModifier(new PartMaxTempModifier(part, partPrefab.maxTemp, maxTemp)); } if (skinMaxTemp > 0) { MaybeAddModifier(new PartSkinMaxTempModifier(part, partPrefab.skinMaxTemp, skinMaxTemp)); } if (crashTolerance > 0) { MaybeAddModifier(new PartCrashToleranceModifier(part, partPrefab.crashTolerance, crashTolerance)); } if (attachNode.IsNotNull()) { if (part.attachRules.allowSrfAttach) { if (part.srfAttachNode.IsNotNull()) { MaybeAddModifier(new PartAttachNodeModifier(part.srfAttachNode, partPrefab.srfAttachNode, attachNode, parent)); } else { OnInitializationError("attachNode specified but part does not have a surface attach node"); } } else { OnInitializationError("attachNode specified but part does not allow surface attach"); } } if (CoMOffset.IsFinite()) { MaybeAddModifier(new PartCoMOffsetModifier(part, partPrefab.CoMOffset, CoMOffset)); } if (CoPOffset.IsFinite()) { MaybeAddModifier(new PartCoPOffsetModifier(part, partPrefab.CoPOffset, CoPOffset)); } if (CoLOffset.IsFinite()) { MaybeAddModifier(new PartCoLOffsetModifier(part, partPrefab.CoLOffset, CoLOffset)); } if (CenterOfBuoyancy.IsFinite()) { MaybeAddModifier(new PartCenterOfBuoyancyModifier(part, partPrefab.CenterOfBuoyancy, CenterOfBuoyancy)); } if (CenterOfDisplacement.IsFinite()) { MaybeAddModifier(new PartCenterOfDisplacementModifier(part, partPrefab.CenterOfDisplacement, CenterOfDisplacement)); } if (stackSymmetry >= 0) { MaybeAddModifier(new PartStackSymmetryModifier(part, partPrefab.stackSymmetry, stackSymmetry)); } foreach (AttachNodeModifierInfo info in attachNodeModifierInfos) { MaybeAddModifier(info.CreateAttachNodeModifier(part, parent, OnInitializationError)); } foreach (TextureSwitchInfo info in textureSwitches) { foreach (TextureReplacement replacement in info.CreateTextureReplacements(part, OnInitializationError)) { MaybeAddModifier(replacement); } } nodes.Clear(); foreach (string nodeName in nodeNames) { string pattern = '^' + Regex.Escape(nodeName).Replace(@"\*", ".*").Replace(@"\?", ".") + '$'; Regex nodeIdRegex = new Regex(pattern); bool foundNode = false; foreach (AttachNode node in part.attachNodes) { if (!nodeIdRegex.IsMatch(node.id)) { continue; } foundNode = true; if (node.nodeType != AttachNode.NodeType.Stack) { OnInitializationError($"Node {node.id} is not a stack node, and thus cannot be managed by ModuleB9PartSwitch"); continue; } nodes.Add(node); partModifiers.Add(new AttachNodeToggler(node)); } if (!foundNode) { OnInitializationError($"No attach nodes matching '{nodeName}' found"); } } if (HasTank) { volumeProvider = new SubtypeVolumeProvider(parent, volumeMultiplier, volumeAdded); foreach (TankResource resource in tankType) { float filledProportion = (resource.percentFilled ?? percentFilled ?? tankType.percentFilled ?? 100f) * 0.01f; bool? tweakable = resourcesTweakable ?? tankType.resourcesTweakable; ResourceModifier resourceModifier = new ResourceModifier(resource, volumeProvider, part, filledProportion, tweakable); MaybeAddModifier(resourceModifier); } } transforms.Clear(); foreach (var transformName in transformNames) { bool foundTransform = false; foreach (Transform transform in part.GetModelTransforms(transformName)) { foundTransform = true; partModifiers.Add(new TransformToggler(transform, part)); transforms.Add(transform); } if (!foundTransform) { OnInitializationError($"No transforms named '{transformName}' found"); } } foreach (TransformModifierInfo transformModifierInfo in transformModifierInfos) { foreach (IPartModifier partModifier in transformModifierInfo.CreatePartModifiers(part, OnInitializationError)) { MaybeAddModifier(partModifier); } } if (!parent.subtypes.Any(subtype => subtype.Name == mirrorSymmetrySubtype)) { OnInitializationError($"Cannot find subtype '{mirrorSymmetrySubtype}' for mirror symmetry subtype"); mirrorSymmetrySubtype = Name; } if (errorString.IsNotNull()) { SeriousWarningHandler.DisplaySeriousWarning(errorString); } }
public void Setup(ModuleB9PartSwitch parent) { if (parent == null) throw new ArgumentNullException("parent cannot be null"); if (parent.part == null) throw new ArgumentNullException("parent.part cannot be null"); this.parent = parent; FindObjects(); FindNodes(); }
public static void Spawn(ModuleB9PartSwitch module) { MaybeCreateResourceRemovalWarning(module, () => CreateDialogue(module)); }