Skip to content

Settings: allow $options to be populated at runtime #1024

Description

@mazany

Summary

$options combobox values are declared in the mod source and fixed at install
time. That means a mod can't offer a picker over anything it discovers on the
machine. I'd like a way for a mod to supply options at runtime — for example an
optional export the settings UI calls, Wh_GetSettingOptions(name).

Filing this as the ambitious one of a small batch. It is clearly larger than
the others and I'd understand it being declined or deferred; the ones alongside
it stand on their own.

Why

$options is the right control whenever a value must be one of a known set.
But "known" currently means "known when the mod was written", which excludes
everything interesting about the machine the mod is running on:

  • installed applications a mod can target
  • files in a folder the mod reads
  • connected monitors, audio devices, profiles
  • window classes or processes discovered at runtime

For those, authors fall back to a free-text field the user must type exactly,
which trades a discoverable, unmistakable control for one that silently does
nothing when misspelled. The mod usually can't even validate it well, because
by the time it reads the setting it isn't in a position to tell the user.

Evidence

I'm building toward a small patch registry: CSS patches live as files, and the
user picks which to apply per application. The natural control is a checkbox
list or a multi-select of the patches present on disk — which is precisely what
can't be expressed, since the patch set changes whenever a file is added.

The workarounds available today, and why each falls short:

  1. Free-text patch ids. Typo-prone, and the mod can only report a
    mismatch to a log the user isn't reading.
  2. Bake $options into the source. Adding a patch then means editing and
    reinstalling the mod, which defeats the point of a file-driven registry.
  3. A directory convention — apply everything in a folder, disable by
    renaming with a leading _.

I shipped (3). It works and needs no engine change, but the enable/disable
affordance is now "rename a file in Explorer" rather than a checkbox in the
settings UI, which is a real step down for anyone who isn't the author.

Note that alpha.2's relaxation of settings-array indices (undeclared rows are
now writable — thank you, that was the other half of this problem) makes the
storage side flexible. It is now only the presentation side that is fixed at
install time.

Suggested shape

An optional export the settings UI calls when rendering, mirroring how mods
already expose lifecycle functions:

// Called by the settings UI. Return NULL / do nothing to keep static $options.
BOOL Wh_GetSettingOptions(PCWSTR settingName, WH_SETTING_OPTIONS* out);

Open questions I don't have a good answer to, and which may well make this
not worth it:

  • Where does it run? The settings UI is not inside a target process. Calling
    into a mod outside its injection context is the hard part of this request, and
    possibly the disqualifying one.
  • What if it's slow or hangs? Needs a timeout and a fallback to static
    options.
  • Refresh semantics. Once when the settings page opens is probably enough.

A cheaper alternative that captures much of the value: let a mod write a
candidate list to a known location, and let $options reference it —
$optionsFrom: "%LOCALAPPDATA%\\my-mod\\options.json". No cross-process call,
no lifetime questions, and the mod controls the contents. If the full version is
too invasive, this variant would still turn (1) and (3) above into a real
picker.

Tested on 2.0.0-alpha.2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions