private void Initialize() { if (initialized) { return; } initialized = true; ConfigNode node = ROLUtils.parseConfigNode(configNodeData); AnimationData animData = new AnimationData(node.GetNode("ANIMATIONDATA")); animationModule = new ROLAnimationModule(part, this, nameof(persistentState), null, nameof(DeployEngineEvent), nameof(RetractEngineEvent)); animationModule.getSymmetryModule = m => ((ROLDeployableEngine)m).animationModule; animationModule.setupAnimations(animData, part.transform.ROLFindRecursive("model"), 0); animationModule.onAnimStateChangeCallback = OnAnimationStateChange; }
/// <summary> /// Initialize the UI controls, including default values, and specifying delegates for their 'onClick' methods.<para/> /// All UI based interaction code will be defined/run through these delegates. /// </summary> private void initializeUI() { Action <ROEModularSRB> modelChangedAction = (m) => { m.updateModulePositions(); m.updateDimensions(); m.updateMassAndCost(); m.updateAttachNodes(true); m.updateAvailableVariants(); m.updateDragCubes(); m.updateRCSModule(); m.updateEngineModule(); ROLModInterop.updateResourceVolume(m.part); }; //set up the core variant UI control string[] variantNames = ROLUtils.getNames(variantSets.Values, m => m.variantName); this.ROLupdateUIChooseOptionControl(nameof(currentVariant), variantNames, variantNames, true, currentVariant); Fields[nameof(currentVariant)].guiActiveEditor = variantSets.Count > 1; Fields[nameof(currentVariant)].uiControlEditor.onFieldChanged = (a, b) => { //TODO find variant set for the currently enabled core model //query the index from that variant set ModelDefinitionVariantSet prevMdvs = getVariantSet(coreModule.definition.name); //this is the index of the currently selected model within its variant set int previousIndex = prevMdvs.indexOf(coreModule.layoutOptions); //grab ref to the current/new variant set ModelDefinitionVariantSet mdvs = getVariantSet(currentVariant); //and a reference to the model from same index out of the new set ([] call does validation internally for IAOOBE) ModelDefinitionLayoutOptions newCoreDef = mdvs[previousIndex]; //now, call model-selected on the core model to update for the changes, including symmetry counterpart updating. this.ROLactionWithSymmetry(m => { m.currentVariant = currentVariant; m.coreModule.modelSelected(newCoreDef.definition.name); modelChangedAction(m); }); }; Fields[nameof(currentDiameter)].uiControlEditor.onFieldChanged = (a, b) => { this.ROLactionWithSymmetry(m => { if (m != this) { m.currentDiameter = this.currentDiameter; } modelChangedAction(m); m.prevDiameter = m.currentDiameter; }); ROLStockInterop.fireEditorUpdate(); }; Fields[nameof(currentVScale)].uiControlEditor.onFieldChanged = (a, b) => { this.ROLactionWithSymmetry(m => { if (m != this) { m.currentVScale = this.currentVScale; } modelChangedAction(m); }); ROLStockInterop.fireEditorUpdate(); }; Fields[nameof(currentNose)].uiControlEditor.onFieldChanged = (a, b) => { noseModule.modelSelected(a, b); this.ROLactionWithSymmetry(modelChangedAction); ROLStockInterop.fireEditorUpdate(); }; Fields[nameof(currentCore)].uiControlEditor.onFieldChanged = (a, b) => { coreModule.modelSelected(a, b); this.ROLactionWithSymmetry(modelChangedAction); ROLStockInterop.fireEditorUpdate(); }; Fields[nameof(currentMount)].uiControlEditor.onFieldChanged = (a, b) => { mountModule.modelSelected(a, b); this.ROLactionWithSymmetry(modelChangedAction); ROLStockInterop.fireEditorUpdate(); }; //------------------MODEL DIAMETER SWITCH UI INIT---------------------// if (maxDiameter == minDiameter) { Fields[nameof(currentDiameter)].guiActiveEditor = false; } else { this.ROLupdateUIFloatEditControl(nameof(currentDiameter), minDiameter, maxDiameter, diameterLargeStep, diameterSmallStep, diameterSlideStep, true, currentDiameter); } Fields[nameof(currentVScale)].guiActiveEditor = enableVScale; //------------------MODULE TEXTURE SWITCH UI INIT---------------------// Fields[nameof(currentNoseTexture)].uiControlEditor.onFieldChanged = noseModule.textureSetSelected; Fields[nameof(currentCoreTexture)].uiControlEditor.onFieldChanged = coreModule.textureSetSelected; Fields[nameof(currentMountTexture)].uiControlEditor.onFieldChanged = mountModule.textureSetSelected; Fields[nameof(currentLowerRCSTexture)].uiControlEditor.onFieldChanged = lowerRCSModule.textureSetSelected; if (HighLogic.LoadedSceneIsEditor) { GameEvents.onEditorShipModified.Add(new EventData <ShipConstruct> .OnEvent(onEditorVesselModified)); } // Force the Textures selection to show up to keep the PAW at the same size Fields[nameof(currentNoseTexture)].guiActiveEditor = true; Fields[nameof(currentCoreTexture)].guiActiveEditor = true; Fields[nameof(currentMountTexture)].guiActiveEditor = true; Fields[nameof(currentLowerRCSTexture)].guiActiveEditor = true; }
/// <summary> /// Initialization method. Sets up model modules, loads their configs from the input config node. Does all initial linking of part-modules.<para/> /// Does NOT set up their UI interaction -- that is all handled during OnStart() /// </summary> private void initialize() { if (initialized) { return; } initialized = true; prevDiameter = currentDiameter; noseNodeNames = ROLUtils.parseCSV(noseManagedNodes); coreNodeNames = ROLUtils.parseCSV(coreManagedNodes); mountNodeNames = ROLUtils.parseCSV(mountManagedNodes); //model-module setup/initialization ConfigNode node = ROLConfigNodeUtils.parseConfigNode(configNodeData); //list of CORE model nodes from config //each one may contain multiple 'model=modelDefinitionName' entries //but must contain no more than a single 'variant' entry. //if no variant is specified, they are added to the 'Default' variant. ConfigNode[] coreDefNodes = node.GetNodes("CORE"); ModelDefinitionLayoutOptions[] coreDefs; List <ModelDefinitionLayoutOptions> coreDefList = new List <ModelDefinitionLayoutOptions>(); int coreDefLen = coreDefNodes.Length; for (int i = 0; i < coreDefLen; i++) { string variantName = coreDefNodes[i].ROLGetStringValue("variant", "Default"); coreDefs = ROLModelData.getModelDefinitionLayouts(coreDefNodes[i].ROLGetStringValues("model")); coreDefList.AddUniqueRange(coreDefs); ModelDefinitionVariantSet mdvs = getVariantSet(variantName); mdvs.addModels(coreDefs); } coreDefs = coreDefList.ToArray(); //model defs - brought here so we can capture the array rather than the config node+method call ModelDefinitionLayoutOptions[] noseDefs = ROLModelData.getModelDefinitions(node.GetNodes("NOSE")); ModelDefinitionLayoutOptions[] mountDefs = ROLModelData.getModelDefinitions(node.GetNodes("MOUNT")); ModelDefinitionLayoutOptions[] rcsDnDefs = ROLModelData.getModelDefinitions(node.GetNodes("LOWERRCS")); noseModule = new ROLModelModule <ROEModularSRB>(part, this, getRootTransform("ROEModularSRB-NOSE"), ModelOrientation.TOP, nameof(currentNose), null, nameof(currentNoseTexture), nameof(noseModulePersistentData)); noseModule.name = "ROEModularSRB-Nose"; noseModule.getSymmetryModule = m => m.noseModule; noseModule.getValidOptions = () => noseDefs; coreModule = new ROLModelModule <ROEModularSRB>(part, this, getRootTransform("ROEModularSRB-CORE"), ModelOrientation.CENTRAL, nameof(currentCore), null, nameof(currentCoreTexture), nameof(coreModulePersistentData)); coreModule.name = "ROEModularSRB-Core"; coreModule.getSymmetryModule = m => m.coreModule; coreModule.getValidOptions = () => getVariantSet(currentVariant).definitions; mountModule = new ROLModelModule <ROEModularSRB>(part, this, getRootTransform("ROEModularSRB-MOUNT"), ModelOrientation.BOTTOM, nameof(currentMount), null, nameof(currentMountTexture), nameof(mountModulePersistentData)); mountModule.name = "ROEModularSRB-Mount"; mountModule.getSymmetryModule = m => m.mountModule; mountModule.getValidOptions = () => mountDefs; lowerRCSModule = new ROLModelModule <ROEModularSRB>(part, this, getRootTransform("ROEModularSRB-LOWERRCS"), ModelOrientation.CENTRAL, nameof(currentLowerRCS), null, nameof(currentLowerRCSTexture), nameof(lowerRCSModulePersistentData)); lowerRCSModule.name = "ROEModularSRB-LowerRCS"; lowerRCSModule.getSymmetryModule = m => m.lowerRCSModule; lowerRCSModule.getValidOptions = () => rcsDnDefs; lowerRCSModule.getLayoutPositionScalar = () => lowerRCSRad; lowerRCSModule.getLayoutScaleScalar = () => 1f; noseModule.volumeScalar = volumeScalingPower; coreModule.volumeScalar = volumeScalingPower; mountModule.volumeScalar = volumeScalingPower; lowerRCSModule.volumeScalar = volumeScalingPower; noseModule.massScalar = massScalingPower; coreModule.massScalar = massScalingPower; mountModule.massScalar = massScalingPower; lowerRCSModule.massScalar = massScalingPower; // Set up the model lists and load the currently selected model noseModule.setupModelList(noseDefs); coreModule.setupModelList(coreDefs); mountModule.setupModelList(mountDefs); mountModule.setupModelList(rcsDnDefs); coreModule.setupModel(); noseModule.setupModel(); mountModule.setupModel(); lowerRCSModule.setupModel(); // Initialize RCS Thrust Transforms getModuleByName(lowerRCSFunctionSource).renameRCSThrustTransforms(lowerRCSThrustTransform); // Initialize Engine Thrust Transforms and Gimbal getModuleByName(engineTransformSource).renameEngineThrustTransforms(engineThrustTransform); getModuleByName(engineTransformSource).renameGimbalTransforms(gimbalTransform); updateModulePositions(); updateDimensions(); updateMassAndCost(); updateAttachNodes(false); updateAvailableVariants(); ROLStockInterop.updatePartHighlighting(part); }