Example #1
0
        public static void RecursiveFixAtmo(CelestialBody Planet, string SunName)
        {
            if (Planet.name != SunName)
            {
                //Scaledspace
                //Utils.FindScaled( input.celestialBody.name ).layer = 1024;
                //Stuff
                MaterialSetDirection msd = Utils.FindScaled(Planet.name).GetComponentInChildren <MaterialSetDirection>();
                if (msd != null)
                {
                    msd.target = GameObject.Find(SunName + "Sun").transform;
                }

                var atmo = Utils.FindScaled(Planet.name).transform.FindChild("Atmosphere");
                if (atmo != null)
                {
                    AtmosphereFromGround afg = atmo.GetComponent <AtmosphereFromGround>();
                    afg.sunLight = GameObject.Find(SunName + "Sun");
                }

                var atmoL = Utils.FindLocal(Planet.name).transform.FindChild("Atmosphere");
                if (atmoL != null)
                {
                    AtmosphereFromGround afgL = atmo.GetComponent <AtmosphereFromGround>();
                    afgL.sunLight = GameObject.Find(SunName + "Sun");
                }
            }
            foreach (CelestialBody child in Planet.orbitingBodies)
            {
                RecursiveFixAtmo(child, SunName);
            }
        }
Example #2
0
            // Parser apply event
            void IParserEventSubscriber.Apply(ConfigNode node)
            {
                // If we don't want an atmosphere, ignore this step
                if (!celestialBody.atmosphere || !addAFG)
                {
                    return;
                }

                // If we don't already have an atmospheric shell generated
                if (scaledVersion.GetComponentsInChildren <AtmosphereFromGround> (true).Length == 0)
                {
                    // Add the material light direction behavior
                    MaterialSetDirection materialLightDirection = scaledVersion.AddComponent <MaterialSetDirection>();
                    materialLightDirection.valueName = "_localLightDirection";

                    // Create the atmosphere shell game object
                    GameObject scaledAtmosphere = new GameObject("Atmosphere");
                    scaledAtmosphere.transform.parent = scaledVersion.transform;
                    scaledAtmosphere.layer            = Constants.GameLayers.ScaledSpaceAtmosphere;
                    MeshRenderer renderer = scaledAtmosphere.AddComponent <MeshRenderer>();
                    renderer.sharedMaterial = new MaterialWrapper.AtmosphereFromGround();
                    MeshFilter meshFilter = scaledAtmosphere.AddComponent <MeshFilter>();
                    meshFilter.sharedMesh = Templates.ReferenceGeosphere;
                    scaledAtmosphere.AddComponent <AtmosphereFromGround>();

                    // Store the AFG
                    atmosphereFromGround = new AtmosphereFromGroundLoader();

                    // Setup known defaults
                    celestialBody.atmospherePressureSeaLevel = 1.0f;
                }
            }
Example #3
0
        /// <summary>
        /// Creates a new AtmosphereFromGround Loader from the Injector context.
        /// </summary>
        public AtmosphereFromGroundLoader()
        {
            // Is this the parser context?
            if (generatedBody == null)
            {
                throw new InvalidOperationException("Must be executed in Injector context.");
            }

            // Store values
            Value = generatedBody.scaledVersion.GetComponentsInChildren <AtmosphereFromGround>(true)
                    ?.FirstOrDefault();

            if (Value == null)
            {
                // Add the material light direction behavior
                MaterialSetDirection materialLightDirection =
                    generatedBody.scaledVersion.AddComponent <MaterialSetDirection>();
                materialLightDirection.valueName = "_localLightDirection";

                // Create the atmosphere shell game object
                GameObject scaledAtmosphere = new GameObject("Atmosphere");
                scaledAtmosphere.transform.parent = generatedBody.scaledVersion.transform;
                scaledAtmosphere.layer            = GameLayers.SCALED_SPACE_ATMOSPHERE;
                MeshRenderer renderer = scaledAtmosphere.AddComponent <MeshRenderer>();
                renderer.sharedMaterial = new Components.MaterialWrapper.AtmosphereFromGround();
                MeshFilter meshFilter = scaledAtmosphere.AddComponent <MeshFilter>();
                meshFilter.sharedMesh = Templates.ReferenceGeosphere;
                Value = scaledAtmosphere.AddComponent <AtmosphereFromGround>();
            }

            Value.planet = generatedBody.celestialBody;
        }
            public AtmosphereFromGroundLoader(CelestialBody body)
            {
                // Is this a spawned body?
                if (body?.scaledBody == null)
                {
                    throw new InvalidOperationException("The body must be already spawned by the PSystemManager.");
                }

                // Store values
                Value = body.afg;

                if (Value == null)
                {
                    // Add the material light direction behavior
                    MaterialSetDirection materialLightDirection = body.scaledBody.AddComponent <MaterialSetDirection>();
                    materialLightDirection.valueName = "_localLightDirection";

                    // Create the atmosphere shell game object
                    GameObject scaledAtmosphere = new GameObject("Atmosphere");
                    scaledAtmosphere.transform.parent = body.scaledBody.transform;
                    scaledAtmosphere.layer            = Constants.GameLayers.ScaledSpaceAtmosphere;
                    MeshRenderer renderer = scaledAtmosphere.AddComponent <MeshRenderer>();
                    renderer.sharedMaterial = new MaterialWrapper.AtmosphereFromGround();
                    MeshFilter meshFilter = scaledAtmosphere.AddComponent <MeshFilter>();
                    meshFilter.sharedMesh = Templates.ReferenceGeosphere;
                    Value = scaledAtmosphere.AddComponent <AtmosphereFromGround>();
                }
                Value.planet = body;
            }
Example #5
0
            // Post apply event
            void IParserEventSubscriber.PostApply(ConfigNode node)
            {
                // Should we remove the atmosphere
                if (body.celestialBody.atmosphere && removeAtmosphere.value)
                {
                    // Find atmosphere from ground and destroy the game object
                    AtmosphereFromGround atmosphere = body.scaledVersion.GetComponentsInChildren <AtmosphereFromGround>(true)[0];
                    atmosphere.transform.parent = null;
                    UnityEngine.Object.Destroy(atmosphere.gameObject);

                    // Destroy the light controller
                    MaterialSetDirection light = body.scaledVersion.GetComponentsInChildren <MaterialSetDirection>(true)[0];
                    UnityEngine.Object.Destroy(light);

                    // No more atmosphere :(
                    body.celestialBody.atmosphere = false;
                }

                // Should we remove the ocean?
                if (body.celestialBody.ocean && removeOcean.value)
                {
                    // Find atmosphere the ocean PQS
                    PQS ocean = body.pqsVersion.GetComponentsInChildren <PQS>(true).Where(pqs => pqs != body.pqsVersion).First();
                    PQSMod_CelestialBodyTransform cbt = body.pqsVersion.GetComponentsInChildren <PQSMod_CelestialBodyTransform>(true).First();

                    // Destroy the ocean PQS (this could be bad - destroying the secondary fades...)
                    cbt.planetFade.secondaryRenderers.Remove(ocean.gameObject);
                    cbt.secondaryFades     = null;
                    ocean.transform.parent = null;
                    UnityEngine.Object.Destroy(ocean);

                    // No more ocean :(
                    body.celestialBody.ocean = false;
                }

                // Figure out what kind of body we are
                if (body.scaledVersion.GetComponentsInChildren(typeof(ScaledSun), true).Length > 0)
                {
                    type = BodyType.Star;
                }
                else if (body.celestialBody.atmosphere)
                {
                    type = BodyType.Atmospheric;
                }
                else
                {
                    type = BodyType.Vacuum;
                }

                Debug.Log("[Kopernicus]: Configuration.Template: Using Template \"" + body.celestialBody.bodyName + "\"");
            }
Example #6
0
        public AtmosphereFromGroundLoader(CelestialBody body)
        {
            // Is this a spawned body?
            if (body.scaledBody == null)
            {
                throw new InvalidOperationException("The body must be already spawned by the PSystemManager.");
            }

            // Store values
            Value = body.afg;

            if (Value == null)
            {
                // Add the material light direction behavior
                MaterialSetDirection materialLightDirection = body.scaledBody.AddOrGetComponent <MaterialSetDirection>();
                materialLightDirection.valueName = "_localLightDirection";

                // Create the atmosphere shell game object
                GameObject scaledAtmosphere = new GameObject("Atmosphere");
                scaledAtmosphere.transform.parent = body.scaledBody.transform;
                scaledAtmosphere.layer            = GameLayers.SCALED_SPACE_ATMOSPHERE;
                MeshRenderer renderer = scaledAtmosphere.AddComponent <MeshRenderer>();
                renderer.sharedMaterial             = new Components.MaterialWrapper.AtmosphereFromGround();
                renderer.sharedMaterial.renderQueue = 3020;
                MeshFilter meshFilter = scaledAtmosphere.AddComponent <MeshFilter>();
                meshFilter.sharedMesh = Templates.ReferenceGeosphere;
                Value            = body.afg = scaledAtmosphere.AddComponent <AtmosphereFromGround>();
                Value.planet     = body;
                Value.sunLight   = Sun.Instance.gameObject;
                Value.mainCamera = ScaledCamera.Instance.transform;
                AtmosphereInfo.StoreAfg(Value);
                AtmosphereInfo.PatchAfg(Value);

                // Set defaults
                SetDefaultValues();
            }

            Value.planet = body;
        }
Example #7
0
            // Post apply event
            void IParserEventSubscriber.PostApply(ConfigNode node)
            {
                // Should we remove the atmosphere
                if (body.celestialBody.atmosphere && removeAtmosphere.Value)
                {
                    // Find atmosphere from ground and destroy the game object
                    AtmosphereFromGround atmosphere = body.scaledVersion.GetComponentsInChildren <AtmosphereFromGround>(true)[0];
                    atmosphere.transform.parent = null;
                    UnityEngine.Object.Destroy(atmosphere.gameObject);

                    // Destroy the light controller
                    MaterialSetDirection light = body.scaledVersion.GetComponentsInChildren <MaterialSetDirection>(true)[0];
                    UnityEngine.Object.Destroy(light);

                    // No more atmosphere :(
                    body.celestialBody.atmosphere = false;
                }

                // If we have a PQS
                if (body.pqsVersion != null)
                {
                    Logger.Active.Log("[Kopernicus]: Configuration.Template: Using Template \"" + body.celestialBody.bodyName + "\"");

                    // Should we remove the ocean?
                    if (body.celestialBody.ocean && removeOcean.Value)
                    {
                        // Find atmosphere the ocean PQS
                        PQS ocean = body.pqsVersion.GetComponentsInChildren <PQS>(true).Where(pqs => pqs != body.pqsVersion).First();
                        PQSMod_CelestialBodyTransform cbt = body.pqsVersion.GetComponentsInChildren <PQSMod_CelestialBodyTransform>(true).First();

                        // Destroy the ocean PQS (this could be bad - destroying the secondary fades...)
                        cbt.planetFade.secondaryRenderers.Remove(ocean.gameObject);
                        cbt.secondaryFades     = null;
                        ocean.transform.parent = null;
                        UnityEngine.Object.Destroy(ocean);

                        // No more ocean :(
                        body.celestialBody.ocean = false;
                        body.pqsVersion.mapOcean = false;
                    }

                    // Selectively remove PQS Mods
                    if (removePQSMods != null && removePQSMods.Value.LongCount() > 0)
                    {
                        // We need a List with Types to remove
                        List <Type> mods = new List <Type>();
                        Dictionary <String, Type> modsPerName = new Dictionary <String, Type>();
                        foreach (String mod in removePQSMods.Value)
                        {
                            // If the definition has a name specified, grab that
                            String mType = mod;
                            String name  = "";
                            if (mType.EndsWith("]"))
                            {
                                String[] split = mType.Split('[');
                                mType = split[0];
                                name  = split[1].Remove(split[1].Length - 1);
                            }

                            // Get the mods matching the String
                            String modName = mType;
                            if (!mod.Contains("PQS"))
                            {
                                modName = "PQSMod_" + mod;
                            }
                            if (name == "")
                            {
                                //mods.Add(Type.GetType(modName + ", Assembly-CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
                                Type t = Parser.ModTypes.Find(m => m.Name == modName);
                                if (t != null)
                                {
                                    mods.Add(t);
                                }
                            }
                            else
                            {
                                //modsPerName.Add(name, Type.GetType(modName + ", Assembly-CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
                                Type t = Parser.ModTypes.Find(m => m.Name == modName);
                                if (t != null)
                                {
                                    modsPerName.Add(name, t);
                                }
                            }
                        }
                        Utility.RemoveModsOfType(mods, body.pqsVersion);
                        foreach (KeyValuePair <String, Type> kvP in modsPerName)
                        {
                            Int32  index = 0;
                            String name  = kvP.Key;
                            if (name.Contains(';'))
                            {
                                String[] split = name.Split(';');
                                name = split[0];
                                Int32.TryParse(split[1], out index);
                            }
                            PQSMod[] allMods = body.pqsVersion.GetComponentsInChildren(kvP.Value, true).Select(m => m as PQSMod).Where(m => m.name == name).ToArray();
                            if (allMods.Length > 0)
                            {
                                if (allMods[index] is PQSCity)
                                {
                                    PQSCity city = allMods[index] as PQSCity;
                                    if (city.lod != null)
                                    {
                                        foreach (PQSCity.LODRange range in city.lod)
                                        {
                                            if (range.objects != null)
                                            {
                                                foreach (GameObject o in range.objects)
                                                {
                                                    UnityEngine.Object.DestroyImmediate(o);
                                                }
                                            }
                                            if (range.renderers != null)
                                            {
                                                foreach (GameObject o in range.renderers)
                                                {
                                                    UnityEngine.Object.DestroyImmediate(o);
                                                }
                                            }
                                        }
                                    }
                                }
                                if (allMods[index] is PQSCity2)
                                {
                                    PQSCity2 city = allMods[index] as PQSCity2;
                                    if (city.objects != null)
                                    {
                                        foreach (PQSCity2.LodObject range in city.objects)
                                        {
                                            if (range.objects != null)
                                            {
                                                foreach (GameObject o in range.objects)
                                                {
                                                    UnityEngine.Object.DestroyImmediate(o);
                                                }
                                            }
                                        }
                                    }
                                }

                                // If no mod is left, delete the game object too
                                GameObject gameObject = allMods[index].gameObject;
                                UnityEngine.Object.DestroyImmediate(allMods[index]);
                                PQSMod[] allRemainingMods = gameObject.GetComponentsInChildren <PQSMod>(true);
                                if (allRemainingMods.Length == 0)
                                {
                                    UnityEngine.Object.DestroyImmediate(gameObject);
                                }
                            }
                        }
                    }

                    if (removeAllMods != null && removeAllMods.Value)
                    {
                        // Remove all mods
                        Utility.RemoveModsOfType(null, body.pqsVersion);
                    }
                }

                // Should we remove the progress tree
                if (removeProgressTree.Value)
                {
                    body.celestialBody.progressTree = null;
                }

                // Figure out what kind of body we are
                if (body.scaledVersion.GetComponentsInChildren <SunShaderController>(true).Length > 0)
                {
                    type = BodyType.Star;
                }
                else if (body.celestialBody.atmosphere)
                {
                    type = BodyType.Atmospheric;
                }
                else
                {
                    type = BodyType.Vacuum;
                }

                // remove coronas
                if (type == BodyType.Star && removeCoronas)
                {
                    foreach (SunCoronas corona in body.scaledVersion.GetComponentsInChildren <SunCoronas>(true))
                    {
                        corona.GetComponent <Renderer>().enabled = false; // RnD hard refs Coronas, so we need to disable them
                    }
                }

                // Event
                Events.OnTemplateLoaderPostApply.Fire(this, node);
            }
Example #8
0
        /// <summary>
        /// Disables an existing atmosphere, or adds a new one if there is none
        /// </summary>
        private void ToggleAtmosphere(CelestialBody body)
        {
            // Disable an existing atmosphere
            if (body.atmosphere)
            {
                // Disable the Atmosphere from Ground
                AtmosphereFromGround[] afgs = body.GetComponentsInChildren <AtmosphereFromGround>();
                foreach (AtmosphereFromGround afg in afgs)
                {
                    afg.gameObject.SetActive(false);
                }

                // Disable the Light controller
                MaterialSetDirection[] msds = body.GetComponentsInChildren <MaterialSetDirection>();
                foreach (MaterialSetDirection msd in msds)
                {
                    msd.gameObject.SetActive(false);
                }

                // No Atmosphere :(
                body.atmosphere = false;

                // Get the material
                Renderer  renderer   = body.scaledBody.GetComponent <Renderer>();
                Material  material   = renderer.sharedMaterial;
                Texture2D diffuseMap = (Texture2D)material.GetTexture("_MainTex");
                Texture2D bumpMap    = (Texture2D)material.GetTexture("_BumpMap");

                // Create a new scaled material
                Material newMaterial = new Material(Shader.Find("Terrain/Scaled Planet (Simple)"));
                newMaterial.SetTexture("_MainTex", diffuseMap);
                newMaterial.SetTexture("_BumpMap", bumpMap);
                newMaterial.SetFloat("_Shininess", material.GetFloat("_Shininess")); // TODO: Investigate
                newMaterial.SetColor("_SpecColor", material.GetColor("_SpecColor")); // TODO: Investigate

                // Apply the material
                renderer.sharedMaterial = newMaterial;

                // Backup the old material
                GameObject backupGameObject = new GameObject("Backup");
                backupGameObject.SetActive(false);
                backupGameObject.AddComponent <MeshRenderer>().material = material;
                backupGameObject.transform.parent = body.scaledBody.transform;

                // Update state
                toRestore.Add(body);
            }
            else
            {
                // Add a new atmosphere, this could get funny
                // We will just copy Laythe for the most parts
                body.atmosphere = true;
                body.atmosphereContainsOxygen = GetRandom(HighLogic.CurrentGame.Seed, 0, 99) < 10; // Oxygen is rare
                body.atmosphereDepth          = (body.pqsController.radiusMax / 10) * GetRandomDouble(HighLogic.CurrentGame.Seed, 0.8, 1.2);
                body.atmosphereAdiabaticIndex =
                    1.39999997615814 * GetRandomDouble(HighLogic.CurrentGame.Seed, 0.8, 1.2);
                body.atmosphereGasMassLapseRate =
                    4.84741125702493 * GetRandomDouble(HighLogic.CurrentGame.Seed, 0.8, 1.2);
                body.atmosphereMolarMass = 0.0289644002914429 * GetRandomDouble(HighLogic.CurrentGame.Seed, 0.8, 1.2);
                Double multiplier = GetRandomDouble(HighLogic.CurrentGame.Seed, 0, 1);
                body.atmospherePressureSeaLevel    = (595 * multiplier) + 5;
                body.atmosphereTemperatureSeaLevel = (270 * multiplier) + 240;
                body.atmDensityASL = (6.9 * multiplier) + 0.1;
                body.atmosphereTemperatureLapseRate         = GetRandomDouble(HighLogic.CurrentGame.Seed, 0.004, 0.005);
                body.atmospherePressureCurveIsNormalized    = true;
                body.atmosphereTemperatureCurveIsNormalized = true;
                body.atmosphereUsePressureCurve             = true;
                body.atmosphereUseTemperatureCurve          = true;

                // Select a curve template
                KeyValuePair <FloatCurve, FloatCurve> template =
                    GetRandomElement(HighLogic.CurrentGame.Seed, CurveTemplates.Atmospheres);
                body.atmospherePressureCurve    = template.Key;
                body.atmosphereTemperatureCurve = template.Value;

                // Now add the visuals
                GameObject scaledVersion = body.scaledBody;

                // Add the material light direction behavior
                MaterialSetDirection materialLightDirection = scaledVersion.AddComponent <MaterialSetDirection>();
                materialLightDirection.valueName = "_localLightDirection";

                // Create the atmosphere shell game object
                GameObject scaledAtmosphere = new GameObject("Atmosphere");
                scaledAtmosphere.transform.parent        = scaledVersion.transform;
                scaledAtmosphere.transform.position      = scaledVersion.transform.position;
                scaledAtmosphere.transform.localPosition = Vector3.zero;
                scaledAtmosphere.layer = 9;
                MeshRenderer mrenderer = scaledAtmosphere.AddComponent <MeshRenderer>();
                mrenderer.sharedMaterial = new Material(Shader.Find("AtmosphereFromGround"));
                MeshFilter meshFilter = scaledAtmosphere.AddComponent <MeshFilter>();
                meshFilter.sharedMesh = Templates.ReferenceGeosphere;
                AtmosphereFromGround atmosphereFromGround = scaledAtmosphere.AddComponent <AtmosphereFromGround>();

                // Get the average color of the current texture
                Renderer  renderer    = body.scaledBody.GetComponent <Renderer>();
                Material  material    = renderer.sharedMaterial;
                Texture2D diffuseMap  = Utility.CreateReadable((Texture2D)material.GetTexture("_MainTex"));
                Texture2D bumpMap     = (Texture2D)material.GetTexture("_BumpMap");
                Color     average     = Utility.GetAverageColor(diffuseMap);
                Color     altered     = AlterColor(average);
                Color     darkAltered = Utility.Dark(altered);

                body.afg = atmosphereFromGround;
                atmosphereFromGround.planet     = body;
                atmosphereFromGround.sunLight   = Planetarium.fetch.Sun.gameObject;
                atmosphereFromGround.mainCamera = PlanetariumCamera.fetch.transform;
                atmosphereFromGround.waveLength = new Color(1 - darkAltered.r, 1 - darkAltered.g, 1 - darkAltered.b, 0.5f);

                // Ambient Light
                body.atmosphericAmbientColor = altered;

                // Scaled Material
                Material newMaterial = new Material(Shader.Find("Terrain/Scaled Planet (RimAerial)"));
                newMaterial.SetTexture("_MainTex", diffuseMap);
                newMaterial.SetTexture("_BumpMap", bumpMap);
                newMaterial.SetFloat("_Shininess", material.GetFloat("_Shininess")); // TODO: Investigate
                newMaterial.SetColor("_SpecColor", material.GetColor("_SpecColor")); // TODO: Investigate
                newMaterial.SetFloat("_rimPower", (Single)GetRandomDouble(HighLogic.CurrentGame.Seed, 3.8, 5));
                newMaterial.SetFloat("_rimBlend", 1f);

                // Generate the atmosphere rim texture
                Gradient gradient = new Gradient();
                gradient.Add(0f, altered);
                gradient.Add(0.2f, new Color(0.0549f, 0.0784f, 0.141f, 1f));
                gradient.Add(1f, new Color(0.0196f, 0.0196f, 0.0196f, 1f));

                // Generate the ramp from a gradient
                Texture2D ramp   = new Texture2D(512, 1);
                Color[]   colors = ramp.GetPixels(0);
                for (Int32 i = 0; i < colors.Length; i++)
                {
                    // Compute the position in the gradient
                    Single k = (Single)i / colors.Length;
                    colors[i] = gradient.ColorAt(k);
                }
                ramp.SetPixels(colors, 0);
                ramp.Apply(true, false);
                ramp.wrapMode   = TextureWrapMode.Clamp;
                ramp.mipMapBias = 0.0f;

                // Set the color ramp
                newMaterial.SetTexture("_rimColorRamp", ramp);

                // Apply the material
                renderer.sharedMaterial = newMaterial;

                // Backup the old material
                GameObject backupGameObject = new GameObject("Backup");
                backupGameObject.SetActive(false);
                backupGameObject.AddComponent <MeshRenderer>().material = material;
                backupGameObject.transform.parent = scaledVersion.transform;

                // Update state
                toDelete.Add(body);
            }
        }
Example #9
0
        // Post apply event
        void IParserEventSubscriber.PostApply(ConfigNode node)
        {
            // Should we remove the atmosphere
            if (Body.celestialBody.atmosphere && RemoveAtmosphere.Value)
            {
                // Find atmosphere from ground and destroy the game object
                AtmosphereFromGround atmosphere =
                    Body.scaledVersion.GetComponentsInChildren <AtmosphereFromGround>(true)[0];
                atmosphere.transform.parent = null;
                Object.Destroy(atmosphere.gameObject);

                // Destroy the light controller
                MaterialSetDirection light = Body.scaledVersion.GetComponentsInChildren <MaterialSetDirection>(true)[0];
                Object.Destroy(light);

                // No more atmosphere :(
                Body.celestialBody.atmosphere = false;
            }

            Logger.Active.Log("Using Template \"" + Body.celestialBody.bodyName + "\"");

            // If we have a PQS
            if (Body.pqsVersion != null)
            {
#if (!KSP_VERSION_1_8)
                // We only support one surface material per body, so use the one with the highest quality available
                if (GameSettings.TERRAIN_SHADER_QUALITY == 3)
                {
                    Material surfaceMaterial = Body.pqsVersion.ultraQualitySurfaceMaterial;
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.highQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.mediumQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.lowQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.surfaceMaterial;
                    }

                    Body.pqsVersion.ultraQualitySurfaceMaterial  = surfaceMaterial;
                    Body.pqsVersion.highQualitySurfaceMaterial   = surfaceMaterial;
                    Body.pqsVersion.mediumQualitySurfaceMaterial = surfaceMaterial;
                    Body.pqsVersion.lowQualitySurfaceMaterial    = surfaceMaterial;
                    Body.pqsVersion.surfaceMaterial = surfaceMaterial;
                }
#endif
                if (GameSettings.TERRAIN_SHADER_QUALITY == 2)
                {
                    Material surfaceMaterial = Body.pqsVersion.highQualitySurfaceMaterial;

                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.mediumQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.lowQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.surfaceMaterial;
                    }

#if (!KSP_VERSION_1_8)
                    Body.pqsVersion.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                    Body.pqsVersion.highQualitySurfaceMaterial   = surfaceMaterial;
                    Body.pqsVersion.mediumQualitySurfaceMaterial = surfaceMaterial;
                    Body.pqsVersion.lowQualitySurfaceMaterial    = surfaceMaterial;
                    Body.pqsVersion.surfaceMaterial = surfaceMaterial;
                }
                else if (GameSettings.TERRAIN_SHADER_QUALITY == 1)
                {
                    Material surfaceMaterial = Body.pqsVersion.mediumQualitySurfaceMaterial;

                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.lowQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.surfaceMaterial;
                    }

#if (!KSP_VERSION_1_8)
                    Body.pqsVersion.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                    Body.pqsVersion.highQualitySurfaceMaterial   = surfaceMaterial;
                    Body.pqsVersion.mediumQualitySurfaceMaterial = surfaceMaterial;
                    Body.pqsVersion.lowQualitySurfaceMaterial    = surfaceMaterial;
                    Body.pqsVersion.surfaceMaterial = surfaceMaterial;
                }
                else if (GameSettings.TERRAIN_SHADER_QUALITY == 0)
                {
                    Material surfaceMaterial = Body.pqsVersion.lowQualitySurfaceMaterial;

                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.lowQualitySurfaceMaterial;
                    }
                    if (!surfaceMaterial)
                    {
                        surfaceMaterial = Body.pqsVersion.surfaceMaterial;
                    }

#if (!KSP_VERSION_1_8)
                    Body.pqsVersion.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                    Body.pqsVersion.highQualitySurfaceMaterial   = surfaceMaterial;
                    Body.pqsVersion.mediumQualitySurfaceMaterial = surfaceMaterial;
                    Body.pqsVersion.lowQualitySurfaceMaterial    = surfaceMaterial;
                    Body.pqsVersion.surfaceMaterial = surfaceMaterial;
                }

                // Should we remove the ocean?
                if (Body.celestialBody.ocean)
                {
                    // Find atmosphere the ocean PQS
                    PQS ocean = Body.pqsVersion.GetComponentsInChildren <PQS>(true)
                                .First(pqs => pqs != Body.pqsVersion);
                    PQSMod_CelestialBodyTransform cbt = Body.pqsVersion
                                                        .GetComponentsInChildren <PQSMod_CelestialBodyTransform>(true).First();
#if (!KSP_VERSION_1_8)
                    if (GameSettings.TERRAIN_SHADER_QUALITY == 3)
                    {
                        Material surfaceMaterial = ocean.ultraQualitySurfaceMaterial;

                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.highQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.mediumQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.lowQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.surfaceMaterial;
                        }
                        ocean.ultraQualitySurfaceMaterial  = surfaceMaterial;
                        ocean.highQualitySurfaceMaterial   = surfaceMaterial;
                        ocean.mediumQualitySurfaceMaterial = surfaceMaterial;
                        ocean.lowQualitySurfaceMaterial    = surfaceMaterial;
                        ocean.surfaceMaterial = surfaceMaterial;
                    }
#endif
                    if (GameSettings.TERRAIN_SHADER_QUALITY == 2)
                    {
                        Material surfaceMaterial = ocean.highQualitySurfaceMaterial;

                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.mediumQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.lowQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.surfaceMaterial;
                        }
#if (!KSP_VERSION_1_8)
                        ocean.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                        ocean.highQualitySurfaceMaterial   = surfaceMaterial;
                        ocean.mediumQualitySurfaceMaterial = surfaceMaterial;
                        ocean.lowQualitySurfaceMaterial    = surfaceMaterial;
                        ocean.surfaceMaterial = surfaceMaterial;
                    }
                    else if (GameSettings.TERRAIN_SHADER_QUALITY == 1)
                    {
                        Material surfaceMaterial = ocean.mediumQualitySurfaceMaterial;

                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.lowQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.surfaceMaterial;
                        }
#if (!KSP_VERSION_1_8)
                        ocean.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                        ocean.highQualitySurfaceMaterial   = surfaceMaterial;
                        ocean.mediumQualitySurfaceMaterial = surfaceMaterial;
                        ocean.lowQualitySurfaceMaterial    = surfaceMaterial;
                        ocean.surfaceMaterial = surfaceMaterial;
                    }
                    else if (GameSettings.TERRAIN_SHADER_QUALITY == 0)
                    {
                        Material surfaceMaterial = ocean.lowQualitySurfaceMaterial;

                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.lowQualitySurfaceMaterial;
                        }
                        if (!surfaceMaterial)
                        {
                            surfaceMaterial = ocean.surfaceMaterial;
                        }
#if (!KSP_VERSION_1_8)
                        ocean.ultraQualitySurfaceMaterial = surfaceMaterial;
#endif
                        ocean.highQualitySurfaceMaterial   = surfaceMaterial;
                        ocean.mediumQualitySurfaceMaterial = surfaceMaterial;
                        ocean.lowQualitySurfaceMaterial    = surfaceMaterial;
                        ocean.surfaceMaterial = surfaceMaterial;
                    }


                    if (RemoveOcean.Value)
                    {
                        // Destroy the ocean PQS (this could be bad - destroying the secondary fades...)
                        cbt.planetFade.secondaryRenderers.Remove(ocean.gameObject);
                        cbt.secondaryFades     = null;
                        ocean.transform.parent = null;
                        Object.Destroy(ocean);

                        // No more ocean :(
                        Body.celestialBody.ocean = false;
                        Body.pqsVersion.mapOcean = false;
                    }
                }

                // Selectively remove PQS Mods
                if (RemovePqsMods != null && RemovePqsMods.Value.LongCount() > 0)
                {
                    // We need a List with Types to remove
                    List <Type> mods = new List <Type>();
                    Dictionary <String, Type> modsPerName = new Dictionary <String, Type>();
                    foreach (String mod in RemovePqsMods.Value)
                    {
                        // If the definition has a name specified, grab that
                        String mType = mod;
                        String mName = "";
                        if (mType.EndsWith("]"))
                        {
                            String[] split = mType.Split('[');
                            mType = split[0];
                            mName = split[1].Remove(split[1].Length - 1);
                        }

                        // Get the mods matching the String
                        String modName = mType;
                        if (!mod.Contains("PQS"))
                        {
                            modName = "PQSMod_" + mod;
                        }

                        if (mName == "")
                        {
                            //mods.Add(Type.GetType(modName + ", Assembly-CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
                            Type t = Parser.ModTypes.Find(m => m.Name == modName);
                            if (t != null)
                            {
                                mods.Add(t);
                            }
                        }
                        else
                        {
                            //modsPerName.Add(name, Type.GetType(modName + ", Assembly-CSharp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"));
                            Type t = Parser.ModTypes.Find(m => m.Name == modName);
                            if (t != null)
                            {
                                modsPerName.Add(mName, t);
                            }
                        }
                    }

                    Utility.RemoveModsOfType(mods, Body.pqsVersion);
                    foreach (KeyValuePair <String, Type> kvP in modsPerName)
                    {
                        Int32  index   = 0;
                        String modName = kvP.Key;
                        if (modName.Contains(';'))
                        {
                            String[] split = modName.Split(';');
                            modName = split[0];
                            Int32.TryParse(split[1], out index);
                        }

                        PQSMod[] allMods = Body.pqsVersion.GetComponentsInChildren(kvP.Value, true)
                                           .OfType <PQSMod>().Where(m => m.name == modName).ToArray();
                        if (allMods.Length <= 0)
                        {
                            continue;
                        }
                        if (allMods[index] is PQSCity)
                        {
                            PQSCity city = (PQSCity)allMods[index];
                            if (city.lod != null)
                            {
                                foreach (PQSCity.LODRange range in city.lod)
                                {
                                    if (range.objects != null)
                                    {
                                        foreach (GameObject o in range.objects)
                                        {
                                            Object.DestroyImmediate(o);
                                        }
                                    }

                                    if (range.renderers == null)
                                    {
                                        continue;
                                    }
                                    {
                                        foreach (GameObject o in range.renderers)
                                        {
                                            Object.DestroyImmediate(o);
                                        }
                                    }
                                }
                            }
                        }

                        if (allMods[index] is PQSCity2)
                        {
                            PQSCity2 city = (PQSCity2)allMods[index];
                            if (city.objects != null)
                            {
                                foreach (PQSCity2.LodObject range in city.objects)
                                {
                                    if (range.objects == null)
                                    {
                                        continue;
                                    }
                                    foreach (GameObject o in range.objects)
                                    {
                                        Object.DestroyImmediate(o);
                                    }
                                }
                            }
                        }

                        // If no mod is left, delete the game object too
                        GameObject gameObject = allMods[index].gameObject;
                        Object.DestroyImmediate(allMods[index]);
                        PQSMod[] allRemainingMods = gameObject.GetComponentsInChildren <PQSMod>(true);
                        if (allRemainingMods.Length == 0)
                        {
                            Object.DestroyImmediate(gameObject);
                        }
                    }
                }

                if (RemoveAllMods != null && RemoveAllMods.Value)
                {
                    // Remove all mods
                    Utility.RemoveModsOfType(null, Body.pqsVersion);
                }
            }

            // Should we remove the progress tree
            if (RemoveProgressTree.Value)
            {
                Body.celestialBody.progressTree = null;
            }

            // Figure out what kind of body we are
            Boolean isStar = Body.scaledVersion.GetComponentsInChildren <SunShaderController>(true).Length > 0;

            // remove coronas
            if (isStar && RemoveCoronas)
            {
                foreach (SunCoronas corona in Body.scaledVersion.GetComponentsInChildren <SunCoronas>(true))
                {
                    // RnD hard refs Coronas, so we need to disable them
                    corona.GetComponent <Renderer>().enabled = false;
                }
            }

            // Event
            Events.OnTemplateLoaderPostApply.Fire(this, node);
        }
        public static PSystemBody GenerateSystemBody(PSystem system, PSystemBody parent, String name, Orbit orbit = null)
        {
            PSystemBody Jool   = Utility.FindBody(system.rootBody, "Jool");             // Need the geosphere for scaled version
            PSystemBody Laythe = Utility.FindBody(system.rootBody, "Laythe");           // Need pqs and ocean definitions

            //Utility.DumpObject (Laythe.celestialBody, " Laythe Celestial Body ");
            //Utility.DumpObject (Laythe.pqsVersion, " Laythe PQS ");
            //Transform laytheOcean = Utility.FindInChildren (Laythe.pqsVersion.transform, "LaytheOcean");
            //Utility.DumpObject (laytheOcean.GetComponent<PQS> (), " Laythe Ocean PQS ");

            // AddBody makes the GameObject and stuff. It also attaches it to the system and parent.
            PSystemBody body = system.AddBody(parent);

            // set up the various parameters
            body.name = name;
            body.flightGlobalsIndex = 100;

            // Some parameters of the celestialBody, which represents the actual planet...
            // PSystemBody is more of a container that associates the planet with its orbit
            // and position in the planetary system, etc.
            body.celestialBody.bodyName        = name;
            body.celestialBody.bodyDescription = "Merciful Kod, this thing just APPEARED! And unlike last time, it wasn't bird droppings on the telescope.";
            body.celestialBody.Radius          = 320000;
            //body.celestialBody.Radius                 = 3380100;
            body.celestialBody.GeeASL = 0.3;
            //body.celestialBody.Mass                   = 6.4185E+23;
            body.celestialBody.Mass = 4.5154812E+21;
            body.celestialBody.timeWarpAltitudeLimits = (float[])Laythe.celestialBody.timeWarpAltitudeLimits.Clone();
            body.celestialBody.rotationPeriod         = 88642.6848;
            body.celestialBody.rotates       = true;
            body.celestialBody.BiomeMap      = GenerateCBAttributeMapSO(name);                     //Dres.celestialBody.BiomeMap;//
            body.celestialBody.scienceValues = Laythe.celestialBody.scienceValues;
            body.celestialBody.ocean         = false;

            // Presumably true of Kerbin. I do not know what the consequences are of messing with this exactly.
            // I think this just affects where the Planetarium/Tracking station starts.
            body.celestialBody.isHomeWorld = false;

            // Setup the orbit of "Kopernicus."  The "Orbit" class actually is built to support serialization straight
            // from Squad, so storing these to files (and loading them) will be pretty easy.
            body.orbitRenderer.orbitColor  = Color.magenta;
            body.orbitDriver.celestialBody = body.celestialBody;
            body.orbitDriver.updateMode    = OrbitDriver.UpdateMode.UPDATE;
            if (orbit == null)
            {
                body.orbitDriver.orbit = new Orbit(0.0, 0.0, 47500000000, 0, 0, 0, 0, system.rootBody.celestialBody);
            }
            else
            {
                body.orbitDriver.orbit = orbit;
            }


            #region PSystemBody.pqsVersion generation

            // Create the PQS controller game object for Kopernicus
            GameObject controllerRoot = new GameObject(name);
            controllerRoot.layer            = Constants.GameLayers.LocalSpace;
            controllerRoot.transform.parent = Utility.Deactivator;

            // Create the PQS object and pull all the values from Dres (has some future proofing i guess? adapts to PQS changes)
            body.pqsVersion = controllerRoot.AddComponent <PQS>();
            Utility.CopyObjectFields(Laythe.pqsVersion, body.pqsVersion);
            //body.pqsVersion.surfaceMaterial = new PQSProjectionSurfaceQuad();
            //body.pqsVersion.fallbackMaterial = new PQSProjectionFallback();
            body.pqsVersion.surfaceMaterial  = new PQSProjectionAerialQuadRelative(Laythe.pqsVersion.surfaceMaterial);            // use until we determine all the functions of the shader textures
            body.pqsVersion.fallbackMaterial = new PQSProjectionFallback(Laythe.pqsVersion.fallbackMaterial);
            body.pqsVersion.radius           = body.celestialBody.Radius;
            body.pqsVersion.mapOcean         = false;

            // Debug
            Utility.DumpObjectProperties(body.pqsVersion.surfaceMaterial, " Surface Material ");
            Utility.DumpObjectProperties(body.pqsVersion.fallbackMaterial, " Fallback Material ");

            // Detail defaults
            body.pqsVersion.maxQuadLenghtsPerFrame = 0.03f;
            body.pqsVersion.minLevel          = 1;
            body.pqsVersion.maxLevel          = 10;
            body.pqsVersion.minDetailDistance = 8;

            // Create the celestial body transform
            GameObject mod = new GameObject("_CelestialBody");
            mod.transform.parent = controllerRoot.transform;
            PQSMod_CelestialBodyTransform celestialBodyTransform = mod.AddComponent <PQSMod_CelestialBodyTransform>();
            celestialBodyTransform.sphere                        = body.pqsVersion;
            celestialBodyTransform.forceActivate                 = false;
            celestialBodyTransform.deactivateAltitude            = 115000;
            celestialBodyTransform.forceRebuildOnTargetChange    = false;
            celestialBodyTransform.planetFade                    = new PQSMod_CelestialBodyTransform.AltitudeFade();
            celestialBodyTransform.planetFade.fadeFloatName      = "_PlanetOpacity";
            celestialBodyTransform.planetFade.fadeStart          = 100000.0f;
            celestialBodyTransform.planetFade.fadeEnd            = 110000.0f;
            celestialBodyTransform.planetFade.valueStart         = 0.0f;
            celestialBodyTransform.planetFade.valueEnd           = 1.0f;
            celestialBodyTransform.planetFade.secondaryRenderers = new List <GameObject>();
            celestialBodyTransform.secondaryFades                = new PQSMod_CelestialBodyTransform.AltitudeFade[0];
            celestialBodyTransform.requirements                  = PQS.ModiferRequirements.Default;
            celestialBodyTransform.modEnabled                    = true;
            celestialBodyTransform.order = 10;

            // Create the color PQS mods
            mod = new GameObject("_Color");
            mod.transform.parent = controllerRoot.transform;
            PQSMod_VertexSimplexNoiseColor vertexSimplexNoiseColor = mod.AddComponent <PQSMod_VertexSimplexNoiseColor>();
            vertexSimplexNoiseColor.sphere       = body.pqsVersion;
            vertexSimplexNoiseColor.seed         = 45;
            vertexSimplexNoiseColor.blend        = 1.0f;
            vertexSimplexNoiseColor.colorStart   = new Color(0.768656731f, 0.6996614f, 0.653089464f, 1);
            vertexSimplexNoiseColor.colorEnd     = new Color(0.0f, 0.0f, 0.0f, 1.0f);
            vertexSimplexNoiseColor.octaves      = 12.0;
            vertexSimplexNoiseColor.persistence  = 0.5;
            vertexSimplexNoiseColor.frequency    = 2.0;
            vertexSimplexNoiseColor.requirements = PQS.ModiferRequirements.MeshColorChannel;
            vertexSimplexNoiseColor.modEnabled   = true;
            vertexSimplexNoiseColor.order        = 200;

            PQSMod_HeightColorMap heightColorMap = mod.AddComponent <PQSMod_HeightColorMap>();
            heightColorMap.sphere = body.pqsVersion;
            List <PQSMod_HeightColorMap.LandClass> landClasses = new List <PQSMod_HeightColorMap.LandClass>();

            PQSMod_HeightColorMap.LandClass landClass = new PQSMod_HeightColorMap.LandClass("AbyPl", 0.0, 0.5, new Color(0.0f, 0.0f, 0.0f, 1.0f), Color.white, double.NaN);
            landClass.lerpToNext = true;
            landClasses.Add(landClass);

            landClass            = new PQSMod_HeightColorMap.LandClass("Beach", 0.5, 0.550000011920929, new Color(0.164179087f, 0.164179087f, 0.164179087f, 1.0f), Color.white, double.NaN);
            landClass.lerpToNext = true;
            landClasses.Add(landClass);

            landClass            = new PQSMod_HeightColorMap.LandClass("Beach", 0.550000011920929, 1.0, new Color(0.373134315f, 0.373134315f, 0.373134315f, 1.0f), Color.white, double.NaN);
            landClass.lerpToNext = false;
            landClasses.Add(landClass);

            // Generate an array from the land classes list
            heightColorMap.landClasses  = landClasses.ToArray();
            heightColorMap.blend        = 0.7f;
            heightColorMap.lcCount      = 3;
            heightColorMap.requirements = PQS.ModiferRequirements.MeshColorChannel;
            heightColorMap.modEnabled   = true;
            heightColorMap.order        = 201;

            // Create the alititude alpha mods
            mod = new GameObject("_Material_ModProjection");
            mod.transform.parent = controllerRoot.transform;
            PQSMod_AltitudeAlpha altitudeAlpha = mod.AddComponent <PQSMod_AltitudeAlpha>();
            altitudeAlpha.sphere          = body.pqsVersion;
            altitudeAlpha.atmosphereDepth = 4000.0;
            altitudeAlpha.invert          = false;
            altitudeAlpha.requirements    = PQS.ModiferRequirements.Default;
            altitudeAlpha.modEnabled      = false;
            altitudeAlpha.order           = 999999999;

            // Create the aerial perspective material
            mod = new GameObject("_Material_AerialPerspective");
            mod.transform.parent = controllerRoot.transform;
            PQSMod_AerialPerspectiveMaterial aerialPerspectiveMaterial = mod.AddComponent <PQSMod_AerialPerspectiveMaterial>();
            aerialPerspectiveMaterial.sphere              = body.pqsVersion;
            aerialPerspectiveMaterial.globalDensity       = -0.00001f;
            aerialPerspectiveMaterial.heightFalloff       = 6.75f;
            aerialPerspectiveMaterial.atmosphereDepth     = 150000;
            aerialPerspectiveMaterial.DEBUG_SetEveryFrame = true;
            aerialPerspectiveMaterial.cameraAlt           = 0;
            aerialPerspectiveMaterial.cameraAtmosAlt      = 0;
            aerialPerspectiveMaterial.heightDensAtViewer  = 0;
            aerialPerspectiveMaterial.requirements        = PQS.ModiferRequirements.Default;
            aerialPerspectiveMaterial.modEnabled          = true;
            aerialPerspectiveMaterial.order = 100;

            // Create the UV planet relative position
            mod = new GameObject("_Material_SurfaceQuads");
            mod.transform.parent = controllerRoot.transform;
            PQSMod_UVPlanetRelativePosition planetRelativePosition = mod.AddComponent <PQSMod_UVPlanetRelativePosition>();
            planetRelativePosition.sphere       = body.pqsVersion;
            planetRelativePosition.requirements = PQS.ModiferRequirements.Default;
            planetRelativePosition.modEnabled   = true;
            planetRelativePosition.order        = 999999;

            // Create the height noise module
            mod = new GameObject("_HeightNoise");
            mod.transform.parent = controllerRoot.transform;
            PQSMod_VertexHeightMap vertexHeightMap = mod.gameObject.AddComponent <PQSMod_VertexHeightMap>();
            vertexHeightMap.sphere = body.pqsVersion;
            //vertexHeightMap.heightMapDeformity = 29457.0;
            vertexHeightMap.heightMapDeformity     = 10000.0;
            vertexHeightMap.heightMapOffset        = -1000.0;
            vertexHeightMap.scaleDeformityByRadius = false;
            vertexHeightMap.requirements           = PQS.ModiferRequirements.MeshCustomNormals | PQS.ModiferRequirements.VertexMapCoords;
            vertexHeightMap.modEnabled             = true;
            vertexHeightMap.order = 20;

            // Load the heightmap for this planet
            Texture2D map = new Texture2D(4, 4, TextureFormat.Alpha8, false);
            map.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Height.png"));
            vertexHeightMap.heightMap = ScriptableObject.CreateInstance <MapSO>();
            vertexHeightMap.heightMap.CreateMap(MapSO.MapDepth.Greyscale, map);
            UnityEngine.Object.DestroyImmediate(map);

            // Create the simplex height module
            PQSMod_VertexSimplexHeight vertexSimplexHeight = mod.AddComponent <PQSMod_VertexSimplexHeight>();
            vertexSimplexHeight.sphere       = body.pqsVersion;
            vertexSimplexHeight.seed         = 670000;
            vertexSimplexHeight.deformity    = 1700.0;
            vertexSimplexHeight.octaves      = 12.0;
            vertexSimplexHeight.persistence  = 0.5;
            vertexSimplexHeight.frequency    = 4.0;
            vertexSimplexHeight.requirements = PQS.ModiferRequirements.MeshCustomNormals;
            vertexSimplexHeight.modEnabled   = true;
            vertexSimplexHeight.order        = 21;

            // SERIOUSLY RECOMMENDED FOR NO OCEAN WORLDS
            // Create the flatten ocean module
            PQSMod_FlattenOcean flattenOcean = mod.AddComponent <PQSMod_FlattenOcean>();
            flattenOcean.sphere       = body.pqsVersion;
            flattenOcean.oceanRadius  = 1.0;
            flattenOcean.requirements = PQS.ModiferRequirements.MeshCustomNormals;
            flattenOcean.modEnabled   = true;
            flattenOcean.order        = 25;

            // Creat the vertex height noise module
            PQSMod_VertexHeightNoise vertexHeightNoise = mod.AddComponent <PQSMod_VertexHeightNoise>();
            vertexHeightNoise.sphere       = body.pqsVersion;
            vertexHeightNoise.noiseType    = PQSMod_VertexHeightNoise.NoiseType.RiggedMultifractal;
            vertexHeightNoise.deformity    = 1000.0f;
            vertexHeightNoise.seed         = 5906;
            vertexHeightNoise.frequency    = 2.0f;
            vertexHeightNoise.lacunarity   = 2.5f;
            vertexHeightNoise.persistance  = 0.5f;
            vertexHeightNoise.octaves      = 4;
            vertexHeightNoise.mode         = LibNoise.Unity.QualityMode.Low;
            vertexHeightNoise.requirements = PQS.ModiferRequirements.MeshColorChannel;
            vertexHeightNoise.modEnabled   = true;
            vertexHeightNoise.order        = 22;

            // Create the material direction
            mod = new GameObject("_Material_SunLight");
            mod.transform.parent = controllerRoot.gameObject.transform;
            PQSMod_MaterialSetDirection materialSetDirection = mod.AddComponent <PQSMod_MaterialSetDirection>();
            materialSetDirection.sphere       = body.pqsVersion;
            materialSetDirection.valueName    = "_sunLightDirection";
            materialSetDirection.requirements = PQS.ModiferRequirements.Default;
            materialSetDirection.modEnabled   = true;
            materialSetDirection.order        = 100;

            // Crete the quad mesh colliders
            mod = new GameObject("QuadMeshColliders");
            mod.transform.parent = controllerRoot.gameObject.transform;
            PQSMod_QuadMeshColliders quadMeshColliders = mod.AddComponent <PQSMod_QuadMeshColliders>();
            quadMeshColliders.sphere                             = body.pqsVersion;
            quadMeshColliders.maxLevelOffset                     = 0;
            quadMeshColliders.physicsMaterial                    = new PhysicMaterial();
            quadMeshColliders.physicsMaterial.name               = "Ground";
            quadMeshColliders.physicsMaterial.dynamicFriction    = 0.6f;
            quadMeshColliders.physicsMaterial.staticFriction     = 0.8f;
            quadMeshColliders.physicsMaterial.bounciness         = 0.0f;
            quadMeshColliders.physicsMaterial.frictionDirection2 = Vector3.zero;
            quadMeshColliders.physicsMaterial.dynamicFriction2   = 0.0f;
            quadMeshColliders.physicsMaterial.staticFriction2    = 0.0f;
            quadMeshColliders.physicsMaterial.frictionCombine    = PhysicMaterialCombine.Maximum;
            quadMeshColliders.physicsMaterial.bounceCombine      = PhysicMaterialCombine.Average;
            quadMeshColliders.requirements                       = PQS.ModiferRequirements.Default;
            quadMeshColliders.modEnabled                         = true;
            quadMeshColliders.order = 100;

            // Create the simplex height absolute
            mod = new GameObject("_FineDetail");
            mod.transform.parent = controllerRoot.gameObject.transform;
            PQSMod_VertexSimplexHeightAbsolute vertexSimplexHeightAbsolute = mod.AddComponent <PQSMod_VertexSimplexHeightAbsolute>();
            vertexSimplexHeightAbsolute.sphere       = body.pqsVersion;
            vertexSimplexHeightAbsolute.seed         = 4234;
            vertexSimplexHeightAbsolute.deformity    = 400.0;
            vertexSimplexHeightAbsolute.octaves      = 6.0;
            vertexSimplexHeightAbsolute.persistence  = 0.5;
            vertexSimplexHeightAbsolute.frequency    = 18.0;
            vertexSimplexHeightAbsolute.requirements = PQS.ModiferRequirements.Default;
            vertexSimplexHeightAbsolute.modEnabled   = true;
            vertexSimplexHeightAbsolute.order        = 30;

            // Surface color map
            mod = new GameObject("_LandClass");
            mod.transform.parent = body.pqsVersion.gameObject.transform;
            PQSMod_VertexColorMap colorMap = mod.AddComponent <PQSMod_VertexColorMap>();
            colorMap.sphere     = body.pqsVersion;
            colorMap.order      = 500;
            colorMap.modEnabled = true;

            // Decompress and load the color
            map = new Texture2D(4, 4, TextureFormat.RGB24, false);
            map.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Color.png"));
            colorMap.vertexColorMap = ScriptableObject.CreateInstance <MapSO>();
            colorMap.vertexColorMap.CreateMap(MapSO.MapDepth.RGB, map);
            UnityEngine.Object.DestroyImmediate(map);

            #endregion

            #region PSystemBody.scaledVersion generation

            // Create the scaled version of the planet for use in map view
            body.scaledVersion                  = new GameObject(name);
            body.scaledVersion.layer            = Constants.GameLayers.ScaledSpace;
            body.scaledVersion.transform.parent = Utility.Deactivator;

            // DEPRECATED - USE PQSMeshWrapper
            // Make sure the scaled version cooresponds to the size of the body
            // Turns out that the localScale is directly related to the planet size.
            // Jool's local scale is {1,1,1}, Kerbin's is {0.1,0.1,0.1}.  Jool's
            // radius is 6000 km, Kerbin's is 600 km.  Notice the relation?
            float scale = (float)body.celestialBody.Radius / 6000000.0f;
            body.scaledVersion.transform.localScale = new Vector3(scale, scale, scale);

            // Generate a mesh to fit the PQS we generated (it would be cool to generate this FROM the PQS)
            Mesh mesh = new Mesh();
            Utility.CopyMesh(Jool.scaledVersion.GetComponent <MeshFilter>().sharedMesh, mesh);

            // Iterate though the UVs
            // Geosphere with a radius of 1000, cooresponds to an object 6000km in radius
            Vector3[] vertices = mesh.vertices;
            for (int i = 0; i < mesh.vertexCount; i++)
            {
                // Get the height offset from the height map
                Vector2 uv           = mesh.uv[i];
                float   displacement = vertexHeightMap.heightMap.GetPixelFloat(uv.x, uv.y);

                // Since this is a geosphere, normalizing the vertex gives the vector to translate on
                Vector3 v = vertices[i];
                v.Normalize();

                // Calculate the real height displacement (in meters), normalized vector "v" scale (1 unit = 6 km)
                displacement = (float)vertexHeightMap.heightMapOffset + (displacement * (float)vertexHeightMap.heightMapDeformity);
                Vector3 offset = v * ((displacement / 6000.0f) / scale);

                // Adjust the displacement
                vertices[i] += offset;
            }
            mesh.vertices = vertices;
            mesh.RecalculateNormals();

            // Create the mesh filter
            MeshFilter meshFilter = body.scaledVersion.AddComponent <MeshFilter> ();
            meshFilter.mesh = mesh;

            // Load and compress the color texture for the custom planet
            Texture2D colorTexture = new Texture2D(4, 4, TextureFormat.RGBA32, true);
            colorTexture.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Color.png"));
            colorTexture.Compress(true);
            colorTexture.Apply(true, true);

            // Load and compress the color texture for the custom planet
            Texture2D normalTexture = new Texture2D(4, 4, TextureFormat.RGB24, true);
            normalTexture.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Normals.png"));
            //normalTexture = GameDatabase.BitmapToUnityNormalMap(normalTexture);
            normalTexture.Compress(true);
            normalTexture.Apply(true, true);

            // Create the renderer and material for the scaled version
            MeshRenderer renderer = body.scaledVersion.AddComponent <MeshRenderer>();
            //ScaledPlanetSimple material = new ScaledPlanetSimple();   // for atmosphereless planets
            ScaledPlanetRimAerial material = new ScaledPlanetRimAerial();
            material.color       = Color.white;
            material.specColor   = Color.black;
            material.mainTexture = colorTexture;
            material.bumpMap     = normalTexture;
            renderer.material    = material;

            // Create the sphere collider
            SphereCollider collider = body.scaledVersion.AddComponent <SphereCollider> ();
            collider.center = Vector3.zero;
            collider.radius = 1000.0f;

            // Create the ScaledSpaceFader to fade the orbit out where we view it (maybe?)
            ScaledSpaceFader fader = body.scaledVersion.AddComponent <ScaledSpaceFader> ();
            fader.celestialBody = body.celestialBody;
            fader.fadeStart     = 95000.0f;
            fader.fadeEnd       = 100000.0f;
            fader.floatName     = "_Opacity";

            #endregion

            #region Atmosphere
            //--------------------- PROPERTIES EXCLUSIVE TO BODIES WITH ATMOSPHERE

            // Load the atmosphere gradient (compress it, does not need to be high quality)
            Texture2D atmosphereGradient = new Texture2D(4, 4, TextureFormat.RGB24, true);
            atmosphereGradient.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/AtmosphereGradient.png"));
            atmosphereGradient.Compress(true);
            atmosphereGradient.wrapMode   = TextureWrapMode.Clamp;
            atmosphereGradient.mipMapBias = 0.0f;
            atmosphereGradient.Apply(true, true);

            // Set the additional settings in the scaledVersion body's shader
            material.rimPower     = 2.06f;
            material.rimBlend     = 0.3f;
            material.rimColorRamp = atmosphereGradient;

            // Atmosphere specific properties (for scaled version root) (copied from duna)
            MaterialSetDirection materialLightDirection = body.scaledVersion.AddComponent <MaterialSetDirection>();
            materialLightDirection.valueName = "_localLightDirection";

            // Create the atmosphere shell itself
            GameObject scaledAtmosphere = new GameObject("atmosphere");
            scaledAtmosphere.transform.parent = body.scaledVersion.transform;
            scaledAtmosphere.layer            = Constants.GameLayers.ScaledSpaceAtmosphere;
            meshFilter            = scaledAtmosphere.AddComponent <MeshFilter>();
            meshFilter.sharedMesh = Jool.scaledVersion.GetComponent <MeshFilter>().sharedMesh;
            renderer          = scaledAtmosphere.AddComponent <MeshRenderer>();
            renderer.material = new Kopernicus.MaterialWrapper.AtmosphereFromGround();
            AtmosphereFromGround atmosphereRenderInfo = scaledAtmosphere.AddComponent <AtmosphereFromGround>();
            atmosphereRenderInfo.waveLength = new Color(0.509f, 0.588f, 0.643f, 0.000f);

            // Technical info for atmosphere
            body.celestialBody.atmosphere = true;
            body.celestialBody.atmosphereContainsOxygen        = true;
            body.celestialBody.staticPressureASL               = 1.0;      // can't find anything that references this, especially with the equation in mind - where is this used?
            body.celestialBody.altitudeMultiplier              = 1.4285f;  // ditto
            body.celestialBody.atmosphereScaleHeight           = 4.0;      // pressure (in atm) = atmosphereMultipler * e ^ -(altitude / (atmosphereScaleHeight * 1000))
            body.celestialBody.atmosphereMultiplier            = 0.8f;
            body.celestialBody.atmoshpereTemperatureMultiplier = 1.0f;     // how does this coorespond?
            body.celestialBody.maxAtmosphereAltitude           = 55000.0f; // i guess this is so the math doesn't drag out?
            body.celestialBody.useLegacyAtmosphere             = true;
            body.celestialBody.atmosphericAmbientColor         = new Color(0.306f, 0.187f, 0.235f, 1.000f);
            #endregion

            #region Ocean
            // ---------------- FOR BODIES WITH OCEANS ----------

            /*body.celestialBody.ocean = true;
             *
             * // Setup the laythe ocean info in master pqs
             * body.pqsVersion.mapOcean = true;
             * body.pqsVersion.mapOceanColor = new Color(0.117f, 0.126f, 0.157f, 1.000f);
             * body.pqsVersion.mapOceanHeight = 0.0f;
             *
             * // Generate the PQS object
             * GameObject oceanRoot       = new GameObject(name + "Ocean");
             * oceanRoot.transform.parent = body.pqsVersion.transform;
             * oceanRoot.layer            = Constants.GameLayers.LocalSpace;
             * PQS oceanPQS               = oceanRoot.AddComponent<PQS>();
             *
             * // Add this new PQS to the secondary renderers of the altitude fade controller
             * celestialBodyTransform.planetFade.secondaryRenderers.Add(oceanRoot);
             *
             * // Setup the PQS object data
             * Utility.CopyObjectFields<PQS>(laytheOcean.GetComponent<PQS>(), oceanPQS);
             * oceanPQS.radius            = body.pqsVersion.radius;
             * oceanPQS.surfaceMaterial   = new PQSOceanSurfaceQuad(laytheOcean.GetComponent<PQS>().surfaceMaterial);
             * oceanPQS.fallbackMaterial  = new PQSOceanSurfaceQuadFallback(laytheOcean.GetComponent<PQS>().fallbackMaterial);
             * Utility.DumpObjectProperties(oceanPQS.surfaceMaterial, oceanPQS.surfaceMaterial.ToString());
             * Utility.DumpObjectProperties(oceanPQS.fallbackMaterial, oceanPQS.fallbackMaterial.ToString());
             *
             * // Create the aerial perspective material
             * mod = new GameObject("_Material_AerialPerspective");
             * mod.transform.parent = oceanRoot.transform;
             * aerialPerspectiveMaterial = mod.AddComponent<PQSMod_AerialPerspectiveMaterial>();
             * aerialPerspectiveMaterial.sphere = body.pqsVersion;
             * aerialPerspectiveMaterial.globalDensity = -0.00001f;
             * aerialPerspectiveMaterial.heightFalloff = 6.75f;
             * aerialPerspectiveMaterial.atmosphereDepth = 150000;
             * aerialPerspectiveMaterial.DEBUG_SetEveryFrame = true;
             * aerialPerspectiveMaterial.cameraAlt = 0;
             * aerialPerspectiveMaterial.cameraAtmosAlt = 0;
             * aerialPerspectiveMaterial.heightDensAtViewer = 0;
             * aerialPerspectiveMaterial.requirements = PQS.ModiferRequirements.Default;
             * aerialPerspectiveMaterial.modEnabled = true;
             * aerialPerspectiveMaterial.order = 100;
             *
             * // Create the UV planet relative position
             * mod = new GameObject("_Material_SurfaceQuads");
             * mod.transform.parent = oceanRoot.transform;
             * planetRelativePosition = mod.AddComponent<PQSMod_UVPlanetRelativePosition>();
             * planetRelativePosition.sphere = body.pqsVersion;
             * planetRelativePosition.requirements = PQS.ModiferRequirements.Default;
             * planetRelativePosition.modEnabled = true;
             * planetRelativePosition.order = 100;
             *
             * // Create the quad map remover (da f**k?)
             * mod = new GameObject("QuadRemoveMap");
             * mod.transform.parent = oceanRoot.transform;
             * PQSMod_RemoveQuadMap removeQuadMap = mod.AddComponent<PQSMod_RemoveQuadMap>();
             * removeQuadMap.mapDeformity = 0.0f;
             * removeQuadMap.minHeight = 0.0f;
             * removeQuadMap.maxHeight = 0.5f;
             * removeQuadMap.requirements = PQS.ModiferRequirements.Default;
             * removeQuadMap.modEnabled = true;
             * removeQuadMap.order = 1000;
             *
             * // Load the heightmap into whatever the hell this is
             * map = new Texture2D(4, 4, TextureFormat.Alpha8, false);
             * map.LoadImage(System.IO.File.ReadAllBytes(KSPUtil.ApplicationRootPath + PluginDirectory + "/Planets/" + name + "/Height.png"));
             * removeQuadMap.map = ScriptableObject.CreateInstance<MapSO>();
             * removeQuadMap.map.CreateMap(MapSO.MapDepth.Greyscale, map);
             * UnityEngine.Object.DestroyImmediate(map);
             *
             * // Setup the ocean effects
             * mod = new GameObject("OceanFX");
             * mod.transform.parent = oceanRoot.transform;
             * PQSMod_OceanFX oceanFX = mod.AddComponent<PQSMod_OceanFX>();
             * oceanFX.watermain = Utility.RecursivelyGetComponent<PQSMod_OceanFX>(laytheOcean).watermain.Clone() as Texture2D[];
             * oceanFX.requirements = PQS.ModiferRequirements.Default;
             * oceanFX.modEnabled = true;
             * oceanFX.order = 100;*/

            #endregion

            // Return the new body
            return(body);
        }
Example #11
0
        // Parser Apply Event
        void IParserEventSubscriber.Apply(ConfigNode node)
        {
            if (Template != null && Template.Body)
            {
                // If we have a template, generatedBody *is* the template body
                GeneratedBody = Template.Body;
                // Patch the game object names in the template
                GeneratedBody.name = Name;
                GeneratedBody.celestialBody.bodyName       = Name;
                GeneratedBody.celestialBody.transform.name = Name;
                GeneratedBody.scaledVersion.name           = Name;
                if (GeneratedBody.pqsVersion != null)
                {
                    GeneratedBody.pqsVersion.name            = Name;
                    GeneratedBody.pqsVersion.gameObject.name = Name;
                    GeneratedBody.pqsVersion.transform.name  = Name;
                    foreach (PQS p in GeneratedBody.pqsVersion.GetComponentsInChildren <PQS>(true))
                    {
                        p.name = p.name.Replace(Template.Body.celestialBody.bodyName, Name);
                    }
                    GeneratedBody.celestialBody.pqsController = GeneratedBody.pqsVersion;
                }
                // If we've changed the name, reset use_The_InName
                if (GeneratedBody.name != Template.OriginalBody.celestialBody.bodyName)
                {
                    GeneratedBody.celestialBody.bodyDisplayName = GeneratedBody.celestialBody.bodyAdjectiveDisplayName = GeneratedBody.celestialBody.bodyName;
                }
                // Create accessors
                Debug         = new DebugLoader();
                ScaledVersion = new ScaledVersionLoader();
                if (Template.OriginalBody.scaledVersion.name.Equals("Jool"))
                {
#if (KSP_VERSION_1_10_1 || KSP_VERSION_1_11_1)
                    if ((!Name.Equals("Jool")) || (Name.Equals("Jool") && (Template.Body.celestialBody.Radius > 6000000))) // This is a Jool-clone, or resized Jool.  We have to handle it special.
                    {
                        //Remove Gas Giant shaders for compatability
                        GasGiantMaterialControls       GGMC  = GeneratedBody.scaledVersion.GetComponent <GasGiantMaterialControls>();
                        MaterialBasedOnGraphicsSetting MBOGS = GeneratedBody.scaledVersion.GetComponent <MaterialBasedOnGraphicsSetting>();
                        GameObject.DestroyImmediate(GGMC);
                        GameObject.DestroyImmediate(MBOGS);
                    }
#endif
                    //We need to destroy the stock GG MSD, it is bugged for our needs.
                    MaterialSetDirection MSD = GeneratedBody.celestialBody.scaledBody.GetComponent <MaterialSetDirection>();
                    GameObject.DestroyImmediate(MSD);
                }
            }
            // Otherwise we have to generate all the things for this body
            else
            {
                // Create the PSystemBody object
                GameObject generatedBodyGameObject = new GameObject(Name);
                generatedBodyGameObject.transform.parent = Utility.Deactivator;
                GeneratedBody = generatedBodyGameObject.AddComponent <PSystemBody>();
                GeneratedBody.flightGlobalsIndex = 0;

                // Create the celestial body
                GameObject generatedBodyProperties = new GameObject(Name);
                generatedBodyProperties.transform.parent = generatedBodyGameObject.transform;
                GeneratedBody.celestialBody = generatedBodyProperties.AddComponent <CelestialBody>();
                GeneratedBody.celestialBody.progressTree = null;

                // Sensible defaults
                GeneratedBody.celestialBody.bodyName        = Name;
                GeneratedBody.celestialBody.bodyDisplayName = GeneratedBody.celestialBody.bodyAdjectiveDisplayName = Name;
                GeneratedBody.celestialBody.atmosphere      = false;
                GeneratedBody.celestialBody.ocean           = false;

                // Create the scaled version
                GeneratedBody.scaledVersion = new GameObject(Name)
                {
                    layer = GameLayers.SCALED_SPACE
                };
                GeneratedBody.scaledVersion.transform.parent = Utility.Deactivator;
                // Create accessors
                Debug         = new DebugLoader();
                ScaledVersion = new ScaledVersionLoader();
            }
            // Event
            Events.OnBodyApply.Fire(this, node);
        }
Example #12
0
            // Post apply event
            void IParserEventSubscriber.PostApply(ConfigNode node)
            {
                // Should we remove the atmosphere
                if (body.celestialBody.atmosphere && removeAtmosphere.value)
                {
                    // Find atmosphere from ground and destroy the game object
                    AtmosphereFromGround atmosphere = body.scaledVersion.GetComponentsInChildren <AtmosphereFromGround>(true)[0];
                    atmosphere.transform.parent = null;
                    UnityEngine.Object.Destroy(atmosphere.gameObject);

                    // Destroy the light controller
                    MaterialSetDirection light = body.scaledVersion.GetComponentsInChildren <MaterialSetDirection>(true)[0];
                    UnityEngine.Object.Destroy(light);

                    // No more atmosphere :(
                    body.celestialBody.atmosphere = false;
                }

                // If we have a PQS
                if (body.pqsVersion != null)
                {
                    Logger.Active.Log("[Kopernicus]: Configuration.Template: Using Template \"" + body.celestialBody.bodyName + "\"");

                    // Should we remove the ocean?
                    if (body.celestialBody.ocean && removeOcean.value)
                    {
                        // Find atmosphere the ocean PQS
                        PQS ocean = body.pqsVersion.GetComponentsInChildren <PQS> (true).Where(pqs => pqs != body.pqsVersion).First();
                        PQSMod_CelestialBodyTransform cbt = body.pqsVersion.GetComponentsInChildren <PQSMod_CelestialBodyTransform> (true).First();

                        // Destroy the ocean PQS (this could be bad - destroying the secondary fades...)
                        cbt.planetFade.secondaryRenderers.Remove(ocean.gameObject);
                        cbt.secondaryFades     = null;
                        ocean.transform.parent = null;
                        UnityEngine.Object.Destroy(ocean);

                        // No more ocean :(
                        body.celestialBody.ocean = false;
                        body.pqsVersion.mapOcean = false;
                    }

                    // Selectively remove PQS Mods
                    if (removePQSMods != null && removePQSMods.value.LongCount() > 0)
                    {
                        // Get a list of all the PQS mods (immediate children, don't f**k the ocean)
                        List <PQSMod> mods = body.pqsVersion.transform.GetComponentsInChildren <PQSMod>(true).Where(mod => mod.transform.parent == body.pqsVersion.transform).ToList();
                        foreach (string mod in removePQSMods.value)
                        {
                            // Get the mods matching the string
                            string modName = "PQSMod_" + mod;
                            foreach (PQSMod m in mods.Where(m => m.GetType().ToString().EndsWith(modName)))
                            {
                                Logger.Active.Log("Removed PQSMod: " + m.name + " (" + m.GetType() + ")");
                                UnityEngine.Object.Destroy(m);
                            }
                        }
                    }
                }

                // Should we remove the progress tree
                if (removeProgressTree.value)
                {
                    body.celestialBody.progressTree = null;
                }

                // Figure out what kind of body we are
                if (body.scaledVersion.GetComponentsInChildren <SunShaderController>(true).Length > 0)
                {
                    type = BodyType.Star;
                }
                else if (body.celestialBody.atmosphere)
                {
                    type = BodyType.Atmospheric;
                }
                else
                {
                    type = BodyType.Vacuum;
                }
            }