Repository navigation
feat(plugins): canvases can read the plugin theme - #210
Merged
eriknihlen merged 1 commit intoOct 8, 2026
Merged
Conversation
A canvas paints its own pixels, so it was never told which plugin theme the player picked under Plugin appearance and could only draw one fixed look. IUiRegistry now carries the selected theme (kind, picker name and palette as PluginColors) and raises ThemeChanged on the plugin callback thread when the player picks another. The graphical host follows PluginUiThemeSettings through BufferedUiRegistry.FollowTheme, so plugins read the saved theme from the moment the interface comes up. The scoped registry both hosts share forwards the theme and drops a plugin's handlers with the plugin. The windowless host answers Classic and never raises a change. Additive with inert defaults: a host that predates this answers Classic. Claude-Session: https://claude.ai/code/session_01SY57mHJLZ6djpWZ5nP37Tw
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
A plugin canvas paints its own pixels, so it is never told which theme the
player picked under Plugin appearance. Markup windows that opt in with
theme="plugin"are restyled by the client, but a HUD drawn on a canvas staysin one fixed look whatever the player chose, and can't change when they switch.
This adds the selected theme to the plugin contract:
IUiRegistry.Theme: aPluginUiThemeInfowith the theme'sKind(Classic, Moss, Brass), the
DisplayNamethe picker shows, and itsPalette, the seven colours themed windows draw in asPluginColors(null under Classic).
IUiRegistry.ThemeChanged: raised on the tick thread, once per change,with the new theme.
How it is bound:
BufferedUiRegistry.FollowThemefollowsPluginUiThemeSettingsfrom the momentRetailUiRuntimemounts plugins,so plugins read the saved theme as soon as the interface is up. It keeps
the last theme across a reconnect. A handler that throws is logged and does
not stop other plugins from hearing.
Themeand tracks eachThemeChangedhandler like any other registration, so a plugin's handlersare removed when it unloads.
PluginUiThemeInfo.Classicand neverraises a change.
Additive: both members have inert defaults, so a host that predates this
answers Classic. The picker's theme names now live in one place
(
PluginUiThemeSettings.ThemeNames), shared byPluginAppearanceBinding.Documented in a new "Plugin theme" section of
docs/plugin-api.md, with apointer from the appearance section of
docs/plugin-ui-markup.md.Tested by
PluginThemeContractTests(inert defaults),ScopedUiRegistryThemeTests(forwarding, removal, unload),BufferedUiRegistryThemeTests(palette values, picker names, publish/follow,throwing handlers) and a headless surface test (Classic without a window).
Original behavior
No change to what the client does in the world. This only exposes the
existing plugin appearance preference to plugins.
Checklist
dotnet build AcDream.slnx -c Releaseis greenexceptions are four
HostParityPeer* IPC parity tests, which time out onthis Mac on clean
maintoo.https://claude.ai/code/session_01SY57mHJLZ6djpWZ5nP37Tw