feat(packages): ludic.settings - a settings store as data: typed reads and writes by id, clamping, rescue values, per-key persistence, a fact per change
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
3514d46954
commit
4318adc98c
9 changed files with 338 additions and 0 deletions
93
packages/ludic.settings/store.ludic
Normal file
93
packages/ludic.settings/store.ludic
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# ludic.settings/store.ludic - the values, by id (a setting's place in the order it was added),
|
||||
# and the verbs: nothing else holds a setting, and every set that changes one is a fact
|
||||
var sg_defs: []SettingDef = null
|
||||
var sg_num: []float = null
|
||||
var sg_text: []string = null
|
||||
var sg_changes: Queue<SettingChanged> = null
|
||||
|
||||
function sg_init() -> void {
|
||||
if sg_defs != null { return }
|
||||
sg_defs = new []SettingDef
|
||||
sg_num = new []float
|
||||
sg_text = new []string
|
||||
}
|
||||
|
||||
export function settings_changes() -> Queue<SettingChanged> {
|
||||
if sg_changes == null { sg_changes = queue_new("settings.changes") }
|
||||
return sg_changes
|
||||
}
|
||||
|
||||
# forget every setting (a test, or a game that declares its table again)
|
||||
export function settings_clear() -> void {
|
||||
sg_defs = new []SettingDef
|
||||
sg_num = new []float
|
||||
sg_text = new []string
|
||||
q_clear(settings_changes())
|
||||
}
|
||||
|
||||
# a setting, at its default; its id is its place in the order added
|
||||
export function settings_add(d: SettingDef) -> int {
|
||||
sg_init()
|
||||
push(sg_defs, d)
|
||||
push(sg_num, d.num)
|
||||
push(sg_text, d.text)
|
||||
return len(sg_defs) - 1
|
||||
}
|
||||
|
||||
export function settings_count() -> int {
|
||||
sg_init()
|
||||
return len(sg_defs)
|
||||
}
|
||||
|
||||
export function settings_def(id: int) -> SettingDef { return sg_defs[id] }
|
||||
|
||||
# the id of `key`, or -1
|
||||
export function settings_id_of(key: string) -> int {
|
||||
sg_init()
|
||||
for i in 0 .. len(sg_defs) { if sg_defs[i].key == key { return i } }
|
||||
return -1
|
||||
}
|
||||
|
||||
export function settings_get_float(id: int) -> float { return sg_num[id] }
|
||||
export function settings_get_int(id: int) -> int { return int(sg_num[id]) }
|
||||
export function settings_get_bool(id: int) -> bool { return sg_num[id] != 0.0 }
|
||||
export function settings_get_text(id: int) -> string { return sg_text[id] }
|
||||
|
||||
function sg_changed(id: int) -> void {
|
||||
let c = new SettingChanged
|
||||
c.id = id
|
||||
c.key = sg_defs[id].key
|
||||
q_push(settings_changes(), c)
|
||||
}
|
||||
|
||||
# a value outside the setting's range is its default: a damaged file never reaches the game
|
||||
export function settings_set_float(id: int, v: float) -> void {
|
||||
let h = settings_held(id, v)
|
||||
if h == sg_num[id] { return }
|
||||
sg_num[id] = h
|
||||
sg_changed(id)
|
||||
}
|
||||
|
||||
export function settings_set_int(id: int, v: int) -> void { settings_set_float(id, float(v)) }
|
||||
|
||||
export function settings_set_bool(id: int, v: bool) -> void {
|
||||
if v { settings_set_float(id, 1.0) } else { settings_set_float(id, 0.0) }
|
||||
}
|
||||
|
||||
export function settings_set_text(id: int, v: string) -> void {
|
||||
if v == sg_text[id] { return }
|
||||
sg_text[id] = v
|
||||
sg_changed(id)
|
||||
}
|
||||
|
||||
# `v` held to the setting's range: outside it, the default
|
||||
export function settings_held(id: int, v: float) -> float {
|
||||
let d = sg_defs[id]
|
||||
var x = v
|
||||
if d.kind == SETTING_BOOL {
|
||||
if x != 0.0 { x = 1.0 }
|
||||
}
|
||||
if d.kind == SETTING_INT { x = float(int(Math.floor(x + 0.5))) }
|
||||
if d.hi >= d.lo and (x < d.lo or x > d.hi) { return d.num }
|
||||
return x
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue