ludic.ui, runtime: the last per-frame allocations in the interface - the top popover found without a list, the popover draw list and the clip stack kept, a select's options in a list the node keeps (and matched to its value without writing the index), a number's text kept on its Value until it changes (value_num_set / Value.num_text), a key's label kept per key code until the layout changes it
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
3915af34c2
commit
50f255eea4
10 changed files with 98 additions and 40 deletions
|
|
@ -149,6 +149,7 @@ export state UiState {
|
||||||
pe_key: string = "" # the element the pointer is captured by
|
pe_key: string = "" # the element the pointer is captured by
|
||||||
pe_btn: int = 0
|
pe_btn: int = 0
|
||||||
pop_list: []UiNode = new []UiNode
|
pop_list: []UiNode = new []UiNode
|
||||||
|
pop_spare: []UiNode = new []UiNode
|
||||||
pp_bx: float = 0.0
|
pp_bx: float = 0.0
|
||||||
pp_by: float = 0.0
|
pp_by: float = 0.0
|
||||||
pp_bw: float = 0.0
|
pp_bw: float = 0.0
|
||||||
|
|
|
||||||
|
|
@ -67,8 +67,11 @@ function ct_build_range(ui_st: mut UiState, n: UiNode) -> void {
|
||||||
push(n.children, ct_part(ui_st, n, "ui-value", ct_value_text(n)))
|
push(n.children, ct_part(ui_st, n, "ui-value", ct_value_text(n)))
|
||||||
}
|
}
|
||||||
function ct_build_select(ui_st: mut UiState, n: UiNode) -> void {
|
function ct_build_select(ui_st: mut UiState, n: UiNode) -> void {
|
||||||
let opts = n.children
|
if n.opts == null { n.opts = new []UiNode } # its options moved to a list the node keeps, not a new one
|
||||||
n.children = new []UiNode
|
let opts = n.opts
|
||||||
|
List.clear(opts)
|
||||||
|
for i in 0 .. len(n.children) { push(opts, n.children[i]) }
|
||||||
|
List.clear(n.children)
|
||||||
ct_label(ui_st, n)
|
ct_label(ui_st, n)
|
||||||
var shown = ""
|
var shown = ""
|
||||||
let at = ct_option_at(n, opts)
|
let at = ct_option_at(n, opts)
|
||||||
|
|
@ -76,14 +79,13 @@ function ct_build_select(ui_st: mut UiState, n: UiNode) -> void {
|
||||||
push(n.children, ct_part(ui_st, n, "ui-prev", "<"))
|
push(n.children, ct_part(ui_st, n, "ui-prev", "<"))
|
||||||
push(n.children, ct_part(ui_st, n, "ui-value", shown))
|
push(n.children, ct_part(ui_st, n, "ui-value", shown))
|
||||||
push(n.children, ct_part(ui_st, n, "ui-next", ">"))
|
push(n.children, ct_part(ui_st, n, "ui-next", ">"))
|
||||||
n.opts = opts
|
|
||||||
}
|
}
|
||||||
# which option the select's value names: an option's value="...", else its place
|
# which option the select's value names: an option's value="...", else its place
|
||||||
function ct_option_at(n: UiNode, opts: []UiNode) -> int {
|
function ct_option_at(n: UiNode, opts: []UiNode) -> int {
|
||||||
let v = ui_attr_text(n, "value")
|
let v = ui_attr_text(n, "value")
|
||||||
for i in 0 .. len(opts) {
|
for i in 0 .. len(opts) {
|
||||||
let ov = ui_attr_text(opts[i], "value")
|
let ov = ui_attr_text(opts[i], "value")
|
||||||
if ov == v or (ov == "" and string(i) == v) { return i }
|
if ov == v or (ov == "" and ct_is_int(v, i)) { return i }
|
||||||
}
|
}
|
||||||
return -1
|
return -1
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,3 +50,16 @@ function ct_submit(ui_st: mut UiState, n: UiNode) -> void {
|
||||||
ui_fire(ui_st, n, "submit", ui_attr(n, "value"))
|
ui_fire(ui_st, n, "submit", ui_attr(n, "value"))
|
||||||
if ui_attr_on(n, "clear-on-submit") { ui_fire(ui_st, n, "change", Value.str("")) }
|
if ui_attr_on(n, "clear-on-submit") { ui_fire(ui_st, n, "change", Value.str("")) }
|
||||||
}
|
}
|
||||||
|
# the text is exactly i's digits, compared without writing i out
|
||||||
|
function ct_is_int(s: string, i: int) -> bool {
|
||||||
|
if i < 0 or len(s) == 0 { return false }
|
||||||
|
var n = i
|
||||||
|
var at = len(s) - 1
|
||||||
|
while at >= 0 {
|
||||||
|
if s[at] != 48 + n % 10 { return false }
|
||||||
|
n = n / 10
|
||||||
|
at -= 1
|
||||||
|
if n == 0 { return at < 0 }
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,9 @@ function fr_clip_push(ui_st: mut UiState, x: float, y: float, w: float, h: float
|
||||||
ui_st.ui_be.clip(x0, y0, Math.max(x1 - x0, 0.0), Math.max(y1 - y0, 0.0))
|
ui_st.ui_be.clip(x0, y0, Math.max(x1 - x0, 0.0), Math.max(y1 - y0, 0.0))
|
||||||
}
|
}
|
||||||
function fr_clip_pop(ui_st: mut UiState) -> void {
|
function fr_clip_pop(ui_st: mut UiState) -> void {
|
||||||
var keep = new []float
|
for i in 0 .. 4 { # the top rectangle taken off in place
|
||||||
for i in 0 .. len(ui_st.fr_clips) - 4 { push(keep, ui_st.fr_clips[i]) }
|
if len(ui_st.fr_clips) > 0 { List.pop(ui_st.fr_clips) }
|
||||||
ui_st.fr_clips = keep
|
}
|
||||||
let n = len(ui_st.fr_clips)
|
let n = len(ui_st.fr_clips)
|
||||||
if n >= 4 { ui_st.ui_be.clip(ui_st.fr_clips[n - 4], ui_st.fr_clips[n - 3], ui_st.fr_clips[n - 2] - ui_st.fr_clips[n - 4], ui_st.fr_clips[n - 1] - ui_st.fr_clips[n - 3]) } else if ui_st.ui_be.unclip != null { ui_st.ui_be.unclip() }
|
if n >= 4 { ui_st.ui_be.clip(ui_st.fr_clips[n - 4], ui_st.fr_clips[n - 3], ui_st.fr_clips[n - 2] - ui_st.fr_clips[n - 4], ui_st.fr_clips[n - 1] - ui_st.fr_clips[n - 3]) } else if ui_st.ui_be.unclip != null { ui_st.ui_be.unclip() }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ function nd_reset_b(n: UiNode) -> void {
|
||||||
n.scroll_y = 0.0
|
n.scroll_y = 0.0
|
||||||
n.bar_c = -1
|
n.bar_c = -1
|
||||||
n.bar_track = -2
|
n.bar_track = -2
|
||||||
n.opts = null
|
if n.opts != null { List.clear(n.opts) }
|
||||||
n.bg_img = ""
|
n.bg_img = ""
|
||||||
n.bi_src = ""
|
n.bi_src = ""
|
||||||
n.bi_slice = 0.0
|
n.bi_slice = 0.0
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,13 @@ function pp_find(n: UiNode, out: []UiNode) -> void {
|
||||||
}
|
}
|
||||||
# the topmost popover open in this tree, or null
|
# the topmost popover open in this tree, or null
|
||||||
function pp_top(root: UiNode) -> UiNode {
|
function pp_top(root: UiNode) -> UiNode {
|
||||||
let all = new []UiNode
|
if root.popover { return root } # the last one pp_find would list, found with no list made
|
||||||
pp_find(root, all)
|
var found: UiNode = null
|
||||||
if len(all) == 0 { return null }
|
for i in 0 .. len(root.children) {
|
||||||
return all[len(all) - 1]
|
let f = pp_top(root.children[i])
|
||||||
|
if f != null { found = f }
|
||||||
|
}
|
||||||
|
return found
|
||||||
}
|
}
|
||||||
# the pointer against the popover: inside it is as usual; a press outside closes it and is spent
|
# the pointer against the popover: inside it is as usual; a press outside closes it and is spent
|
||||||
function pp_pointer(ui_st: mut UiState, top: UiNode) -> bool {
|
function pp_pointer(ui_st: mut UiState, top: UiNode) -> bool {
|
||||||
|
|
@ -26,7 +29,9 @@ function pp_pointer(ui_st: mut UiState, top: UiNode) -> bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
function pp_draw_top(ui_st: mut UiState) -> void {
|
function pp_draw_top(ui_st: mut UiState) -> void {
|
||||||
let list = ui_st.pop_list
|
let list = ui_st.pop_list # drawn from while what they open goes to the spare, then swapped
|
||||||
ui_st.pop_list = new []UiNode
|
ui_st.pop_list = ui_st.pop_spare
|
||||||
|
List.clear(ui_st.pop_list)
|
||||||
for i in 0 .. len(list) { fr_draw(ui_st, list[i]) }
|
for i in 0 .. len(list) { fr_draw(ui_st, list[i]) }
|
||||||
|
ui_st.pop_spare = list
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,17 +13,12 @@ function vl_truthy(v: Val) -> bool {
|
||||||
function vl_text(v: Val) -> string {
|
function vl_text(v: Val) -> string {
|
||||||
let k = Value.kind(v)
|
let k = Value.kind(v)
|
||||||
if k == 0 { return "" }
|
if k == 0 { return "" }
|
||||||
if k == 1 { return string(Value.as_int(v)) }
|
if k == 1 or k == 2 or k == 7 { return Value.num_text(v) } # kept on the Value until it changes
|
||||||
if k == 3 {
|
if k == 3 {
|
||||||
if Value.as_int(v) != 0 { return "true" }
|
if Value.as_int(v) != 0 { return "true" }
|
||||||
return "false"
|
return "false"
|
||||||
}
|
}
|
||||||
if k == 4 { return Value.as_str(v) }
|
if k == 4 { return Value.as_str(v) }
|
||||||
if k == 2 or k == 7 {
|
|
||||||
let f = Value.as_float(v)
|
|
||||||
if f == float(int(f)) { return string(int(f)) }
|
|
||||||
return string(f)
|
|
||||||
}
|
|
||||||
return Json.encode(v)
|
return Json.encode(v)
|
||||||
}
|
}
|
||||||
function vl_arith(ui_st: mut UiState, op: string, a: Val, b: Val) -> Val {
|
function vl_arith(ui_st: mut UiState, op: string, a: Val, b: Val) -> Val {
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,8 @@ export state RtInputState {
|
||||||
input_rec: words = null # recorded key per frame
|
input_rec: words = null # recorded key per frame
|
||||||
input_recn: int = 0 # frames recorded
|
input_recn: int = 0 # frames recorded
|
||||||
input_pos: int = 0 # replay / record cursor
|
input_pos: int = 0 # replay / record cursor
|
||||||
|
in_label_chr: words = null # input_key_label: the character each key's kept name was made for
|
||||||
|
in_label_str: []string = null
|
||||||
in_have_frame_driver: bool = false
|
in_have_frame_driver: bool = false
|
||||||
in_ready: bool = false
|
in_ready: bool = false
|
||||||
in_sim: words = null # simulated held set (Input.press / release) — persists
|
in_sim: words = null # simulated held set (Input.press / release) — persists
|
||||||
|
|
@ -380,7 +382,27 @@ function input_key_released(rt_input_st: mut RtInputState, k: int) -> bool { in_
|
||||||
# own layout types there: 'w' reads "W" on QWERTY and "Z" on AZERTY, and a binding
|
# own layout types there: 'w' reads "W" on QWERTY and "Z" on AZERTY, and a binding
|
||||||
# shown as "W" is never a key the player cannot find. Named keys and the arrows get words.
|
# shown as "W" is never a key the player cannot find. Named keys and the arrows get words.
|
||||||
# Headless, and on a platform that cannot ask the layout, it is the US character.
|
# Headless, and on a platform that cannot ask the layout, it is the US character.
|
||||||
function input_key_label(k: int) -> string {
|
# a key's name, kept per key code and made again only when the layout gives the key another character -
|
||||||
|
# a HUD asks for its keys' names every frame, and each asking made a string (Ludic frees nothing)
|
||||||
|
function input_key_label(rt_input_st: mut RtInputState, k: int) -> string {
|
||||||
|
if k < 0 or k > 255 { return input_key_label_new(k) }
|
||||||
|
var c = -1
|
||||||
|
if is_windowed() { c = win_key_char(k) }
|
||||||
|
if rt_input_st.in_label_chr == null {
|
||||||
|
rt_input_st.in_label_chr = words(256)
|
||||||
|
rt_input_st.in_label_str = new []string
|
||||||
|
for i in 0 .. 256 {
|
||||||
|
rt_input_st.in_label_chr[i] = -2
|
||||||
|
push(rt_input_st.in_label_str, "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if rt_input_st.in_label_chr[k] != c {
|
||||||
|
rt_input_st.in_label_str[k] = input_key_label_new(k)
|
||||||
|
rt_input_st.in_label_chr[k] = c
|
||||||
|
}
|
||||||
|
return rt_input_st.in_label_str[k]
|
||||||
|
}
|
||||||
|
function input_key_label_new(k: int) -> string {
|
||||||
if k == 32 { return "Space" }
|
if k == 32 { return "Space" }
|
||||||
if k == 10 { return "Enter" }
|
if k == 10 { return "Enter" }
|
||||||
if k == 27 { return "Esc" }
|
if k == 27 { return "Esc" }
|
||||||
|
|
|
||||||
|
|
@ -480,6 +480,7 @@ namespace Value {
|
||||||
alias as_str(value) = value_as_str
|
alias as_str(value) = value_as_str
|
||||||
alias free(value) = value_free
|
alias free(value) = value_free
|
||||||
alias clear(value) = value_clear
|
alias clear(value) = value_clear
|
||||||
|
alias num_text(value) = value_num_text
|
||||||
alias become(value, tag) = value_become
|
alias become(value, tag) = value_become
|
||||||
alias be_int(value, n) = value_be_int
|
alias be_int(value, n) = value_be_int
|
||||||
alias be_float(value, x) = value_be_float
|
alias be_float(value, x) = value_be_float
|
||||||
|
|
|
||||||
|
|
@ -90,11 +90,11 @@ function value_slot(o: Val, key: pointer, tag: int) -> Val {
|
||||||
}
|
}
|
||||||
function value_set_int(o: Val, key: pointer, n: int) -> void {
|
function value_set_int(o: Val, key: pointer, n: int) -> void {
|
||||||
let v = value_slot(o, key, 1)
|
let v = value_slot(o, key, 1)
|
||||||
v.num = n
|
value_num_set(v, n)
|
||||||
}
|
}
|
||||||
function value_set_float(o: Val, key: pointer, x: float) -> void {
|
function value_set_float(o: Val, key: pointer, x: float) -> void {
|
||||||
let v = value_slot(o, key, 7)
|
let v = value_slot(o, key, 7)
|
||||||
v.num = float_bits(x)
|
value_num_set(v, float_bits(x))
|
||||||
}
|
}
|
||||||
function value_set_str(o: Val, key: pointer, s: pointer) -> void {
|
function value_set_str(o: Val, key: pointer, s: pointer) -> void {
|
||||||
let v = value_slot(o, key, 4)
|
let v = value_slot(o, key, 4)
|
||||||
|
|
@ -102,8 +102,8 @@ function value_set_str(o: Val, key: pointer, s: pointer) -> void {
|
||||||
}
|
}
|
||||||
function value_set_bool(o: Val, key: pointer, b: bool) -> void {
|
function value_set_bool(o: Val, key: pointer, b: bool) -> void {
|
||||||
let v = value_slot(o, key, 3)
|
let v = value_slot(o, key, 3)
|
||||||
v.num = 0
|
value_num_set(v, 0)
|
||||||
if b { v.num = 1 }
|
if b { value_num_set(v, 1) }
|
||||||
}
|
}
|
||||||
# a list field of an object set in place: the list under `key` is kept, and item i keeps its Value when it
|
# a list field of an object set in place: the list under `key` is kept, and item i keeps its Value when it
|
||||||
# is already that kind (a component's model, filled into the same object every frame)
|
# is already that kind (a component's model, filled into the same object every frame)
|
||||||
|
|
@ -128,14 +128,14 @@ function value_set_ints(o: Val, key: pointer, xs: []int) -> void {
|
||||||
let l = value_list_fit(o, key, len(xs))
|
let l = value_list_fit(o, key, len(xs))
|
||||||
for i in 0 .. len(xs) {
|
for i in 0 .. len(xs) {
|
||||||
let v = value_item(l, i, 1)
|
let v = value_item(l, i, 1)
|
||||||
v.num = xs[i]
|
value_num_set(v, xs[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function value_set_floats(o: Val, key: pointer, xs: []float) -> void {
|
function value_set_floats(o: Val, key: pointer, xs: []float) -> void {
|
||||||
let l = value_list_fit(o, key, len(xs))
|
let l = value_list_fit(o, key, len(xs))
|
||||||
for i in 0 .. len(xs) {
|
for i in 0 .. len(xs) {
|
||||||
let v = value_item(l, i, 7)
|
let v = value_item(l, i, 7)
|
||||||
v.num = float_bits(xs[i])
|
value_num_set(v, float_bits(xs[i]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function value_set_strs(o: Val, key: pointer, xs: []string) -> void {
|
function value_set_strs(o: Val, key: pointer, xs: []string) -> void {
|
||||||
|
|
@ -149,15 +149,15 @@ function value_set_bools(o: Val, key: pointer, xs: []bool) -> void {
|
||||||
let l = value_list_fit(o, key, len(xs))
|
let l = value_list_fit(o, key, len(xs))
|
||||||
for i in 0 .. len(xs) {
|
for i in 0 .. len(xs) {
|
||||||
let v = value_item(l, i, 3)
|
let v = value_item(l, i, 3)
|
||||||
v.num = 0
|
value_num_set(v, 0)
|
||||||
if xs[i] { v.num = 1 }
|
if xs[i] { value_num_set(v, 1) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# a Value turned into a blank one of kind `tag`, its own lists (if it has them) kept and emptied - for
|
# a Value turned into a blank one of kind `tag`, its own lists (if it has them) kept and emptied - for
|
||||||
# a pool that hands the same records out again (ludic.ui's, frame after frame)
|
# a pool that hands the same records out again (ludic.ui's, frame after frame)
|
||||||
function value_become(v: Val, tag: int) -> Val {
|
function value_become(v: Val, tag: int) -> Val {
|
||||||
v.tag = tag
|
v.tag = tag
|
||||||
v.num = 0
|
value_num_set(v, 0)
|
||||||
v.txt = null
|
v.txt = null
|
||||||
if tag == 5 or tag == 6 { value_lists(v) }
|
if tag == 5 or tag == 6 { value_lists(v) }
|
||||||
if v.kids != null { value_clear(v) }
|
if v.kids != null { value_clear(v) }
|
||||||
|
|
@ -165,12 +165,12 @@ function value_become(v: Val, tag: int) -> Val {
|
||||||
}
|
}
|
||||||
function value_be_int(v: Val, n: int) -> Val {
|
function value_be_int(v: Val, n: int) -> Val {
|
||||||
value_become(v, 1)
|
value_become(v, 1)
|
||||||
v.num = n
|
value_num_set(v, n)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
function value_be_float(v: Val, x: float) -> Val {
|
function value_be_float(v: Val, x: float) -> Val {
|
||||||
value_become(v, 7)
|
value_become(v, 7)
|
||||||
v.num = float_bits(x)
|
value_num_set(v, float_bits(x))
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
function value_be_str(v: Val, s: pointer) -> Val {
|
function value_be_str(v: Val, s: pointer) -> Val {
|
||||||
|
|
@ -187,12 +187,12 @@ function value_into(into: Val, tag: int) -> Val {
|
||||||
function value_into_null(into: Val) -> Val { return value_into(into, 0) }
|
function value_into_null(into: Val) -> Val { return value_into(into, 0) }
|
||||||
function value_into_int(into: Val, n: int) -> Val {
|
function value_into_int(into: Val, n: int) -> Val {
|
||||||
let v = value_into(into, 1)
|
let v = value_into(into, 1)
|
||||||
v.num = n
|
value_num_set(v, n)
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
function value_into_float(into: Val, x: float) -> Val {
|
function value_into_float(into: Val, x: float) -> Val {
|
||||||
let v = value_into(into, 7)
|
let v = value_into(into, 7)
|
||||||
v.num = float_bits(x)
|
value_num_set(v, float_bits(x))
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
function value_into_str(into: Val, s: pointer) -> Val {
|
function value_into_str(into: Val, s: pointer) -> Val {
|
||||||
|
|
@ -202,14 +202,14 @@ function value_into_str(into: Val, s: pointer) -> Val {
|
||||||
}
|
}
|
||||||
function value_into_bool(into: Val, b: bool) -> Val {
|
function value_into_bool(into: Val, b: bool) -> Val {
|
||||||
let v = value_into(into, 3)
|
let v = value_into(into, 3)
|
||||||
if b { v.num = 1 }
|
if b { value_num_set(v, 1) }
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
# a list result: `into`'s items are kept and changed in place where they are already that kind
|
# a list result: `into`'s items are kept and changed in place where they are already that kind
|
||||||
function value_into_list(into: Val, n: int) -> Val {
|
function value_into_list(into: Val, n: int) -> Val {
|
||||||
if into == null { return value_list() }
|
if into == null { return value_list() }
|
||||||
into.tag = 5
|
into.tag = 5
|
||||||
into.num = 0
|
value_num_set(into, 0)
|
||||||
into.txt = null
|
into.txt = null
|
||||||
value_lists(into)
|
value_lists(into)
|
||||||
while len(into.kids) > n { List.pop(into.kids) }
|
while len(into.kids) > n { List.pop(into.kids) }
|
||||||
|
|
@ -219,7 +219,7 @@ function value_into_ints(into: Val, xs: []int) -> Val {
|
||||||
let l = value_into_list(into, len(xs))
|
let l = value_into_list(into, len(xs))
|
||||||
for i in 0 .. len(xs) {
|
for i in 0 .. len(xs) {
|
||||||
let v = value_item(l, i, 1)
|
let v = value_item(l, i, 1)
|
||||||
v.num = xs[i]
|
value_num_set(v, xs[i])
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
@ -227,7 +227,7 @@ function value_into_floats(into: Val, xs: []float) -> Val {
|
||||||
let l = value_into_list(into, len(xs))
|
let l = value_into_list(into, len(xs))
|
||||||
for i in 0 .. len(xs) {
|
for i in 0 .. len(xs) {
|
||||||
let v = value_item(l, i, 7)
|
let v = value_item(l, i, 7)
|
||||||
v.num = float_bits(xs[i])
|
value_num_set(v, float_bits(xs[i]))
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
|
@ -243,11 +243,30 @@ function value_into_bools(into: Val, xs: []bool) -> Val {
|
||||||
let l = value_into_list(into, len(xs))
|
let l = value_into_list(into, len(xs))
|
||||||
for i in 0 .. len(xs) {
|
for i in 0 .. len(xs) {
|
||||||
let v = value_item(l, i, 3)
|
let v = value_item(l, i, 3)
|
||||||
v.num = 0
|
value_num_set(v, 0)
|
||||||
if xs[i] { v.num = 1 }
|
if xs[i] { value_num_set(v, 1) }
|
||||||
}
|
}
|
||||||
return l
|
return l
|
||||||
}
|
}
|
||||||
|
# a number set where it is kept: its text (value_num_text) is dropped only when the number changes
|
||||||
|
function value_num_set(v: Val, n: int) -> void {
|
||||||
|
if v.num == n { return }
|
||||||
|
v.num = n
|
||||||
|
if v.tag != 4 { v.txt = null }
|
||||||
|
}
|
||||||
|
# a number's text, kept on the Value until the number changes (a count shown in a HUD every frame wrote
|
||||||
|
# its text every frame; Ludic frees nothing)
|
||||||
|
function value_num_text(v: Val) -> string {
|
||||||
|
if v.txt != null { return v.txt }
|
||||||
|
if v.tag == 1 { v.txt = string(v.num) }
|
||||||
|
else if v.tag == 7 {
|
||||||
|
let f = float_from_bits(v.num)
|
||||||
|
if f == float(int(f)) { v.txt = string(int(f)) } else { v.txt = string(f) }
|
||||||
|
}
|
||||||
|
else if v.tag == 2 { v.txt = json_fixed_str(v.num) }
|
||||||
|
if v.txt == null { return "" }
|
||||||
|
return v.txt
|
||||||
|
}
|
||||||
# a list or an object emptied in place, its room kept - for one filled again every frame
|
# a list or an object emptied in place, its room kept - for one filled again every frame
|
||||||
function value_clear(v: Val) -> void {
|
function value_clear(v: Val) -> void {
|
||||||
if v.kids == null { return }
|
if v.kids == null { return }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue