├── EditorStyleScriptable
├── Example.meta
├── Scripts.meta
├── Scripts
│ ├── Editor.meta
│ ├── EditorStyleScriptable.cs.meta
│ ├── Editor
│ │ ├── EditorStyleEditor.cs.meta
│ │ └── EditorStyleEditor.cs
│ └── EditorStyleScriptable.cs
├── EditorStyleScriptable
│ ├── Example.meta
│ ├── Scripts.meta
│ ├── Scripts
│ │ ├── Editor.meta
│ │ ├── Editor
│ │ │ ├── EditorStyleEditor.cs.meta
│ │ │ └── EditorStyleEditor.cs
│ │ ├── EditorStyleScriptable.cs.meta
│ │ └── EditorStyleScriptable.cs
│ ├── EditorStyles.asset.meta
│ └── Example
│ │ ├── ExampleGUITest.cs.meta
│ │ └── ExampleGUITest.cs
├── EditorStyles.asset.meta
└── Example
│ ├── ExampleGUITest.cs.meta
│ └── ExampleGUITest.cs
├── LICENSE
├── .gitignore
└── README.md
/EditorStyleScriptable/Example.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d2dc1d7b81aef194c95959d1acce65cc
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/Scripts.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e8ffd2f4ef09900409ba66f9df6603b5
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/Scripts/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a5b5f436a7c25ae4db34e426e4201853
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyleScriptable/Example.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d2dc1d7b81aef194c95959d1acce65cc
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyleScriptable/Scripts.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e8ffd2f4ef09900409ba66f9df6603b5
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyles.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d0b6bf578bdb8fb48814a6915a5b86c7
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 0
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyleScriptable/Scripts/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a5b5f436a7c25ae4db34e426e4201853
3 | folderAsset: yes
4 | DefaultImporter:
5 | externalObjects: {}
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyleScriptable/EditorStyles.asset.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d0b6bf578bdb8fb48814a6915a5b86c7
3 | NativeFormatImporter:
4 | externalObjects: {}
5 | mainObjectFileID: 0
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/Example/ExampleGUITest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3587830093cd86b4cbabe9679981a69d
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/Scripts/EditorStyleScriptable.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e179756097a0f694d92b0eb818ae69f1
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/Scripts/Editor/EditorStyleEditor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4c29cbda6bb04fe48adc6ab0834942d0
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyleScriptable/Example/ExampleGUITest.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3587830093cd86b4cbabe9679981a69d
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyleScriptable/Scripts/Editor/EditorStyleEditor.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4c29cbda6bb04fe48adc6ab0834942d0
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyleScriptable/Scripts/EditorStyleScriptable.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e179756097a0f694d92b0eb818ae69f1
3 | MonoImporter:
4 | externalObjects: {}
5 | serializedVersion: 2
6 | defaultReferences: []
7 | executionOrder: 0
8 | icon: {instanceID: 0}
9 | userData:
10 | assetBundleName:
11 | assetBundleVariant:
12 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Damian Slocombe
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # This .gitignore file should be placed at the root of your Unity project directory
2 | #
3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
4 | #
5 | /[Ll]ibrary/
6 | /[Tt]emp/
7 | /[Oo]bj/
8 | /[Bb]uild/
9 | /[Bb]uilds/
10 | /[Ll]ogs/
11 | /[Mm]emoryCaptures/
12 |
13 | # Asset meta data should only be ignored when the corresponding asset is also ignored
14 | !/[Aa]ssets/**/*.meta
15 |
16 | # Uncomment this line if you wish to ignore the asset store tools plugin
17 | # /[Aa]ssets/AssetStoreTools*
18 |
19 | # Autogenerated Jetbrains Rider plugin
20 | [Aa]ssets/Plugins/Editor/JetBrains*
21 |
22 | # Visual Studio cache directory
23 | .vs/
24 |
25 | # Gradle cache directory
26 | .gradle/
27 |
28 | # Autogenerated VS/MD/Consulo solution and project files
29 | ExportedObj/
30 | .consulo/
31 | *.csproj
32 | *.unityproj
33 | *.sln
34 | *.suo
35 | *.tmp
36 | *.user
37 | *.userprefs
38 | *.pidb
39 | *.booproj
40 | *.svd
41 | *.pdb
42 | *.mdb
43 | *.opendb
44 | *.VC.db
45 |
46 | # Unity3D generated meta files
47 | *.pidb.meta
48 | *.pdb.meta
49 | *.mdb.meta
50 |
51 | # Unity3D generated file on crash reports
52 | sysinfo.txt
53 |
54 | # Builds
55 | *.apk
56 | *.unitypackage
57 |
58 | # Crashlytics generated file
59 | crashlytics-build.properties
60 |
61 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | Editor Styles Scriptable
3 |
4 |
5 | Small utility addon for Unity to have all EditorStyles cached in a ScriptableObject with previews. Can use the GUIStyles for custom editors, tools or even at game runtime.
6 |
7 |
8 | ## About
9 |
10 | Just while doing some quick debugging, I got really fed up of having to create GUIStyles with tiny changes that were similar to EditorStyles. Now it's super convenient to see the styles and also have them instantly rather than having to create/reference GUIStyles in OnGUI methods.
11 |
12 |
13 |
14 |
15 |
16 | ## Usage
17 |
18 | #### EditorStyleScriptable
19 | The ScriptableObject with all the EditorStyles. Provides some methods for clearing all styles (generally for the editor), adding styles and also finding styles at runtime:
20 |
21 | ```cs
22 | public class ExampleGUITest : MonoBehaviour
23 | {
24 | [SerializeField]
25 | private EditorStyleScriptable editorStyles;
26 |
27 | [SerializeField]
28 | private GUIStyle headerStyle;
29 |
30 | public void Start()
31 | {
32 | //Find the style
33 | headerStyle = editorStyles.GetStyle("BoldLabel");
34 | }
35 |
36 | public void OnGUI()
37 | {
38 | GUI.Label (new Rect(10, 10, 100, 100), "Time values", headerStyle);
39 | }
40 | }
41 | ```
42 |
43 | #### EditorStyleEditor
44 | The editor class containing all reflection behaviour to find the styles. Also custom draws and displays the examples in the ScriptableObject.
45 |
46 | #### ExampleGUITest
47 | Example provided showing a slightly more expansive version of the above.
48 |
49 | ## Feedback
50 |
51 | If there are any problems, or requests to expand upon this, feel free to add an issue or pull request!
52 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/Example/ExampleGUITest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using UnityEngine;
3 | #pragma warning disable CS0649
4 |
5 | public class ExampleGUITest : MonoBehaviour
6 | {
7 | [System.Serializable]
8 | private class DebugValues
9 | {
10 | public string name;
11 | public float value;
12 |
13 | public DebugValues(string name)
14 | {
15 | this.name = name;
16 | }
17 |
18 | public void DrawAsGUI(GUIStyle labelStyle, GUIStyle valueStyle)
19 | {
20 | GUILayout.BeginHorizontal ();
21 | {
22 | GUILayout.Label (name, labelStyle);
23 | GUILayout.Label (value.ToString(), valueStyle);
24 | }
25 | GUILayout.EndHorizontal ();
26 | }
27 | }
28 |
29 | [SerializeField]
30 | private EditorStyleScriptable editorStyles;
31 |
32 | [SerializeField]
33 | private GUIStyle headerStyle, labelStyle, valueStyle;
34 |
35 | private DebugValues[] values = new DebugValues[3]
36 | {
37 | new DebugValues("Delta"),
38 | new DebugValues("Frame Count"),
39 | new DebugValues("Time"),
40 | };
41 |
42 | // Start is called before the first frame update
43 | private void Start()
44 | {
45 | if (editorStyles == null)
46 | {
47 | Debug.LogWarning ("EditorStyles is not assigned!");
48 | return;
49 | }
50 |
51 | headerStyle = editorStyles.GetStyle ("ObjectFieldThumb");
52 | headerStyle.alignment = TextAnchor.MiddleCenter;
53 |
54 | labelStyle = editorStyles.GetStyle ("BoldLabel");
55 | valueStyle = editorStyles.GetStyle ("HelpBox");
56 | }
57 |
58 | // Update is called once per frame
59 | private void Update()
60 | {
61 | values[0].value = Time.deltaTime;
62 | values[1].value = Time.frameCount;
63 | values[2].value = Time.time;
64 | }
65 |
66 | private void OnGUI()
67 | {
68 | if (editorStyles == null)
69 | return;
70 |
71 | //19 is the height of a field (normally)
72 | //So 19*3 for each of the floats, then another 19 for the header
73 | Rect rect = new Rect (10f, 10f, Screen.width - 20f, 19f * 4f);
74 |
75 | //Draw group of values, can call GUI.skin still too for convenience
76 | GUI.BeginGroup (rect, GUI.skin.box);
77 | {
78 | //Use GUILayout to auto layout
79 | GUILayout.Label ("Time values", headerStyle);
80 |
81 | foreach (var value in values)
82 | value.DrawAsGUI (labelStyle, valueStyle);
83 | }
84 | GUI.EndGroup ();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyleScriptable/Example/ExampleGUITest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using UnityEngine;
3 | #pragma warning disable CS0649
4 |
5 | public class ExampleGUITest : MonoBehaviour
6 | {
7 | [System.Serializable]
8 | private class DebugValues
9 | {
10 | public string name;
11 | public float value;
12 |
13 | public DebugValues(string name)
14 | {
15 | this.name = name;
16 | }
17 |
18 | public void DrawAsGUI(GUIStyle labelStyle, GUIStyle valueStyle)
19 | {
20 | GUILayout.BeginHorizontal ();
21 | {
22 | GUILayout.Label (name, labelStyle);
23 | GUILayout.Label (value.ToString(), valueStyle);
24 | }
25 | GUILayout.EndHorizontal ();
26 | }
27 | }
28 |
29 | [SerializeField]
30 | private EditorStyleScriptable editorStyles;
31 |
32 | [SerializeField]
33 | private GUIStyle headerStyle, labelStyle, valueStyle;
34 |
35 | private DebugValues[] values = new DebugValues[3]
36 | {
37 | new DebugValues("Delta"),
38 | new DebugValues("Frame Count"),
39 | new DebugValues("Time"),
40 | };
41 |
42 | // Start is called before the first frame update
43 | private void Start()
44 | {
45 | if (editorStyles == null)
46 | {
47 | Debug.LogWarning ("EditorStyles is not assigned!");
48 | return;
49 | }
50 |
51 | headerStyle = editorStyles.GetStyle ("ObjectFieldThumb");
52 | headerStyle.alignment = TextAnchor.MiddleCenter;
53 |
54 | labelStyle = editorStyles.GetStyle ("BoldLabel");
55 | valueStyle = editorStyles.GetStyle ("HelpBox");
56 | }
57 |
58 | // Update is called once per frame
59 | private void Update()
60 | {
61 | values[0].value = Time.deltaTime;
62 | values[1].value = Time.frameCount;
63 | values[2].value = Time.time;
64 | }
65 |
66 | private void OnGUI()
67 | {
68 | if (editorStyles == null)
69 | return;
70 |
71 | //19 is the height of a field (normally)
72 | //So 19*3 for each of the floats, then another 19 for the header
73 | Rect rect = new Rect (10f, 10f, Screen.width - 20f, 19f * 4f);
74 |
75 | //Draw group of values, can call GUI.skin still too for convenience
76 | GUI.BeginGroup (rect, GUI.skin.box);
77 | {
78 | //Use GUILayout to auto layout
79 | GUILayout.Label ("Time values", headerStyle);
80 |
81 | foreach (var value in values)
82 | value.DrawAsGUI (labelStyle, valueStyle);
83 | }
84 | GUI.EndGroup ();
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/EditorStyleScriptable/Scripts/EditorStyleScriptable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | [CreateAssetMenu ()]
6 | public class EditorStyleScriptable : ScriptableObject, ISerializationCallbackReceiver
7 | {
8 | [Serializable]
9 | public class GUIStyleRef
10 | {
11 | public string name;
12 | public GUIStyle style;
13 |
14 | public GUIStyleRef(GUIStyle style)
15 | {
16 | this.name = style.name;
17 | this.style = style;
18 | }
19 | }
20 |
21 | [SerializeField]
22 | private List editorStyles = new List ();
23 | private static Dictionary styleLookup;
24 |
25 | ///
26 | /// Current style count
27 | ///
28 | public int StyleCount => editorStyles.Count;
29 |
30 | ///
31 | /// Add a style to the collection.
32 | ///
33 | public void AddStyle(GUIStyle style)
34 | {
35 | if (styleLookup.ContainsKey (style.name))
36 | return;
37 |
38 | GUIStyleRef styleRef = new GUIStyleRef (style);
39 | editorStyles.Add (styleRef);
40 | styleLookup.Add (styleRef.name, style);
41 | }
42 |
43 | ///
44 | /// Add multiple styles. Will call for each one.
45 | ///
46 | public void AddStyles(IEnumerable styles)
47 | {
48 | foreach (var style in styles)
49 | AddStyle (style);
50 | }
51 |
52 | ///
53 | /// Clear all style information.
54 | ///
55 | public void ClearStyles()
56 | {
57 | editorStyles.Clear ();
58 | styleLookup?.Clear ();
59 | }
60 |
61 | ///
62 | /// Find a style with the given name.
63 | ///
64 | /// Name of the style to find
65 | public GUIStyle GetStyle(string name)
66 | {
67 | if (string.IsNullOrEmpty (name))
68 | return null;
69 |
70 | if (styleLookup.ContainsKey (name))
71 | return styleLookup[name];
72 |
73 | return null;
74 | }
75 |
76 | public int GetStyleIndex(string name)
77 | {
78 | return editorStyles.FindIndex (s => s.name == name);
79 | }
80 |
81 | ///
82 | /// Return all styles found
83 | ///
84 | public IEnumerable GetStyles()
85 | {
86 | return editorStyles;
87 | }
88 |
89 | #region Serialization
90 |
91 | public void OnBeforeSerialize()
92 | {
93 | if (styleLookup == null)
94 | styleLookup = new Dictionary ();
95 | }
96 |
97 | public void OnAfterDeserialize()
98 | {
99 | if (styleLookup == null)
100 | styleLookup = new Dictionary ();
101 |
102 | //Add the style or update
103 | foreach (var style in editorStyles)
104 | {
105 | if (!styleLookup.ContainsKey (style.name))
106 | styleLookup.Add (style.name, style.style);
107 | else
108 | styleLookup[style.name] = style.style;
109 | }
110 | }
111 |
112 | #endregion
113 | }
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyleScriptable/Scripts/EditorStyleScriptable.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using UnityEngine;
4 |
5 | [CreateAssetMenu ()]
6 | public class EditorStyleScriptable : ScriptableObject, ISerializationCallbackReceiver
7 | {
8 | [Serializable]
9 | public class GUIStyleRef
10 | {
11 | public string name;
12 | public GUIStyle style;
13 |
14 | public GUIStyleRef(GUIStyle style)
15 | {
16 | this.name = style.name;
17 | this.style = style;
18 | }
19 | }
20 |
21 | [SerializeField]
22 | private List editorStyles = new List ();
23 | private static Dictionary styleLookup;
24 |
25 | ///
26 | /// Current style count
27 | ///
28 | public int StyleCount => editorStyles.Count;
29 |
30 | ///
31 | /// Add a style to the collection.
32 | ///
33 | public void AddStyle(GUIStyle style)
34 | {
35 | if (styleLookup.ContainsKey (style.name))
36 | return;
37 |
38 | GUIStyleRef styleRef = new GUIStyleRef (style);
39 | editorStyles.Add (styleRef);
40 | styleLookup.Add (styleRef.name, style);
41 | }
42 |
43 | ///
44 | /// Add multiple styles. Will call for each one.
45 | ///
46 | public void AddStyles(IEnumerable styles)
47 | {
48 | foreach (var style in styles)
49 | AddStyle (style);
50 | }
51 |
52 | ///
53 | /// Clear all style information.
54 | ///
55 | public void ClearStyles()
56 | {
57 | editorStyles.Clear ();
58 | styleLookup?.Clear ();
59 | }
60 |
61 | ///
62 | /// Find a style with the given name.
63 | ///
64 | /// Name of the style to find
65 | public GUIStyle GetStyle(string name)
66 | {
67 | if (string.IsNullOrEmpty (name))
68 | return null;
69 |
70 | if (styleLookup.ContainsKey (name))
71 | return styleLookup[name];
72 |
73 | return null;
74 | }
75 |
76 | public int GetStyleIndex(string name)
77 | {
78 | return editorStyles.FindIndex (s => s.name == name);
79 | }
80 |
81 | ///
82 | /// Return all styles found
83 | ///
84 | public IEnumerable GetStyles()
85 | {
86 | return editorStyles;
87 | }
88 |
89 | #region Serialization
90 |
91 | public void OnBeforeSerialize()
92 | {
93 | if (styleLookup == null)
94 | styleLookup = new Dictionary ();
95 | }
96 |
97 | public void OnAfterDeserialize()
98 | {
99 | if (styleLookup == null)
100 | styleLookup = new Dictionary ();
101 |
102 | //Add the style or update
103 | foreach (var style in editorStyles)
104 | {
105 | if (!styleLookup.ContainsKey (style.name))
106 | styleLookup.Add (style.name, style.style);
107 | else
108 | styleLookup[style.name] = style.style;
109 | }
110 | }
111 |
112 | #endregion
113 | }
--------------------------------------------------------------------------------
/EditorStyleScriptable/Scripts/Editor/EditorStyleEditor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using UnityEngine;
6 | using UnityEditor;
7 |
8 |
9 | [CustomEditor (typeof (EditorStyleScriptable))]
10 | public class EditorStyleEditor : Editor
11 | {
12 | private enum ExampleType { BUTTON, LABEL, POPUP, TEXT_FIELD, TOGGLE, SELECTABLE }
13 | private ExampleType exampleType = ExampleType.LABEL;
14 |
15 | // === Reference ===
16 | private EditorStyleScriptable cache;
17 | private SerializedProperty styleProperty;
18 | private List serializedStyles;
19 |
20 | // === Display ===
21 | private readonly string exampleText = "GUIStyle Example";
22 | private string styleLookupTest;
23 | private GUIStyle styleLookup;
24 |
25 | // === Reflection ===
26 | private EditorStyles stylesClass;
27 |
28 | private Type styleType = typeof (EditorStyles);
29 | private FieldInfo[] styleFields;
30 |
31 | private List foundStyles;
32 |
33 | private readonly BindingFlags methodBindings = BindingFlags.NonPublic | BindingFlags.Instance;
34 | private readonly BindingFlags fieldBindings = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public;
35 |
36 | // === Helpers ===
37 | private bool HasStyles => cache?.StyleCount > 0;
38 |
39 | private void OnEnable()
40 | {
41 | cache = target as EditorStyleScriptable;
42 |
43 | foundStyles = new List ();
44 | foreach (var style in cache.GetStyles ())
45 | foundStyles.Add (style.style);
46 | }
47 |
48 | public override void OnInspectorGUI()
49 | {
50 | serializedObject.UpdateIfRequiredOrScript ();
51 |
52 | if (styleProperty == null)
53 | {
54 | styleProperty = serializedObject.FindProperty ("editorStyles");
55 | CacheSerializedStyles ();
56 | }
57 |
58 | DrawHeaderGUI ();
59 |
60 | if (foundStyles == null || foundStyles.Count == 0)
61 | return;
62 |
63 | DrawContentGUI ();
64 | }
65 |
66 | private void DrawHeaderGUI()
67 | {
68 | styleLookupTest = EditorGUILayout.DelayedTextField ("Style Lookup", styleLookupTest);
69 | styleLookup = cache.GetStyle (styleLookupTest);
70 |
71 | if (styleLookup != null)
72 | {
73 | int index = cache.GetStyleIndex (styleLookupTest);
74 | DrawStyle (styleProperty.GetArrayElementAtIndex (index), foundStyles[index]);
75 | }
76 | else
77 | {
78 | EditorGUILayout.LabelField ("Search for GUIStyle above to display");
79 | }
80 |
81 | EditorGUILayout.BeginVertical (EditorStyles.helpBox);
82 | {
83 | EditorGUILayout.BeginHorizontal ();
84 | {
85 | if (GUILayout.Button ("Get Styles"))
86 | GetStyles ();
87 |
88 | if (GUILayout.Button ("Clear Styles"))
89 | ClearAll ();
90 | }
91 | EditorGUILayout.EndHorizontal ();
92 | }
93 | EditorGUILayout.EndVertical ();
94 | }
95 |
96 | private void DrawContentGUI()
97 | {
98 | //Display styles and display example GUIStyle
99 | EditorGUILayout.BeginVertical (EditorStyles.helpBox);
100 | {
101 | string info = HasStyles
102 | ? "Editor Styles"
103 | : "No styles found, click the buttonto get all editor styles.";
104 |
105 | EditorGUILayout.BeginHorizontal ();
106 | {
107 | EditorGUILayout.LabelField (info, EditorStyles.boldLabel);
108 | exampleType = (ExampleType)EditorGUILayout.EnumPopup (exampleType);
109 | }
110 | EditorGUILayout.EndHorizontal ();
111 |
112 | EditorGUILayout.Space ();
113 |
114 | EditorGUI.indentLevel++;
115 | {
116 | for (int i = 0; i < serializedStyles.Count; i++)
117 | DrawStyle (serializedStyles[i], foundStyles[i]);
118 | }
119 | EditorGUI.indentLevel--;
120 | }
121 | EditorGUILayout.EndVertical ();
122 | }
123 |
124 | ///
125 | /// Finds all from the EditorStyle class and adds them to the target scriptable.
126 | ///
127 | private void GetStyles()
128 | {
129 | cache.ClearStyles ();
130 |
131 | if (stylesClass == null)
132 | stylesClass = Activator.CreateInstance ();
133 |
134 | //Get method and initialize the styles. This just makes sure the styles are all setup prior
135 | MethodInfo initMethod = styleType.GetMethod ("InitSharedStyles", methodBindings);
136 | initMethod.Invoke (stylesClass, null);
137 |
138 | //Get fields required
139 | styleFields = styleType.GetFields (fieldBindings);
140 |
141 | //Add all styles to list for convenient sorting
142 | foundStyles = new List ();
143 |
144 | foreach (var item in styleFields)
145 | {
146 | object val = item.GetValue (stylesClass);
147 |
148 | if (val is GUIStyle)
149 | foundStyles.Add (val as GUIStyle);
150 | }
151 |
152 | foundStyles.OrderBy (style => style.name);
153 | cache.AddStyles (foundStyles);
154 |
155 | serializedObject.Update ();
156 |
157 | CacheSerializedStyles ();
158 | }
159 |
160 | #region Draw Styles
161 |
162 | private void DrawExample(GUIStyle style)
163 | {
164 | switch (exampleType)
165 | {
166 | case ExampleType.BUTTON:
167 | GUILayout.Button (exampleText, style);
168 | break;
169 |
170 | case ExampleType.LABEL:
171 | EditorGUILayout.LabelField (exampleText, style);
172 | break;
173 |
174 | case ExampleType.POPUP:
175 | EditorGUILayout.Popup (0, new string[] { "One", "Two", "Three" }, style);
176 |
177 | break;
178 |
179 | case ExampleType.TEXT_FIELD:
180 | EditorGUILayout.TextField (exampleText, style);
181 | break;
182 |
183 | case ExampleType.TOGGLE:
184 | EditorGUILayout.ToggleLeft (exampleText, true, style);
185 | break;
186 |
187 | case ExampleType.SELECTABLE:
188 | EditorGUILayout.SelectableLabel (exampleText, style);
189 |
190 | break;
191 |
192 |
193 | }
194 | }
195 |
196 | private void DrawStyle(SerializedProperty property, GUIStyle style)
197 | {
198 | EditorGUILayout.BeginHorizontal ();
199 | {
200 | property.isExpanded = EditorGUILayout.Foldout (property.isExpanded, property.displayName, true);
201 |
202 | GUILayout.FlexibleSpace ();
203 |
204 | DrawExample (style);
205 | }
206 | EditorGUILayout.EndHorizontal ();
207 |
208 | //Do this so the whole window width can be used for the GUIStyle settings
209 | if (property.isExpanded)
210 | {
211 | EditorGUI.indentLevel++;
212 | DrawChildren (property);
213 | EditorGUI.indentLevel--;
214 | }
215 | }
216 |
217 | private void DrawChildren(SerializedProperty parent)
218 | {
219 | bool checkChildren = true;
220 |
221 | SerializedProperty copy = parent.Copy ();
222 | int index = 0;
223 | while (copy.NextVisible (checkChildren))
224 | {
225 | if (SerializedProperty.EqualContents (copy, parent.GetEndProperty ()))
226 | break;
227 |
228 | EditorGUILayout.PropertyField (copy, true);
229 |
230 | if (!checkChildren)
231 | index++;
232 |
233 | checkChildren = false;
234 | }
235 | }
236 |
237 | #endregion
238 |
239 | #region Helpers
240 |
241 | private void CacheSerializedStyles()
242 | {
243 | serializedStyles = new List ();
244 |
245 | for (int i = 0; i < styleProperty.arraySize; i++)
246 | serializedStyles.Add (styleProperty.GetArrayElementAtIndex (i));
247 | }
248 |
249 | private void ClearAll()
250 | {
251 | cache.ClearStyles ();
252 | serializedStyles.Clear ();
253 | foundStyles.Clear ();
254 | }
255 |
256 | #endregion
257 | }
--------------------------------------------------------------------------------
/EditorStyleScriptable/EditorStyleScriptable/Scripts/Editor/EditorStyleEditor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using UnityEngine;
6 | using UnityEditor;
7 |
8 |
9 | [CustomEditor (typeof (EditorStyleScriptable))]
10 | public class EditorStyleEditor : Editor
11 | {
12 | private enum ExampleType { BUTTON, LABEL, POPUP, TEXT_FIELD, TOGGLE, SELECTABLE }
13 | private ExampleType exampleType = ExampleType.LABEL;
14 |
15 | // === Reference ===
16 | private EditorStyleScriptable cache;
17 | private SerializedProperty styleProperty;
18 | private List serializedStyles;
19 |
20 | // === Display ===
21 | private readonly string exampleText = "GUIStyle Example";
22 | private string styleLookupTest;
23 | private GUIStyle styleLookup;
24 |
25 | // === Reflection ===
26 | private EditorStyles stylesClass;
27 |
28 | private Type styleType = typeof (EditorStyles);
29 | private FieldInfo[] styleFields;
30 |
31 | private List foundStyles;
32 |
33 | private readonly BindingFlags methodBindings = BindingFlags.NonPublic | BindingFlags.Instance;
34 | private readonly BindingFlags fieldBindings = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public;
35 |
36 | // === Helpers ===
37 | private bool HasStyles => cache?.StyleCount > 0;
38 |
39 | private void OnEnable()
40 | {
41 | cache = target as EditorStyleScriptable;
42 |
43 | foundStyles = new List ();
44 | foreach (var style in cache.GetStyles ())
45 | foundStyles.Add (style.style);
46 | }
47 |
48 | public override void OnInspectorGUI()
49 | {
50 | serializedObject.UpdateIfRequiredOrScript ();
51 |
52 | if (styleProperty == null)
53 | {
54 | styleProperty = serializedObject.FindProperty ("editorStyles");
55 | CacheSerializedStyles ();
56 | }
57 |
58 | DrawHeaderGUI ();
59 |
60 | if (foundStyles == null || foundStyles.Count == 0)
61 | return;
62 |
63 | DrawContentGUI ();
64 | }
65 |
66 | private void DrawHeaderGUI()
67 | {
68 | styleLookupTest = EditorGUILayout.DelayedTextField ("Style Lookup", styleLookupTest);
69 | styleLookup = cache.GetStyle (styleLookupTest);
70 |
71 | if (styleLookup != null)
72 | {
73 | int index = cache.GetStyleIndex (styleLookupTest);
74 | DrawStyle (styleProperty.GetArrayElementAtIndex (index), foundStyles[index]);
75 | }
76 | else
77 | {
78 | EditorGUILayout.LabelField ("Search for GUIStyle above to display");
79 | }
80 |
81 | EditorGUILayout.BeginVertical (EditorStyles.helpBox);
82 | {
83 | EditorGUILayout.BeginHorizontal ();
84 | {
85 | if (GUILayout.Button ("Get Styles"))
86 | GetStyles ();
87 |
88 | if (GUILayout.Button ("Clear Styles"))
89 | ClearAll ();
90 | }
91 | EditorGUILayout.EndHorizontal ();
92 | }
93 | EditorGUILayout.EndVertical ();
94 | }
95 |
96 | private void DrawContentGUI()
97 | {
98 | //Display styles and display example GUIStyle
99 | EditorGUILayout.BeginVertical (EditorStyles.helpBox);
100 | {
101 | string info = HasStyles
102 | ? "Editor Styles"
103 | : "No styles found, click the buttonto get all editor styles.";
104 |
105 | EditorGUILayout.BeginHorizontal ();
106 | {
107 | EditorGUILayout.LabelField (info, EditorStyles.boldLabel);
108 | exampleType = (ExampleType)EditorGUILayout.EnumPopup (exampleType);
109 | }
110 | EditorGUILayout.EndHorizontal ();
111 |
112 | EditorGUILayout.Space ();
113 |
114 | EditorGUI.indentLevel++;
115 | {
116 | for (int i = 0; i < serializedStyles.Count; i++)
117 | DrawStyle (serializedStyles[i], foundStyles[i]);
118 | }
119 | EditorGUI.indentLevel--;
120 | }
121 | EditorGUILayout.EndVertical ();
122 | }
123 |
124 | ///
125 | /// Finds all from the EditorStyle class and adds them to the target scriptable.
126 | ///
127 | private void GetStyles()
128 | {
129 | cache.ClearStyles ();
130 |
131 | if (stylesClass == null)
132 | stylesClass = Activator.CreateInstance ();
133 |
134 | //Get method and initialize the styles. This just makes sure the styles are all setup prior
135 | MethodInfo initMethod = styleType.GetMethod ("InitSharedStyles", methodBindings);
136 | initMethod.Invoke (stylesClass, null);
137 |
138 | //Get fields required
139 | styleFields = styleType.GetFields (fieldBindings);
140 |
141 | //Add all styles to list for convenient sorting
142 | foundStyles = new List ();
143 |
144 | foreach (var item in styleFields)
145 | {
146 | object val = item.GetValue (stylesClass);
147 |
148 | if (val is GUIStyle)
149 | foundStyles.Add (val as GUIStyle);
150 | }
151 |
152 | foundStyles.OrderBy (style => style.name);
153 | cache.AddStyles (foundStyles);
154 |
155 | serializedObject.Update ();
156 |
157 | CacheSerializedStyles ();
158 | }
159 |
160 | #region Draw Styles
161 |
162 | private void DrawExample(GUIStyle style)
163 | {
164 | switch (exampleType)
165 | {
166 | case ExampleType.BUTTON:
167 | GUILayout.Button (exampleText, style);
168 | break;
169 |
170 | case ExampleType.LABEL:
171 | EditorGUILayout.LabelField (exampleText, style);
172 | break;
173 |
174 | case ExampleType.POPUP:
175 | EditorGUILayout.Popup (0, new string[] { "One", "Two", "Three" }, style);
176 |
177 | break;
178 |
179 | case ExampleType.TEXT_FIELD:
180 | EditorGUILayout.TextField (exampleText, style);
181 | break;
182 |
183 | case ExampleType.TOGGLE:
184 | EditorGUILayout.ToggleLeft (exampleText, true, style);
185 | break;
186 |
187 | case ExampleType.SELECTABLE:
188 | EditorGUILayout.SelectableLabel (exampleText, style);
189 |
190 | break;
191 |
192 |
193 | }
194 | }
195 |
196 | private void DrawStyle(SerializedProperty property, GUIStyle style)
197 | {
198 | EditorGUILayout.BeginHorizontal ();
199 | {
200 | property.isExpanded = EditorGUILayout.Foldout (property.isExpanded, property.displayName, true);
201 |
202 | GUILayout.FlexibleSpace ();
203 |
204 | DrawExample (style);
205 | }
206 | EditorGUILayout.EndHorizontal ();
207 |
208 | //Do this so the whole window width can be used for the GUIStyle settings
209 | if (property.isExpanded)
210 | {
211 | EditorGUI.indentLevel++;
212 | DrawChildren (property);
213 | EditorGUI.indentLevel--;
214 | }
215 | }
216 |
217 | private void DrawChildren(SerializedProperty parent)
218 | {
219 | bool checkChildren = true;
220 |
221 | SerializedProperty copy = parent.Copy ();
222 | int index = 0;
223 | while (copy.NextVisible (checkChildren))
224 | {
225 | if (SerializedProperty.EqualContents (copy, parent.GetEndProperty ()))
226 | break;
227 |
228 | EditorGUILayout.PropertyField (copy, true);
229 |
230 | if (!checkChildren)
231 | index++;
232 |
233 | checkChildren = false;
234 | }
235 | }
236 |
237 | #endregion
238 |
239 | #region Helpers
240 |
241 | private void CacheSerializedStyles()
242 | {
243 | serializedStyles = new List ();
244 |
245 | for (int i = 0; i < styleProperty.arraySize; i++)
246 | serializedStyles.Add (styleProperty.GetArrayElementAtIndex (i));
247 | }
248 |
249 | private void ClearAll()
250 | {
251 | cache.ClearStyles ();
252 | serializedStyles.Clear ();
253 | foundStyles.Clear ();
254 | }
255 |
256 | #endregion
257 | }
--------------------------------------------------------------------------------