Skip to content

Add WindowSkin: let a separate plugin theme the settings window - #126

Merged
ManlyMarco merged 1 commit into
BepInEx:masterfrom
MikalaiKryvusha:window-skin
Oct 11, 2026
Merged

ManlyMarco merged 1 commit into
BepInEx:masterfrom
MikalaiKryvusha:window-skin

Conversation

@MikalaiKryvusha

@MikalaiKryvusha MikalaiKryvusha commented Oct 11, 2026 •

Copy link
Copy Markdown
Contributor

What

A small extension point so that a separate plugin can give the settings window the look of the game it is used in. The plugin itself ships no themes and its default look does not change.

  • ConfigurationManager.WindowSkin (GUISkin, null by default). When set, the window, its controls and tooltips are drawn with it, and its window style draws the window background instead of the built-in grey one. The dimmed backdrop behind a window that has not been moved yet keeps the default skin.
  • Plugin and category headers use the skin's custom styles named ConfigurationManager.PluginHeader and ConfigurationManager.CategoryHeader (constants PluginHeaderStyleName / CategoryHeaderStyleName) if the skin has them. Otherwise they are built from the skin's label as before. The private fields _pluginHeaderSkin / _categoryHeaderSkin keep their names, so plugins that already reach into them keep working.

Usage from a theme plugin:

var manager = (ConfigurationManager.ConfigurationManager)Chainloader.PluginInfos[ConfigurationManager.ConfigurationManager.GUID].Instance;
manager.WindowSkin = myGameSkin; // optionally with customStyles named ConfigurationManager.PluginHeader / CategoryHeader

Why

Mods that want the window to match their game currently have to patch it with Harmony: replace GUI.skin in a prefix to OnGUI, force _windowWasMoved so that the grey background is not drawn under a themed window, and restyle the header styles through reflection. That breaks whenever the internals change. With WindowSkin the theme stays in its own plugin and needs no patches. Separate from #125 (translation): this PR touches only the skin handling.

Testing

Unity 2020.3 Mono game, BepInEx 5.4.23.5. The theme plugin is the game's own UI mod: dark paper and old gold. It uses WindowSkin when the property exists and falls back to its old Harmony path otherwise.

  • Default look, unchanged (WindowSkin null):

    default

  • WindowSkin set by the theme plugin, headers from its named custom styles:

    themed

  • The same in the game:

    in game

  • Turning the theme off at runtime (setting WindowSkin back to null) returns the default look immediately.

  • 19.0 with the same theme plugin, through its old Harmony path, looks the same as before.

  • Builds: ConfigurationManager (BepInEx 5, net35) and ConfigurationManager.IL2CPP, 0 errors. Not run in an IL2CPP game.

(The window in the screenshots is in Russian because of #125's translation file; this PR does not depend on it.)

🤖 Generated with Claude Code

…ok of the game

WindowSkin (null by default) is used to draw the window, its controls and tooltips; its window style draws the
window background instead of the built-in grey one. Plugin and category headers use the skin's custom styles named
ConfigurationManager.PluginHeader / ConfigurationManager.CategoryHeader if present. The default look is unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@ManlyMarco
ManlyMarco merged commit 1345246 into BepInEx:master Oct 11, 2026
@ManlyMarco

Copy link
Copy Markdown
Member

Let me know when you're done working on this plugins and I'll make a release.

@MikalaiKryvusha

Copy link
Copy Markdown
Contributor Author

Thank you so much for the quick and thoughtful reviews, and for merging both PRs! I was really glad to help. I'm done working on this plugin, so feel free to make the release whenever it suits you.

@MikalaiKryvusha

Copy link
Copy Markdown
Contributor Author

Sorry, one tiny last fix after all: #127 (the slider value box was a fixed 50px and clipped numbers with a bigger font). After that, that's really everything from me. Huge thanks again! We'll be happy to download the release with these changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants