From bd2d62ddca5f7cb046f9129bfe8b3e32608127a1 Mon Sep 17 00:00:00 2001 From: Orkuncakilkaya Date: Mon, 28 Sep 2026 21:09:08 +0300 Subject: [PATCH] ludic.ui: a select matches a number as a number (its text was made every frame per select); the fired-event queue's lists made with room; ludic.inventory: the counts made at full length at once Co-Authored-By: Claude Opus 5.5 --- packages/ludic.inventory/verbs.ludic | 14 ++++++++++---- packages/ludic.ui/backend.ludic | 12 ++++++------ packages/ludic.ui/controls_build.ludic | 16 ++++++++++++++++ packages/ludic.ui/index.ludic | 1 + packages/ludic.ui/native_room.ludic | 24 ++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 packages/ludic.ui/native_room.ludic diff --git a/packages/ludic.inventory/verbs.ludic b/packages/ludic.inventory/verbs.ludic index e98ec789..d9c32983 100644 --- a/packages/ludic.inventory/verbs.ludic +++ b/packages/ludic.inventory/verbs.ludic @@ -40,10 +40,16 @@ export function inv_set(inventory_st: mut InventoryState, it: int, n: int) -> vo # everything gone, silently: a new trip, or before a load export function inv_clear(inventory_st: mut InventoryState) -> void { - if inventory_st.iv_counts == null { - @alloc_ok("once: the counts are made the first time the pack is cleared") - inventory_st.iv_counts = new []int - } + if inventory_st.iv_counts == null { inventory_st.iv_counts = iv_counts__new(inv_kinds(inventory_st)) } List.clear(inventory_st.iv_counts) for i in 0 .. inv_kinds(inventory_st) { kept_push(inventory_st.iv_counts, 0) } } + +# the counts made at their full length at once: a list grown a push at a time in play is a new block +@alloc_ok("once: the counts are made the first time the pack is cleared") +function iv_counts__new(n: int) -> []int { + let xs = new []int + for i in 0 .. n { push(xs, 0) } + List.clear(xs) + return xs +} diff --git a/packages/ludic.ui/backend.ludic b/packages/ludic.ui/backend.ludic index 76d78f7e..e9eacd62 100644 --- a/packages/ludic.ui/backend.ludic +++ b/packages/ludic.ui/backend.ludic @@ -147,12 +147,12 @@ export state UiState { lc_prev_unmounts: []UiAct = new []UiAct lc_prev_envs: []UiEnv = new []UiEnv nt_list: []UiNative = new []UiNative - nt_sp_nodes: []UiNode = new []UiNode # native.ludic: the queue's spare, swapped while it runs - nt_sp_names: []string = new []string - nt_sp_vals: []Val = new []Val - nt_q_nodes: []UiNode = new []UiNode - nt_q_names: []string = new []string - nt_q_vals: []Val = new []Val + nt_sp_nodes: []UiNode = nt_nodes__new() # native.ludic: the queue's spare, swapped while it runs; + nt_sp_names: []string = nt_names__new() # each list is made with room for a busy frame's events + nt_sp_vals: []Val = nt_vals__new() + nt_q_nodes: []UiNode = nt_nodes__new() + nt_q_names: []string = nt_names__new() + nt_q_vals: []Val = nt_vals__new() fr_hover: []string = new []string fr_hover_sp: []string = new []string fr_press_key: string = "" diff --git a/packages/ludic.ui/controls_build.ludic b/packages/ludic.ui/controls_build.ludic index 18f6122d..fd21f0a4 100644 --- a/packages/ludic.ui/controls_build.ludic +++ b/packages/ludic.ui/controls_build.ludic @@ -83,6 +83,8 @@ function ct_build_select(ui_st: mut UiState, n: UiNode) -> void { } # which option the select's value names: an option's value="...", else its place function ct_option_at(n: UiNode, opts: []UiNode) -> int { + let nv = ui_attr(n, "value") + if ct_numeric(nv) { return ct_option_num(nv, opts) } let v = ui_attr_text(n, "value") for i in 0 .. len(opts) { let ov = ui_attr_text(opts[i], "value") @@ -96,3 +98,17 @@ function ct_field_text(ui_st: mut UiState, n: UiNode) -> string { if t == "number" { return ct_num_shown(ui_st, n) } return ui_attr_text(n, "value") } + +# a number held by a select (the usual case: a setting's value) matched as a number: its text was +# made every frame for every select on screen. An option with no value of its own is its index +function ct_numeric(v: Val) -> bool { return Value.kind(v) == 1 or Value.kind(v) == 7 } +function ct_option_num(nv: Val, opts: []UiNode) -> int { + let x = Value.as_float(nv) + for i in 0 .. len(opts) { + let ov = ui_attr(opts[i], "value") + if Value.kind(ov) == 0 and x == float(i) { return i } + if ct_numeric(ov) and Value.as_float(ov) == x { return i } + if Value.kind(ov) == 4 and el_num(Value.as_str(ov)) == x and len(Value.as_str(ov)) > 0 { return i } + } + return -1 +} diff --git a/packages/ludic.ui/index.ludic b/packages/ludic.ui/index.ludic index 54dbc3e5..84096edb 100644 --- a/packages/ludic.ui/index.ludic +++ b/packages/ludic.ui/index.ludic @@ -24,6 +24,7 @@ import "env.ludic" import "eval.ludic" import "act.ludic" import "native.ludic" +import "native_room.ludic" import "controls.ludic" import "controls_build.ludic" import "controls_parts.ludic" diff --git a/packages/ludic.ui/native_room.ludic b/packages/ludic.ui/native_room.ludic new file mode 100644 index 00000000..7287217e --- /dev/null +++ b/packages/ludic.ui/native_room.ludic @@ -0,0 +1,24 @@ +# native_room.ludic - the fired-event queue's lists made with room already: a list's first growth +# is made at start rather than in the frame that first fires an event +const NT_ROOM: int = 32 +@alloc_ok("once: made with the state") +function nt_nodes__new() -> []UiNode { + let xs = new []UiNode + for i in 0 .. NT_ROOM { push(xs, null) } + List.clear(xs) + return xs +} +@alloc_ok("once: made with the state") +function nt_names__new() -> []string { + let xs = new []string + for i in 0 .. NT_ROOM { push(xs, "") } + List.clear(xs) + return xs +} +@alloc_ok("once: made with the state") +function nt_vals__new() -> []Val { + let xs = new []Val + for i in 0 .. NT_ROOM { push(xs, null) } + List.clear(xs) + return xs +}