Styling¶
Purpose¶
Turns the theme into GUIStyle objects and RectOffset geometry, caches them, and invalidates the cache when the theme or the editor skin changes. This is the layer that stops a long editor session allocating a GUIStyle and a Texture2D on every repaint.
Owns¶
StyleCache— the cached style getters consumers readStyleRegistry— the backing fields and the single completeClear()StyleDrawer— layout helpers, the generated-texture cache, the theme designer's own drawing, and deferred live refreshGUIStyleFactory— construction primitivesGUIStyleExtensions— the fluentSetFont/SetPadding/SetMarginsetSkintGeometry— every padding and margin, derived from four theme tokensQuantizedColorKey— the texture cache key
Does NOT Own¶
- The theme model or its persistence — that is Core and the package root
- Widget behaviour and layout — that is UI
- Window lifecycle — that is Editor
- Deciding when a theme changed; it is told
Allowed Dependencies¶
Styling may depend on:
UnityEditorGUI APIs,EditorStyles,UnityEngine- Core, for the theme and the resolver
Styling should avoid depending on:
- UI and Editor territories
- File IO
Notes¶
Caching is the point of this territory, so cache invalidation is its main hazard. StyleRegistry.Clear() is deliberately the only complete clear: there were once five partial paths that each forgot something different. It also drops the generated textures, because HideFlags.DontSave means Unity can reclaim a texture while a dictionary still holds the reference — so the texture cache validates entries on read as well.
ApplyLiveStyleRefresh defers through EditorApplication.delayCall with a guard. Rebuilding styles in the middle of the layout pass that is reading them is not survivable.
SkintGeometry derives fifteen distinct padding and margin values from four theme tokens using fixed per-site offsets. This does not eliminate the magic numbers — it names them, puts them in one file, and gives the user a density control rather than sixty dials. Individual edges cannot be tuned in isolation, which is the cost.
The column layout in StyleDrawer.DrawThemeSelector commits its width measurement at the end of a Repaint pass, never where it is taken. IMGUI runs Layout and Repaint as separate passes over the same code and both must emit the same number of layout groups; measuring at the top of Repaint meant the two passes could choose different column counts, which produces "You are pushing more GUIClips than you are popping" and a corrupted layout.
Future Candidates¶
StyleCache.csis around 700 lines of near-identical lazy getters. Splitting them across partial-class files would move line counts without reducing coupling, so it is deliberately left alone.- Borders and corner radii are not themeable.