Skip to content

Skinflap/SettingsVault

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

SettingsVault — settings + remappable controls for Godot 4, persisted right

Every game needs an options menu and most need rebindable controls. The naive version breaks in the same two ways: a missing or corrupted config key returns the wrong type and crashes, and "rebind your keys" turns out to mean serializing InputEvents by hand. SettingsVault is the drop-in that does both correctly, in one human-readable file on disk.

Godot 4.x · GDScript · no dependencies · ~250 lines you can read in one sitting.

What it does that naive options code doesn't

  • Typed defaults, real reset. Every setting has a registered default, so a missing or garbage key returns the right type — never null where you expected a float. reset(), reset_section(), and reset_all() actually return to those defaults.
  • Remappable controls that persist. Rebind an action at runtime; SettingsVault applies it to the InputMap and serializes it to disk. On the next launch, load() restores it. reset_binding() returns an action to the project defaults you captured at startup.
  • Covers what players actually rebind — keyboard, mouse buttons, joypad buttons and axes — serialized properly, not stringified guesswork.
  • One ConfigFile. Everything lives in one readable .cfg, so saves are inspectable and pair cleanly with SaveVault for the rest of your persistence.

Install

  1. Copy addons/settings_vault/ into your project.
  2. Project → Project Settings → Plugins → enable SettingsVault (or add settings_vault.gd as an autoload named SettingsVault yourself).

Use

func _ready() -> void:
    # Declare your settings and their defaults, once.
    SettingsVault.register_defaults({
        "video": {"fullscreen": false, "vsync": true},
        "audio": {"master": 1.0, "music": 0.8},
    })
    # Snapshot the project's InputMap defaults so reset_binding() has a target.
    SettingsVault.capture_defaults(["jump", "move_left", "move_right"])
    # Restore whatever the player saved last session (missing file is fine).
    SettingsVault.load()

# Read and write settings — set_value autosaves by default.
var full := SettingsVault.get_value("video", "fullscreen")
SettingsVault.set_value("audio", "master", 0.5)

# React to changes anywhere (e.g. apply the volume live).
SettingsVault.setting_changed.connect(func(section, key, value):
    if section == "audio":
        apply_volume(key, value))

Rebinding controls

# In your "press a key to rebind" UI, on the captured input event:
func _on_rebind(action: StringName, event: InputEvent) -> void:
    SettingsVault.rebind(action, event)        # applied to InputMap + saved

SettingsVault.add_binding("jump", controller_a_button)  # a second key for the same action
SettingsVault.reset_binding("jump")                     # back to the captured default
var events := SettingsVault.get_bindings("jump")        # for drawing the current binding

Batch edits in a settings menu

Turn off autosave, let the player fiddle, then commit on Apply:

SettingsVault.autosave = false
# ... player changes a dozen things ...
SettingsVault.save()   # one write

API

Call Does
register_default(section, key, default) Declare one setting + its default.
register_defaults(tree) Bulk register from {section: {key: default}}.
get_value(section, key, fallback=null) Stored value, else default, else fallback.
set_value(section, key, value) Set, emit setting_changed, autosave.
has_value(section, key) Whether an explicit value was set.
reset(section, key) / reset_section(s) / reset_all() Drop overrides back to defaults.
capture_defaults(actions) Snapshot InputMap events as reset targets (call at startup).
rebind(action, event) Replace an action's events with one, apply + persist.
add_binding(action, event) Add another event to an action.
get_bindings(action) Current Array[InputEvent] for an action.
reset_binding(action) Restore captured default events.
save() / load() Write / read the ConfigFile (returns an Error).
config_path Where it's stored (default user://settings.cfg).
autosave Auto-write on every change (default true).

Tested

tests/test_settings_vault.gd is a headless suite covering typed defaults and fallbacks, all three reset paths, the change signal, a save/load round-trip across instances, and keyboard/mouse binding rebind → persist → restore → reset. Run it:

godot --headless --path . -s tests/test_settings_vault.gd

License

MIT. Drop it in a commercial game, no attribution required.

About

No description, website, or topics provided.

Resources

License

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors