Beispiel #1
0
    private void ProbeFinish()
    {
        EditorApplication.isPlaying = false;
        mset.SkyManager skmgr = mset.SkyManager.Get();
        foreach (mset.Sky sky in skmgr.SkiesToProbe)
        {
            if (sky.SpecularCube as Cubemap)
            {
                mset.CubeMipProcessor.CreateSubMips(sky.SpecularCube as Cubemap);
                mset.SHUtil.projectCube(ref sky.SH, sky.SpecularCube as Cubemap, 3, true);
                mset.SHUtil.convolve(ref sky.SH);
                sky.SH.copyToBuffer();
            }
            sky.Dirty = true;
        }
        proProbe           = null;
        freeProbe          = null;
        skmgr.SkiesToProbe = null;
        AssetDatabase.Refresh();

        skmgr.ShowSkybox = skmgr.ShowSkybox;
        skmgr.EditorUpdate(true);
        skmgr.ProbeExposures = Vector4.one;

        EditorUtility.ClearProgressBar();
        mset.SkyInspector.forceRefresh();

        if (DoneCallback != null)
        {
            DoneCallback();
        }
        DoneCallback = null;

        Close();
    }
Beispiel #2
0
 public void OnEnable()
 {
     mset.SkyManager mgr = target as mset.SkyManager;
     if (mgr.GlobalSky == null)
     {
         mgr.GlobalSky = GameObject.FindObjectOfType <mset.Sky>();
     }
     mgr.EditorUpdate(true);
 }
Beispiel #3
0
        public override void OnInspectorGUI()
        {
            GUI.changed = false;
            bool dirty    = false;              //flag for changed sky parameters
            bool dirtyRef = false;              //flag for changed sky cubemap references (causes SH recompute and preview refresh)

            mset.Sky           sky    = target as mset.Sky;
            mset.SkyApplicator app    = sky.gameObject.GetComponent <mset.SkyApplicator>();
            mset.SkyManager    skymgr = mset.SkyManager.Get();

            //sync GUI from sky
            camExposure     = sky.CamExposure;
            masterIntensity = sky.MasterIntensity;
            skyIntensity    = sky.SkyIntensity;
            diffIntensity   = sky.DiffIntensity;
            specIntensity   = sky.SpecIntensity;
            diffIntensityLM = sky.DiffIntensityLM;
            specIntensityLM = sky.SpecIntensityLM;

            //sync and sync from CubeGUIs
            refSIM.computeSH = (sky.CustomSH == null);

            dirtyRef |= skyToGUI(sky.SkyboxCube, sky.HDRSky, sky.SH, refSKY, sky.name, true);
            bool    prevHDR = sky.HDRSky;
            bool    currHDR = sky.HDRSky;
            Texture refCube = sky.SkyboxCube;

            dirtyRef |= GUIToSky(ref refCube, ref currHDR, null, refSKY);
            if (refCube != sky.SkyboxCube)
            {
                sky.SkyboxCube = refCube;
            }
            if (currHDR != prevHDR)
            {
                sky.HDRSky = currHDR;
            }

            dirtyRef |= skyToGUI(sky.SpecularCube, sky.HDRSpec, sky.SH, refSIM, sky.name, true);
            prevHDR   = sky.HDRSpec;
            currHDR   = sky.HDRSpec;
            refCube   = sky.SpecularCube;
            dirtyRef |= GUIToSky(ref refCube, ref currHDR, sky.SH, refSIM);
            if (refCube != sky.SpecularCube)
            {
                sky.SpecularCube = refCube;
            }
            if (currHDR != prevHDR)
            {
                sky.HDRSpec = currHDR;
            }

            EditorGUILayout.Space();
            EditorGUILayout.BeginHorizontal();

            string ashTip = "Accepts custom diffuse irradiance .asset files generated in other software (such as Knald Lys: www.knaldtech.com)\n\nWill override diffuse light generated from the specular cubemap.";

            EditorGUILayout.LabelField(new GUIContent("Custom Diffuse SH (Optional)", ashTip), GUILayout.Width(248));
            if (GUILayout.Button("None", GUILayout.Width(50), GUILayout.Height(14)))
            {
                sky.CustomSH     = null;
                refSIM.computeSH = true;
                refSIM.reloadReference();
            }
            EditorGUILayout.EndHorizontal();

            sky.CustomSH = EditorGUILayout.ObjectField(sky.CustomSH, typeof(mset.SHEncodingFile), false, GUILayout.Width(320)) as mset.SHEncodingFile;
            if (sky.CustomSH != null)
            {
                sky.SH.copyFrom(sky.CustomSH.SH);
                sky.SH.copyToBuffer();
            }
            refSIM.computeSH = (sky.CustomSH == null);

            GUIStyle buttonStyle = new GUIStyle("Button");

            buttonStyle.padding.top  = buttonStyle.padding.bottom = 0;
            buttonStyle.padding.left = buttonStyle.padding.right = 0;

            EditorGUILayout.Space();
            EditorGUILayout.Space();
            EditorGUILayout.Space();
            EditorGUILayout.Space();

            GUILayout.BeginHorizontal();
            //Global button
            if (skymgr != null)
            {
                bool alreadyGlobal = skymgr.GlobalSky == sky;
                EditorGUI.BeginDisabledGroup(alreadyGlobal);
                bool setAsGlobal = GUILayout.Button(new GUIContent("Make Global Sky", "Sets this sky as the global sky in the Sky Manager."), GUILayout.Width(120));
                if (setAsGlobal)
                {
                    skymgr.GlobalSky = sky;
                    SceneView.RepaintAll();
                }
                EditorGUI.EndDisabledGroup();
            }
            //Local Apply button
            EditorGUI.BeginDisabledGroup(app == null || !app.TriggerIsActive);
            string trigTip = "Applies this sky locally only to renderers contained within its Sky Applicator trigger volume.";

            if (app == null || !app.TriggerIsActive)
            {
                trigTip = "Requires Sky Applicator component with active trigger.";
            }

            if (GUILayout.Button(new GUIContent("Preview Apply", trigTip), GUILayout.Width(100)))
            {
                Renderer[] all = GameObject.FindObjectsOfType <Renderer>();
                foreach (Renderer r in all)
                {
                    app.ApplyInside(r);
                }
            }
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();

            //color detection is always on, but still required for LDR skies to function

            /*bool detect = EditorGUILayout.Toggle(new GUIContent("Auto-Detect Color Space","If enabled, attempts to detect the project's gamma correction setting and enables/disables the Linear Space option accordingly"), sky.AutoDetectColorSpace);
             * if( detect != sky.AutoDetectColorSpace ) {
             *      mset.EditorUtil.RegisterUndo(sky, "Color-Space Detection Change");
             *      sky.AutoDetectColorSpace = detect;
             * }
             * bool prevLinear = sky.LinearSpace;
             */

            sky.AutoDetectColorSpace = true;
            if (sky.AutoDetectColorSpace)
            {
                detectColorSpace(ref sky);
            }


            /*
             * EditorGUI.BeginDisabledGroup(sky.AutoDetectColorSpace);
             *      bool userLinearSpace = EditorGUILayout.Toggle(new GUIContent("Linear Space","Enable if gamma correction is enabled for this project (Edit -> Project Settings -> Player -> Color Space: Linear)"), sky.LinearSpace);
             *      if( userLinearSpace != sky.LinearSpace ) {
             *              mset.EditorUtil.RegisterUndo(sky, "Color-Space Change");
             *              sky.LinearSpace = userLinearSpace;
             *      }
             * EditorGUI.EndDisabledGroup();
             * if( prevLinear != sky.LinearSpace ){
             * //	dirty = true;
             * }
             */

            sky.IsProbe = EditorGUILayout.Toggle(new GUIContent("Is Probe", "Enable if this sky has been rendered from within the scene. The \"Probe All Skies\" feature will only process skies marked as probes."), sky.IsProbe);

            bool prevProj = sky.HasDimensions;
            bool boxProj  = EditorGUILayout.Toggle(new GUIContent("Box Projected", "Assign box dimensions to this sky for parallaxed specular reflection."), sky.HasDimensions);

            if (boxProj != prevProj)
            {
                mset.EditorUtil.RegisterUndo(sky, "Box Projection Toggle");
                sky.HasDimensions = boxProj;
            }

            EditorGUILayout.BeginHorizontal();
            if (skymgr != null)
            {
                skymgr.ProbeOnlyStatic = EditorGUILayout.Toggle(new GUIContent("Probe Only Static Objects", ""), skymgr.ProbeOnlyStatic);
                EditorGUI.BeginDisabledGroup(true);
                EditorGUILayout.LabelField("(Global Setting)", GUILayout.Width(320));
                EditorGUI.EndDisabledGroup();
            }
            else
            {
                EditorGUI.BeginDisabledGroup(true);
                EditorGUILayout.Toggle(new GUIContent("Probe Only Static Objects", "Requires a Sky Manager object to be present in the scene."), false);
                EditorGUILayout.LabelField("(Missing Sky Manager in scene)", GUILayout.Width(320));
                EditorGUI.EndDisabledGroup();
            }
            EditorGUILayout.EndHorizontal();

            bool hasTrigger = app && app.TriggerIsActive;

            EditMode prevMode = editMode;

            EditorGUILayout.Space();
            Bounds dim = sky.Dimensions;

            dim.center     = EditorGUILayout.Vector3Field("Projector Center", dim.center);
            dim.size       = EditorGUILayout.Vector3Field("Projector Size", dim.size);
            sky.Dimensions = dim;

            EditorGUILayout.Space();
            EditorGUILayout.Space();

            GUIStyle style = new GUIStyle();

            style.richText = true;
            GUILayout.Label("<b>Viewport Edit Mode</b>", style);

            if (editIconListFull == null)
            {
                editIconListFull = new Texture2D[] {
                    Resources.Load <Texture2D>("editTrans"),
                    Resources.Load <Texture2D>("editProbe"),
                    Resources.Load <Texture2D>("editProjection"),
                    Resources.Load <Texture2D>("editTrigger")
                };

                editIconListAdd = new Texture2D[] {
                    editIconListFull[0],
                    editIconListFull[1],
                    Resources.Load <Texture2D>("addProjection"),
                    Resources.Load <Texture2D>("addTrigger")
                };

                editIconListProj = new Texture2D[] {
                    editIconListFull[0],
                    editIconListFull[1],
                    editIconListFull[2],
                    editIconListAdd[3]                     //no trigger
                };

                editIconListTrigger = new Texture2D[] {
                    editIconListFull[0],
                    editIconListFull[1],
                    editIconListAdd[2],                     //no projection
                    editIconListFull[3]
                };
            }

            int barWidth = 340;

            //reset edit mode if we've lost the tools we need for this sky configuration
            if (editMode == EditMode.PROJECTOR && !boxProj)
            {
                editMode = EditMode.TRANSFORM;
            }
            if (editMode == EditMode.TRIGGER && !hasTrigger)
            {
                editMode = EditMode.TRANSFORM;
            }

            if (hasTrigger && boxProj)
            {
                editMode = (EditMode)GUILayout.Toolbar((int)editMode, editIconListFull, GUILayout.Width(barWidth));
            }
            else if (boxProj)
            {
                editMode = (EditMode)GUILayout.Toolbar((int)editMode, editIconListProj, GUILayout.Width(barWidth));
            }
            else if (hasTrigger)
            {
                editMode = (EditMode)GUILayout.Toolbar((int)editMode, editIconListTrigger, GUILayout.Width(barWidth));
            }
            else
            {
                editMode = (EditMode)GUILayout.Toolbar((int)editMode, editIconListAdd, GUILayout.Width(barWidth));
            }

            if (!boxProj && editMode == EditMode.PROJECTOR)
            {
                boxProj           = true;
                sky.HasDimensions = true;
                editMode          = EditMode.PROJECTOR;
            }

            if (!hasTrigger && editMode == EditMode.TRIGGER)
            {
                hasTrigger = true;
                if (!app)
                {
                    app = sky.gameObject.AddComponent <mset.SkyApplicator>();
                }
                app.TriggerIsActive = true;
            }

            EditorGUILayout.BeginHorizontal(GUILayout.Width(barWidth));
            GUILayout.Label("Transform", GUILayout.Width(82));
            GUILayout.Label("Probe Origin", GUILayout.Width(82));
            if (boxProj)
            {
                GUILayout.Label("Projector", GUILayout.Width(86));
            }
            else
            {
                GUILayout.Label("Add Projector", GUILayout.Width(86));
            }
            if (hasTrigger)
            {
                GUILayout.Label("Trigger", GUILayout.Width(60));
            }
            else
            {
                GUILayout.Label("Add Trigger", GUILayout.Width(80));
            }
            EditorGUILayout.EndHorizontal();

            //edit mode has changed, sync or sync from stored bound centers
            if (prevMode != editMode)
            {
                projCenter = sky.transform.localToWorldMatrix.MultiplyPoint(sky.Dimensions.center);
                if (app)
                {
                    appCenter = sky.transform.localToWorldMatrix.MultiplyPoint(app.TriggerDimensions.center);
                }
                else
                {
                    appCenter = sky.transform.position;
                }
            }
            //turn on applicator resize handle drawing
            mset.SkyApplicatorInspector.triggerEdit = editMode == EditMode.TRIGGER;

            EditorGUILayout.Space();
            EditorGUILayout.Space();
            EditorGUILayout.Space();

            //sync sky from GUI
            EditorGUILayout.LabelField(new GUIContent("Master Intensity", "Multiplier on the Sky, Diffuse, and Specular cube intensities"));
            masterIntensity = EditorGUILayout.Slider(masterIntensity, 0f, 10f);
            if (sky.MasterIntensity != masterIntensity)
            {
                mset.EditorUtil.RegisterUndo(sky, "Intensity Change");
                sky.MasterIntensity = masterIntensity;
            }

            EditorGUILayout.LabelField(new GUIContent("Skybox Intensity", "Brightness of the skybox"));
            skyIntensity = EditorGUILayout.Slider(skyIntensity, 0f, 10f);
            if (sky.SkyIntensity != skyIntensity)
            {
                mset.EditorUtil.RegisterUndo(sky, "Intensity Change");
                sky.SkyIntensity = skyIntensity;
            }

            EditorGUILayout.LabelField(new GUIContent("Diffuse Intensity", "Multiplier on the diffuse light put out by this sky"));
            diffIntensity = EditorGUILayout.Slider(diffIntensity, 0f, 10f);
            if (sky.DiffIntensity != diffIntensity)
            {
                mset.EditorUtil.RegisterUndo(sky, "Intensity Change");
                sky.DiffIntensity = diffIntensity;
            }

            EditorGUILayout.LabelField(new GUIContent("Specular Intensity", "Multiplier on the specular light put out by this sky"));
            specIntensity = EditorGUILayout.Slider(specIntensity, 0f, 10f);
            if (sky.SpecIntensity != specIntensity)
            {
                mset.EditorUtil.RegisterUndo(sky, "Intensity Change");
                sky.SpecIntensity = specIntensity;
            }

            EditorGUILayout.Space();
            EditorGUILayout.Space();
            EditorGUILayout.Space();

            EditorGUILayout.LabelField(new GUIContent("Camera Exposure", "Multiplier on all light coming into the camera, including IBL, direct light, and glow maps"));
            camExposure = EditorGUILayout.Slider(camExposure, 0f, 10f);
            if (sky.CamExposure != camExposure)
            {
                mset.EditorUtil.RegisterUndo(sky, "Exposure Change");
                sky.CamExposure = camExposure;
            }

            EditorGUILayout.Space();
            EditorGUILayout.Space();

            EditorGUILayout.LabelField(new GUIContent("Lightmapped Diffuse Multiplier", "Multiplier on the diffuse intensity for lightmapped surfaces"));
            diffIntensityLM = EditorGUILayout.Slider(diffIntensityLM, 0f, 1f);
            if (sky.DiffIntensityLM != diffIntensityLM)
            {
                mset.EditorUtil.RegisterUndo(sky, "Multiplier Change");
                sky.DiffIntensityLM = diffIntensityLM;
            }

            EditorGUILayout.LabelField(new GUIContent("Lightmapped Specular Multiplier", "Multiplier on the specular intensity for lightmapped surfaces"));
            specIntensityLM = EditorGUILayout.Slider(specIntensityLM, 0f, 1f);
            if (sky.SpecIntensityLM != specIntensityLM)
            {
                mset.EditorUtil.RegisterUndo(sky, "Multiplier Change");
                sky.SpecIntensityLM = specIntensityLM;
            }

            dirty |= GUI.changed;

            if (forceDirty)
            {
                refSKY.reloadReference();
                refSIM.reloadReference();

                dirtyRef   = true;
                forceDirty = false;
                dirty      = true;
                Repaint();
            }

            //guess input path
            if (dirtyRef)
            {
                string inPath = refSKY.fullPath;
                if (inPath.Length == 0)
                {
                    inPath = refSIM.fullPath;
                }
                if (inPath.Length > 0)
                {
                    int uscore = inPath.LastIndexOf("_");
                    if (uscore > -1)
                    {
                        inPath = inPath.Substring(0, uscore);
                    }
                    else
                    {
                        inPath = Path.GetDirectoryName(inPath) + "/" + Path.GetFileNameWithoutExtension(inPath);
                    }
                    refSKY.inputPath     =
                        refSIM.inputPath = inPath;
                }
                else
                {
                    refSKY.inputPath     =
                        refSIM.inputPath = "";
                }
                dirty = true;
            }

            if (GUI.changed)
            {
                EditorUtility.SetDirty(target);
            }

            //reapply and repaint with manager
            mset.SkyManager mgr = mset.SkyManager.Get();

            if (!Application.isPlaying)
            {
                if (dirty || mgr && mgr.GlobalSky)
                {
                    sky.EditorUpdate();
                    if (mgr)
                    {
                        mgr.EditorUpdate(true);
                        SceneView.RepaintAll();
                    }
                }
            }
        }
Beispiel #4
0
        //	Vector3 dotPos;
        public void OnSceneGUI()
        {
            mset.Sky sky = target as mset.Sky;

            if (this.editMode == EditMode.TRIGGER)
            {
                return;
            }

            if (sky.HasDimensions)
            {
                Vector3 campos = Vector3.zero;
                if (Camera.current != null)
                {
                    campos = Camera.current.transform.position;
                }

                Vector3 skyScale = sky.transform.lossyScale;
                if (skyScale.x == 0)
                {
                    skyScale.x = 0.001f;
                }
                if (skyScale.y == 0)
                {
                    skyScale.y = 0.001f;
                }
                if (skyScale.z == 0)
                {
                    skyScale.z = 0.001f;
                }

                xscale = x2scale = sky.Dimensions.size.x * 0.5f * skyScale.x;
                yscale = y2scale = sky.Dimensions.size.y * 0.5f * skyScale.y;
                zscale = z2scale = sky.Dimensions.size.z * 0.5f * skyScale.z;

                if (this.editMode == EditMode.PROJECTOR)
                {
                    Handles.color = new Color(0.2f, 0.8f, 1f, 0.9f);
                    Vector3 dotpos;

                    Vector3 boxcenter = sky.transform.localToWorldMatrix.MultiplyPoint(sky.Dimensions.center);

                    dotpos = boxcenter + xscale * sky.transform.right;
                    dotpos = Handles.Slider(dotpos, sky.transform.right, (dotpos - campos).magnitude / 10.0f, Handles.ArrowHandleCap, 0.05f);
                    xscale = ((dotpos - boxcenter)).magnitude;

                    dotpos  = boxcenter + x2scale * -sky.transform.right;
                    dotpos  = Handles.Slider(dotpos, -sky.transform.right, (dotpos - campos).magnitude / 10.0f, Handles.ArrowHandleCap, 0.05f);
                    x2scale = ((dotpos - boxcenter)).magnitude;

                    dotpos = boxcenter + yscale * sky.transform.up;
                    dotpos = Handles.Slider(dotpos, sky.transform.up, (dotpos - campos).magnitude / 10.0f, Handles.ArrowHandleCap, 0.05f);
                    yscale = ((dotpos - boxcenter)).magnitude;

                    dotpos  = boxcenter + y2scale * -sky.transform.up;
                    dotpos  = Handles.Slider(dotpos, -sky.transform.up, (dotpos - campos).magnitude / 10.0f, Handles.ArrowHandleCap, 0.05f);
                    y2scale = ((dotpos - boxcenter)).magnitude;

                    dotpos = boxcenter + zscale * sky.transform.forward;
                    dotpos = Handles.Slider(dotpos, sky.transform.forward, (dotpos - campos).magnitude / 10.0f, Handles.ArrowHandleCap, 0.05f);
                    zscale = ((dotpos - boxcenter)).magnitude;

                    dotpos  = boxcenter + z2scale * -sky.transform.forward;
                    dotpos  = Handles.Slider(dotpos, -sky.transform.forward, (dotpos - campos).magnitude / 10.0f, Handles.ArrowHandleCap, 0.05f);
                    z2scale = ((dotpos - boxcenter)).magnitude;

                    float xposDiff = sky.Dimensions.size.x - (xscale / skyScale.x) * 2 - (sky.Dimensions.size.x - (x2scale / skyScale.x) * 2);
                    float yposDiff = sky.Dimensions.size.y - (yscale / skyScale.y) * 2 - (sky.Dimensions.size.y - (y2scale / skyScale.y) * 2);
                    float zposDiff = sky.Dimensions.size.z - (zscale / skyScale.z) * 2 - (sky.Dimensions.size.z - (z2scale / skyScale.z) * 2);

                    Bounds dim = sky.Dimensions;
                    dim.center += new Vector3(-xposDiff * 0.25f, -yposDiff * 0.25f, -zposDiff * 0.25f);
                    dim.size    = new Vector3((xscale + x2scale) / skyScale.x, (yscale + y2scale) / skyScale.y, (zscale + z2scale) / skyScale.z);

                    if (!dim.center.Equals(sky.Dimensions.center) || !dim.size.Equals(sky.Dimensions.size))
                    {
                        Undo.RecordObject(sky, "Sky Projection Resize");
                        sky.Dimensions = dim;
                        mset.SkyManager mgr = mset.SkyManager.Get();
                        if (mgr)
                        {
                            mgr.EditorUpdate(true);
                        }
                    }
                }
            }

            mset.SkyApplicator app = sky.gameObject.GetComponent <mset.SkyApplicator>();
            if (this.editMode == EditMode.PROBE)
            {
                //moving probe around, recompute local-space sky dimensions from world-space, cached centers
                Bounds dim = sky.Dimensions;
                dim.center = sky.transform.worldToLocalMatrix.MultiplyPoint(projCenter);

                if (dim.center != sky.Dimensions.center)
                {
                    if (app)
                    {
                        UnityEngine.Object[] undoList = { sky, app };
                        Undo.RecordObjects(undoList, "Probe Center Move");
                    }
                    else
                    {
                        Undo.RecordObject(sky, "Probe Center Move");
                    }
                }

                sky.Dimensions = dim;
                if (app)
                {
                    dim                   = app.TriggerDimensions;
                    dim.center            = sky.transform.worldToLocalMatrix.MultiplyPoint(appCenter);
                    app.TriggerDimensions = dim;
                }
            }
            else
            {
                //moving everything around, cache world-space centers of bounds
                projCenter = sky.transform.localToWorldMatrix.MultiplyPoint(sky.Dimensions.center);
                if (app)
                {
                    appCenter = sky.transform.localToWorldMatrix.MultiplyPoint(app.TriggerDimensions.center);
                }
                else
                {
                    appCenter = sky.transform.position;
                }
            }
        }
Beispiel #5
0
        public override void OnInspectorGUI()
        {
            GUI.changed = false;

            mset.SkyManager skmgr = target as mset.SkyManager;
            mset.Sky        nusky = EditorGUILayout.ObjectField("Global Sky", skmgr.GlobalSky, typeof(mset.Sky), true) as mset.Sky;
            if (skmgr.GlobalSky != nusky)
            {
                //TODO: is this necessary?
                if (!Application.isPlaying && nusky != null)
                {
                    nusky.Apply();
                }
                if (nusky == null)
                {
                    RenderSettings.skybox = null;
                }
                skmgr.GlobalSky = nusky;
            }

            skmgr.ShowSkybox = GUILayout.Toggle(skmgr.ShowSkybox, new GUIContent("Show Skybox", "Toggles rendering the global sky's background image in both play and edit modes"));

            EditorGUILayout.Space();
            skmgr.ProjectionSupport = GUILayout.Toggle(skmgr.ProjectionSupport, new GUIContent("Box Projection Support", "Optimization for disabling all box projected cubemap distortion at the shader level"));
            skmgr.BlendingSupport   = GUILayout.Toggle(skmgr.BlendingSupport, new GUIContent("Blending Support", "Optimization for disabling blending transitions between skies at the shader level"));
            skmgr.LocalBlendTime    = EditorGUILayout.FloatField("Local Sky Blend Time", skmgr.LocalBlendTime);
            skmgr.GlobalBlendTime   = EditorGUILayout.FloatField("Global Sky Blend Time", skmgr.GlobalBlendTime);
            EditorGUILayout.Space();


            GUILayout.BeginHorizontal();
            skmgr.GameAutoApply = GUILayout.Toggle(skmgr.GameAutoApply, new GUIContent("Auto-Apply in Game", "If enabled for game mode, Sky Manager will keep and constantly update a list of dynamic renderers in the scene, applying local skies to them as they move around.\n\nRequired for dynamic sky binding and Sky Applicator triggers.\n\nNOTE: This feature causes material instances to be spawned at runtime and may hurt render batching."), GUILayout.Width(128));
            EditorGUI.BeginDisabledGroup(true);
            GUILayout.Label("(Creates material instances)");
            EditorGUI.EndDisabledGroup();
            GUILayout.EndHorizontal();

            skmgr.EditorAutoApply = GUILayout.Toggle(skmgr.EditorAutoApply, new GUIContent("Auto-Apply in Editor", "If enabled for edit mode, Sky Manager will apply local skies to renderers contained in their Sky Applicator trigger volumes.\n\nAffects editor viewport only."));
            skmgr.AutoMaterial    = GUILayout.Toggle(skmgr.AutoMaterial, new GUIContent("Dynamic Materials", "Periodically update the material caches in Sky Anchors. Enable if material lists of renderers are going to change at runtime (e.g. adding, removing, or replacing material references of renderers, property changes won't matter)."));

            //NOTE: The _ vars are stored in sky manager because they're part of the saved state. Pulling the list of layers from the bit mask instead of a full int array would sort the layer list every frame.
            skmgr._IgnoredLayerCount = EditorGUILayout.IntField("Ignored Layer Count", skmgr._IgnoredLayerCount);

            //if never allocated before, allocate ignoredLayers list here, it's only ever used here to display and configure the true hero: IgnoredLayerMask
            if (skmgr._IgnoredLayers == null)
            {
                skmgr._IgnoredLayers = new int[32];
            }

            skmgr.IgnoredLayerMask = 0;
            for (int i = 0; i < skmgr._IgnoredLayerCount; ++i)
            {
                skmgr._IgnoredLayers[i] = EditorGUILayout.LayerField(" ", skmgr._IgnoredLayers[i]);
                skmgr.IgnoredLayerMask |= 1 << skmgr._IgnoredLayers[i];
            }

            GUILayout.BeginHorizontal();
            if (GUILayout.Button(new GUIContent("Preview Auto-Apply", "Updates editor viewport to show an accurate representation of which renderers will be bound to which skies in the game.\n\nEditor Auto-Apply performs this every frame."), GUILayout.Width(140)))
            {
                skmgr.EditorUpdate(true);
                SceneView.RepaintAll();
            }
            GUILayout.EndHorizontal();


            EditorGUILayout.Space();

            string tipExponent = "Highest gloss exponent use in the specular mip chain when capturing probes. Other exponents in the chain are generated from this value.";

            skmgr.ProbeExponent = EditorGUILayout.IntField(new GUIContent("Probe Specular Exponent", tipExponent), skmgr.ProbeExponent);
            skmgr.ProbeExponent = Mathf.Max(1, skmgr.ProbeExponent);

            string staticTip = "If enabled, only GameObjects marked as \"Static\" will be rendered when capturing cubemaps.";

            skmgr.ProbeOnlyStatic = GUILayout.Toggle(skmgr.ProbeOnlyStatic, new GUIContent("Probe Only Static Objects", staticTip));

            string dx11Tip = "Uses HDR render-textures to capture sky probes faster and with better quality.\n\nRequires project to be in Direct3D 11 mode while capturing.";

            if (PlayerSettings.useDirect3D11)
            {
                skmgr.ProbeWithCubeRT = GUILayout.Toggle(skmgr.ProbeWithCubeRT, new GUIContent("Probe Using Render-to-Cubemap", dx11Tip));
            }
            else
            {
                EditorGUI.BeginDisabledGroup(true);
                GUILayout.Toggle(false, new GUIContent("Probe Using Render-to-Cubemap (Requires Direct3D11)", dx11Tip));
                EditorGUI.EndDisabledGroup();
            }

            string camTip = "Sky probing is performed using the settings and clipping planes of this camera. If field is empty, Main Camera is used.";

            skmgr.ProbeCamera = EditorGUILayout.ObjectField(new GUIContent("Probe with Camera", camTip), skmgr.ProbeCamera, typeof(Camera), true) as Camera;


            GUILayout.BeginHorizontal();
            if (GUILayout.Button(new GUIContent("Probe Skies (Direct)"), GUILayout.Width(140)))
            {
                bool probeNonProbes = false;
                bool probeIBL       = false;
                Probeshop.ProbeSkies(null, GameObject.FindObjectsOfType <mset.Sky>(), probeNonProbes, probeIBL, null);
            }
            if (GUILayout.Button("Probe Skies (Direct+IBL)", GUILayout.Width(170)))
            {
                bool probeNonProbes = false;
                bool probeIBL       = true;
                Probeshop.ProbeSkies(null, GameObject.FindObjectsOfType <mset.Sky>(), probeNonProbes, probeIBL, null);
            }
            GUILayout.EndHorizontal();

            if (GUI.changed)
            {
                skmgr.EditorUpdate(true);
                EditorUtility.SetDirty(target);
                SceneView.RepaintAll();
            }
        }