# 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 export state SettingsState { sg_defs: []SettingDef = new []SettingDef sg_num: []float = new []float sg_text: []string = new []string sg_changes: Queue = sg_changes__new() } export function settings_changes(settings_st: SettingsState) -> Queue { return settings_st.sg_changes } # forget every setting (a test, or a game that declares its table again) export function settings_clear(settings_st: mut SettingsState) -> void { settings_st.sg_defs = new []SettingDef settings_st.sg_num = new []float settings_st.sg_text = new []string q_clear(settings_changes(settings_st)) } # a setting, at its default; its id is its place in the order added export function settings_add(settings_st: mut SettingsState, d: SettingDef) -> int { push(settings_st.sg_defs, d) push(settings_st.sg_num, d.num) push(settings_st.sg_text, d.text) return len(settings_st.sg_defs) - 1 } export function settings_count(settings_st: SettingsState) -> int { return len(settings_st.sg_defs) } export function settings_def(settings_st: SettingsState, id: int) -> SettingDef { return settings_st.sg_defs[id] } # the id of `key`, or -1 export function settings_id_of(settings_st: SettingsState, key: string) -> int { for i in 0 .. len(settings_st.sg_defs) { if settings_st.sg_defs[i].key == key { return i } } return -1 } export function settings_get_float(settings_st: SettingsState, id: int) -> float { return settings_st.sg_num[id] } export function settings_get_int(settings_st: SettingsState, id: int) -> int { return int(settings_st.sg_num[id]) } export function settings_get_bool(settings_st: SettingsState, id: int) -> bool { return settings_st.sg_num[id] != 0.0 } export function settings_get_text(settings_st: SettingsState, id: int) -> string { return settings_st.sg_text[id] } function sg_changed(settings_st: SettingsState, id: int) -> void { var c = q_rec(settings_changes(settings_st)) if c == null { @alloc_ok("past the ring: more of these in a frame than its records, then kept in it") c = new SettingChanged q_ring_add(settings_changes(settings_st), c) } c.id = id c.key = settings_st.sg_defs[id].key q_push(settings_changes(settings_st), c) } # a value outside the setting's range is its default: a damaged file never reaches the game export function settings_set_float(settings_st: mut SettingsState, id: int, v: float) -> void { let h = settings_held(settings_st, id, v) if h == settings_st.sg_num[id] { return } settings_st.sg_num[id] = h sg_changed(settings_st, id) } export function settings_set_int(settings_st: mut SettingsState, id: int, v: int) -> void { settings_set_float(settings_st, id, float(v)) } export function settings_set_bool(settings_st: mut SettingsState, id: int, v: bool) -> void { if v { settings_set_float(settings_st, id, 1.0) } else { settings_set_float(settings_st, id, 0.0) } } export function settings_set_text(settings_st: mut SettingsState, id: int, v: string) -> void { if v == settings_st.sg_text[id] { return } settings_st.sg_text[id] = v sg_changed(settings_st, id) } # `v` held to the setting's range: outside it, the default export function settings_held(settings_st: SettingsState, id: int, v: float) -> float { let d = settings_st.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 } function sg_changes__new() -> Queue { return queue_new("settings.changes") }