public override void OnStart(StartState state) { base.OnStart(state); initialize(); float max = techLimitMaxDiameter < maxTankDiameter ? techLimitMaxDiameter : maxTankDiameter; string[] names = SSTUUtils.getNames(mainTankModules, m => m.name); this.updateUIChooseOptionControl("currentTankType", names, names, true, currentTankType); this.updateUIFloatEditControl("currentTankDiameter", minTankDiameter, max, tankDiameterIncrement * 2, tankDiameterIncrement, tankDiameterIncrement * 0.05f, true, currentTankDiameter); updateAvailableVariants(); updateUIScaleControls(); Fields["currentTankDiameter"].uiControlEditor.onFieldChanged = tankDiameterUpdated; Fields["currentTankVerticalScale"].uiControlEditor.onFieldChanged = tankHeightScaleUpdated; Fields["currentTankType"].uiControlEditor.onFieldChanged = tankTypeUpdated; Fields["currentNoseType"].uiControlEditor.onFieldChanged = noseTypeUpdated; Fields["currentMountType"].uiControlEditor.onFieldChanged = mountTypeUpdated; Fields["currentNoseTexture"].uiControlEditor.onFieldChanged = onNoseTextureUpdated; Fields["currentTankTexture"].uiControlEditor.onFieldChanged = onTankTextureUpdated; Fields["currentMountTexture"].uiControlEditor.onFieldChanged = onMountTextureUpdated; Fields["currentTankType"].guiActiveEditor = mainTankModules.Length > 1; Fields["currentNoseType"].guiActiveEditor = noseModules.Length > 1; Fields["currentMountType"].guiActiveEditor = mountModules.Length > 1; SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onPartGeometryUpdate(part, true); if (HighLogic.LoadedSceneIsEditor) { GameEvents.onEditorShipModified.Add(new EventData <ShipConstruct> .OnEvent(onEditorVesselModified)); } }
public override void OnStart(StartState state) { base.OnStart(state); loadConfigData(); //initialize the container instances, including initializing default values if needed updateMassAndCost(); //update cached part mass and cost values updatePersistentData(); //update persistent data in case tank was just initialized updateFuelSelections(); //update the selections for the 'FuelType' UI slider, this adds or removes the 'custom' option as needed updatePartStats(); //update part stats for crash tolerance and heat, as determined by the container modifiers //disable next fuel event button if main container does not have more than one preset type available BaseField fuelSelection = Fields["guiFuelType"]; fuelSelection.guiActiveEditor = enableFuelTypeChange && getBaseContainer().fuelPresets.Length > 1; fuelSelection.uiControlEditor.onFieldChanged = onFuelTypeUpdated; BaseEvent editContainerEvent = Events["openGUIEvent"]; editContainerEvent.active = enableContainerEdit; if (!initializedResources && (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight)) { initializedResources = true; updateTankResources(); SSTUStockInterop.fireEditorUpdate();//update cost } }
protected virtual void setMountModuleFromEditor(String newMountType, bool updateSymmetry) { MountModelData newModule = Array.Find(mountModules, m => m.name == newMountType); currentMountModule.destroyCurrentModel(); currentMountModule = newModule; newModule.setupModel(part, getMountRootTransform(false), ModelOrientation.BOTTOM); currentMountType = newModule.name; if (!currentMountModule.isValidTextureSet(currentMountTexture)) { currentMountTexture = currentMountModule.getDefaultTextureSet(); } currentMountModule.enableTextureSet(currentMountTexture); currentMountModule.updateTextureUIControl(this, "currentMountTexture", currentMountTexture); updateEditorStats(true); if (updateSymmetry) { foreach (Part p in part.symmetryCounterparts) { p.GetComponent <SSTUModularFuelTank>().setMountModuleFromEditor(newMountType, false); } } SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onPartGeometryUpdate(part, true); }
private void buildFairing() { fairingBase.clearProfile(); UVMap uvs = UVMap.GetUVMapGlobal(uvMap); fairingBase.outsideUV = uvs.getArea("outside"); fairingBase.insideUV = uvs.getArea("inside"); fairingBase.edgesUV = uvs.getArea("edges"); float halfHeight = currentHeight * 0.5f; fairingBase.addRing(-halfHeight, currentBottomDiameter * 0.5f); if (currentTopDiameter != currentBottomDiameter) { fairingBase.addRing(-halfHeight + currentTaperHeight, currentBottomDiameter * 0.5f); } if (currentHeight != currentTaperHeight || currentTopDiameter == currentBottomDiameter) { fairingBase.addRing(halfHeight, currentTopDiameter * 0.5f); } fairingBase.generateColliders = this.generateColliders; fairingBase.generateFairing(); fairingBase.setMaterial(fairingMaterial); fairingBase.setOpacity(HighLogic.LoadedSceneIsEditor && editorTransparency ? 0.25f : 1.0f); updateEnginePositionAndScale(); SSTUModInterop.onPartGeometryUpdate(part, true); SSTUStockInterop.fireEditorUpdate(); }
protected virtual void setMainTankModuleFromEditor(String newMainTank, bool updateSymmetry) { TankModelData newModule = Array.Find(mainTankModules, m => m.name == newMainTank); currentMainTankModule.destroyCurrentModel(); currentMainTankModule = newModule; currentMainTankModule.setupModel(getTankRootTransform(false), ModelOrientation.CENTRAL); currentTankType = newModule.name; if (!currentMainTankModule.isValidTextureSet(currentTankTexture)) { currentTankTexture = currentMainTankModule.getDefaultTextureSet(); } currentMainTankModule.enableTextureSet(currentTankTexture); currentMainTankModule.updateTextureUIControl(this, "currentTankTexture", currentTankTexture); updateUIScaleControls(); updateEditorStats(true); lastSelectedVariant = currentMainTankModule.variantName; if (updateSymmetry) { foreach (Part p in part.symmetryCounterparts) { p.GetComponent <SSTUModularFuelTank>().setMainTankModuleFromEditor(newMainTank, false); } } SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onPartGeometryUpdate(part, true); }
public void LateUpdate() { if (externalUpdateData != null) { updateFromExternalData(externalUpdateData); } if (needsStatusUpdate) { needsStatusUpdate = false; updateFairingStatus(); } if (needsRebuilt) { updateFairingStatus(); rebuildFairing(); updatePersistentDataString(); updateEditorFields(false); SSTUStockInterop.fireEditorUpdate(); needsGuiUpdate = true; needsRebuilt = false; } if (needsGuiUpdate) { updateGuiState(); needsGuiUpdate = false; } }
private void setDiameterFromEditor(float newDiameter, bool updateSymmetry) { if (newDiameter > maxDiameter) { newDiameter = maxDiameter; } if (newDiameter < minDiameter) { newDiameter = minDiameter; } currentDiameter = newDiameter; updateModelScale(); updateDragCubes(); updatePartCost(); updatePartMass(); if (updateSymmetry) { if (updateSymmetry) { foreach (Part p in part.symmetryCounterparts) { p.GetComponent <SSTUWeldingDockingPort>().setDiameterFromEditor(newDiameter, false); } } SSTUStockInterop.fireEditorUpdate(); } }
public void LateUpdate() { //MonoBehaviour.print("Checking late update1: " + needsStatusUpdate + " :: " + needsRebuilt); if (externalUpdateData != null) { updateFromExternalData(externalUpdateData); } //MonoBehaviour.print("Checking late update2: " + needsStatusUpdate + " :: " + needsRebuilt); if (needsStatusUpdate) { updateFairingStatus(); } //MonoBehaviour.print("Checking late update3: " + needsStatusUpdate + " :: " + needsRebuilt); if (needsRebuilt) { rebuildFairing(); updatePersistentDataString(); SSTUStockInterop.fireEditorUpdate(); needsGuiUpdate = true; needsRebuilt = false; } if (needsGuiUpdate) { updateGuiState(); needsGuiUpdate = false; } if (HighLogic.LoadedSceneIsEditor && fairingParts != null) { updateOpacity(); } }
public void setContainerPercents(float[] percents, float totalVolume) { int len = containers.Length; if (len != percents.Length) { throw new IndexOutOfRangeException("Input container percents length does not match containers length: " + percents.Length + " : " + len); } float total = 0; for (int i = 0; i < len - 1; i++) { total += percents[i]; containers[i].setContainerPercent(percents[i]); } if (total > 1) { throw new InvalidOperationException("Input percents total > 1"); } containers[len - 1].setContainerPercent(1.0f - total); volume = totalVolume; updateContainerVolumes(); updateMassAndCost(); updateTankResources(); updateFuelSelections(); updatePersistentData(); SSTUStockInterop.fireEditorUpdate(); }
public void recreateModel() { setModelParameters(); model.recreateModel(); updatePhysicalAttributes(); updateDecouplerForce(); SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onPartGeometryUpdate(part, true); }
public void invertEnginesEvent() { invertEngines = !invertEngines; this.actionWithSymmetry(m => { m.invertEngines = invertEngines; m.updateEnginePositionAndScale(); }); SSTUStockInterop.fireEditorUpdate(); }
public override void OnStart(StartState state) { base.OnStart(state); initialize(); string[] groupNames = TankSet.getSetNames(tankSets); this.updateUIChooseOptionControl("currentTankSet", groupNames, groupNames, true, currentTankSet); string[] names = currentTankSetModule.getModelNames(); string[] descs = currentTankSetModule.getTankDescriptions(); this.updateUIChooseOptionControl("currentTankType", names, descs, true, currentTankType); if (maxTankDiameter == minTankDiameter) { Fields["currentTankDiameter"].guiActiveEditor = false; } else { this.updateUIFloatEditControl("currentTankDiameter", minTankDiameter, maxTankDiameter, tankDiameterIncrement * 2, tankDiameterIncrement, tankDiameterIncrement * 0.05f, true, currentTankDiameter); } updateAvailableVariants(); updateUIScaleControls(); currentNoseModule.updateTextureUIControl(this, "currentNoseTexture", currentNoseTexture); currentMainTankModule.updateTextureUIControl(this, "currentTankTexture", currentTankTexture); currentMountModule.updateTextureUIControl(this, "currentMountTexture", currentMountTexture); bool useModelSelectionGUI = HighLogic.CurrentGame.Parameters.CustomParams <SSTUGameSettings>().useModelSelectGui; Events["selectNoseEvent"].guiActiveEditor = useModelSelectionGUI; Events["selectMountEvent"].guiActiveEditor = useModelSelectionGUI; Fields["currentTankDiameter"].uiControlEditor.onFieldChanged = tankDiameterUpdated; Fields["currentTankVerticalScale"].uiControlEditor.onFieldChanged = tankHeightScaleUpdated; Fields["currentTankSet"].uiControlEditor.onFieldChanged = tankSetUpdated; Fields["currentTankType"].uiControlEditor.onFieldChanged = tankTypeUpdated; Fields["currentNoseType"].uiControlEditor.onFieldChanged = noseTypeUpdated; Fields["currentMountType"].uiControlEditor.onFieldChanged = mountTypeUpdated; Fields["currentNoseTexture"].uiControlEditor.onFieldChanged = onNoseTextureUpdated; Fields["currentTankTexture"].uiControlEditor.onFieldChanged = onTankTextureUpdated; Fields["currentMountTexture"].uiControlEditor.onFieldChanged = onMountTextureUpdated; Fields["currentTankSet"].guiActiveEditor = tankSets.Length > 1; Fields["currentTankType"].guiActiveEditor = currentTankSetModule.Length > 1; Fields["currentNoseType"].guiActiveEditor = !useModelSelectionGUI && noseModules.Length > 1; Fields["currentMountType"].guiActiveEditor = !useModelSelectionGUI && mountModules.Length > 1; SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onPartGeometryUpdate(part, true); if (HighLogic.LoadedSceneIsEditor) { GameEvents.onEditorShipModified.Add(new EventData <ShipConstruct> .OnEvent(onEditorVesselModified)); } }
public override void OnStart(StartState state) { base.OnStart(state); initialize(); Fields[nameof(currentModel)].guiName = uiLabel; Fields[nameof(currentModel)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { models.modelSelected(a, b); this.actionWithSymmetry(m => { m.models.setScale(currentScale); m.models.updateModelMeshes(); m.models.updateSelections(); m.updateMassAndCost(); m.updateAttachNodes(true); SSTUModInterop.updateResourceVolume(m.part); SSTUModInterop.onPartGeometryUpdate(m.part, true); }); SSTUStockInterop.fireEditorUpdate(); }; Fields[nameof(currentScale)].guiActiveEditor = canAdjustScale; UI_FloatEdit fe = (UI_FloatEdit)Fields[nameof(currentScale)].uiControlEditor; if (fe != null) { fe.minValue = minScale; fe.maxValue = maxScale; fe.incrementLarge = incScaleLarge; fe.incrementSmall = incScaleSmall; fe.incrementSlide = incScaleSlide; } Fields[nameof(currentScale)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { this.actionWithSymmetry(m => { m.models.setScale(currentScale); m.models.updateModelMeshes(); m.updateMassAndCost(); m.updateAttachNodes(true); SSTUModInterop.updateResourceVolume(m.part); SSTUModInterop.onPartGeometryUpdate(m.part, true); }); SSTUStockInterop.fireEditorUpdate(); }; Fields[nameof(currentTexture)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { models.textureSetSelected(a, b); }; Fields[nameof(currentTexture)].guiActiveEditor = models.definition.textureSets.Length > 1; SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onPartGeometryUpdate(part, true); }
public void invertEnginesEvent() { invertEngines = !invertEngines; updateEnginePositionAndScale(); this.forEachSymmetryCounterpart(module => { module.invertEngines = this.invertEngines; module.updateEnginePositionAndScale(); }); SSTUStockInterop.fireEditorUpdate(); }
/// <summary> /// Recalculates volume for all containers by finding all IContainerVolumeContributor implementors, and summing the volume for each container from the returned values. /// Removes the need to manually calculate new % values for each container. /// </summary> public void recalcVolume() { if (!initializedResources || containers == null) { //not yet initialized -- recalc will be called during Start, so ignore for now return; } float[] volumes = new float[numberOfContainers]; IContainerVolumeContributor[] contributors = part.FindModulesImplementing <IContainerVolumeContributor>().ToArray(); ContainerContribution[] cts; int len = contributors.Length; for (int i = 0; i < len; i++) { if (contributors[i] == null) { SSTULog.error("NULL Container Contributor"); } cts = contributors[i].getContainerContributions(); if (cts == null) { SSTULog.error("NULL Container Contributor Contributions"); } int len2 = cts.Length; for (int k = 0; k < len2; k++) { int idx = cts[k].containerIndex; if (idx < volumes.Length && idx >= 0) { volumes[cts[k].containerIndex] += cts[k].containerVolume; } } } len = containers.Length; for (int i = 0; i < len; i++) { if (containers[i] == null) { SSTULog.error("NULL Container definition for index: " + i); } containers[i].setContainerVolume(volumes[i]); } updateMassAndCost(); //update cached part mass and cost values updatePersistentData(); //update persistent data in case tank was just initialized updateFuelSelections(); //update the selections for the 'FuelType' UI slider, this adds or removes the 'custom' option as needed updatePartStats(); //update part stats for crash tolerance and heat, as determined by the container modifiers updateGUIControls(); updateTankResources(); SSTUStockInterop.fireEditorUpdate(); }
/// <summary> /// Update the resources for the part from the resources in the currently configured containers /// </summary> private void updateTankResources() { SSTUResourceList list = new SSTUResourceList(); int len = containers.Length; for (int i = 0; i < len; i++) { containers[i].getResources(list); } list.setResourcesToPart(part); updateMassAndCost(); SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onContainerUpdated(this); }
public void onVolumeUpdated(float newVolume) { if (newVolume != volume) { volume = newVolume; updateContainerVolumes(); updateMassAndCost(); updateTankResources(); updateFuelSelections(); updatePersistentData(); SSTUStockInterop.fireEditorUpdate(); } Events["openGUIEvent"].guiActiveEditor = volume > 0; }
private void initialize() { if (initialized) { return; } initialized = true; double hsp = 1; double dens = 1; PartResourceDefinition resource = PartResourceLibrary.Instance.GetDefinition(resourceName); hsp = resource.specificHeatCapacity; dens = resource.density; fluxPerResourceUnit = hsp * ablationEfficiency * dens; baseSkinIntMult = part.skinInternalConductionMult; baseCondMult = part.heatConductivity; ConfigNode node = SSTUConfigNodeUtils.parseConfigNode(configNodeData); Transform mhsRoot = part.transform.FindRecursive("model").FindOrCreate("SSTU-MHS-Root"); ConfigNode[] modelNodes = node.GetNodes("MODELS"); ModelDefinitionLayoutOptions[] models = SSTUModelData.getModelDefinitions(modelNodes); model = new ModelModule <SSTUModularHeatShield>(part, this, mhsRoot, ModelOrientation.CENTRAL, nameof(currentShieldModel), null, nameof(currentShieldTexture), nameof(modelPersistentData), null, null, null, null); model.getSymmetryModule = (m) => m.model; model.setupModelList(models); model.setupModel(); model.setScaleForDiameter(currentDiameter); model.setPosition(0); model.updateModelMeshes(); model.updateSelections(); model.volumeScalar = resourceScalePower; model.massScalar = resourceScalePower; if (standAlonePart) { updateDragCube(); updateAttachNodes(false); } SSTUModInterop.updateResourceVolume(part); ConfigNode[] typeNodes = node.GetNodes("SHIELDTYPE"); shieldTypeData = HeatShieldTypeData.load(typeNodes); currentShieldTypeData = Array.Find(shieldTypeData, m => m.baseType.name == currentShieldType); updateModuleStats(); updatePartCost(); SSTUModInterop.onPartGeometryUpdate(part, false); SSTUModInterop.updateResourceVolume(part); SSTUStockInterop.fireEditorUpdate();//update for mass/cost/etc. }
public void onVolumeUpdated(float newVolume) { if (newVolume != volume) { volume = newVolume; updateContainerVolumes(); updateMassAndCost(); updateTankResources(); updateFuelSelections(); updatePersistentData(); SSTUStockInterop.fireEditorUpdate(); } updateGUIControls(); }
/// <summary> /// Update the resources for the part from the resources in the currently configured containers /// </summary> private void updateTankResources() { SSTUResourceList list = new SSTUResourceList(); int len = containers.Length; for (int i = 0; i < len; i++) { containers[i].getResources(list); } list.setResourcesToPart(part, inflationMultiplier, HighLogic.LoadedSceneIsFlight); updateMassAndCost(); SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onContainerUpdated(this); }
private void setTankScaleFromEditor(float editorScaleValue, bool updateSymmetry) { currentTankVerticalScale = editorScaleValue; restoreEditorFields(); updateEditorStats(true); if (updateSymmetry) { foreach (Part p in part.symmetryCounterparts) { p.GetComponent <SSTUModularFuelTank>().setTankScaleFromEditor(editorScaleValue, false); } } SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onPartGeometryUpdate(part, true); }
public void updatePhysicalAttributes() { float r = diameter * 0.5f; float h = height; float t = thickness; float innerCylVolume = 0; float outerCylVolume = 0; float innerCylRadius = (r) - (t); float outerCylRadius = (r); innerCylVolume = (float)Math.PI * innerCylRadius * innerCylRadius * h; outerCylVolume = (float)Math.PI * outerCylRadius * outerCylRadius * h; volume = outerCylVolume - innerCylVolume; modifiedMass = volume * massPerCubicMeter; modifiedCost = volume * costPerCubicMeter; part.mass = modifiedMass; SSTUStockInterop.fireEditorUpdate(); }
private void setTankDiameterFromEditor(float newDiameter, bool updateSymmetry) { float oldDiameter = prevTankDiameter; currentTankDiameter = newDiameter; restoreEditorFields(); updateEditorStats(true); SSTUAttachNodeUtils.updateSurfaceAttachedChildren(part, oldDiameter, newDiameter); if (updateSymmetry) { foreach (Part p in part.symmetryCounterparts) { p.GetComponent <SSTUModularFuelTank>().setTankDiameterFromEditor(newDiameter, false); } } SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onPartGeometryUpdate(part, true); }
private void setShieldTypeFromEditor(String newType, bool updateSymmetry) { currentShieldType = newType; currentShieldTypeData = SSTUDatabase.getHeatShieldType(newType); updateModuleStats(); updatePartResources(); updatePartCost(); updateEditorFields(); if (updateSymmetry) { SSTUModularHeatShield mhs; foreach (Part p in part.symmetryCounterparts) { mhs = p.GetComponent <SSTUModularHeatShield>(); mhs.setShieldTypeFromEditor(newType, false); } SSTUStockInterop.fireEditorUpdate(); } }
private void setSolarEditor(string newSolar, bool updateSymmetry) { currentSolar = newSolar; solarModule.disable(); solarModule = Array.Find(solarModules, m => m.name == currentSolar);//TODO cleanup solarModule.enable(getSolarRoot(false), coreModule.currentVerticalPosition); updateSolarModules(); updateCost(); updateMass(); updateDragCubes(); updateGUI(); SSTUStockInterop.fireEditorUpdate();//update editor for mass/cost values if (updateSymmetry) { foreach (Part p in part.symmetryCounterparts) { p.GetComponent <SSTUModularStationCore>().setSolarEditor(newSolar, false); } } }
/// <summary> /// Update the resources for the part from the resources in the currently configured containers /// </summary> private void updateTankResources() { SSTUResourceList list = new SSTUResourceList(); int len = containers.Length; for (int i = 0; i < len; i++) { containers[i].getResources(list); } list.setResourcesToPart(part, inflationMultiplier, HighLogic.LoadedSceneIsFlight, blacklistedResources); updateMassAndCost(); SSTUStockInterop.fireEditorUpdate(); SSTUModInterop.onContainerUpdated(this); SSTUResourceBoiloff rb = part.GetComponent <SSTUResourceBoiloff>(); if (rb != null) { rb.onPartResourcesChanged(); } }
public override void OnStart(StartState state) { base.OnStart(state); loadConfigData(); //initialize the container instances, including initializing default values if needed updateMassAndCost(); //update cached part mass and cost values updatePersistentData(); //update persistent data in case tank was just initialized updateFuelSelections(); //update the selections for the 'FuelType' UI slider, this adds or removes the 'custom' option as needed updatePartStats(); //update part stats for crash tolerance and heat, as determined by the container modifiers updateGUIControls(); BaseField fuelSelection = Fields[nameof(guiFuelType)]; fuelSelection.uiControlEditor.onFieldChanged = onFuelTypeUpdated; if (!initializedResources && (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight)) { initializedResources = true; updateTankResources(); SSTUStockInterop.fireEditorUpdate();//update cost } }
private void setSingleFuelType(string presetName, bool updateSymmetry) { ContainerFuelPreset preset = Array.Find(getBaseContainer().fuelPresets, m => m.name == presetName); if (preset == null) { throw new NullReferenceException("Fuel preset cannot be null. Name: " + presetName); } getBaseContainer().setFuelPreset(preset); updateTankResources(); updatePersistentData(); updateFuelSelections(); if (updateSymmetry) { foreach (Part p in part.symmetryCounterparts) { p.GetComponent <SSTUVolumeContainer>().setSingleFuelType(presetName, false); } } SSTUStockInterop.fireEditorUpdate(); }
private void onDiameterChanged(BaseField field, System.Object obj) { if (currentDiameter > maxDiameter) { currentDiameter = maxDiameter; } if (currentDiameter < minDiameter) { currentDiameter = minDiameter; } this.actionWithSymmetry(m => { if (m != this) { m.currentDiameter = this.currentDiameter; } m.updateModelScale(); m.updateDragCubes(); m.updatePartCost(); m.updatePartMass(); }); SSTUStockInterop.fireEditorUpdate(); }
/// <summary> /// OnStart override, does basic startup/init stuff, including building models and registering for editor events /// </summary> /// <param name="state"></param> public override void OnStart(StartState state) { base.OnStart(state); initialize(); this.updateUIFloatEditControl(nameof(currentTankDiameter), minTankDiameter, maxTankDiameter, tankDiameterIncrement * 2, tankDiameterIncrement, tankDiameterIncrement * 0.05f, true, currentTankDiameter); float diff = maxVScale - minVScale; this.updateUIFloatEditControl(nameof(currentTankHeight), minVScale, maxVScale, diff * 0.2f, diff * 0.05f, diff * 0.001f, true, currentTankHeight); Action <SSTUModularUpperStage> modelChangeAction = m => { m.updateModules(true); m.updateModels(); m.updateTankStats(); m.updateRCSModule(); m.updateContainerVolume(); m.updateGuiState(); }; Fields[nameof(splitTank)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { this.actionWithSymmetry(m => { m.splitTank = splitTank; if (m.splitTank) { m.intertankModule.setupModel(); m.lowerModule.setupModel(); } else { m.intertankModule.model.destroyCurrentModel(); m.lowerModule.model.destroyCurrentModel(); } m.Fields[nameof(currentIntertank)].guiActiveEditor = m.splitTank; m.Fields[nameof(currentLower)].guiActiveEditor = m.splitTank; m.Fields[nameof(currentIntertankTexture)].guiActiveEditor = m.splitTank; m.Fields[nameof(currentLowerTexture)].guiActiveEditor = m.splitTank; modelChangeAction(m); }); }; Fields[nameof(currentNose)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { noseModule.modelSelected(currentNose); this.actionWithSymmetry(modelChangeAction); }; Fields[nameof(currentUpper)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { upperModule.modelSelected(currentUpper); this.actionWithSymmetry(modelChangeAction); }; Fields[nameof(currentIntertank)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { intertankModule.modelSelected(currentIntertank); this.actionWithSymmetry(modelChangeAction); }; Fields[nameof(currentLower)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { lowerModule.modelSelected(currentLower); this.actionWithSymmetry(modelChangeAction); }; Fields[nameof(currentMount)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { mountModule.modelSelected(currentMount); this.actionWithSymmetry(modelChangeAction); }; Fields[nameof(currentRCS)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { rcsModule.modelSelected(currentRCS); this.actionWithSymmetry(m => { MonoBehaviour.print("RCS model updated!"); m.updateRCSModule(); modelChangeAction(m); }); }; Fields[nameof(currentNoseTexture)].uiControlEditor.onFieldChanged = noseModule.textureSetSelected; Fields[nameof(currentUpperTexture)].uiControlEditor.onFieldChanged = upperModule.textureSetSelected; Fields[nameof(currentMountTexture)].uiControlEditor.onFieldChanged = mountModule.textureSetSelected; Fields[nameof(currentIntertankTexture)].uiControlEditor.onFieldChanged = intertankModule.textureSetSelected; Fields[nameof(currentLowerTexture)].uiControlEditor.onFieldChanged = lowerModule.textureSetSelected; Fields[nameof(currentRCSTexture)].uiControlEditor.onFieldChanged = rcsModule.textureSetSelected; Callback <BaseField, System.Object> editorUpdateDelegate = delegate(BaseField a, System.Object b) { this.actionWithSymmetry(m => { if (m != this) { m.currentTankDiameter = currentTankDiameter; } //else it conflicts with stock slider functionality if (m != this) { m.currentTankHeight = currentTankHeight; } modelChangeAction(m); }); SSTUStockInterop.fireEditorUpdate(); }; Fields[nameof(currentTankDiameter)].uiControlEditor.onFieldChanged = editorUpdateDelegate; Fields[nameof(currentTankHeight)].uiControlEditor.onFieldChanged = editorUpdateDelegate; Fields[nameof(supportPercent)].uiControlEditor.onFieldChanged = delegate(BaseField a, System.Object b) { this.actionWithSymmetry(m => { if (m != this) { m.supportPercent = supportPercent; } //else it conflicts with stock slider functionality m.updateContainerVolume(); m.updateGuiState(); }); SSTUStockInterop.fireEditorUpdate(); }; Fields[nameof(currentNose)].guiActiveEditor = noseModule.models.Count > 1; Fields[nameof(currentUpper)].guiActiveEditor = upperModule.models.Count > 1; Fields[nameof(currentIntertank)].guiActiveEditor = splitTank && intertankModule.models.Count > 1; Fields[nameof(currentLower)].guiActiveEditor = splitTank && lowerModule.models.Count > 1; Fields[nameof(currentMount)].guiActiveEditor = mountModule.models.Count > 1; Fields[nameof(currentRCS)].guiActiveEditor = rcsModule.models.Count > 1; Fields[nameof(currentIntertankTexture)].guiActiveEditor = splitTank; Fields[nameof(currentLowerTexture)].guiActiveEditor = splitTank; SSTUModInterop.onPartGeometryUpdate(part, true); SSTUStockInterop.fireEditorUpdate(); }