/// <summary>
            /// Creates a new ScaledVersion Loader from a spawned CelestialBody.
            /// </summary>
            public ScaledVersionLoader(CelestialBody body)
            {
                // Is this a spawned body?
                if (body?.scaledBody == null || Injector.IsInPrefab)
                {
                    throw new InvalidOperationException("The body must be already spawned by the PSystemManager.");
                }

                // Get the scaled version object
                Value   = body;
                coronas = Value.scaledBody.GetComponentsInChildren <SunCoronas>(true).Select(c => new CoronaLoader(c))
                          .ToList();

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

                // Assign the proper scaled space loaders
                if (material == null)
                {
                    return;
                }
                if (ScaledPlanetSimple.UsesSameShader(material))
                {
                    material = new ScaledPlanetSimpleLoader(material);
                }
                if (ScaledPlanetRimAerial.UsesSameShader(material))
                {
                    material = new ScaledPlanetRimAerialLoader(material);
                }
                if (EmissiveMultiRampSunspots.UsesSameShader(material))
                {
                    material = new EmissiveMultiRampSunspotsLoader(material);
                }
            }
            // Parser apply event
            void IParserEventSubscriber.Apply(ConfigNode node)
            {
                // Get any existing material we might have on this scaled version
                Material   material = scaledVersion.GetComponent <Renderer>().sharedMaterial;
                ConfigNode data     = node.GetNode(materialNodeName);

                // Check for bad condition (no material, no new material)
                if (material == null && data == null)
                {
                    throw new Exception("Scaled version has no material information");
                }

                // Are we a planet or moon?
                if (type.value != BodyType.Star)
                {
                    // If we are not a star, we need a scaled space fader and a sphere collider
                    if (scaledVersion.GetComponent <ScaledSpaceFader> () == null)
                    {
                        ScaledSpaceFader fader = scaledVersion.AddComponent <ScaledSpaceFader> ();
                        fader.floatName     = "_Opacity";
                        fader.celestialBody = owner;
                    }

                    // Add a sphere collider if we need one
                    if (scaledVersion.GetComponent <SphereCollider> () == null)
                    {
                        SphereCollider collider = scaledVersion.AddComponent <SphereCollider>();
                        collider.center = Vector3.zero;
                        collider.radius = 1000.0f;
                    }

                    // Generate new atmospheric body material
                    if (type.value == BodyType.Atmospheric)
                    {
                        ScaledPlanetRimAerialLoader newMaterial = null;
                        if (material != null && ScaledPlanetRimAerial.UsesSameShader(material))
                        {
                            newMaterial = new ScaledPlanetRimAerialLoader(material);
                            if (data != null)
                            {
                                Parser.LoadObjectFromConfigurationNode(newMaterial, data);
                            }
                        }
                        else
                        {
                            newMaterial = Parser.CreateObjectFromConfigNode <ScaledPlanetRimAerialLoader> (data);
                        }
                        newMaterial.name = Guid.NewGuid().ToString();
                        if (newMaterial.rimColorRamp != null)
                        {
                            newMaterial.rimColorRamp.wrapMode   = TextureWrapMode.Clamp;
                            newMaterial.rimColorRamp.mipMapBias = 0.0f;
                        }
                        scaledVersion.GetComponent <Renderer>().sharedMaterial = newMaterial;
                    }

                    // Generate new vacuum body material
                    else
                    {
                        ScaledPlanetSimpleLoader newMaterial = null;
                        if (material != null && ScaledPlanetSimple.UsesSameShader(material))
                        {
                            newMaterial = new ScaledPlanetSimpleLoader(material);
                            if (data != null)
                            {
                                Parser.LoadObjectFromConfigurationNode(newMaterial, data);
                            }
                        }
                        else
                        {
                            newMaterial = Parser.CreateObjectFromConfigNode <ScaledPlanetSimpleLoader> (data);
                        }
                        newMaterial.name = Guid.NewGuid().ToString();
                        scaledVersion.GetComponent <Renderer>().sharedMaterial = newMaterial;
                    }
                }

                // Otherwise we are a star
                else
                {
                    // Add the SunShaderController behavior
                    if (scaledVersion.GetComponent <SunShaderController>() == null)
                    {
                        scaledVersion.AddComponent <SunShaderController>();
                    }

                    // Add the ScaledSun behavior
                    // TODO - apparently there can only be one of these (or it destroys itself)
                    if (scaledVersion.GetComponent <ScaledSun>() == null)
                    {
                        scaledVersion.AddComponent <ScaledSun>();
                    }

                    // Add the Kopernicus star componenet
                    component    = scaledVersion.AddComponent <StarComponent> ();
                    lightShifter = new LightShifterLoader();

                    // Generate a new material for the star
                    EmissiveMultiRampSunspotsLoader newMaterial = null;
                    if (material != null && EmissiveMultiRampSunspots.UsesSameShader(material))
                    {
                        newMaterial = new EmissiveMultiRampSunspotsLoader(material);
                        if (data != null)
                        {
                            Parser.LoadObjectFromConfigurationNode(newMaterial, data);
                        }
                    }
                    else
                    {
                        newMaterial = Parser.CreateObjectFromConfigNode <EmissiveMultiRampSunspotsLoader> (data);
                    }

                    newMaterial.name = Guid.NewGuid().ToString();
                    scaledVersion.GetComponent <Renderer>().sharedMaterial = newMaterial;
                }
            }
        /// <summary>
        /// Creates a new ScaledVersion Loader from a spawned CelestialBody.
        /// </summary>
        public ScaledVersionLoader(CelestialBody body)
        {
            // Is this a spawned body?
            if (body.scaledBody == null || Injector.IsInPrefab)
            {
                throw new InvalidOperationException("The body must be already spawned by the PSystemManager.");
            }

            // Get the scaled version object
            Value   = body;
            Coronas = Value.scaledBody.GetComponentsInChildren <SunCoronas>(true).Select(c => new CoronaLoader(c))
                      .ToList();
            if (!Coronas.Any())
            {
                Coronas = null;
            }

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

            if (Type != BodyType.Star)
            {
                ScaledSpaceFader fader = Value.scaledBody.GetComponent <ScaledSpaceFader>();
                if (!(fader is SharedScaledSpaceFader))
                {
                    Utility.CopyObjectFields(fader, Value.scaledBody.AddComponent <SharedScaledSpaceFader>());
                    Object.Destroy(fader);
                }
            }
            else
            {
                SunShaderController controller = Value.scaledBody.GetComponent <SunShaderController>();
                if (controller != null && !(controller is SharedSunShaderController))
                {
                    Utility.CopyObjectFields(controller, Value.scaledBody.AddComponent <SharedSunShaderController>());
                    Object.Destroy(controller);
                }
            }

            // Assign the proper scaled space loaders
            if (Material == null)
            {
                return;
            }

            if (ScaledPlanetSimple.UsesSameShader(Material))
            {
                Material = new ScaledPlanetSimpleLoader(Material);
            }

            if (ScaledPlanetRimAerial.UsesSameShader(Material))
            {
                Material = new ScaledPlanetRimAerialLoader(Material);
            }

            if (EmissiveMultiRampSunspots.UsesSameShader(Material))
            {
                Material = new EmissiveMultiRampSunspotsLoader(Material);
            }

            if (Options != null)
            {
                return;
            }

            Options = new PlanetTextureExporter.TextureOptions();
            if (body.pqsController == null)
            {
                return;
            }

            Options.Resolution   = body.pqsController.mapFilesize;
            Options.TextureDelta = body.pqsController.mapMaxHeight;
        }
        // Parser apply event
        void IParserEventSubscriber.Apply(ConfigNode node)
        {
            // Get any existing material we might have on this scaled version
            ConfigNode data = node.GetNode(MATERIAL_NODE_NAME);

            // Check for bad condition (no material, no new material)
            if (Material == null && data == null)
            {
                throw new Exception("Scaled version has no material information");
            }

            // Are we a planet or moon?
            if (Type.Value != BodyType.Star)
            {
                // If we are not a star, we need a scaled space fader and a sphere collider
                ScaledSpaceFader fader = Value.scaledBody.GetComponent <ScaledSpaceFader>();
                if (fader == null)
                {
                    fader               = Value.scaledBody.AddComponent <SharedScaledSpaceFader>();
                    fader.floatName     = "_Opacity";
                    fader.celestialBody = Value;
                }
                else if (!(fader is SharedScaledSpaceFader))
                {
                    Utility.CopyObjectFields(fader, Value.scaledBody.AddComponent <SharedScaledSpaceFader>());
                    Object.DestroyImmediate(fader);
                }

                // Add a sphere collider if we need one
                if (Value.scaledBody.GetComponent <SphereCollider>() == null)
                {
                    SphereCollider collider = Value.scaledBody.AddComponent <SphereCollider>();
                    collider.center = Vector3.zero;
                    collider.radius = 1000.0f;
                }

                // Generate new atmospheric body material
                if (Type.Value == BodyType.Atmospheric)
                {
                    if (Material != null && ScaledPlanetRimAerial.UsesSameShader(Material))
                    {
                        Material = new ScaledPlanetRimAerialLoader(Material);
                    }
                    else
                    {
                        Material = new ScaledPlanetRimAerialLoader();
                    }

                    Material.name = Guid.NewGuid().ToString();
                }

                // Generate new vacuum body material
                else
                {
                    if (Material != null && ScaledPlanetSimple.UsesSameShader(Material))
                    {
                        Material = new ScaledPlanetSimpleLoader(Material);
                    }
                    else
                    {
                        Material = new ScaledPlanetSimpleLoader();
                    }

                    Material.name = Guid.NewGuid().ToString();
                }
            }

            // Otherwise we are a star
            else
            {
                // Add the SunShaderController behavior
                SunShaderController controller = Value.scaledBody.GetComponent <SunShaderController>();
                if (controller == null)
                {
                    Value.scaledBody.AddComponent <SharedSunShaderController>();
                }
                else if (!(controller is SharedSunShaderController))
                {
                    Utility.CopyObjectFields(controller, Value.scaledBody.AddComponent <SharedSunShaderController>());
                    Object.DestroyImmediate(controller);
                }

                // Add the ScaledSun behavior
                // TODO - apparently there can only be one of these (or it destroys itself)
                if (Value.scaledBody.GetComponent <ScaledSun>() == null)
                {
                    Value.scaledBody.AddComponent <ScaledSun>();
                }

                // Add the Kopernicus star component
                Value.scaledBody.AddComponent <StarComponent>();

                // Generate a new material for the star
                if (Material != null && EmissiveMultiRampSunspots.UsesSameShader(Material))
                {
                    Material = new EmissiveMultiRampSunspotsLoader(Material);
                }
                else
                {
                    Material = new EmissiveMultiRampSunspotsLoader();
                }

                Material.name = Guid.NewGuid().ToString();


                // Backup existing coronas
                foreach (SunCoronas corona in Value.scaledBody.GetComponentsInChildren <SunCoronas>(true))
                {
                    corona.transform.parent = Utility.Deactivator;
                }
            }

            // Event
            Events.OnScaledVersionLoaderApply.Fire(this, node);
        }