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); } }
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); } }