예제 #1
0
        public void ResetModel()
        {
            if (lengthWidth)
            {
                return;
            }

            currentDiameter = coreModule.definition.diameter;
            currentVScale   = 0;

            this.ROLupdateUIFloatEditControl(nameof(currentDiameter), minDiameter, maxDiameter, diameterLargeStep, diameterSmallStep, diameterSlideStep, true, currentDiameter);
            this.ROLupdateUIFloatEditControl(nameof(currentVScale), -1, 1, 0.25f, 0.05f, 0.001f, true, currentVScale);

            updateModulePositions();
            updateAttachNodes(true);
            updateAvailableVariants();
            updateDragCubes();

            if (scaleMass)
            {
                updateMass();
            }
            if (scaleCost)
            {
                updateCost();
            }
            ROLStockInterop.updatePartHighlighting(part);
            UpdateTankVolume(lengthWidth);
        }
예제 #2
0
 /// <summary>
 /// Updates part highlight renderer list, sends message to ModuleROTFlagDecal to update its renderer,
 ///  sends message to FAR to update voxels, or if createDefaultCube==true will re-render the 'default' stock drag cube for the part<para/>
 /// Should be called anytime the model geometry in a part is changed -- either models added/deleted, procedural meshes updated.  Other methods exist for pure drag-cube updating in ROLStockInterop.
 /// </summary>
 /// <param name="part"></param>
 /// <param name="createDefaultCube"></param>
 public static void onPartGeometryUpdate(Part part, bool createDefaultCube)
 {
     if (!HighLogic.LoadedSceneIsEditor && !HighLogic.LoadedSceneIsFlight)
     {
         return;
     }                                                                                //noop on prefabs
     //MonoBehaviour.print(System.Environment.StackTrace);
     ROLStockInterop.updatePartHighlighting(part);
     part.airlock = locateAirlock(part);
     partGeometryUpdate(part);
     if (isFARInstalled())
     {
         ROLStockInterop.addFarUpdatePart(part);
         //FARdebug(part);
         //part.SendMessage("GeometryPartModuleRebuildMeshData");
     }
     else if (createDefaultCube && (HighLogic.LoadedSceneIsEditor || HighLogic.LoadedSceneIsFlight))
     {
         ROLStockInterop.addDragUpdatePart(part);
     }
     if (HighLogic.LoadedSceneIsEditor && part.parent == null && part != EditorLogic.RootPart) //likely the part under the cursor; this fixes problems with modular parts not wanting to attach to stuff
     {
         part.gameObject.SetLayerRecursive(1, 2097152);                                        //1<<21 = Part Triggers get skipped by the relayering (hatches, ladders, ??)
     }
 }
예제 #3
0
 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();
         ROLStockInterop.fireEditorUpdate();
         needsGuiUpdate = true;
         needsRebuilt   = false;
     }
     if (needsGuiUpdate)
     {
         UpdateGuiState();
         needsGuiUpdate = false;
     }
     if (HighLogic.LoadedSceneIsEditor && fairingParts != null)
     {
         UpdateOpacity();
     }
 }
예제 #4
0
 public void Start()
 {
     INSTANCE = this;
     KSPShaderTools.TexturesUnlimitedLoader.addPostLoadCallback(KSPShaderToolsPostLoad);
     GameObject.DontDestroyOnLoad(this);
     MonoBehaviour.print("ROTStockInterop Start");
 }
예제 #5
0
 internal void ModelChangedHandler(bool pushNodes)
 {
     if (validateNose || validateMount)
     {
         ValidateModules();
     }
     ValidateLength();
     UpdateModulePositions();
     UpdateTankVolume(lengthWidth);
     UpdateDimensions();
     UpdateModelMeshes();
     UpdateAttachNodes(pushNodes);
     UpdateAvailableVariants();
     //UpdateFairing(true);
     UpdateDragCubes();
     if (scaleMass)
     {
         UpdateMass();
     }
     if (scaleCost)
     {
         UpdateCost();
     }
     ROLStockInterop.UpdatePartHighlighting(part);
     if (HighLogic.LoadedSceneIsEditor)
     {
         GameEvents.onEditorShipModified.Fire(EditorLogic.fetch.ship);
     }
 }
예제 #6
0
 /// <summary>
 /// Internal method to update the persistent data state(s) from the current animation state.
 /// </summary>
 /// <param name="newState"></param>
 protected void onAnimationStateChange(ROLAnimState newState, bool updateExternal = false)
 {
     animationState = newState;
     persistentData = newState.ToString();
     if (updateDragCube)
     {
         ROLStockInterop.addDragUpdatePart(part);
     }
     if (updateExternal && onAnimStateChangeCallback != null)
     {
         onAnimStateChangeCallback(newState);
     }
 }
예제 #7
0
 internal void ModelChangedHandler(bool pushNodes)
 {
     stl         = SolarTechLimit.GetTechLevel(techLevel);
     retractable = stl.retractable && solarPanelType != "static";
     UpdateModulePositions();
     startFSM();
     UpdateAttachNodes(pushNodes);
     UpdateAvailableVariants();
     UpdateDragCubes();
     UpdateMassAndCost();
     RecalculateStats();
     ROLStockInterop.UpdatePartHighlighting(part);
     if (HighLogic.LoadedSceneIsEditor)
     {
         ROLStockInterop.FireEditorUpdate();
     }
 }
예제 #8
0
        /// <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>
        public void InitializeUI()
        {
            ROLLog.debug($"ModuleDeployablePart.deployState: {this.deployState}");
            ROLLog.debug($"{modName}InitalizeUI() modelChangedAction");
            Action <ModuleROSolar> modelChangedAction = (m) =>
            {
                m.stl = SolarTechLimit.GetTechLevel(techLevel);
                m.UpdateModulePositions();
                m.UpdateAttachNodes(true);
                m.UpdateAvailableVariants();
                m.UpdateDragCubes();
                m.UpdateMassAndCost();
                m.RecalculateStats();
            };

            // 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) =>
            {
                // 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);
                    lengthWidth = coreModule.definition.lengthWidth;
                    if (!lengthWidth)
                    {
                        Fields[nameof(panelLength)].guiActiveEditor = false;
                        Fields[nameof(panelWidth)].guiActiveEditor  = false;
                        Fields[nameof(panelScale)].guiActiveEditor  = true;
                        this.ROLupdateUIFloatEditControl(nameof(panelScale), 0.1f, 100f, largeStep, smallStep, slideStep, true, panelScale);
                    }
                    else
                    {
                        Fields[nameof(panelLength)].guiActiveEditor = true;
                        Fields[nameof(panelWidth)].guiActiveEditor  = true;
                        Fields[nameof(panelScale)].guiActiveEditor  = false;
                        this.ROLupdateUIFloatEditControl(nameof(panelLength), minLength, maxLength, largeStep, smallStep, slideStep, true, panelLength);
                        this.ROLupdateUIFloatEditControl(nameof(panelWidth), minWidth, maxWidth, largeStep, smallStep, slideStep, true, panelWidth);
                    }
                    m.ResetModel();
                    modelChangedAction(m);
                });
            };

            Fields[nameof(currentCore)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                coreModule.modelSelected(a, b);
                lengthWidth = coreModule.definition.lengthWidth;
                if (!lengthWidth)
                {
                    Fields[nameof(panelLength)].guiActiveEditor = false;
                    Fields[nameof(panelWidth)].guiActiveEditor  = false;
                    Fields[nameof(panelScale)].guiActiveEditor  = true;
                    this.ROLupdateUIFloatEditControl(nameof(panelScale), 0.1f, 100f, largeStep, smallStep, slideStep, true, panelScale);
                }
                else
                {
                    Fields[nameof(panelLength)].guiActiveEditor = true;
                    Fields[nameof(panelWidth)].guiActiveEditor  = true;
                    Fields[nameof(panelScale)].guiActiveEditor  = false;
                    this.ROLupdateUIFloatEditControl(nameof(panelLength), minLength, maxLength, largeStep, smallStep, slideStep, true, panelLength);
                    this.ROLupdateUIFloatEditControl(nameof(panelWidth), minWidth, maxWidth, largeStep, smallStep, slideStep, true, panelWidth);
                }
                this.ROLactionWithSymmetry(modelChangedAction);
                ROLStockInterop.fireEditorUpdate();
            };

            Fields[nameof(panelLength)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                this.ROLactionWithSymmetry(m =>
                {
                    if (m != this)
                    {
                        m.panelLength = this.panelLength;
                    }
                    modelChangedAction(m);
                    m.prevLength = m.panelLength;
                });
                ROLStockInterop.fireEditorUpdate();
            };

            Fields[nameof(panelWidth)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                this.ROLactionWithSymmetry(m =>
                {
                    if (m != this)
                    {
                        m.panelWidth = this.panelWidth;
                    }
                    modelChangedAction(m);
                    m.prevWidth = m.panelWidth;
                });
                ROLStockInterop.fireEditorUpdate();
            };

            Fields[nameof(panelScale)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                this.ROLactionWithSymmetry(m =>
                {
                    if (m != this)
                    {
                        m.panelScale = this.panelScale;
                    }
                    modelChangedAction(m);
                    m.prevScale = m.panelScale;
                });
                ROLStockInterop.fireEditorUpdate();
            };

            if (maxLength == minLength || !lengthWidth)
            {
                Fields[nameof(panelLength)].guiActiveEditor = false;
            }
            else
            {
                this.ROLupdateUIFloatEditControl(nameof(panelLength), minLength, maxLength, largeStep, smallStep, slideStep, true, panelLength);
            }

            if (maxWidth == minWidth || !lengthWidth)
            {
                Fields[nameof(panelWidth)].guiActiveEditor = false;
            }
            else
            {
                this.ROLupdateUIFloatEditControl(nameof(panelWidth), minWidth, maxWidth, largeStep, smallStep, slideStep, true, panelWidth);
            }

            if (lengthWidth)
            {
                Fields[nameof(panelScale)].guiActiveEditor = false;
            }
            else
            {
                Fields[nameof(panelScale)].guiActiveEditor = true;
                this.ROLupdateUIFloatEditControl(nameof(panelScale), 0.1f, 100f, largeStep, smallStep, slideStep, true, panelScale);
            }

            if (HighLogic.LoadedSceneIsEditor)
            {
                GameEvents.onEditorShipModified.Add(new EventData <ShipConstruct> .OnEvent(onEditorVesselModified));
            }

            Fields[nameof(TechLevel)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                UpdateMassAndCost();
                RecalculateStats();
                this.ROLactionWithSymmetry(modelChangedAction);
                ROLStockInterop.fireEditorUpdate();
            };
        }
예제 #9
0
        /// <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;
            }
            ROLLog.debug($"{modName}: Initialize Starting");
            initialized = true;

            prevLength = panelLength;
            prevWidth  = panelWidth;
            prevScale  = panelScale;

            ROLLog.debug($"{modName}: Initialize() parseCSV");
            coreNodeNames = ROLUtils.parseCSV(coreManagedNodes);

            ROLLog.debug($"{modName}: Initialize() Model-Module Initialization");
            // Model-Module Setup / Initialization
            ConfigNode node = ROLConfigNodeUtils.parseConfigNode(configNodeData);

            ROLLog.debug($"{modName}: Initialize() Core Model Nodes");
            // 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");

            ROLLog.debug($"{modName}: Initialize() MDLO");
            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();

            coreModule      = new ROLModelModule <ModuleROSolar>(part, this, getRootTransform("ModuleROSolar-CORE"), ModelOrientation.CENTRAL, nameof(currentCore), null, null, null);
            coreModule.name = "ModuleROSolar-Core";
            coreModule.getSymmetryModule = m => m.coreModule;
            coreModule.getValidOptions   = () => getVariantSet(currentVariant).definitions;

            coreModule.setupModelList(coreDefs);
            coreModule.setupModel();

            if (GameDatabase.Instance.GetConfigNode("ROSolar/TechLimits/ROSOLAR_CONFIG") is ConfigNode ROSconfig)
            {
                SolarTechLimit.Init(ROSconfig);
            }

            stl = SolarTechLimit.GetTechLevel(techLevel);

            UpdateModulePositions();
            UpdateAttachNodes(false);
            UpdateAvailableVariants();
            UpdateMassAndCost();
            RecalculateStats();
            ROLStockInterop.updatePartHighlighting(part);
        }
예제 #10
0
        private void SetModelFromDimensions()
        {
            currentVScale = 0.0f;

            if (!lengthWidth)
            {
                return;
            }

            Action <ModuleROTank> modelChangedAction = (m) =>
            {
                m.updateModulePositions();
                m.updateDimensions();
                m.updateAttachNodes(true);
                m.updateAvailableVariants();
                m.updateDragCubes();
                if (scaleMass)
                {
                    m.updateMass();
                }
                if (scaleCost)
                {
                    m.updateCost();
                }
                m.UpdateTankVolume(lengthWidth);
            };

            float  dimRatio, modelRatio = 0.0f;
            string s = "1.0x-Kerolox";

            dimRatio = currentLength / currentDiameter;

            if (dimRatio < 0.625)
            {
                modelRatio = 0.5f;
            }
            else if (dimRatio < 1.25)
            {
                modelRatio = 1.0f;
            }
            else if (dimRatio < 1.75)
            {
                modelRatio = 1.5f;
            }
            else if (dimRatio < 2.25)
            {
                modelRatio = 2.0f;
            }
            else if (dimRatio < 2.75)
            {
                modelRatio = 2.5f;
            }
            else if (dimRatio < 3.25)
            {
                modelRatio = 3.0f;
            }
            else if (dimRatio < 3.75)
            {
                modelRatio = 3.5f;
            }
            else if (dimRatio < 4.25)
            {
                modelRatio = 4.0f;
            }
            else if (dimRatio < 4.75)
            {
                modelRatio = 4.5f;
            }
            else if (dimRatio < 5.25)
            {
                modelRatio = 5.0f;
            }
            else if (dimRatio < 5.75)
            {
                modelRatio = 5.5f;
            }
            else if (dimRatio < 6.25)
            {
                modelRatio = 6.0f;
            }
            else if (dimRatio < 6.75)
            {
                modelRatio = 6.5f;
            }
            else if (dimRatio < 7.25)
            {
                modelRatio = 7.0f;
            }
            else if (dimRatio < 7.75)
            {
                modelRatio = 7.5f;
            }
            else
            {
                modelRatio = 8.0f;
            }

            string ratioName = string.Format("{0:0.0}", modelRatio);

            s = $"{ratioName}x-{currentVariant}";
            ROLLog.debug($"dimRatio: {dimRatio}, modelRatio: {modelRatio}, string: {s}");

            currentVScale = (dimRatio / modelRatio) - 1;

            coreModule.modelSelected(s);
            this.ROLactionWithSymmetry(modelChangedAction);
            ROLStockInterop.fireEditorUpdate();
        }
예제 #11
0
        /// <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>
        public void initializeUI()
        {
            Action <ModuleROTank> modelChangedAction = (m) =>
            {
                m.updateModulePositions();
                m.updateDimensions();
                m.updateAttachNodes(true);
                m.updateAvailableVariants();
                m.updateDragCubes();
                if (scaleMass)
                {
                    m.updateMass();
                }
                if (scaleCost)
                {
                    m.updateCost();
                }
                //ROLModInterop.updateResourceVolume(m.part);
                m.UpdateTankVolume(lengthWidth);
            };

            //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;
                    if (lengthWidth)
                    {
                        m.SetModelFromDimensions();
                    }
                    else
                    {
                        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;
                    }
                    if (lengthWidth)
                    {
                        m.SetModelFromDimensions();
                    }
                    modelChangedAction(m);
                    m.prevDiameter = m.currentDiameter;
                });
                ROLStockInterop.fireEditorUpdate();
            };

            Fields[nameof(currentLength)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                this.ROLactionWithSymmetry(m =>
                {
                    if (m != this)
                    {
                        m.currentLength = this.currentLength;
                    }
                    m.SetModelFromDimensions();
                    modelChangedAction(m);
                    m.prevLength = m.currentLength;
                });
                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 / LENGTH SWITCH UI INIT---------------------//
            if (maxDiameter == minDiameter)
            {
                Fields[nameof(currentDiameter)].guiActiveEditor = false;
            }
            else
            {
                this.ROLupdateUIFloatEditControl(nameof(currentDiameter), minDiameter, maxDiameter, diameterLargeStep, diameterSmallStep, diameterSlideStep, true, currentDiameter);
            }

            if (maxLength == minLength || !lengthWidth)
            {
                Fields[nameof(currentLength)].guiActiveEditor = false;
            }
            else
            {
                this.ROLupdateUIFloatEditControl(nameof(currentLength), minLength, maxLength, diameterLargeStep, diameterSmallStep, diameterSlideStep, true, currentLength);
            }

            if (!lengthWidth)
            {
                Fields[nameof(currentVScale)].guiActiveEditor = enableVScale;
                Events[nameof(ResetModel)].guiActiveEditor    = true;
            }

            if (lengthWidth)
            {
                Fields[nameof(currentVScale)].guiActiveEditor = false;
                Events[nameof(ResetModel)].guiActiveEditor    = false;
            }

            //------------------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;

            if (HighLogic.LoadedSceneIsEditor)
            {
                GameEvents.onEditorShipModified.Add(new EventData <ShipConstruct> .OnEvent(onEditorVesselModified));
            }
        }
예제 #12
0
        /// <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;
            if (lengthWidth)
            {
                prevLength = currentLength;
            }

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

            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
            noseDefs  = ROLModelData.getModelDefinitions(node.GetNodes("NOSE"));
            mountDefs = ROLModelData.getModelDefinitions(node.GetNodes("MOUNT"));

            noseModule      = new ROLModelModule <ModuleROTank>(part, this, getRootTransform("ModularPart-NOSE"), ModelOrientation.TOP, nameof(currentNose), null, nameof(currentNoseTexture), nameof(noseModulePersistentData));
            noseModule.name = "ModuleROTank-Nose";
            noseModule.getSymmetryModule = m => m.noseModule;
            noseModule.getValidOptions   = () => noseDefs;

            coreModule      = new ROLModelModule <ModuleROTank>(part, this, getRootTransform("ModularPart-CORE"), ModelOrientation.CENTRAL, nameof(currentCore), null, nameof(currentCoreTexture), nameof(coreModulePersistentData));
            coreModule.name = "ModuleROTank-Core";
            coreModule.getSymmetryModule = m => m.coreModule;
            coreModule.getValidOptions   = () => getVariantSet(currentVariant).definitions;

            mountModule      = new ROLModelModule <ModuleROTank>(part, this, getRootTransform("ModularPart-MOUNT"), ModelOrientation.BOTTOM, nameof(currentMount), null, nameof(currentMountTexture), nameof(mountModulePersistentData));
            mountModule.name = "ModuleROTank-Mount";
            mountModule.getSymmetryModule = m => m.mountModule;
            mountModule.getValidOptions   = () => mountDefs;

            noseModule.volumeScalar  = volumeScalingPower;
            coreModule.volumeScalar  = volumeScalingPower;
            mountModule.volumeScalar = volumeScalingPower;

            //set up the model lists and load the currently selected model
            noseModule.setupModelList(noseDefs);
            coreModule.setupModelList(coreDefs);
            mountModule.setupModelList(mountDefs);
            coreModule.setupModel();
            noseModule.setupModel();
            mountModule.setupModel();

            updateModulePositions();
            updateDimensions();
            updateAttachNodes(false);
            updateAvailableVariants();
            if (scaleMass)
            {
                updateMass();
            }
            if (scaleCost)
            {
                updateCost();
            }
            ROLStockInterop.updatePartHighlighting(part);
            UpdateTankVolume(lengthWidth);
        }
예제 #13
0
        private void UpdateTankVolume(bool lw)
        {
            if (!lw)
            {
                float totalVol = noseModule.moduleVolume + coreModule.moduleVolume + mountModule.moduleVolume;
                SendVolumeChangedEvent(totalVol);
                return;
            }

            Action <ModuleROTank> modelChangedAction = (m) =>
            {
                m.updateModulePositions();
                m.updateDimensions();
                m.updateAttachNodes(true);
                m.updateDragCubes();
                if (scaleMass)
                {
                    m.updateMass();
                }
                if (scaleCost)
                {
                    m.updateCost();
                }
                ROLModInterop.realFuelsVolumeUpdate(m.part, m.effectiveVolume);
            };

            float horScale   = currentDiameter / coreModule.definition.diameter;
            float domeLength = currentDiameter / 2;

            noseEffectiveLength  = horScale * noseModule.definition.effectiveLength;
            mountEffectiveLength = horScale * mountModule.definition.effectiveLength;
            coreEffectiveLength  = currentLength - domeLength;
            effectiveLength      = noseEffectiveLength + mountEffectiveLength + coreEffectiveLength;

            /*
             * debug("================================================");
             * debug("<color=green>EFFECTIVE LENGTH INFORMATION</color>");
             * debug($"horScale: {horScale}, domeLength: {domeLength}");
             * debug($"noseEffectiveLength: {noseEffectiveLength}, mountEffectiveLength: {mountEffectiveLength}, coreEffectiveLength: {coreEffectiveLength}");
             * debug($"effectiveLength: {effectiveLength}");
             * debug("================================================");
             */

            // Set the minimum length based on domeLength
            minLength = Math.Max(0.1f, domeLength - (noseEffectiveLength + mountEffectiveLength));

            // Update the float controller to reset the proper minimum length
            this.ROLupdateUIFloatEditControl(nameof(currentLength), minLength, maxLength, diameterLargeStep, diameterSmallStep, diameterSlideStep, true, currentLength);

            // Set the tank length to be the same size as the minLength if it is currently smaller
            if (currentLength < minLength)
            {
                currentLength = minLength;
            }

            // Calculate the new volume
            // First, get the additional volume from the nose and mounts
            float noseDiameter = noseModule.definition.shouldInvert(noseModule.definition.orientation) ? noseModule.definition.upperDiameter : noseModule.definition.lowerDiameter;
            float noseScale    = currentDiameter / noseDiameter;

            noseScale = Mathf.Pow(noseScale, 3);

            float mountDiameter = mountModule.definition.shouldInvert(mountModule.definition.orientation) ? mountModule.definition.lowerDiameter : mountModule.definition.upperDiameter;
            float mountScale    = currentDiameter / mountDiameter;

            mountScale = Mathf.Pow(mountScale, 3);

            noseAdditionalVol  = noseScale * noseModule.definition.additionalVolume * 1000f;
            mountAdditionalVol = mountScale * mountModule.definition.additionalVolume * 1000f;

            // Calculate the volume of the main tank
            float r = currentDiameter / 2;

            effectiveVolume  = (EllipsoidVolume(r, r, r / 2) + CylinderVolume(r, effectiveLength)) * 1000f;
            effectiveVolume += noseAdditionalVol + mountAdditionalVol;

            /*
             * debug("================================================");
             * debug("<color=blue>EFFECTIVE VOLUME INFORMATION</color>");
             * debug($"noseScale: {noseScale}, mountScale: {mountScale}");
             * debug($"noseAdditionalOrig: {noseModule.definition.additionalVolume}, noseAdditionalVol: {noseAdditionalVol}, coreAdditionalOrig: {mountModule.definition.additionalVolume}, mountAdditionalVol: {mountAdditionalVol}");
             * debug($"origEffectiveVolume: {effectiveVolume - noseAdditionalVol - mountAdditionalVol}");
             * debug($"effectiveVolume: {effectiveVolume}");
             * debug("================================================");
             */

            this.ROLactionWithSymmetry(modelChangedAction);
            ROLStockInterop.fireEditorUpdate();
        }