[Zios] Editor Theme Support

Description (What is this?)

Zios Themes provides the Unity Editor with adjustable, hot-swappable GUI themes across all elements using native and custom data formats.

Reason (Why was it made?)

The system was initially created to provide on-the-fly adjustable styling standards for custom editor windows/inspectors/properties. It was later extended for global editor usage. It’s intended to allow users to establish general-purpose aesthetics that are adaptable to needs as well as uniform to their existing development applications.

Features (What can it do?)

  • Supports swapping of editor themes globally or between individual custom editors.

  • Supports palette (color) adjustment. Palettes are usable between different themes. Alt+F1 and Alt+F2 are hotkeys for previous and next palette.

  • Supports system color usage (select Windows versions only) as well as manual adjustment.

  • Supports forced interval repainting as Responsive UI option to allow for global hover/interaction effects.

  • Supports theme variations and keywords within .unityTheme files.

  • Supports GUIStyle and GUIContent overriding in base skin as well as static style-container instances.

Approach (How was it done?)

Since the introduction of GUISkin data types (~Unity 2), it’s been possible to retrieve and adjust the active GUI.skin for the sake of custom editors. These styles are used for the majority (if not all) of Unity’s default immediate-mode-GUI elements. The downside is that many of these core styles are used as independent GUIStyle instances sprinkled through the assembly rather than referenced to the core styles. Below I detail the processes I use to locate, group, localize, and apply these elements as a centralized theme.
Advanced

Themes.SaveGUI. Locate and build assets for style/content data.

  • Reflect the entire UnityEditor assembly for common style/content storage classes. I’ve found that these are generally stored in Styles, styles, s_GOStyles, s_Current, s_Styles, m_Styles, ms_Styles, constants, and Constants. As this step needs to manually create instances in some cases (to retrieve default values), it can cause mild error warnings. You’ll want to change your editor layout (top-right) after running to prevent render issues upon restart.
  • Dump all GUIStyle fields to their own path-named .guiSkin file as customStyles. Styles are labeled by variable name (with the base style in brackets).
  • Dump all GUIContent and GUIContent to a path-named .guiContent file. Contents are labeled by variable name. Currently, this step also will dump GUIContent assets to a respective GUIContent subfolder. This process will likely be offset to Themes.SaveAssets in the future.

Themes.SaveAssets. Create assets used by GUISkin.

  • Scan folder for GUISkin files. Save background images and fonts. A “Background” and “Font” folder are created in the path specified.

Themes.LocalizeAssets. Reference created assets.

  • Scan folder for GUISkin files. Override internal/existing background/font references with any name-matched local files from the Themes.SaveAssets step.

Themes.Apply. Load created style/content data.

  • Reflectively apply each saved guiSkin at their supplied fully qualified paths by either overriding or modifying their contents inline.
  • Overriding with a reference to the new GUIStyle is generally the better option. This greatly aids in realtime editing of GUISkin files for interface artists; however, due to some anomalies with load/refresh order when changing skins, inline loading is set by default for general use. Reference/Inline usage for GUIStyles can be toggled via `+2.
  • Each skin is applied by its variable name (rather than order) to give a modicum of cross-version compatibility without requiring specialized skin files for each. If a variable from a newer version is used with an older version of Unity where it does not exist, it will simply be ignored. In the event of missing variables (from newer Unity versions), the system will still load what is available, but new GUIskin/GUIStyle files will need to be built to accommodate the new style fields.
  • Some internal visual elements rely on defined colors, initialization calls/flags, and specialized styles. These are set manually during the Apply process. Manual style overriding is done to combat extreme cases, such as PreferencesWindow.sectionHeader, where the instanced GUIStyle is modified inline with local changes in code after being initialized.

Themes.RebuildData. Flush style data.

  • Due to the nature of instanced GUIStyles from the core GUI.skin, adjustments to the core typically require rebuilding of style caches for the local values to inherit properly.

Advanced

Creation (How do you create a theme?)

Each theme is comprised of a .unityTheme configuration file, .guiSkin for adjusting builtin immediate-mode GUI styles, and .guiContent files for adjusting non-style editor graphics. Additionally, .unityPalette files may be used by any theme for unified color applications. Although building themes by using only instanced GUIStyles will offer the most per-element customization, using the core skin (to some degree) is recommended. From the @Default folder, it is recommended that @Default.guiskin (rename to your theme name) and UnityEditor.EditorStyles.s_Current.guiSkin (EditorStyles) are copied to get started.
Advanced

Themes (.unityTheme)

Each item of this configuration is parsed/distinguished by newlines. Style variants are marked by text enclosed in brackets . Variants marked with a + at the start of their name are applied as toggles in the preference window. The first variant is used as the base theme. Usable keywords for variants are as follows :

  • AllowCustomization : Toggle the user’s options for any customization.
  • AllowColorCustomization : Toggle the user’s option for palettes and colors.
  • AllowSystemColor : Toggle the user’s option to use their system’s color for palettes.
  • UseSystemColor : Set the default state for using the system color. When this option is on, dark and light offsets are automatically calculated at a multiplicative value of 0.8 and 1.3 intensity respectively.
  • UseColorAssets : Toggle whether color textures need to be generated/maintained.
  • WindowBackgroundOverride : Define a texture by name to be used for window background overlays.
  • Palette : Set the default palette (by name) to be used.

Palettes (.unityPalette)

Each item of this configuration is parsed/distinguished by newlines. Each color is defined by a 6 digit (RGB) or 8 digit (RGBA) hex value or comma delimited decimal color (normalized if decimal points used). This file type defines important colors used by your theme. When UseColorAssets is enabled by a theme, a 1x1 solid texture as well as a 9x9 border texture is generated and updated per color for use in your theme’s GUIStyle backgrounds. Besides texture usage, the color definitions below alter the following :

Color : Background used by windows.
LightColor : Cursor and curve property background.
DarkColor : Selected text and curve property foreground.

GUIContent (.guiContent)

Each item of this configuration is parsed/distinguished by newlines. The name of each .guiContent file should be a fully qualified namespace. This can be manually defined, but will often be generated by the Themes.SaveGUI reflection scan. Each file contains serialized definitions of GUIContent separated by bracket-enclosed field names. Each field has the following keywords available :

text: String value used for the element (if any).
tooltip: Text that will display after hovering for some time.
image: Name of texture to use. The theme’s local GUIContent sub-folder will be searched for matching png files of the name chosen.

Skins (.guiSkin)

The name of each .guiSkin file should be a fully qualified namespace. This can be manually defined, but will often be generated by the Themes.SaveGUI reflection scan. These are normal Unity guiSkin files that can be edited natively. The main editor skin file will use the same name as your .unityTheme file. Only the main skin file will use the basic GUIStyles (box, button, etc.). All other skin files rely only on the GUIStyles defined in customStyles.

Advanced

Future (What features are planned?)

  • Additional interfaces/references for developers to unify their custom editor’s styles.

  • Extension of color system to support user-defined names/values.

  • Support Linux/MacOS for useSystemColor field.

  • Support for quick overriding and adjustment of font family/sizes and text colors used by a theme.

  • Option to automatically inverse text colors for elements on backdrops with similar brightness.

  • Custom .guiContent editor/inspector for in-editor tweaking.

  • Custom .guiSkin editor with search and group replacement functionality.

  • Build foundation default skin reference files from all classes containing GUIStyle & GUIContent rather than just known style containers.

  • Allow Texture2D elements (such as the build window’s platform icons) to be collected and replaced

Limitations (What cannot be done with themes?)

One of the biggest limiting factor of themes is caused by Unity’s hard-coded (constant) vertical-spacing value of 16. Due to this, it’s very difficult to create a theme that can use larger fonts or pad out with breathing room. While styles do have exposed parameters for margins/padding, these are used rarely in full degree by Unity.
Developer Note

One solution I briefly explored was using a base custom property drawer globally to inject spacing on all elements via an offset to the GetPropertyHeight method. While this worked for most components in the inspector, it proved somewhat limited since custom editors as well as many of Unity’s internal editors/inspectors did not correctly not apply its effects – breaking uniformity benefits.

Developer Note

Additionally, unlike IDEs such as Visual Studio, the main window decorator (application titlebar) along with the system menu bar are currently not tweakable.
Developer Note I’ve ran a few traces internally with ILspy with the [MenuItem] attribute as a starting point, but these mostly have just led to internal calls – meaning configuration data concerning these two aspects is locked down at a program level until Unity exposes them.
Developer Note

Compatibility (What environments will it function with?)

Although the system’s premise could theoretically function as far back as Unity 2/3, many of the internal extensions used limit this due to their reliance on modern usage patterns. Currently, the system has been built and tested on Unity 5.0 through 5.4b21 on Windows/Mac. Back-porting to Unity 4 (or earlier) will require adjustments to account for Unity’s internal functions changing significantly between major versions.

Issues (What problems are known?)

Bugs should be discussed/reported on the public repository’s issue tracker.
Developer Note Issues with unstyled or incorrectly styled elements usually relate to the theme itself rather than the system. Bear in mind that there are 508 main GUIStyles (as of Unity 5.4b21) with 8 states each that have to be examined and altered. It’s very difficult to assign a style if you cannot preview the scenarios where it’s used, but this is compounded by sluggish editor inspector performance on large GUISkin as well as many styles having locally instanced overrides to account for.
Developer Note

Download (Where can I obtain it?)

You can obtain the latest release from here. It includes a pre-built x64 dll for Unity 5, several palettes, and one (work-in-progress) example theme titled Simplicity. The source code is also available for usage/extension/contribution under an MIT license.

Usage (How do you use it?)

Extract the zip file to your project’s Assets folder. Configure at Edit > Preferences > Themes.

Contact (How can I reach you?)

If you’d like to make a direct inquiry regarding my work or if you just want a friendly conversation, you can find me idling in the Game Dev League Discord server under the alias Bradical. Failing that, I’m also reachable via email at bradsmithee@gmail.com or (infrequently) on these boards. I’ll also accept email invites to idle in developer Slack servers.

Preview (What does it look like?)

Visual Studio next to Unity Editor.

49 Likes

Thats awesome!
But prepare for takesown in 3, 2, 1…

13 Likes

14 Likes

Excellent documentation.

Unity should have offered something like this, at this level of customization at least for Plus and Pro versions. But all this time, it was actually possible to. That is quite a deep rabbit hole you went down into to bring this out for everyone.

3 Likes

This is amazing - holy smokes…

Round of applause to you, sir.

3 Likes

Outstanding work, this should have been included with Unity :). The themes do not seem to apply to the console window and to the second column of the “Project” window (if you choose the two column layout). Also could you and anyone here good with GUIs show how to create these themes?

1 Like

It should work in both of these cases. What version of Unity and the theme system are you running? Can you provide steps for recreating the areas that aren’t loading? In the meantime, Try hitting `+1 (Manual Refresh). Failing that, restarting Unity should apply things correctly.

I touched up on it in the “Creations” section of my main post, but I’ll see about creating a video primer on theme editing.

I am using 5.3.5p3. I dragged the Zios Themes 485 package in the assets folder and selected the Simplicity them with the elegance palette. Tried restarting, but it remains the same (only the above two mentioned areas are the default color, rest of them change and look great).

Sounds great! Will try to modify the Simplicity GUI skin and see if I can figure out how to do this :). Thanks again for the themes.

Great stuff!

To the other comments talking about “Unity should have implemented this themselves”. I rather have them fixing bugs than focusing on cosmetics.

3 Likes

Of course we all would rather have them do that, but we would never have any new features since 1.0 if the only thing all the Unity programmers were told to do were fixing bugs.

1 Like

I doubt it would have been a significant setback to the bug fix schedule. Unity has over 1000 employees. It only took 1 person to implement custom theming. Let’s not forget it was a business decision to have a grey skin for the plebs and a dark skin for the elite.

2 Likes

Let me be clear here that my intention has nothing to do with Unity default personal/pro skins. This addon (and its example color-neutral theme) is about providing users and editor extension creators a singular, standard foundation for elements – without forcing them to cater to an individual’s local environment settings. It is also a means to keep a user’s entire development toolkit visually uniform. These are not features provided by any version of Unity.

To my knowledge this addon doesn’t violate the EULA, forum rules, or have any legal complications. I do not modify the binary/unity files or provide any assets from the pro version. It’s all being done with managed code within the editor using basic C# reflection – approaches that I actually picked up from Unite conference presentations.

Additionally, keep in mind that (for the time being) creating a skin is a fairly daunting, time-consuming task full of tedium and trial/error – even with all of the systems/mechanism I have in place. 70% of my development time was spent figuring out which styles were used in which context so I could assemble the current example theme. As of right now, I’ve not reworked every default style (yet). If your needs don’t extend to unifying your custom editors or if you demand a fully complete/polished, soft-gradient environment, Unity’s existing offerings might serve a better fit.

1 Like

Sure, but from Unity’s point of view, after the Pro features were integrated into the Personal edition, the dark skin was one of the few things they had left to offer Pro users over the Personal edition. As a sorry owner of a Pro license it’s funny/bittersweet to see this pretty petty perk more or less rendered moot now. Indeed the last few days Unity’s refusal to relieve free users’ eye strain has been a major point of contention. Had your solution arrived a few days earlier it might have given us all more leverage against Unity’s new pricing.

Kinda joking here, but who knows?

Really nice work here :slight_smile:
Many options are always better than two or no option!

For some reason i really like the squared Win10 type theme on Unity editor you have there. Looks nice.

This is some absolutely pro work considering how much you’ve had to dig into the engine to find all those GUI references. The fact that you’ve released this for free when you could have put it behind a paywall on the Asset Store is a great service to the Unity community. Well done!

1 Like

And lot of other thing - like serialization - instead of tweaking visual stuff.

Hi. This is a great plugin, however it is constantly taking input from my number keys 1 through 3 and using them as hotkeys. Is there any way to disable this?

1 Like

This is really, really cool. :hushed:

Unity needs to implement this. This is something we should have had a “long” time ago.

Will there be any support for icons? Such as folders?

1 Like

I’ll need to track down the internal field that manages them, but I don’t see why not. In the meantime, you could use PhannGor’s RainbowFolders addon.

There was a bug with the assigned hotkeys. This should be fixed if you pull the latest the GIT version. Here’s a quick patched dll. There should be another release in a few days that addresses this and some other known bugs.

2685778–189893–Zios.Themes.Hotkey.Fix.zip (77.7 KB)

1 Like

The only thing Unity will implement is a fix for this “loophole” so people can’t get dark theme for free.