Example #1
0
        public ModelLayoutData getLayout(string name)
        {
            ModelLayoutData mld = layouts.ROLFind(m => m.name == name);

            if (mld == null)
            {
                ROLLog.error("ERROR: Could not locate layout for name: " + name);
            }
            return(mld);
        }
        public readonly float gimbalFlightRange;     //how far the gimbal may be actuated while in flight from the adjusted reference angle

        public ModelEngineTransformData(ConfigNode node)
        {
            thrustTransformName = node.ROLGetStringValue("thrustTransform");
            if (string.IsNullOrEmpty(thrustTransformName))
            {
                ROLLog.error("ERROR: THrust transform name was null for model def engine transform data");
            }
            gimbalTransformName   = node.ROLGetStringValue("gimbalTransform");
            gimbalAdjustmentRange = node.ROLGetFloatValue("gimbalAdjustRange", 0);
            gimbalFlightRange     = node.ROLGetFloatValue("gimbalFlightRange", 0);
        }
Example #3
0
 public ModelDefinitionLayoutOptions(ROLModelDefinition def, ModelLayoutData[] layouts)
 {
     this.definition = def;
     if (definition == null)
     {
         ROLLog.error("Model definition was null when creating model layout options!");
     }
     this.layouts = layouts;
     if (this.layouts == null || this.layouts.Length < 1)
     {
         throw new InvalidOperationException("ERROR: No valid layout data specified.");
     }
 }
Example #4
0
 public ModelDefinitionLayoutOptions(ROLModelDefinition def)
 {
     definition = def;
     if (definition == null)
     {
         ROLLog.error("Model definition was null when creating model layout options!");
     }
     layouts = ROLModelLayout.findLayouts(new string[] { "default" });
     if (this.layouts == null || this.layouts.Length < 1)
     {
         throw new InvalidOperationException("ERROR: No valid layout data specified.");
     }
 }
Example #5
0
        /// <summary>
        /// Create a group of model definition layout sets.  Loads the model definitions + their supported layout configurations.
        /// </summary>
        /// <param name="nodes"></param>
        /// <returns></returns>
        public static ModelDefinitionLayoutOptions[] getModelDefinitions(ConfigNode[] nodes)
        {
            int len = nodes.Length;

            List <ModelDefinitionLayoutOptions> options = new List <ModelDefinitionLayoutOptions>();
            List <ModelLayoutData> layoutDataList       = new List <ModelLayoutData>();
            ROLModelDefinition     def;

            string[] groupedNames;
            string[] groupedLayouts;
            int      len2;

            for (int i = 0; i < len; i++)
            {
                //because configNode.ToString() reverses the order of values, and model def layouts are always loaded from string-cached config nodes
                //we need to reverse the order of the model and layout names during parsing
                groupedNames   = nodes[i].ROLGetStringValues("model");
                groupedLayouts = nodes[i].ROLGetStringValues("layout", new string[] { "default" });
                len2           = groupedNames.Length;
                for (int k = 0; k < len2; k++)
                {
                    def = ROLModelData.getModelDefinition(groupedNames[k]);
                    layoutDataList.AddRange(ROLModelLayout.findLayouts(groupedLayouts));
                    if (nodes[i].HasValue("position") || nodes[i].HasValue("rotation") || nodes[i].HasValue("scale"))
                    {
                        Vector3           pos    = nodes[i].ROLGetVector3("position", Vector3.zero);
                        Vector3           scale  = nodes[i].ROLGetVector3("scale", Vector3.one);
                        Vector3           rot    = nodes[i].ROLGetVector3("rotation", Vector3.zero);
                        ModelPositionData mpd    = new ModelPositionData(pos, scale, rot);
                        ModelLayoutData   custom = new ModelLayoutData("default", new ModelPositionData[] { mpd });
                        if (layoutDataList.Exists(m => m.name == "default"))
                        {
                            ModelLayoutData del = layoutDataList.Find(m => m.name == "default");
                            layoutDataList.Remove(del);
                        }
                        layoutDataList.Add(custom);
                    }
                    if (def == null)
                    {
                        ROLLog.error("Model definition was null for name: " + groupedNames[k] + ". Skipping definition during loading of part");
                    }
                    else
                    {
                        options.Add(new ModelDefinitionLayoutOptions(def, layoutDataList.ToArray()));
                    }
                    layoutDataList.Clear();
                }
            }
            return(options.ToArray());
        }
Example #6
0
        public static ModelLayoutData findLayout(string name)
        {
            if (!loaded)
            {
                load();
            }
            ModelLayoutData mld;

            if (!layouts.TryGetValue(name, out mld))
            {
                ROLLog.error("Could not find layout by name: " + name);
            }
            return(mld);
        }
Example #7
0
        public static Vector3 ROLGetVector3(this ConfigNode node, String name, Vector3 defaultValue)
        {
            String value = node.GetValue(name);

            if (value == null)
            {
                return(defaultValue);
            }
            String[] vals = value.Split(',');
            if (vals.Length < 3)
            {
                ROLLog.error("ERROR parsing values for Vector3 from input: " + value + ". found less than 3 values, cannot create Vector3");
                return(defaultValue);
            }
            return(new Vector3((float)ROLUtils.safeParseDouble(vals[0]), (float)ROLUtils.safeParseDouble(vals[1]), (float)ROLUtils.safeParseDouble(vals[2])));
        }
Example #8
0
        public override void OnStart(StartState state)
        {
            base.OnStart(state);

            if (!FindDecoupler())
            {
                ROLLog.error("Unable to find any Decoupler modules");
                isEnabled = enabled = false;
                return;
            }

            if (HighLogic.LoadedSceneIsFlight)
            {
                decouple.isOmniDecoupler = isOmniDecoupler;
            }
        }
Example #9
0
        public static T ROLFind <T>(this T[] array, Func <T, bool> predicate)
        {
            int len = array.Length;

            for (int i = 0; i < len; i++)
            {
                if (array[i] == null)
                {
                    ROLLog.error("ERROR: Null value in array in Find method, at index: " + i);
                }
                if (predicate(array[i]))
                {
                    return(array[i]);
                }
            }
            //return default in order to properly handle value types (structs)
            //should return either null for reference types or default value for structs
            return(default(T));
        }
Example #10
0
        public override void OnStartFinished(StartState state)
        {
            base.OnStartFinished(state);

            ROLLog.debug("OnStartFinished()...");
            if (!FindModularPart())
            {
                ROLLog.error("Unable to find any Modular Part modules");
                isEnabled = enabled = false;
                return;
            }

            SetupUICallbacks();

            if (HighLogic.LoadedSceneIsEditor)
            {
                UpdateImpulseValues();
            }
        }
Example #11
0
        /// <summary>
        /// Create a group of model definition layout options by model definition name, with default (single position) layouts.
        /// </summary>
        /// <param name="names"></param>
        /// <returns></returns>
        public static ModelDefinitionLayoutOptions[] getModelDefinitionLayouts(string[] names)
        {
            List <ModelDefinitionLayoutOptions> defs = new List <ModelDefinitionLayoutOptions>();
            int len = names.Length;

            for (int i = 0; i < len; i++)
            {
                ROLModelDefinition def = getModelDefinition(names[i]);
                if (def != null)
                {
                    defs.Add(new ModelDefinitionLayoutOptions(def));
                }
                else
                {
                    ROLLog.error("Could not locate model defintion for name: " + names[i]);
                }
            }
            return(defs.ToArray());
        }
 public void SetupSubmodel(GameObject modelRoot)
 {
     if (modelMeshes.Length > 0)
     {
         List <Transform> toKeep  = new List <Transform>();
         List <Transform> toCheck = new List <Transform>();
         foreach (Transform tr in modelRoot.transform.ROLGetAllChildren())
         {
             if (tr is Transform)
             {
                 if (IsActiveMesh(tr.name))
                 {
                     toKeep.Add(tr);
                 }
                 else
                 {
                     toCheck.Add(tr);
                 }
             }
         }
         foreach (Transform tr in toCheck.Where(x => !IsParent(x, toKeep)))
         {
             GameObject.DestroyImmediate(tr.gameObject);
         }
     }
     foreach (string renameMesh in renameMeshes)
     {
         string[] split = renameMesh.Split(',');
         if (split.Length < 2)
         {
             ROLLog.error("ERROR: Mesh rename format invalid, must specify <oldName>,<newName>");
             continue;
         }
         string oldName = split[0].Trim();
         string newName = split[1].Trim();
         foreach (Transform tr in modelRoot.transform.ROLFindChildren(oldName))
         {
             tr.name = newName;
         }
     }
 }
 public override void OnStartFinished(StartState state)
 {
     base.OnStartFinished(state);
     decouple    = part.FindModuleImplementing <ModuleDecouple>();
     modularPart = part.FindModuleImplementing <ModuleROTank>();
     if (!(decouple is ModuleDecouple && modularPart is ModuleROTank))
     {
         ROLLog.error($"{part} Unable to find ModuleDecouple or ModuleROTank modules");
         isEnabled = enabled = false;
         return;
     }
     else
     {
         decouple.isOmniDecoupler = isOmniDecoupler;
         if (modularPart is ModuleROTank)
         {
             modularPart.Fields[nameof(modularPart.currentDiameter)].uiControlEditor.onFieldChanged += OnDiameterChange;
         }
         UpdateImpulseValues();
     }
 }
Example #14
0
        private static void loadDefs()
        {
            if (defsLoaded)
            {
                return;
            }
            defsLoaded = true;
            ConfigNode[]       modelDatas = GameDatabase.Instance.GetConfigNodes("ROL_MODEL");
            ROLModelDefinition data;

            foreach (ConfigNode node in modelDatas)
            {
                data = new ROLModelDefinition(node);
                ROLLog.log("Loading model definition data for name: " + data.name + " with model URL: " + data.modelName);
                if (baseModelData.ContainsKey(data.name))
                {
                    ROLLog.error("Model defs already contains def for name: " + data.name + ".  Please check your configs as this is an error.  The duplicate entry was found in the config node of:\n" + node);
                    continue;
                }
                baseModelData.Add(data.name, data);
            }
        }
Example #15
0
        public static bool RealFuelsVolumeUpdate(Part part, float liters)
        {
            if (!IsRFInstalled() && !IsMFTInstalled())
            {
                ROLLog.error($"Config for {part} is set to use RF/MFT, but neither RF nor MFT is installed, cannot update part volumes through them.  Please check your configs and/or patches for errors.");
                return(false);
            }

            if (MFTChangeTotalVolumeMI is MethodInfo && MFTCalculateMassMI is MethodInfo && GetModuleFuelTanks(part) is PartModule pm)
            {
                double volumeLiters = liters;
                MFTChangeTotalVolumeMI.Invoke(pm, new object[] { volumeLiters, false });
                MFTCalculateMassMI.Invoke(pm, new object[] { });
                UpdatePartResourceDisplay(part);
                ROLLog.debug($"ROTModInterop - Set RF/MFT total tank volume to: {volumeLiters} Liters for part: {part.name}");
                return(true);
            }
            else
            {
                ROLLog.error($"Could not find ModuleFuelTank in part {part} for RealFuels/MFT!");
                return(false);
            }
        }
        /// <summary>
        /// Construct the model definition from the data in the input ConfigNode.<para/>
        /// All data constructs MUST conform to the expected format (see documentation), or things will not load properly and the model will likely not work as expected.
        /// </summary>
        /// <param name="node"></param>
        public ROLModelDefinition(ConfigNode node)
        {
            //load basic model definition values -- data that pertains to every model definition regardless of end-use.
            configNode = node;
            name       = node.ROLGetStringValue("name", String.Empty);
            if (string.IsNullOrEmpty(name))
            {
                ROLLog.error("ERROR: Cannot load ROLModelDefinition with null or empty name.  Full config:\n" + node.ToString());
            }
            title                  = node.ROLGetStringValue("title", name);
            description            = node.ROLGetStringValue("description", title);
            modelName              = node.ROLGetStringValue("modelName", string.Empty);
            upgradeUnlock          = node.ROLGetStringValue("upgradeUnlock", upgradeUnlock);
            height                 = node.ROLGetFloatValue("height", height);
            actualHeight           = node.ROLGetFloatValue("actualHeight", actualHeight);
            volume                 = node.ROLGetFloatValue("volume", volume);
            mass                   = node.ROLGetFloatValue("mass", mass);
            cost                   = node.ROLGetFloatValue("cost", cost);
            diameter               = node.ROLGetFloatValue("diameter", diameter);
            minVerticalScale       = node.ROLGetFloatValue("minVerticalScale", minVerticalScale);
            maxVerticalScale       = node.ROLGetFloatValue("maxVerticalScale", maxVerticalScale);
            upperDiameter          = node.ROLGetFloatValue("upperDiameter", diameter);
            lowerDiameter          = node.ROLGetFloatValue("lowerDiameter", diameter);
            panelLength            = node.ROLGetFloatValue("panelLength", panelLength);
            panelWidth             = node.ROLGetFloatValue("panelWidth", panelWidth);
            panelArea              = node.ROLGetFloatValue("panelArea", panelArea);
            panelScale             = node.ROLGetFloatValue("panelScale", panelScale);
            secondaryTransformName = node.ROLGetStringValue("secondaryTransformName", secondaryTransformName);
            pivotName              = node.ROLGetStringValue("pivotName", pivotName);
            animationName          = node.ROLGetStringValue("animationName", animationName);
            lengthWidth            = node.ROLGetBoolValue("lengthWidth", lengthWidth);
            isTracking             = node.ROLGetBoolValue("isTracking", isTracking);
            effectiveLength        = node.ROLGetFloatValue("effectiveLength", effectiveLength);
            additionalVolume       = node.ROLGetFloatValue("additionalVolume", additionalVolume);
            if (node.HasValue("verticalOffset"))
            {
                positionOffset = new Vector3(0, node.ROLGetFloatValue("verticalOffset"), 0);
            }
            else
            {
                positionOffset = node.ROLGetVector3("positionOffset", Vector3.zero);
            }
            rotationOffset = node.ROLGetVector3("rotationOffset", rotationOffset);
            scaleOffset    = node.ROLGetVector3("scaleOffset", Vector3.one);

            orientation = (ModelOrientation)Enum.Parse(typeof(ModelOrientation), node.ROLGetStringValue("orientation", ModelOrientation.TOP.ToString()));
            invertAxis  = node.ROLGetVector3("invertAxis", invertAxis);

            //load sub-model definitions
            ConfigNode[] subModelNodes = node.GetNodes("SUBMODEL");
            int          len           = subModelNodes.Length;

            if (len == 0)//no defined submodel data, check for regular single model definition, if present, build a submodel definition for it.
            {
                if (!string.IsNullOrEmpty(modelName))
                {
                    SubModelData smd = new SubModelData(modelName, new string[0], string.Empty, positionOffset, rotationOffset, scaleOffset);
                    subModelData = new SubModelData[] { smd };
                }
                else//is an empty proxy model with no meshes
                {
                    subModelData = new SubModelData[0];
                }
            }
            else
            {
                subModelData = new SubModelData[len];
                for (int i = 0; i < len; i++)
                {
                    subModelData[i] = new SubModelData(subModelNodes[i]);
                }
            }

            if (node.HasNode("MERGEDMODELS"))
            {
                ConfigNode[] mergeNodes = node.GetNodes("MERGEDMODELS");
                len       = mergeNodes.Length;
                mergeData = new MeshMergeData[len];
                for (int i = 0; i < len; i++)
                {
                    mergeData[i] = new MeshMergeData(mergeNodes[i]);
                }
            }
            else
            {
                mergeData = new MeshMergeData[0];
            }

            //Load texture set definitions.
            List <TextureSet> textureSetList = new List <TextureSet>();

            foreach (string tsName in node.ROLGetStringValues("textureSet"))
            {
                if (TexturesUnlimitedLoader.getTextureSet(tsName) is TextureSet ts)
                {
                    textureSetList.Add(ts);
                }
            }
            //then load any of the model-specific sets
            foreach (ConfigNode tsNode in node.GetNodes("KSP_TEXTURE_SET"))
            {
                textureSetList.Add(new TextureSet(tsNode));
            }
            textureSets = textureSetList.ToArray();

            //Load the default texture set specification
            defaultTextureSet = node.ROLGetStringValue("defaultTextureSet");
            //if none is defined in the model def, but texture sets are present, set it to the name of the first defined texture set
            if (string.IsNullOrEmpty(defaultTextureSet) && textureSets.Length > 0)
            {
                defaultTextureSet = textureSets[0].name;
            }

            if (node.HasValue("topNode"))
            {
                topNodeData = new AttachNodeBaseData(node.ROLGetStringValue("topNode"));
            }
            else
            {
                float y = height;
                if (orientation == ModelOrientation.CENTRAL)
                {
                    y *= 0.5f;
                }
                else if (orientation == ModelOrientation.BOTTOM)
                {
                    y = 0;
                }
                topNodeData = new AttachNodeBaseData(0, y, 0, 0, 1, 0, diameter / 1.25f);
            }
            if (node.HasValue("bottomNode"))
            {
                bottomNodeData = new AttachNodeBaseData(node.ROLGetStringValue("bottomNode"));
            }
            else
            {
                float y = -height;
                if (orientation == ModelOrientation.CENTRAL)
                {
                    y *= 0.5f;
                }
                else if (orientation == ModelOrientation.TOP)
                {
                    y = 0;
                }
                bottomNodeData = new AttachNodeBaseData(0, y, 0, 0, -1, 0, diameter / 1.25f);
            }
            if (node.HasValue("bodyNode"))
            {
                string[] nodeData = node.ROLGetStringValues("bodyNode");
                len          = nodeData.Length;
                bodyNodeData = new AttachNodeBaseData[len];
                for (int i = 0; i < len; i++)
                {
                    bodyNodeData[i] = new AttachNodeBaseData(nodeData[i]);
                }
            }

            //load the surface attach node specifications, or create default if none are defined.
            if (node.HasValue("surface"))
            {
                surfaceNode = new AttachNodeBaseData(node.ROLGetStringValue("surface"));
            }
            else
            {
                surfaceNode = new AttachNodeBaseData($"{diameter / 2},0,0,1,0,0,2");
            }

            if (node.HasNode("COMPOUNDMODEL"))
            {
                compoundModelData = new CompoundModelData(node.GetNode("COMPOUNDMODEL"));
            }

            if (node.HasNode("CONSTRAINT"))
            {
                constraintData = new ModelConstraintData(node.GetNode("CONSTRAINT"));
            }

            if (node.HasNode("RCSDATA"))
            {
                rcsModuleData = new ModelRCSModuleData(node.GetNode("RCSDATA"));
            }

            if (node.HasNode("RCSPOSITION"))
            {
                ConfigNode[] pns = node.GetNodes("RCSPOSITION");
                len             = pns.Length;
                rcsPositionData = new ModelAttachablePositionData[len];
                for (int i = 0; i < len; i++)
                {
                    rcsPositionData[i] = new ModelAttachablePositionData(pns[i]);
                }
            }

            if (node.HasNode("ENGINE_THRUST"))
            {
                engineThrustData = new ModelEngineThrustData(node.GetNode("ENGINE_THRUST"));
            }

            if (node.HasNode("ENGINE_TRANSFORM"))
            {
                engineTransformData = new ModelEngineTransformData(node.GetNode("ENGINE_TRANSFORM"));
            }
        }