internal void OnPreCull()
        {
            if (HighLogic.LoadedScene != GameScenes.MAINMENU && screenSpaceShadowGO != null && body.pqsController != null)
            {
                Matrix4x4 bodies = Matrix4x4.zero;
                int       i      = 0;
                foreach (CelestialBody cb in shadowList)
                {
                    if (cb != null && cb.transform != null)
                    {
                        bodies.SetRow(i, cb.transform.position);
                        bodies[i, 3] = (float)(cb.Radius);
                        i++;
                        if (i == 4)
                        {
                            break;
                        }
                    }
                }

                if (shadowMat != null)
                {
                    shadowMat.SetVector(ShaderProperties._SunPos_PROPERTY, Sun.Instance.sun.transform.position);
                    shadowMat.SetMatrix(ShaderProperties._ShadowBodies_PROPERTY, bodies);
                }

                screenSpaceShadowGO.SetActive(body.pqsController.isActive);
                screenSpaceShadow.SetActive(body.pqsController.isActive);
            }
        }
        internal void Apply(CelestialBody celestialBody, Transform scaledCelestialTransform, CloudsMaterial cloudsMaterial, string name, float radius, float arc, Tools.Layer layer = Tools.Layer.Scaled)
        {
            CloudsManager.Log("Applying 2D clouds...");
            Remove();
            this.celestialBody            = celestialBody;
            this.scaledCelestialTransform = scaledCelestialTransform;
            if (arc == 360)
            {
                HalfSphere hp = new HalfSphere(radius, ref CloudMaterial, CloudShader);
                CloudMesh = hp.GameObject;
            }
            else
            {
                UVSphere hp = new UVSphere(radius, arc, ref CloudMaterial, CloudShader);
                CloudMesh = hp.GameObject;
            }
            CloudMesh.name            = name;
            CloudMaterial.name        = "Clouds2D";
            this.radius               = radius;
            this.arc                  = arc;
            macroCloudMaterial.Radius = radius;
            this.cloudsMat            = cloudsMaterial;
            this.scaledLayer          = layer;

            CloudMaterial.SetMatrix(ShaderProperties._ShadowBodies_PROPERTY, Matrix4x4.zero);

            if (shadowMaterial != null)
            {
                ShadowProjectorGO                = new GameObject("EVE ShadowProjector");
                ShadowProjector                  = ShadowProjectorGO.AddComponent <Projector>();
                ShadowProjector.nearClipPlane    = 10;
                ShadowProjector.fieldOfView      = 60;
                ShadowProjector.aspectRatio      = 1;
                ShadowProjector.orthographic     = true;
                ShadowProjector.transform.parent = celestialBody.transform;
                ShadowProjector.material         = new Material(CloudShadowShader);
                shadowMaterial.ApplyMaterialProperties(ShadowProjector.material);

                // Workaround Unity bug (Case 841236)
                ShadowProjector.enabled = false;
                ShadowProjector.enabled = true;

                // Here create the screenSpaceShadowMaterialStuff
                screenSpaceShadowGO = new GameObject("EVE ScreenSpaceShadow");
                screenSpaceShadowGO.transform.parent = celestialBody.transform;
                screenSpaceShadow          = screenSpaceShadowGO.AddComponent <ScreenSpaceShadow>(); //can this be a single class that will handle the mesh, and meshrenderer and everything?
                screenSpaceShadow.material = new Material(ScreenSpaceCloudShadowShader);
                shadowMaterial.ApplyMaterialProperties(screenSpaceShadow.material);
                screenSpaceShadow.Init();
                screenSpaceShadowGO.SetActive(false);
                screenSpaceShadow.SetActive(false);
            }


            Scaled = true;
        }
        public void Reassign(Tools.Layer layer, Transform parent, float worldScale)
        {
            CloudMesh.transform.parent        = parent;
            CloudMesh.transform.localPosition = Vector3.zero;

            float localScale;

            if (isMainMenu)
            {
                localScale = worldScale * (joolRadius / (float)celestialBody.Radius);
            }
            else
            {
                localScale = (worldScale / parent.lossyScale.x);
            }

            CloudMesh.transform.localScale = (Vector3.one) * localScale;
            CloudMesh.layer = (int)layer;

            float radiusScaleWorld = radius * worldScale;

            radiusScaleLocal = radius * localScale;


            macroCloudMaterial.ApplyMaterialProperties(CloudMaterial, worldScale);
            cloudsMat.ApplyMaterialProperties(CloudMaterial, worldScale);

            if (layer == Tools.Layer.Local)
            {
                Sunlight = Sun.Instance.GetComponent <Light>();

                CloudMaterial.SetFloat("_OceanRadius", (float)celestialBody.Radius * worldScale);
                CloudMaterial.EnableKeyword("WORLD_SPACE_ON");
                CloudMaterial.EnableKeyword("SOFT_DEPTH_ON");
                CloudMaterial.renderQueue = (int)Tools.Queue.Transparent - 1;
            }
            else
            {
                //hack to get protected variable
                FieldInfo field = typeof(Sun).GetFields(BindingFlags.Instance | BindingFlags.NonPublic).First(
                    f => f.Name == "scaledSunLight");
                Sunlight = (Light)field.GetValue(Sun.Instance);
                CloudMaterial.DisableKeyword("WORLD_SPACE_ON");
                CloudMaterial.DisableKeyword("SOFT_DEPTH_ON");
                CloudMaterial.renderQueue = (int)Tools.Queue.Transparent - 1;
            }

            if (isMainMenu)
            {
                try
                {
                    Sunlight = GameObject.FindObjectsOfType <Light>().Last(l => l.isActiveAndEnabled);
                }
                catch { }
            }

            if (ShadowProjector != null)
            {
                float dist = (float)(2 * radiusScaleWorld);
                ShadowProjector.farClipPlane     = dist;
                ShadowProjector.orthographicSize = radiusScaleWorld;

                macroCloudMaterial.ApplyMaterialProperties(ShadowProjector.material, worldScale);
                cloudsMat.ApplyMaterialProperties(ShadowProjector.material, worldScale);

                ShadowProjector.material.SetFloat("_Radius", (float)radiusScaleLocal);
                ShadowProjector.material.SetFloat("_PlanetRadius", (float)celestialBody.Radius * worldScale);
                ShadowProjector.transform.parent = parent;

                ShadowProjectorGO.layer = (int)Tools.Layer.Scaled; //move these to init since no longer need to change
                if (layer == Tools.Layer.Scaled)
                {
                    ShadowProjector.ignoreLayers = ~layer.Mask();
                    ShadowProjector.material.DisableKeyword("WORLD_SPACE_ON");
                }

                if (screenSpaceShadowGO != null)
                {
                    macroCloudMaterial.ApplyMaterialProperties(screenSpaceShadow.material, worldScale);
                    cloudsMat.ApplyMaterialProperties(screenSpaceShadow.material, worldScale);

                    screenSpaceShadow.material.SetFloat("_Radius", (float)radiusScaleLocal);
                    screenSpaceShadow.material.SetFloat("_PlanetRadius", (float)celestialBody.Radius * worldScale);

                    screenSpaceShadowGO.SetActive(layer == Tools.Layer.Local);
                    screenSpaceShadow.SetActive(layer == Tools.Layer.Local);
                }
            }
        }
        public void Apply()
        {
            ShadowManager.Log("Applying to " + body);
            CelestialBody celestialBody = Tools.GetCelestialBody(body);

            Transform transform = Tools.GetScaledTransform(body);

            if (transform != null)
            {
                Renderer mr = transform.GetComponent <Renderer>();
                if (mr != null && hasSurface)
                {
                    shadowMat = new Material(ShadowShader);
                    GameObject go = new GameObject();
                    go.name = "EVE Shadows";

                    localShadowMat = new Material(ScreenSpaceShadowShader);

                    screenSpaceShadowGO = new GameObject("EVE Celestial ScreenSpaceShadow");
                    screenSpaceShadowGO.transform.parent = celestialBody.transform;
                    screenSpaceShadow          = screenSpaceShadowGO.AddComponent <ScreenSpaceShadow>();
                    screenSpaceShadow.material = localShadowMat;
                    screenSpaceShadow.Init();
                    screenSpaceShadowGO.SetActive(false);
                    screenSpaceShadow.SetActive(false);

                    shadowMat.SetFloat(ShaderProperties._SunRadius_PROPERTY, (float)(ScaledSpace.InverseScaleFactor * Sun.Instance.sun.Radius));
                    localShadowMat.SetFloat(ShaderProperties._SunRadius_PROPERTY, (float)(Sun.Instance.sun.Radius));

                    shadowMat.name        = materialName;
                    shadowMat.renderQueue = (int)Tools.Queue.Geometry + 3;

                    localShadowMat.name        = materialName;
                    localShadowMat.renderQueue = (int)Tools.Queue.Geometry + 3;

                    DeferredRenderer.Add(mr.gameObject, shadowMat);
                }

                ScaledShadowComponent sc  = transform.gameObject.AddComponent <ScaledShadowComponent>();
                LocalShadowComponent  lsc = FlightCamera.fetch.mainCamera.gameObject.AddComponent <LocalShadowComponent>();

                List <CelestialBody> casters = new List <CelestialBody>();
                if (caster != null)
                {
                    foreach (String b in caster)
                    {
                        casters.Add(Tools.GetCelestialBody(b));
                    }
                }
                sc.Apply(shadowMat, celestialBody, casters);
                lsc.Apply(localShadowMat, celestialBody, casters, screenSpaceShadowGO, screenSpaceShadow);
            }

            ApplyToMainMenu();

            GameEvents.onGameSceneLoadRequested.Add(SceneLoaded);
            if (HighLogic.LoadedScene == GameScenes.MAINMENU)
            {
                ApplyToMainMenu();
            }
        }