D
D
Dmitry Korolev2017-01-25 20:51:58
C++ / C#
Dmitry Korolev, 2017-01-25 20:51:58

How to implement such a regulator in the inspector?

1a575179ecf648639366134d7fadbabe.png
how to implement such a controller in a script?

Answer the question

In order to leave comments, you need to log in

1 answer(s)
D
Daniil Basmanov, 2017-01-26
@adressmoeistranici

There is no such slider in the API, but you can get to the bottom of it with a decompiler:

UnityEditor.ShadowCascadeSplitGUI
namespace UnityEditor
{
    using System;
    using System.Linq;
    using UnityEngine;

    internal static class ShadowCascadeSplitGUI
    {
        private static readonly Color[] kCascadeColors = new Color[] { new Color(0.5f, 0.5f, 0.6f, 1f), new Color(0.5f, 0.6f, 0.5f, 1f), new Color(0.6f, 0.6f, 0.5f, 1f), new Color(0.6f, 0.5f, 0.5f, 1f) };
        private const int kPartitionHandleExtraHitAreaWidth = 2;
        private const int kPartitionHandleWidth = 2;
        private const int kSliderbarBottomMargin = 2;
        private const int kSliderbarHeight = 0x18;
        private const int kSliderbarTopMargin = 2;
        private static readonly GUIStyle s_CascadeSliderBG = "LODSliderRange";
        private static readonly int s_CascadeSliderId;
        private static DragCache s_DragCache;
        private static DrawCameraMode s_OldSceneDrawMode;
        private static bool s_OldSceneLightingMode;
        private static SceneView s_RestoreSceneView;
        private static readonly GUIStyle s_TextCenteredStyle;

        static ShadowCascadeSplitGUI()
        {
            GUIStyle style = new GUIStyle(EditorStyles.whiteMiniLabel) {
                alignment = TextAnchor.MiddleCenter
            };
            s_TextCenteredStyle = style;
            s_CascadeSliderId = "s_CascadeSliderId".GetHashCode();
            s_OldSceneDrawMode = DrawCameraMode.Textured;
        }

        public static void HandleCascadeSliderGUI(ref float[] normalizedCascadePartitions)
        {
            GUILayout.Label("Cascade splits", new GUILayoutOption[0]);
            GUILayoutOption[] options = new GUILayoutOption[] { GUILayout.Height(28f), GUILayout.ExpandWidth(true) };
            Rect position = GUILayoutUtility.GetRect(GUIContent.none, s_CascadeSliderBG, options);
            GUI.Box(position, GUIContent.none);
            float x = position.x;
            float y = position.y + 2f;
            float num3 = position.width - (normalizedCascadePartitions.Length * 2);
            Color color = GUI.color;
            Color backgroundColor = GUI.backgroundColor;
            int index = -1;
            float[] destinationArray = new float[normalizedCascadePartitions.Length + 1];
            Array.Copy(normalizedCascadePartitions, destinationArray, normalizedCascadePartitions.Length);
            destinationArray[destinationArray.Length - 1] = 1f - normalizedCascadePartitions.Sum();
            int controlID = GUIUtility.GetControlID(s_CascadeSliderId, FocusType.Passive);
            Event current = Event.current;
            int activePartition = -1;
            for (int i = 0; i < destinationArray.Length; i++)
            {
                float num8 = destinationArray[i];
                index = (index + 1) % kCascadeColors.Length;
                GUI.backgroundColor = kCascadeColors[index];
                float width = num3 * num8;
                Rect rect2 = new Rect(x, y, width, 24f);
                GUI.Box(rect2, GUIContent.none, s_CascadeSliderBG);
                x += width;
                GUI.color = Color.white;
                Rect rect3 = rect2;
                string t = string.Format("{0}\n{1:F1}%", i, num8 * 100f);
                GUI.Label(rect3, GUIContent.Temp(t, t), s_TextCenteredStyle);
                if (i == (destinationArray.Length - 1))
                {
                    break;
                }
                GUI.backgroundColor = Color.black;
                Rect rect4 = rect2;
                rect4.x = x;
                rect4.width = 2f;
                GUI.Box(rect4, GUIContent.none, s_CascadeSliderBG);
                Rect rect5 = rect4;
                rect5.xMin -= 2f;
                rect5.xMax += 2f;
                if (rect5.Contains(current.mousePosition))
                {
                    activePartition = i;
                }
                if (s_DragCache == null)
                {
                    EditorGUIUtility.AddCursorRect(rect5, MouseCursor.ResizeHorizontal, controlID);
                }
                x += 2f;
            }
            GUI.color = color;
            GUI.backgroundColor = backgroundColor;
            EventType typeForControl = current.GetTypeForControl(controlID);
            if (typeForControl == EventType.MouseDown)
            {
                if (activePartition >= 0)
                {
                    s_DragCache = new DragCache(activePartition, normalizedCascadePartitions[activePartition], current.mousePosition);
                    if (GUIUtility.hotControl == 0)
                    {
                        GUIUtility.hotControl = controlID;
                    }
                    current.Use();
                    if (s_RestoreSceneView == null)
                    {
                        s_RestoreSceneView = SceneView.lastActiveSceneView;
                        if (s_RestoreSceneView != null)
                        {
                            s_OldSceneDrawMode = s_RestoreSceneView.renderMode;
                            s_OldSceneLightingMode = s_RestoreSceneView.m_SceneLighting;
                            s_RestoreSceneView.renderMode = DrawCameraMode.ShadowCascades;
                        }
                    }
                }
            }
            else if (typeForControl == EventType.MouseUp)
            {
                if (GUIUtility.hotControl == controlID)
                {
                    GUIUtility.hotControl = 0;
                    current.Use();
                }
                s_DragCache = null;
                if (s_RestoreSceneView != null)
                {
                    s_RestoreSceneView.renderMode = s_OldSceneDrawMode;
                    s_RestoreSceneView.m_SceneLighting = s_OldSceneLightingMode;
                    s_RestoreSceneView = null;
                }
            }
            else if ((typeForControl == EventType.MouseDrag) && (GUIUtility.hotControl == controlID))
            {
                Vector2 vector = current.mousePosition - s_DragCache.m_LastCachedMousePosition;
                float num10 = vector.x / num3;
                bool flag = (destinationArray[s_DragCache.m_ActivePartition] + num10) > 0f;
                bool flag2 = (destinationArray[s_DragCache.m_ActivePartition + 1] - num10) > 0f;
                if (flag && flag2)
                {
                    s_DragCache.m_NormalizedPartitionSize += num10;
                    normalizedCascadePartitions[s_DragCache.m_ActivePartition] = s_DragCache.m_NormalizedPartitionSize;
                    if (s_DragCache.m_ActivePartition < (normalizedCascadePartitions.Length - 1))
                    {
                        normalizedCascadePartitions[s_DragCache.m_ActivePartition + 1] -= num10;
                    }
                    GUI.changed = true;
                }
                s_DragCache.m_LastCachedMousePosition = current.mousePosition;
                current.Use();
            }
        }

        private class DragCache
        {
            public int m_ActivePartition;
            public Vector2 m_LastCachedMousePosition;
            public float m_NormalizedPartitionSize;

            public DragCache(int activePartition, float normalizedPartitionSize, Vector2 currentMousePos)
            {
                this.m_ActivePartition = activePartition;
                this.m_NormalizedPartitionSize = normalizedPartitionSize;
                this.m_LastCachedMousePosition = currentMousePos;
            }
        }
    }
}

As you can see from the code above, a regular GUI.Box is used in combination with an Event . To get something similar, you have to do a lot of manual work, I would not bother if I were you, until it is completely pinned down. You can also try using ShadowCascadeSplitGUI through reflection, but not the fact that it will start.
It is called from the QualitySettingsEditor as follows:
private void DrawCascadeSplitGUI<T>(ref SerializedProperty shadowCascadeSplit)
{
    float[] normalizedCascadePartitions = null;
    Type type = typeof(T);
    if (type == typeof(float))
    {
        normalizedCascadePartitions = new float[] { shadowCascadeSplit.floatValue };
    }
    else if (type == typeof(Vector3))
    {
        Vector3 vector = shadowCascadeSplit.vector3Value;
        normalizedCascadePartitions = new float[] { Mathf.Clamp(vector[0], 0f, 1f), Mathf.Clamp((float)(vector[1] - vector[0]), (float)0f, (float)1f), Mathf.Clamp((float)(vector[2] - vector[1]), (float)0f, (float)1f) };
    }
    if (normalizedCascadePartitions != null)
    {
        EditorGUI.BeginChangeCheck();
        // ↓↓↓↓
        ShadowCascadeSplitGUI.HandleCascadeSliderGUI(ref normalizedCascadePartitions);
        // ↑↑↑↑
        if (EditorGUI.EndChangeCheck())
        {
            if (type == typeof(float))
            {
                shadowCascadeSplit.floatValue = normalizedCascadePartitions[0];
            }
            else
            {
                Vector3 vector2 = new Vector3();
                vector2[0] = normalizedCascadePartitions[0];
                vector2[1] = vector2[0] + normalizedCascadePartitions[1];
                vector2[2] = vector2[1] + normalizedCascadePartitions[2];
                shadowCascadeSplit.vector3Value = vector2;
            }
        }
    }
}

At the same time, I decompiled the editor of the LODGroup component, where there is a similar slider, but the code there is much more confusing.
UnityEditor.LODGroupEditor
UnityEditor.LODGroupGUI

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question