Esempio n. 1
0
 private void initialize()
 {
     //MonoBehaviour.print("NodeFairingInit: "+fairingCreated+ " :: " +fairingForceDisabled+ " :: "+fairingJettisoned + " :: " +fairingEnabled);
     if (rendersToRemove != null && rendersToRemove.Length > 0)
     {
         ROTUtils.removeTransforms(part, ROTUtils.parseCSV(rendersToRemove));
     }
     loadFairingData(ROTConfigNodeUtils.parseConfigNode(configNodeData));
     if (externalUpdateData != null)
     {
         updateFromExternalData(externalUpdateData);
     }
     if (fairingCreated || (fairingEnabled && !fairingJettisoned && !fairingForceDisabled && string.IsNullOrEmpty(nodeName)))//previously existed, recreate it, or should exist by default values in the config
     {
         buildFairing();
         if (!string.IsNullOrEmpty(nodeName))
         {
             AttachNode n = part.FindAttachNode(nodeName);
             if (n != null && n.attachedPart != null)
             {
                 prevAttachedPart = n.attachedPart;
                 //MonoBehaviour.print("Setting initial attached part to: " + prevAttachedPart);
             }
         }
     }
     else if (!fairingJettisoned && !fairingForceDisabled && !string.IsNullOrEmpty(nodeName))//else could potentially be activated by a node...check for activation
     {
         needsStatusUpdate = true;
     }
     updateTextureSet(false);
     needsGuiUpdate = true;
     //MonoBehaviour.print("NodeFairingInit End: " + fairingCreated + " :: " + fairingForceDisabled + " :: " + fairingJettisoned + " :: " + fairingEnabled);
 }
Esempio n. 2
0
 public AttachNodeBaseData(String nodeData)
 {
     String[] dataVals = nodeData.Split(new String[] { "," }, StringSplitOptions.None);
     position    = new Vector3(ROTUtils.safeParseFloat(dataVals[0].Trim()), ROTUtils.safeParseFloat(dataVals[1].Trim()), ROTUtils.safeParseFloat(dataVals[2].Trim()));
     orientation = new Vector3(ROTUtils.safeParseFloat(dataVals[3].Trim()), ROTUtils.safeParseFloat(dataVals[4].Trim()), ROTUtils.safeParseFloat(dataVals[5].Trim()));
     size        = dataVals.Length > 6 ? ROTUtils.safeParseInt(dataVals[6]) : 4;
 }
Esempio n. 3
0
 public void loadPersistence(String data)
 {
     String[] csv = ROTUtils.parseCSV(data);
     topY         = ROTUtils.safeParseFloat(csv[0]);
     bottomY      = ROTUtils.safeParseFloat(csv[1]);
     topRadius    = ROTUtils.safeParseFloat(csv[2]);
     bottomRadius = ROTUtils.safeParseFloat(csv[3]);
 }
Esempio n. 4
0
 public void setOpacity(float value)
 {
     opacity = value;
     if (rootObject != null)
     {
         ROTUtils.setOpacityRecursive(rootObject.transform, value);
     }
 }
Esempio n. 5
0
        public static bool[] GetBoolValues(this ConfigNode node, String name)
        {
            String[] values = node.GetValues(name);
            int      len    = values.Length;

            bool[] vals = new bool[len];
            for (int i = 0; i < len; i++)
            {
                vals[i] = ROTUtils.safeParseBool(values[i]);
            }
            return(vals);
        }
Esempio n. 6
0
        private void initialize()
        {
            if (initialized)
            {
                return;
            }
            initialized = true;

            prevDiameter = currentDiameter;

            coreNodeNames = ROTUtils.parseCSV(coreManagedNodes);

            //model-module setup/initialization
            ConfigNode node = ROTConfigNodeUtils.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].GetStringValue("variant", "Default");
                coreDefs = ROTModelData.getModelDefinitionLayouts(coreDefNodes[i].GetStringValues("model"));
                coreDefList.AddUniqueRange(coreDefs);
                ModelDefinitionVariantSet mdvs = getVariantSet(variantName);
                mdvs.addModels(coreDefs);
            }
            coreDefs = coreDefList.ToArray();

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

            coreModule.massScalar   = massScalingPower;
            coreModule.volumeScalar = volumeScalingPower;

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

            updateModulePositions();
            updateMassAndDimensions();
            updateAttachNodes(false);
            updateAvailableVariants();
            ROTStockInterop.updatePartHighlighting(part);
        }
Esempio n. 7
0
        public static float[] GetFloatValues(this ConfigNode node, String name, float[] defaults)
        {
            String baseVal = node.GetStringValue(name);

            if (!String.IsNullOrEmpty(baseVal))
            {
                String[] split = baseVal.Split(new char[] { ',' });
                float[]  vals  = new float[split.Length];
                for (int i = 0; i < split.Length; i++)
                {
                    vals[i] = ROTUtils.safeParseFloat(split[i]);
                }
                return(vals);
            }
            return(defaults);
        }
Esempio n. 8
0
        public static Vector3 GetVector3(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)
            {
                MonoBehaviour.print("ERROR parsing values for Vector3 from input: " + value + ". found less than 3 values, cannot create Vector3");
                return(defaultValue);
            }
            return(new Vector3((float)ROTUtils.safeParseDouble(vals[0]), (float)ROTUtils.safeParseDouble(vals[1]), (float)ROTUtils.safeParseDouble(vals[2])));
        }
Esempio n. 9
0
        public static int[] GetIntValues(this ConfigNode node, string name, int[] defaultValues = null)
        {
            int[]    values       = defaultValues;
            string[] stringValues = node.GetValues(name);
            if (stringValues == null || stringValues.Length == 0)
            {
                return(values);
            }
            int len = stringValues.Length;

            values = new int[len];
            for (int i = 0; i < len; i++)
            {
                values[i] = ROTUtils.safeParseInt(stringValues[i]);
            }
            return(values);
        }
Esempio n. 10
0
        public GameObject[] generatePanels(Transform parent)
        {
            //each panelEdgeGroup should now contain the vertical edge loops for each vertical panel grouping
            //from here, need to generate meshes for panels depending upon splitPanels setting
            int len = panelGroups.Length;

            GameObject[] gos = new GameObject[panels];
            for (int i = 0; i < len; i++)
            {
                gos[i] = parent.FindOrCreate("FairingPanel-" + i).gameObject;
                ROTUtils.destroyChildren(gos[i].transform);//remove any existing colliders
                MeshFilter mf = gos[i].GetComponent <MeshFilter>();
                if (mf == null)
                {
                    mf = gos[i].AddComponent <MeshFilter>();
                }
                mf.mesh = panelGroups[i].generatePanels(offset, outsideUV, insideUV, edgesUV);
                if (colliders)
                {
                    GameObject[] cols = panelGroups[i].generateColliders(offset, facesPerCollider);
                    for (int k = 0; k < cols.Length; k++)
                    {
                        cols[k].transform.NestToParent(gos[i].transform);
                    }
                }
                MeshRenderer mr = gos[i].GetComponent <MeshRenderer>();
                if (mr == null)
                {
                    mr = gos[i].AddComponent <MeshRenderer>();
                }
                gos[i].transform.parent        = parent;
                gos[i].transform.localPosition = Vector3.zero;
                gos[i].transform.rotation      = parent.rotation;
            }
            Transform[] trs;
            for (int i = len; i < 8; i++)//destroy extra unused panels
            {
                trs = parent.transform.FindChildren("FairingPanel-" + i);
                for (int k = 0; k < trs.Length; k++)
                {
                    GameObject.DestroyImmediate(trs[k].gameObject);
                }
            }
            return(gos);
        }
Esempio n. 11
0
        public static FloatCurve GetFloatCurve(this ConfigNode node, String name, FloatCurve defaultValue = null)
        {
            FloatCurve curve = new FloatCurve();

            if (node.HasNode(name))
            {
                ConfigNode curveNode = node.GetNode(name);
                String[]   values    = curveNode.GetValues("key");
                int        len       = values.Length;
                String[]   splitValue;
                float      a, b, c, d;
                for (int i = 0; i < len; i++)
                {
                    splitValue = Regex.Replace(values[i], @"\s+", " ").Split(' ');
                    if (splitValue.Length > 2)
                    {
                        a = ROTUtils.safeParseFloat(splitValue[0]);
                        b = ROTUtils.safeParseFloat(splitValue[1]);
                        c = ROTUtils.safeParseFloat(splitValue[2]);
                        d = ROTUtils.safeParseFloat(splitValue[3]);
                        curve.Add(a, b, c, d);
                    }
                    else
                    {
                        a = ROTUtils.safeParseFloat(splitValue[0]);
                        b = ROTUtils.safeParseFloat(splitValue[1]);
                        curve.Add(a, b);
                    }
                }
            }
            else if (defaultValue != null)
            {
                foreach (Keyframe f in defaultValue.Curve.keys)
                {
                    curve.Add(f.time, f.value, f.inTangent, f.outTangent);
                }
            }
            else
            {
                curve.Add(0, 0);
                curve.Add(1, 1);
            }
            return(curve);
        }
Esempio n. 12
0
        public static Material loadMaterial(String diffuse, String normal, String emissive, String shader)
        {
            Material material;
            Texture  diffuseTexture  = ROTUtils.findTexture(diffuse, false);
            Texture  normalTexture   = String.IsNullOrEmpty(normal) ? null : ROTUtils.findTexture(normal, true);
            Texture  emissiveTexture = String.IsNullOrEmpty(emissive) ? null : ROTUtils.findTexture(emissive, false);

            material = new Material(Shader.Find(shader));
            material.SetTexture("_MainTex", diffuseTexture);
            if (normalTexture != null)
            {
                material.SetTexture("_BumpMap", normalTexture);
            }
            if (emissiveTexture != null)
            {
                material.SetTexture("_Emissive", emissiveTexture);
            }
            return(material);
        }
Esempio n. 13
0
        public static void findShieldedPartsCylinder(Part basePart, Bounds fairingRenderBounds, List <Part> shieldedParts, float topY, float bottomY, float topRadius, float bottomRadius)
        {
            float height        = topY - bottomY;
            float largestRadius = topRadius > bottomRadius ? topRadius : bottomRadius;

            Vector3 lookupCenterLocal  = new Vector3(0, bottomY + (height * 0.5f), 0);
            Vector3 lookupTopLocal     = new Vector3(0, topY, 0);
            Vector3 lookupBottomLocal  = new Vector3(0, bottomY, 0);
            Vector3 lookupCenterGlobal = basePart.transform.TransformPoint(lookupCenterLocal);

            Ray lookupRay = new Ray(lookupBottomLocal, new Vector3(0, 1, 0));

            List <Part> partsFound = new List <Part>();

            Collider[] foundColliders = Physics.OverlapSphere(lookupCenterGlobal, height * 1.5f, 1);
            foreach (Collider col in foundColliders)
            {
                Part pt = col.gameObject.GetComponentUpwards <Part>();
                if (pt != null && pt != basePart && pt.vessel == basePart.vessel && !partsFound.Contains(pt))
                {
                    partsFound.Add(pt);
                }
            }

            Bounds[] otherPartBounds;
            Vector3  otherPartCenterLocal;

            float partYPos;
            float partYPercent;
            float partYRadius;
            float radiusOffset = topRadius - bottomRadius;

            foreach (Part pt in partsFound)
            {
                //check basic render bounds for containment

                //TODO this check misses the case where the fairing is long/tall, containing a wide part; it will report that the wide part can fit inside
                //of the fairing, due to the relative size of their colliders
                otherPartBounds = pt.GetRendererBounds();
                if (PartGeometryUtil.MergeBounds(otherPartBounds, pt.transform).size.sqrMagnitude > fairingRenderBounds.size.sqrMagnitude)
                {
                    continue;
                }

                Vector3 otherPartCenter = pt.partTransform.TransformPoint(PartGeometryUtil.FindBoundsCentroid(otherPartBounds, pt.transform));
                if (!fairingRenderBounds.Contains(otherPartCenter))
                {
                    continue;
                }

                //check part bounds center point against conic projection of the fairing
                otherPartCenterLocal = basePart.transform.InverseTransformPoint(otherPartCenter);

                //check vs top and bottom of the shielded area
                if (otherPartCenterLocal.y > lookupTopLocal.y || otherPartCenterLocal.y < lookupBottomLocal.y)
                {
                    continue;
                }

                //quick check vs cylinder radius
                float distFromLine = ROTUtils.distanceFromLine(lookupRay, otherPartCenterLocal);
                if (distFromLine > largestRadius)
                {
                    continue;
                }

                //more precise check vs radius of the cone at that Y position
                partYPos     = otherPartCenterLocal.y - lookupBottomLocal.y;
                partYPercent = partYPos / height;
                partYRadius  = partYPercent * radiusOffset;
                if (distFromLine > (partYRadius + bottomRadius))
                {
                    continue;
                }
                shieldedParts.Add(pt);
            }
        }
Esempio n. 14
0
 public void enableColliders(bool val)
 {
     ROTUtils.enableColliderRecursive(rootObject.transform, val);
 }
Esempio n. 15
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>
        private void initializeUI()
        {
            Action <ModuleROTank> modelChangedAction = (m) =>
            {
                m.updateModulePositions();
                m.updateDimensions();
                m.updateAttachNodes(true);
                m.updateFairing(true);
                m.updateAvailableVariants();
                m.updateDragCubes();
                ROTModInterop.updateResourceVolume(m.part);
            };

            //set up the core variant UI control
            string[] variantNames = ROTUtils.getNames(variantSets.Values, m => m.variantName);
            this.updateUIChooseOptionControl(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.actionWithSymmetry(m =>
                {
                    m.currentVariant = currentVariant;
                    m.coreModule.modelSelected(newCoreDef.definition.name);
                    modelChangedAction(m);
                });
            };

            Fields[nameof(currentDiameter)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                this.actionWithSymmetry(m =>
                {
                    if (m != this)
                    {
                        m.currentDiameter = this.currentDiameter;
                    }
                    modelChangedAction(m);
                    m.prevDiameter = m.currentDiameter;
                });
                ROTStockInterop.fireEditorUpdate();
            };

            Fields[nameof(currentVScale)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                this.actionWithSymmetry(m =>
                {
                    if (m != this)
                    {
                        m.currentVScale = this.currentVScale;
                    }
                    modelChangedAction(m);
                });
                ROTStockInterop.fireEditorUpdate();
            };

            Fields[nameof(currentNose)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                noseModule.modelSelected(a, b);
                this.actionWithSymmetry(modelChangedAction);
                ROTStockInterop.fireEditorUpdate();
            };

            Fields[nameof(currentCore)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                coreModule.modelSelected(a, b);
                this.actionWithSymmetry(modelChangedAction);
                ROTStockInterop.fireEditorUpdate();
            };

            Fields[nameof(currentMount)].uiControlEditor.onFieldChanged = (a, b) =>
            {
                mountModule.modelSelected(a, b);
                this.actionWithSymmetry(modelChangedAction);
                ROTStockInterop.fireEditorUpdate();
            };

            //------------------MODEL DIAMETER SWITCH UI INIT---------------------//
            if (maxDiameter == minDiameter)
            {
                Fields[nameof(currentDiameter)].guiActiveEditor = false;
            }
            else
            {
                this.updateUIFloatEditControl(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;

            if (HighLogic.LoadedSceneIsEditor)
            {
                GameEvents.onEditorShipModified.Add(new EventData <ShipConstruct> .OnEvent(onEditorVesselModified));
            }
        }
Esempio n. 16
0
        //TODO clean this up to be easier to read/understand now that it is optimized for cylinder check only
        public static void findShieldedPartsCylinder(Part basePart, List <Part> shieldedParts, float topY, float bottomY, float topRadius, float bottomRadius)
        {
            float height        = topY - bottomY;
            float largestRadius = topRadius > bottomRadius ? topRadius : bottomRadius;

            Vector3 lookupCenterLocal  = new Vector3(0, bottomY + (height * 0.5f), 0);
            Vector3 lookupTopLocal     = new Vector3(0, topY, 0);
            Vector3 lookupBottomLocal  = new Vector3(0, bottomY, 0);
            Vector3 lookupCenterGlobal = basePart.transform.TransformPoint(lookupCenterLocal);

            Ray lookupRay = new Ray(lookupBottomLocal, new Vector3(0, 1, 0));

            List <Part> partsFound = new List <Part>();

            //do a basic sphere check vs the maximal size of the cylinder
            Collider[] foundColliders = Physics.OverlapSphere(lookupCenterGlobal, height * 1.5f, 1);
            foreach (Collider col in foundColliders)
            {
                Part pt = col.gameObject.GetComponentUpwards <Part>();
                if (pt != null && pt != basePart && pt.vessel == basePart.vessel && !partsFound.Contains(pt))
                {
                    partsFound.Add(pt);
                }
            }

            Vector3 otherPartCenterLocal;

            float partYPos;
            float partYPercent;
            float partYRadius;
            float radiusOffset = topRadius - bottomRadius;

            foreach (Part pt in partsFound)
            {
                Vector3 otherPartCenter = pt.partTransform.TransformPoint(PartGeometryUtil.FindBoundsCentroid(pt.GetRendererBounds(), pt.transform));
                //check part bounds center point against conic projection of the fairing
                otherPartCenterLocal = basePart.transform.InverseTransformPoint(otherPartCenter);

                //check vs top and bottom of the shielded area
                if (otherPartCenterLocal.y > lookupTopLocal.y || otherPartCenterLocal.y < lookupBottomLocal.y)
                {
                    continue;
                }

                //quick check vs cylinder radius
                float distFromLine = ROTUtils.distanceFromLine(lookupRay, otherPartCenterLocal);
                if (distFromLine > largestRadius)
                {
                    continue;
                }

                //more precise check vs radius of the cone at that Y position
                partYPos     = otherPartCenterLocal.y - lookupBottomLocal.y;
                partYPercent = partYPos / height;
                partYRadius  = partYPercent * radiusOffset;
                if (distFromLine > (partYRadius + bottomRadius))
                {
                    continue;
                }
                shieldedParts.Add(pt);
                //print("Shielding part: " + pt);
            }
        }
Esempio n. 17
0
        //creates/recreates FairingData instances from data from config node and any persistent node (if applicable)
        private void loadFairingData(ConfigNode node)
        {
            recolorHandler = new RecoloringHandler(Fields[nameof(customColorData)]);

            ConfigNode[] fairingNodes = node.GetNodes("FAIRING");
            fairingParts = new ROTNodeFairingData[fairingNodes.Length];

            Transform modelBase = part.transform.FindRecursive("model");
            Transform parent;

            ModuleROTNodeFairing[] cs = part.GetComponents <ModuleROTNodeFairing>();
            int l           = Array.IndexOf(cs, this);
            int moduleIndex = l;

            for (int i = 0; i < fairingNodes.Length; i++)
            {
                parent          = modelBase.FindOrCreate(fairingName + "-" + moduleIndex + "-" + i);
                fairingParts[i] = new ROTNodeFairingData();
                fairingParts[i].load(fairingNodes[i], parent.gameObject);
                if (fairingParts[i].canAdjustTop)
                {
                    enableTopDiameterControls = true;
                    if (guiTopDiameter < 0)
                    {
                        guiTopDiameter = fairingParts[i].topRadius * 2f;
                    }
                    else
                    {
                        fairingParts[i].topRadius = guiTopDiameter * 0.5f;
                    }
                }
                if (fairingParts[i].canAdjustBottom)
                {
                    enableBottomDiameterControls = true;
                    if (guiBottomDiameter < 0)
                    {
                        guiBottomDiameter = fairingParts[i].bottomRadius * 2f;
                    }
                    else
                    {
                        fairingParts[i].bottomRadius = guiBottomDiameter * 0.5f;
                    }
                }
            }
            //reload fairing data from persistence;
            //it -should- already match the guiTopDiameter/guiBottomDiameter (or else was already corrupted/invalid when saved out).
            if (!String.IsNullOrEmpty(persistentDataString))
            {
                String[] datas  = ROTUtils.parseCSV(persistentDataString, ":");
                int      length = datas.Length;
                for (int i = 0; i < length; i++)
                {
                    fairingParts[i].loadPersistence(datas[i]);
                }
            }
            string[]   names  = node.GetStringValues("textureSet");
            string[]   titles = ROTUtils.getNames(TexturesUnlimitedLoader.getTextureSets(names), m => m.title);
            TextureSet t      = TexturesUnlimitedLoader.getTextureSet(currentTextureSet);

            if (t == null)
            {
                currentTextureSet = names[0];
                t = TexturesUnlimitedLoader.getTextureSet(currentTextureSet);
                initializedColors = false;
            }
            if (!initializedColors)
            {
                initializedColors = true;
                recolorHandler.setColorData(t.maskColors);
            }
            this.updateUIChooseOptionControl(nameof(currentTextureSet), names, titles, true, currentTextureSet);
        }
Esempio n. 18
0
 public string[] getLayoutTitles()
 {
     return(ROTUtils.getNames(layouts, m => m.title));
 }