Beispiel #1
0
        public static Vector3 GetSize(Vessel v)
        {
            Bounds  bounds = default(Bounds);
            Vector3 orgPos = v.parts[0].orgPos;

            bounds.center = orgPos;
            List <Bounds> list = new List <Bounds>();

            foreach (Part current in v.parts)
            {
                MPLog.Writelog("[Maritime Pack] part: " + current.name + " WCoM" + current.WCoM);
                MPLog.Writelog("[Maritime Pack] part: " + current.name + " CoB" + current.CenterOfBuoyancy);
                MPLog.Writelog("[Maritime Pack] part: " + current.name + " CoD" + current.CenterOfDisplacement);

                Bounds[] partRendererBounds = PartGeometryUtil.GetPartRendererBounds(current);
                Bounds[] array = partRendererBounds;
                for (int i = 0; i < array.Length; i++)
                {
                    Bounds bounds2 = array[i];
                    Bounds bounds3 = bounds2;
                    bounds3.size *= current.boundsMultiplier;
                    Vector3 size = bounds3.size;
                    bounds3.Expand(current.GetModuleSize(size));
                    list.Add(bounds2);
                }
            }
            return(PartGeometryUtil.MergeBounds(list.ToArray(), v.parts[0].transform.root).size);
        }
Beispiel #2
0
        private static float EstimatePartVolume(Part part)
        {
            var boundsSize = PartGeometryUtil.MergeBounds(part.GetRendererBounds(), part.transform).size;
            var volume     = boundsSize.x * boundsSize.y * boundsSize.z * 1000f;

            return(volume);
        }
Beispiel #3
0
        public static float GetPartVolume(Part partPrefab)
        {
            Bounds[] rendererBounds = PartGeometryUtil.GetRendererBounds(partPrefab);
            Vector3  boundsSize     = PartGeometryUtil.MergeBounds(rendererBounds, partPrefab.transform).size;
            float    volume         = boundsSize.x * boundsSize.y * boundsSize.z;

            return(volume * 1000);
        }
Beispiel #4
0
        public static float GetArea(this Part part)
        {
            var   boundsSize  = PartGeometryUtil.MergeBounds(part.GetRendererBounds(), part.transform).size;
            float sfcAreaCalc = 2f * (boundsSize.x * boundsSize.y) + 2f * (boundsSize.y * boundsSize.z) + 2f * (boundsSize.x * boundsSize.z);

            //Debug.Log("[BDArmory]: Surface Area1: " + part.surfaceAreas.magnitude);
            //Debug.Log("[BDArmory]: Surface Area2: " + sfcAreaCalc);

            return(sfcAreaCalc);
        }
Beispiel #5
0
        public static float GetVolume(Vessel v)
        {
            float volume = 0.0f;

            foreach (Part mypart in v.parts)
            {
                var boundsSize = PartGeometryUtil.MergeBounds(mypart.GetRendererBounds(), mypart.transform).size;
                volume = boundsSize.x * boundsSize.y * boundsSize.z * 1000f;
            }
            return(volume);
        }
Beispiel #6
0
        //This will provide a list of lines that make up the part's geometry, oriented so that they are in part-oriented space
        private static List <Line> GenerateLinesFromPart(Part p)
        {
            Transform partTransform = p.transform;
            Bounds    colliderBounds, meshBounds;

            colliderBounds = PartGeometryUtil.MergeBounds(p.GetColliderBounds(), partTransform);
            meshBounds     = PartGeometryUtil.MergeBounds(p.GetRendererBounds(), partTransform);

            List <Vector3> vertexList;
            List <int>     triangleIndices;

            //If the mesh shape is much larger than the colliders, then unfortunately, we have to use the raw mesh
            //Otherwise, use the collider because it has fewer verts and tris to work with
            //if (UseMeshBounds(colliderBounds, meshBounds, 0.05f))
            //{
            Transform[] meshTransforms = FARGeoUtil.PartModelTransformArray(p);
            Mesh[]      meshes         = new Mesh[meshTransforms.Length];

            for (int i = 0; i < meshTransforms.Length; i++)
            {
                MeshFilter mf = meshTransforms[i].GetComponent <MeshFilter>();
                if (mf == null)
                {
                    continue;
                }
                meshes[i] = mf.sharedMesh;
            }
            vertexList      = GetVertexList(meshes, meshTransforms, partTransform);
            triangleIndices = GetTriangleVerts(meshes);

            /*}
             * else
             * {
             *  MeshCollider[] meshColliders = p.GetComponents<MeshCollider>();
             *  Transform[] meshTransforms = new Transform[meshColliders.Length];
             *  Mesh[] meshes = new Mesh[meshColliders.Length];
             *
             *  for (int i = 0; i < meshColliders.Length; i++)
             *  {
             *      MeshCollider mc = meshColliders[i];
             *      meshTransforms[i] = mc.transform;
             *      meshes[i] = mc.sharedMesh;
             *  }
             *  vertexList = GetVertexList(meshes, meshTransforms, partTransform);
             *  triangleIndices = GetTriangleVerts(meshes);
             * }*/

            return(GenerateLinesFromVertsAndTris(vertexList, triangleIndices));
        }
Beispiel #7
0
        /// <summary>Returns part's volume basing on its geometrics.</summary>
        /// <remarks>Geometry of a part depends on the state (e.g. solar panel can be deployed and take
        /// more space). It's not possible (nor practical) for KIS to figure out which state of the part
        /// is the most compact one. So, when calculating part's volume the initial state of the mesh
        /// renderers in the prefab is considered the right ones. If parts's initial state is deployed
        /// (e.g. Drill-O-Matic) then it will take more space than it could have.</remarks>
        /// <param name="partInfo">A part to get volume for.</param>
        /// <returns>Volume in liters.</returns>
        public static float GetPartVolume(AvailablePart partInfo)
        {
            var   p = partInfo.partPrefab;
            float volume;

            // If there is a KIS item volume then use it but still apply scale tweaks.
            var kisItem = p.GetComponent <ModuleKISItem>();

            if (kisItem && kisItem.volumeOverride > 0)
            {
                volume = kisItem.volumeOverride;
            }
            else
            {
                var boundsSize = PartGeometryUtil.MergeBounds(p.GetRendererBounds(), p.transform).size;
                volume = boundsSize.x * boundsSize.y * boundsSize.z * 1000f;
            }

            // Apply cube of the scale modifier since volume involves all 3 axis.
            return((float)(volume * Math.Pow(GetPartExternalScaleModifier(partInfo), 3)));
        }
Beispiel #8
0
 public static Vector3 GetBoundsSize(Part part)
 {
     return(PartGeometryUtil.MergeBounds(part.GetRendererBounds(), part.transform).size);
 }
        void GetPartData(AvailablePart part)
        {
            bool    started = false;
            Vector3 pg      = new Vector3();

            StartLine(part.name);
            started = true;
            if (partAttrs[(int)PartAttrEnum.DimensionsInfo - 1] != null && partAttrs[(int)PartAttrEnum.DimensionsInfo - 1].enabled)
            {
                //
                // Now get the part dimensions: x,y,z
                //
                List <Bounds> list = new List <Bounds>();
                if (!(part.partPrefab.Modules.GetModule <LaunchClamp>(0) != null))
                {
                    Bounds[] partRendererBounds = PartGeometryUtil.GetPartRendererBounds(part.partPrefab);
                    int      num = partRendererBounds.Length;
                    for (int j = 0; j < num; j++)
                    {
                        Bounds bounds2 = partRendererBounds[j];
                        Bounds bounds3 = bounds2;
                        bounds3.size *= part.partPrefab.boundsMultiplier;
                        Vector3 size = bounds3.size;
                        bounds3.Expand(part.partPrefab.GetModuleSize(size, ModifierStagingSituation.CURRENT));
                        list.Add(bounds2);
                    }
                }

                pg = PartGeometryUtil.MergeBounds(list.ToArray(), part.partPrefab.transform.root).size;
#if false
                if (!started)
                {
                    StartLine(pg.x.ToString("F3"));
                }
                else
                {
                    AppendLine(pg.x.ToString("F3"));
                }
                AppendLine(pg.y.ToString("F3"));
                AppendLine(pg.z.ToString("F3"));
                started = true;
#endif
#if false
                string resources = "";
                foreach (AvailablePart.ResourceInfo r in part.resourceInfos)
                {
                    if (r.resourceName != "ElectricCharge" && r.resourceName != "Ablator")
                    {
                        resources += r.resourceName + ",";
                    }
                }
                if (resources != "")
                {
                    Log.Info("part: " + part.name + ", part.title: " + part.title + ", descr: " + part.description.Replace(",", ".") +
                             ", mass: " + part.partPrefab.mass + ", techRequired: " + part.TechRequired +
                             ", height x,y,z: " + pg.x.ToString() + ", " + pg.y.ToString() + ", " + pg.z.ToString() + "," + resources);
                }
#endif
            }

            DataDump.activeMod = "PART";
            var    a       = part.GetType();
            bool   b       = false;
            Module partmod = new Module("PART", "PART", a);
            // ConfigNode partNode = part.partConfig.GetNode("PART");
            //Log.Info("partConfig: " + part.partConfig);
            if (ActiveLists.activePropertyList.TryGetValue(Property.GetKey(partmod.modName, partmod.moduleName), out Property p))
            {
                foreach (FldInfo s in p.fields) //FromReflection)
                {
                    if (!b)
                    {
                        //string value = part.partConfig.GetValue(s.Name);


                        b = true;
                        for (var partAttr = PartAttrEnum.first + 1; partAttr < PartAttrEnum.last; partAttr++)
                        {
                            if (DataDump.partAttrs[(int)partAttr - 1] != null && DataDump.partAttrs[(int)partAttr - 1].enabled)
                            {
                                switch (partAttr)
                                {
                                case PartAttrEnum.DimensionsInfo:
                                    AppendLine(pg.x.ToString("F3"));
                                    AppendLine(pg.y.ToString("F3"));
                                    AppendLine(pg.z.ToString("F3"));
                                    break;

                                case PartAttrEnum.Resources:
                                    var nodes = part.partConfig.GetNodes("RESOURCE").ToList().OrderBy(r => r.GetValue("name"));
                                    int cnt   = 0;
                                    foreach (var n in nodes)
                                    {
                                        string name      = n.GetValue("name");
                                        string maxAmount = n.GetValue("maxAmount");

                                        if (cnt < maxResources)
                                        {
                                            AppendLine(name + ":" + maxAmount);
                                        }
                                        cnt++;
                                        if (cnt >= maxResources)
                                        {
                                            break;
                                        }
                                    }
                                    break;

                                case PartAttrEnum.TechRequired:
                                    AppendLine(part.TechRequired);
                                    break;

                                case PartAttrEnum.entryCost:
                                    AppendLine(part.entryCost);
                                    break;

                                case PartAttrEnum.cost:
                                    AppendLine(part.cost);
                                    break;

                                case PartAttrEnum.category:
                                    AppendLine(part.category.ToString());
                                    break;

                                default:
                                    string str = "n/a";
                                    str = "";

                                    if (!part.partConfig.TryGetValue(partAttr.ToString(), ref str))
                                    {
                                        if (useDefaultValues)
                                        {
                                            Part p1 = new Part();

                                            switch (partAttr)
                                            {
                                            case PartAttrEnum.breakingForce:
                                                str = p1.breakingForce.ToString();
                                                break;

                                            case PartAttrEnum.breakingtorque:
                                                str = p1.breakingTorque.ToString();
                                                break;

                                            case PartAttrEnum.minimum_drag:
                                                str = p1.minimum_drag.ToString();
                                                break;

                                            case PartAttrEnum.maximum_drag:
                                                str = p1.maximum_drag.ToString();
                                                break;

                                            case PartAttrEnum.angularDrag:
                                                str = p1.angularDrag.ToString();
                                                break;

                                            case PartAttrEnum.crashTolerance:
                                                str = p1.crashTolerance.ToString();
                                                break;

                                            case PartAttrEnum.maxTemp:
                                                str = p1.maxTemp.ToString();
                                                break;

                                            case PartAttrEnum.mass:
                                                AppendLine("Default: " + p1.mass);
                                                break;
                                            }
                                        }
                                        else
                                        {
                                            Log.Error("data not found");
                                        }
                                    }

                                    //str = part.partConfig.GetValue(partAttr.ToString());

                                    AppendLine(str);

                                    break;
                                }
                            }
                        }
                    }

                    Field field = new Field(partmod.modName, partmod.moduleName, s.Name);
                    if (s.Name == "entryCost")
                    {
                        s.Name = "_entryCost";
                    }
                    if (ActiveLists.activeFieldsList.TryGetValue(field.ActiveKey, out field))
                    {
                        if (field != null && field.enabled)
                        {
                            string value = part.partConfig.GetValue(s.Name);
                            if (value == null || value == "")
                            {
                                Type fieldsType = typeof(AvailablePart);
                                // Get an array of FieldInfo objects.
                                FieldInfo[] fields = fieldsType.GetFields(BindingFlags.FlattenHierarchy |
                                                                          BindingFlags.Instance |
                                                                          BindingFlags.Public | BindingFlags.NonPublic |
                                                                          BindingFlags.Static);
                                foreach (var f in fields)
                                {
                                    string v = "";


                                    var    fieldtype = s.FieldType.ToString();
                                    string t         = "System.Collections.Generic";
                                    if (fieldtype.StartsWith(t))
                                    {
                                        fieldtype = fieldtype.Substring(t.Length + 1);
                                    }


                                    if (f.Name == s.Name)
                                    {
                                        switch (fieldtype)
                                        {
                                        case "System.Single":
                                            v     = "float";
                                            value = ((float)f.GetValue(part)).ToString();
                                            break;

                                        case "System.Double":
                                            v     = "double";
                                            value = ((double)f.GetValue(part)).ToString();
                                            break;

                                        case "System.Int32":
                                            v     = "int";
                                            value = ((int)f.GetValue(part)).ToString();
                                            break;

                                        case "System.UInt32":
                                            v     = "uint";
                                            value = ((uint)f.GetValue(part)).ToString();
                                            break;

                                        case "System.String":
                                            v     = "string";
                                            value = (string)f.GetValue(part);
                                            if (s.Name == "description")
                                            {
                                                value = StripHtml(value);
                                                if (value.Length > maxLen && s.Name == "description")
                                                {
                                                    value = value.Substring(0, maxLen);
                                                }
                                                value = value.Replace("\n", " ").Replace("\r", " ");
                                            }
                                            break;

                                        case "System.Boolean":
                                            v     = "boolean";
                                            value = ((bool)f.GetValue(part)).ToString();
                                            break;

                                        case "UnityEngine.Vector3":
                                            v     = "Vector3";
                                            value = ((Vector3)f.GetValue(part)).ToString();
                                            break;
                                        }
                                        break;
                                    }
                                    Log.Info("v: " + v);
                                }
                            }
                            if (!started)
                            {
                            }
                            else
                            {
                                AppendLine(value);
                            }
                        }
                    }
                    else
                    {
#if false
                        if (field == null)
                        {
                            Log.Error("GetPartData, field is null");
                        }
                        else if (field.ActiveKey == null)
                        {
                            Log.Error("GetPartData, field.ActiveKey is null");
                        }
                        else
                        {
                            Log.Error("GetPartData, not found: " + field.ActiveKey);
                        }
#endif
                    }
                }
            }
        }
Beispiel #10
0
        public static float GetVolume(this Part part)
        {
            var boundsSize = PartGeometryUtil.MergeBounds(part.GetRendererBounds(), part.transform).size;

            return(boundsSize.x * boundsSize.y * boundsSize.z);
        }
Beispiel #11
0
        public static float GetAverageBoundSize(this Part part)
        {
            var boundsSize = PartGeometryUtil.MergeBounds(part.GetRendererBounds(), part.transform).size;

            return((boundsSize.x + boundsSize.y + boundsSize.z) / 3f);
        }
Beispiel #12
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 = SSTUUtils.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);
            }
        }
        void enableShielding()
        {
            disableShielding();

            var attached = getFairingParams();

            if (!sideFairing)
            {
                return;
            }

            //  Get all parts in range.

            var parts = new List <Part>();

            var colliders = Physics.OverlapSphere(part.transform.TransformPoint(lookupCenter), lookupRad, 1);

            for (int i = colliders.Length - 1; i >= 0; --i)
            {
                var p = colliders [i].gameObject.GetComponentUpwards <Part>();

                if (p != null)
                {
                    parts.AddUnique(p);
                }
            }

            //  Filter parts.

            float sizeSqr       = lookupRad * lookupRad * 4;
            float boundCylRadSq = boundCylRad * boundCylRad;

            bool isInline  = (sideFairing.inlineHeight > 0);
            bool topClosed = false;

            Matrix4x4 w2l = Matrix4x4.identity, w2lb = Matrix4x4.identity;

            Bounds topBounds = default(Bounds);

            if (isInline)
            {
                w2l  = part.transform.worldToLocalMatrix;
                w2lb = w2l;

                for (int i = 0; i < 3; ++i)
                {
                    for (int j = 0; j < 3; ++j)
                    {
                        w2lb [i, j] = Mathf.Abs(w2lb [i, j]);
                    }
                }

                topBounds = new Bounds(new Vector3(0, boundCylY1, 0), new Vector3(sideFairing.topRad * 2, sideFairing.sideThickness, sideFairing.topRad * 2));
            }

            for (int pi = 0; pi < parts.Count; ++pi)
            {
                var pt = parts [pi];

                //  Check special cases.

                if (pt == part)
                {
                    shieldedParts.Add(pt);

                    continue;
                }

                bool isSide = false;

                for (int i = 0; i < attached.Length; ++i)
                {
                    if (attached [i].attachedPart == pt)
                    {
                        isSide = true;

                        break;
                    }
                }

                if (isSide)
                {
                    continue;
                }

                //  Check if the top is closed in the inline case.

                var bounds = pt.GetRendererBounds();

                var box = PartGeometryUtil.MergeBounds(bounds, pt.transform);

                if (isInline && !topClosed && pt.vessel == vessel)
                {
                    var wb = box; wb.Expand(sideFairing.sideThickness * 4);

                    var b = new Bounds(w2l.MultiplyPoint3x4(wb.center), w2lb.MultiplyVector(wb.size));

                    if (b.Contains(topBounds.min) && b.Contains(topBounds.max))
                    {
                        topClosed = true;
                    }
                }

                //  Check if the centroid is within the fairing bounds.

                var c = part.transform.InverseTransformPoint(PartGeometryUtil.FindBoundsCentroid(bounds, null));

                float y = c.y;

                if (y < boundCylY0 || y > boundCylY1)
                {
                    continue;
                }

                float xsq = new Vector2(c.x, c.z).sqrMagnitude;

                if (xsq > boundCylRadSq)
                {
                    continue;
                }

                //  Accurate centroid check.

                float x = Mathf.Sqrt(xsq);

                bool inside = false;

                for (int i = 1; i < shape.Length; ++i)
                {
                    var p0 = shape [i - 1];
                    var p1 = shape [i];

                    if (p0.y > p1.y)
                    {
                        var p = p0;

                        p0 = p1;
                        p1 = p;
                    }

                    if (y < p0.y || y > p1.y)
                    {
                        continue;
                    }

                    float dy = p1.y - p0.y, r;

                    if (dy <= 1e-6f)
                    {
                        r = (p0.x + p1.x) * 0.5f;
                    }
                    else
                    {
                        r = (p1.x - p0.x) * (y - p0.y) / dy + p0.x;
                    }

                    if (x > r)
                    {
                        continue;
                    }

                    inside = true;

                    break;
                }

                if (!inside)
                {
                    continue;
                }

                shieldedParts.Add(pt);
            }

            if (isInline && !topClosed)
            {
                disableShielding();

                return;
            }

            //  Add shielding.

            for (int i = 0; i < shieldedParts.Count; ++i)
            {
                shieldedParts [i].AddShield(this);
            }

            numShieldedDisplay = shieldedParts.Count;

            var fbase = part.GetComponent <ProceduralFairingBase>();

            if (fbase != null)
            {
                fbase.onShieldingEnabled(shieldedParts);
            }
        }
Beispiel #14
0
        public void Start()
        {
            Settings.LoadConfig();
            if (CheckForKIFA())
            {
                return;
            }
            Start2();
            Stopwatch stopwatch = new Stopwatch();

            stopwatch.Start();
            List <AvailablePart> loadedParts = PartLoader.LoadedPartsList; // PartLoader.Instance.loadedParts;

            StringBuilder stringBuilder;

            bool fileExists = File.Exists(VOL_CFG_FILE);

            Log.Info("Finding Parts Volume....");
            using (List <AvailablePart> .Enumerator partEnumerator = loadedParts.GetEnumerator())
            {
                while (partEnumerator.MoveNext())
                {
                    AvailablePart current = partEnumerator.Current;

                    string[] urlParts = current.partUrl.Split('/');
                    string   urlName  = urlParts[urlParts.Length - 1];

                    //
                    // urlName more precisely correspond to part name in the config than current.name,
                    // but KerbalEVA and flag have empty urlname and need to be filtered, so:
                    //

                    string partName = urlParts[urlParts.Length - 1];
                    if (partName == "")
                    {
                        partName = current.name;
                    }

                    if (partBlacklist.Contains(partName) ||
                        Regex.IsMatch(partName, blacklistRegexPattern))
                    {
                        Log.Info(String.Format("partName: {0, -40} found in the blacklist and ignored.", partName + ","));
                        continue;
                    }

                    bool contains_ModuleCargoPart     = false;
                    bool contains_ModuleInventoryPart = false;
                    bool contains_KSPPartVolumeModule = false;

                    bool containsCrew        = false;
                    bool isTank              = false;
                    bool isTankNotIgnoreable = false;
                    bool sizeTooBig          = false;
                    bool isStock             = false;

                    bool       isRcsPart        = false;
                    bool       isEnginePart     = false;
                    ConfigNode currentCargoPart = null;



                    if (!Settings.doStock)
                    {
                        if (urlParts[0] == "Squad" || urlParts[0] == "SquadExpansion")
                        {
                            if (!partWhitelist.Contains(partName))
                            {
                                isStock = true;
                            }
                        }
                    }
                    var moduleNodes = current.partConfig.GetNodes("MODULE");
                    for (int i = 0; i < moduleNodes.Length; i++)
                    {
                        var name = moduleNodes[i].GetValue("name");

                        if (name == "ModuleCargoPart")
                        {
                            contains_ModuleCargoPart = true;
                            currentCargoPart         = moduleNodes[i];
                        }
                        if (name == "ModuleInventoryPart")
                        {
                            contains_ModuleInventoryPart = true;
                        }
                        if (name == "KSPPartVolumeModule")
                        {
                            contains_KSPPartVolumeModule = true;
                        }
                        if (name == "ModuleRCS" || name == "ModuleRCSFX")
                        {
                            isRcsPart = true;
                        }
                        if (name == "ModuleEngines" || name == "ModuleEnginesFX")
                        {
                            isEnginePart = true;
                        }

                        //  Check for manned
                        if (!Settings.manned)
                        {
                            int CrewCapacity = 0;
                            if (current.partConfig.TryGetValue("CrewCapacity", ref CrewCapacity))
                            {
                                if (CrewCapacity > 0)
                                {
                                    containsCrew = true;
                                }
                            }
                        }
                    }
                    if (contains_KSPPartVolumeModule)
                    {
                        contains_ModuleCargoPart = false;
                    }
                    var   resNodes = current.partConfig.GetNodes("RESOURCE");
                    float mass     = 0;
                    current.partConfig.TryGetValue("mass", ref mass);
                    float totalResMass = 0;

                    //if (!Settings.doTanks)
                    {
                        foreach (var resNode in resNodes)
                        {
                            var name = resNode.GetValue("name");

                            if (resourceBlackList.Contains(name))
                            {
                                continue;
                            }

                            float maxAmount = 0;
                            resNode.TryGetValue("maxAmount", ref maxAmount);
                            var definition = PartResourceLibrary.Instance.GetDefinition(name);
                            if (definition != null)
                            {
                                var   density = definition.density;
                                float resMass = maxAmount * density;
                                totalResMass += resMass;
                            }
                        }

                        if (totalResMass > mass)
                        {
                            isTankNotIgnoreable = true;
                            isTank = !Settings.doTanks;
                        }
                    }
                    stringBuilder = new StringBuilder();

                    Bounds bounds = default(Bounds);
                    foreach (Bounds rendererBound in PartGeometryUtil.GetRendererBounds((Part)current.partPrefab))
                    {
                        bounds.Encapsulate(rendererBound);
                    }

#if false
                    Bounds colliderBounds = default(Bounds);
                    foreach (Bounds rendererBound in PartGeometryUtil.GetPartColliderBounds((Part)current.partPrefab))
                    {
                        colliderBounds.Encapsulate(rendererBound);
                    }

                    Bounds allBounds = default(Bounds);
                    var    a         = PartGeometryUtil.GetPartColliderBounds(current.partPrefab);
                    allBounds = PartGeometryUtil.MergeBounds(a, current.iconPrefab.transform.root);
#endif

                    float vol = (float)(bounds.size.x * bounds.size.y * bounds.size.z) * 1000f;

                    if (vol > Settings.largestAllowablePart && Settings.limitSize)
                    {
                        sizeTooBig = true;
                    }

                    var maxLen  = Math.Max(bounds.size.x, Math.Max(bounds.size.y, bounds.size.z));
                    var minLen  = Math.Min(bounds.size.x, Math.Min(bounds.size.y, bounds.size.z));
                    var tankVol = Math.Pow(minLen * 0.5, 2) * maxLen * Math.PI * 1000;

                    var adjVol = AdjustedVolume(current, vol, isEnginePart, isRcsPart, out float adj);

                    int stackableQuantity = Math.Min((int)Settings.maxCommonStackVolume / (int)adjVol, Settings.maxPartsInStack);

                    bool   isManipulableOnly            = false;
                    bool   isKSP_PartVolumeModule       = false;
                    string currentCargoPartPackedVolume = "";

                    if (currentCargoPart != null)
                    {
                        Log.Info("currentCargoPart: " + current.name);
                        if (currentCargoPart.HasValue("packedVolume"))
                        {
                            currentCargoPartPackedVolume = currentCargoPart.GetValue("packedVolume");
                            currentCargoPart.SetValue("packedVolume", adjVol.ToString("F0"));

                            Log.Info(String.Format("partName: {0, -40} packedVolume: {1,7}, calcPackedVolume: {2,7:F0}",
                                                   partName + ",", currentCargoPartPackedVolume, adjVol));

                            var v = float.Parse(currentCargoPartPackedVolume);
                            if (v <= 0)
                            {
                                isManipulableOnly = true;
                            }

                            isKSP_PartVolumeModule = currentCargoPart.HasValue("KSP_PartVolume");
                        }
                        else
                        {
                            Log.Error(String.Format("partName: {0, -40} packedVolume not found", partName + ","));
                        }
                    }
                    if (contains_ModuleInventoryPart)
                    {
                        adjVol = -1;
                    }

                    StringBuilder tmp = new StringBuilder();
                    tmp.AppendLine("// " + current.partUrl);

                    tmp.AppendLine("// Dimensions: x: " + bounds.size.x.ToString("F2") + ", y: " + bounds.size.y.ToString("F2") + ", z: " + bounds.size.z.ToString("F2"));

                    tmp.AppendLine(string.Format("// Bounding Box Size: {0} liters", vol));
                    tmp.AppendLine("// Volume adjustment: " + (adj * 100).ToString("F0") + "%");
                    if (isRcsPart)
                    {
                        tmp.AppendLine("// RCS module detected");
                    }
                    if (isEnginePart)
                    {
                        tmp.AppendLine("// Engine module detected");
                    }
                    Part part = UnityEngine.Object.Instantiate(current.partPrefab);
                    part.gameObject.SetActive(value: false);

                    if (isTankNotIgnoreable)
                    {
                        var volume = DetermineVolume(part) * 1000;
                        stringBuilder.AppendLine("//      Calculated tank volume: " + volume.ToString("F1"));
                        stringBuilder.AppendLine("//      Calculated tankVol (max x min) volume: " + tankVol.ToString("F1"));
                    }

                    tmp.AppendLine("//");

                    if (!containsCrew && !isTank && !sizeTooBig && !isStock && !contains_ModuleInventoryPart &&
                        (!contains_ModuleCargoPart ||
                         (contains_ModuleCargoPart && Settings.processManipulableOnly && isManipulableOnly) ||
                         (!isKSP_PartVolumeModule && partWhitelist.Contains(partName))
                        ))
                    {
                        stringBuilder.Append(tmp);
                        string adjName = partName.Replace(' ', '?').Replace('(', '?').Replace(')', '?');
                        if (contains_ModuleCargoPart)
                        {
                            stringBuilder.AppendLine("@PART[" + adjName + "]:HAS[@MODULE[ModuleCargoPart]]:Final");
                            stringBuilder.AppendLine("{");
                            stringBuilder.AppendLine("    @MODULE[ModuleCargoPart]");
                            stringBuilder.AppendLine("    {");
                            stringBuilder.AppendLine("        %packedVolume = " + adjVol.ToString("F0"));
                        }
                        else
                        {
                            stringBuilder.AppendLine("@PART[" + adjName + "]:HAS[!MODULE[ModuleCargoPart]]:Final");
                            stringBuilder.AppendLine("{");
                            stringBuilder.AppendLine("    MODULE");
                            stringBuilder.AppendLine("    {");
                            stringBuilder.AppendLine("        name = ModuleCargoPart");
                            stringBuilder.AppendLine("        packedVolume = " + adjVol.ToString("F0"));
                        }


                        if (Settings.stackParts && stackableQuantity > 1)
                        {
                            stringBuilder.AppendLine("        %stackableQuantity = " + stackableQuantity);
                        }

                        {
                            stringBuilder.AppendLine("        %KSP_PartVolume = true");
                            stringBuilder.AppendLine("    }");
                            stringBuilder.AppendLine("}");
                        }

                        RestartWindowVisible = true;
                        newPartsDetected     = true;
                        part = UnityEngine.Object.Instantiate(current.partPrefab);
                        part.gameObject.SetActive(value: false);
                        foreach (PartModule m in part.Modules)
                        {
                            if (m.moduleName == "ModuleCargoPart")
                            {
                                var mcp = m as ModuleCargoPart;
                                mcp.part         = part;
                                mcp.packedVolume = adjVol;

                                if (stackableQuantity > 1)
                                {
                                    mcp.stackableQuantity = stackableQuantity;
                                }

                                for (int i = current.moduleInfos.Count - 1; i >= 0; --i)
                                {
                                    AvailablePart.ModuleInfo info = current.moduleInfos[i];
                                    if (info.moduleName == Localizer.Format("#autoLOC_8002221")) // Cargo Part
                                    {
                                        try
                                        {
                                            info.info = mcp.GetInfo();
                                        }
                                        catch (Exception ex)
                                        {
                                            Log.Error("PartInfo.Start, Part: " + current.partUrl + ", Exception caught in ModuleCargoPart.GetInfo, exception: " + ex.Message + "\n" + ex.StackTrace);
                                            info.info = "KSP_PartVolume error";
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        if (!fileExists)
                        {
                            stringBuilder.Append(tmp);
                            stringBuilder.AppendLine("//   Bypass reasons:");
                            if (containsCrew)
                            {
                                stringBuilder.AppendLine("//      contains crew ");
                            }
                            if (isTank)
                            {
                                stringBuilder.AppendLine("//      is tank");
                            }
                            if (sizeTooBig)
                            {
                                stringBuilder.AppendLine("//      size exceeds largestAllowablePart: " + Settings.largestAllowablePart);
                            }
                            if (isStock)
                            {
                                stringBuilder.AppendLine("//      is stock");
                            }
                            if (contains_ModuleCargoPart && !Settings.processManipulableOnly ||
                                contains_ModuleCargoPart && !isManipulableOnly)
                            {
                                stringBuilder.AppendLine("//      contains ModuleCargoPart (packedVolume = " + currentCargoPartPackedVolume + ")");
                            }
                            if (contains_ModuleInventoryPart)
                            {
                                stringBuilder.AppendLine("//      contains ModuleInventoryPart");
                            }
                            stringBuilder.AppendLine("//");

                            adjVol = -999;
#if true
                            current.partConfig.RemoveNode(currentCargoPart);
                            //Part part = UnityEngine.Object.Instantiate(current.partPrefab);
                            //part.gameObject.SetActive(value: false);

                            Statics.Check4DelModCargoPart(part);
                            //Destroy(part);
#endif
                        }
                    }
                    Destroy(part);
                    if (!Statics.modifiedParts.ContainsKey(current.partUrl))
                    {
                        Statics.modifiedParts.Add(current.partUrl, new PartModification(stringBuilder, adjVol, adjVol == -999));
                    }
                    else
                    {
                        Log.Error("modifiedParts already contains: " + current.partUrl);
                    }
                    if (!fileExists)
                    {
                        stringBuilder.AppendLine("// ----------------------------------------------------------------------");
                    }
                }
            }


            stringBuilder = new StringBuilder();
            if (Statics.modifiedParts.Count > 0)
            {
                foreach (var d in Statics.modifiedParts)
                {
                    stringBuilder.Append(d.Value.cfg.ToString());
                }

                File.AppendAllText(VOL_CFG_FILE, stringBuilder.ToString());
            }

            stopwatch.Stop();
            Log.Info("File written to " + VOL_CFG_FILE);
            Log.Info(string.Format("Run in {0}ms", (object)stopwatch.ElapsedMilliseconds));
            //if (numCargoPartsAdded > 0)
            //    ShowWarning(numCargoPartsAdded);
        }
Beispiel #15
0
        public Dictionary <string, blackListPart> loadData(string fname)
        {
            Dictionary <string, blackListPart> blpList = new Dictionary <string, blackListPart>();

            List <AvailablePart> loadedParts = new List <AvailablePart>();

            if (PartLoader.Instance != null)
            {
                loadedParts.AddRange(PartLoader.LoadedPartsList);
            }

#if false
            // This code is used to export various information about parts and their resources
            // used to rebalance fuel tanks
            foreach (AvailablePart part in loadedParts)
            {
                List <Bounds> list = new List <Bounds>();
                if (!(part.partPrefab.Modules.GetModule <LaunchClamp>(0) != null))
                {
                    Bounds[] partRendererBounds = PartGeometryUtil.GetPartRendererBounds(part.partPrefab);
                    int      num = partRendererBounds.Length;
                    for (int j = 0; j < num; j++)
                    {
                        Bounds bounds2 = partRendererBounds[j];
                        Bounds bounds3 = bounds2;
                        bounds3.size *= part.partPrefab.boundsMultiplier;
                        Vector3 size = bounds3.size;
                        bounds3.Expand(part.partPrefab.GetModuleSize(size, ModifierStagingSituation.CURRENT));
                        list.Add(bounds2);
                    }
                }

                var    pg        = PartGeometryUtil.MergeBounds(list.ToArray(), part.partPrefab.transform.root).size;
                string resources = "";
                foreach (AvailablePart.ResourceInfo r in part.resourceInfos)
                {
                    if (r.resourceName != "ElectricCharge" && r.resourceName != "Ablator")
                    {
                        resources += r.resourceName + ",";
                    }
                }
                if (resources != "")
                {
                    Log.Info("part: " + part.name + ", part.title: " + part.title + ", descr: " + part.description.Replace(",", ".") +
                             ", mass: " + part.partPrefab.mass + ", techRequired: " + part.TechRequired +
                             ", height x,y,z: " + pg.x.ToString() + ", " + pg.y.ToString() + ", " + pg.z.ToString() + "," + resources);
                }
            }
#endif
            Log.Info("loadData, fname: " + fname);
            if (fname != "" && File.Exists(fname))
            {
                using (StreamReader f = File.OpenText(fname))
                {
                    string l = "";
                    while ((l = f.ReadLine()) != null)
                    {
                        string[] s = l.Split(',');
                        if (s.Length >= 2)
                        {
                            blackListPart blp = new blackListPart();
                            blp.modName = s[0];
                            if (s[1] == "ALL")
                            {
                                blp.where = blackListType.ALL;
                            }
                            if (s[1] == "SPH")
                            {
                                blp.where = blackListType.SPH;
                            }
                            if (s[1] == "VAB")
                            {
                                blp.where = blackListType.VAB;
                            }

                            AvailablePart p = loadedParts.Find(part => part.name == blp.modName);
                            if (p != null)
                            {
                                blp.title = p.title;
                                Log.Info("Blacklist mod: " + blp.modName);
                                Log.Info("partTitle: " + blp.title);
                                blp.permapruned = false;

                                blpList.Add(blp.modName, blp);
                            }
                        }
                    }
                }
                return(blpList);
            }
            else
            {
                return(blpList);
            }
        }