tmedwards / sugarcube-2

SugarCube is a free (gratis and libre) story format for Twine/Twee.
https://www.motoslave.net/sugarcube/2/
BSD 2-Clause "Simplified" License
185 stars 42 forks source link

Setting.change() method suggestion #236

Closed MalifaciousGames closed 4 months ago

MalifaciousGames commented 1 year ago

Currently, changing the value of a setting through means other than the dedicated dialog is a three steps process:

I feel this process could be simplified through a dedicated Setting.change() method that would take the setting's name and new value as arguments, very much like State.setVar().

Setting.change('mySetting', 'new value');

//could replace:

settings.mySetting = 'new value';
setup.mySettingChange();
Setting.save();

I can submit a pull request on the develop branch if it is convenient to do so, cordially, Maliface.

tmedwards commented 1 year ago

I'd want it to be full get/set pair. E.g., something like:

Setting.get(name: string) → value: any
Setting.set(name: string, value: any) → result: boolean

I'll take care of implementing it—though I appreciate the offer. I need to make some changes in the API internals anyway and I'll probably want to do some kind of type validation on the set value.

tmedwards commented 1 year ago

The API additions ended up being:

/*
    Add a value-type setting.

    NOTE: Value-type settings do not receive a control under the Settings menu.
*/
Setting.addValue(name: string, definition?: object)

/*
    Returns the value of the given setting name—equivalent to `settings[name]`.
    Works with any setting type.
*/
Setting.getValue(name: string) → value: any

/*
    Sets the value of the given setting name, saves the settings, and calls the
    associated `onChange` handler, if one exists.  Works with any setting type.
*/
Setting.setValue(name: string, value: any) → result: boolean

Value-type settings must be initialized via Setting.addValue() before they may be used:

// You can omit the definition entirely and just initialize the setting.
Setting.addValue('secret1');

// Alternatively, like other setting types, you can specify a definition to get more functionality.
Setting.addValue('secret2', {
    default : 42,

    onInit() {
        console.log(`${this.name} onInit:`, this);
    },
    onChange(data) {
        console.log(`${data.name} onChange:`, data);
    }
});
MalifaciousGames commented 1 year ago

Very nice! Love to see settings objects of arbitrary type, thank you for the continued development effort!