lingmodeler
↓ 0 downloadsLingModeler: box modeling with quads and tris, rigging + weight painting, 2D vector illustration and animation, procedural textures and game assets; .lmesh / .ling native formats, OBJ, glTF and SVG import / export
Keywords 3d, modeling, vector, svg, gltf, obj, rigging, animation, textures, ling
lingfu install lingmodelerCode / Files (67)
ling/lingfmt.ling
# ━━━ lingfmt.ling — native formats that are also valid Ling source ━━━
# .lmesh = a 3D scene, .ling = a 2D vector document (the SVG intermediary). Both are modules:
# use "hero.lmesh" -> lm_object_count(), lm_o0_vx() ... and draw_<Name>(ox, oy, oz, scale) (lit triangles via triangle3d)
# use "logo.ling" -> lv_item_count() ... and draw_<name>(ox, oy, scale) (draw_poly + draw_line)
# Data lines are single-line functions: fn lm_<key>() { return <value> } where value is a number, a "string",
# lm_nums("1,2,3") or lm_strs("a|b"). LingModeler reads them back line by line; other programs just call them.
fn lf_esc(s) {
bind t = str_replace(s, "\\", "/")
bind t = str_replace(t, "\"", "'")
bind t = str_replace(t, "|", "/")
bind t = str_replace(t, "\n", " ")
return t
}
fn lf_ident(s) {
bind ok = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
bind out = ""
bind i = 0.0
while i < str_len(s) {
bind c = str_slice(s, i, 1.0)
if str_find(ok, c) >= 0.0 { bind out = out + c } else { bind out = out + "_" }
bind i = i + 1.0
}
if out == "" { return "item" }
return out
}
fn lf_nums(l) {
bind parts = list_new()
bind i = 0.0
while i < len(l) { bind parts = list_push(parts, mx_num(list_get(l, i))) bind i = i + 1.0 }
return "lm_nums(\"" + p_join(parts, ",") + "\")"
}
fn lf_strs(l) {
bind parts = list_new()
bind i = 0.0
while i < len(l) { bind parts = list_push(parts, lf_esc(list_get(l, i))) bind i = i + 1.0 }
return "lm_strs(\"" + p_join(parts, "|") + "\")"
}
fn lf_line(prefix, key, value) { return "fn " + prefix + key + "() { return " + value + " }" }
fn lf_helpers() {
return ["# helpers (decode the packed lists)", "fn lm_nums(s) {", " bind out = list_new()", " if s == \"\" { return out }", " bind parts = str_split(s, \",\")", " bind i = 0.0", " while i < len(parts) { bind out = list_push(out, to_number(list_get(parts, i))) bind i = i + 1.0 }", " return out", "}", "fn lm_strs(s) {", " if s == \"\" { return list_new() }", " return str_split(s, \"|\")", "}"]
}
# ── reading: returns the number of data lines; values land in st under "lfv_<key>" ──
fn lf_read(path, prefix) {
if !file_exists(path) { return 0.0 - 1.0 }
bind text = read_file(path)
bind lines = str_split(text, "\n")
bind head = "fn " + prefix
bind n = 0.0
bind keys = list_new()
bind i = 0.0
while i < len(lines) {
bind ln = str_trim(list_get(lines, i))
if str_starts_with(ln, head) {
bind p = str_find(ln, "()")
bind r = str_find(ln, "{ return ")
if p > 0.0 && r > 0.0 {
bind key = str_slice(ln, str_len(head), p - str_len(head))
bind val = str_slice(ln, r + 9.0, str_len(ln) - r - 9.0)
if str_ends_with(val, " }") { bind val = str_slice(val, 0.0, str_len(val) - 2.0) }
bind val = str_trim(val)
bind v = 0.0
if str_starts_with(val, "lm_nums(\"") {
bind inner = str_slice(val, 9.0, str_len(val) - 11.0)
bind v = list_new()
if inner != "" {
bind parts = str_split(inner, ",")
bind q = 0.0
while q < len(parts) { bind v = list_push(v, to_number(list_get(parts, q))) bind q = q + 1.0 }
}
} else if str_starts_with(val, "lm_strs(\"") {
bind inner = str_slice(val, 9.0, str_len(val) - 11.0)
bind v = sel(inner == "", list_new(), str_split(inner, "|"))
} else if str_starts_with(val, "\"") {
bind v = str_slice(val, 1.0, str_len(val) - 2.0)
} else { bind v = to_number(val) }
st_set("lfv_" + key, v)
bind keys = list_push(keys, key)
bind n = n + 1.0
}
}
bind i = i + 1.0
}
st_set("lf_keys", keys)
return n
}
fn lf_get(key, d) { if st_has("lfv_" + key) > 0.5 { return st_get("lfv_" + key, d) } return d }
fn lf_clear() {
bind keys = st_get("lf_keys", [])
bind i = 0.0
while i < len(keys) { st_set("lfv_" + list_get(keys, i), 0.0) bind i = i + 1.0 }
}
# ── .lmesh ───────────────────────────────────────────────────────────────────
fn lf_obj_schema() {
# [key, type] type: n number, s string, l number list, t string list
return ["name", "s", "px", "n", "py", "n", "pz", "n", "rx", "n", "ry", "n", "rz", "n", "sx", "n", "sy", "n", "sz", "n", "col", "n", "vis", "n", "tex", "n", "smooth", "n", "bound", "n", "act_cur", "n", "vx", "l", "vy", "l", "vz", "l", "fi", "l", "fs", "l", "fc", "l", "uv", "l", "fcol", "l", "wb", "l", "bn_name", "t", "bn_par", "l", "bn_hx", "l", "bn_hy", "l", "bn_hz", "l", "bn_tx", "l", "bn_ty", "l", "bn_tz", "l", "bp_rx", "l", "bp_ry", "l", "bp_rz", "l", "bp_tx", "l", "bp_ty", "l", "bp_tz", "l", "bp_sx", "l", "bp_sy", "l", "bp_sz", "l", "act_names", "t", "act_len", "l"]
}
fn lf_save_lmesh(path) {
bind out = list_new()
bind out = list_push(out, "# LingModeler scene (.lmesh) - valid Ling source. `use` it and call draw_<Object>(ox, oy, oz, scale).")
bind out = list_push(out, "# Faces are polygons (tris, quads, n-gons): lm_oN_fi = corner vertex indices, lm_oN_fs = first corner, lm_oN_fc = corner count.")
bind out = list_push(out, lf_line("lm_", "format", "\"lmesh\""))
bind out = list_push(out, lf_line("lm_", "version", "1"))
bind out = list_push(out, lf_line("lm_", "app", "\"LingModeler " + APP_VERSION + "\""))
bind ids = me_ids()
bind out = list_push(out, lf_line("lm_", "object_count", num_str(len(ids))))
bind out = list_push(out, lf_line("lm_", "cursor", lf_nums([st_get("cursor_x", 0.0), st_get("cursor_y", 0.0), st_get("cursor_z", 0.0)])))
bind out = list_push(out, lf_line("lm_", "timeline", lf_nums([st_get("tl_start", 0.0), st_get("tl_end", 48.0), st_get("tl_fps", 24.0)])))
bind schema = lf_obj_schema()
bind j = 0.0
while j < len(ids) {
bind o = list_get(ids, j)
bind pre = "o" + num_str(j) + "_"
bind q = 0.0
while q + 1.0 < len(schema) {
bind key = list_get(schema, q) bind ty = list_get(schema, q + 1.0)
bind v = st_get(mk(o, key), 0.0)
bind txt = ""
if ty == "s" { bind txt = "\"" + lf_esc(v) + "\"" }
if ty == "n" { bind txt = mx_num(v) }
if ty == "l" { bind txt = lf_nums(sel(is_list_val(v), v, [])) }
if ty == "t" { bind txt = lf_strs(sel(is_list_val(v), v, [])) }
bind out = list_push(out, lf_line("lm_", pre + key, txt))
bind q = q + 2.0
}
# actions: one key list per action
bind acts = st_get(mk(o, "act_data"), [])
bind a = 0.0
while a < len(acts) { bind out = list_push(out, lf_line("lm_", pre + "act_" + num_str(a), lf_nums(list_get(acts, a)))) bind a = a + 1.0 }
bind j = j + 1.0
}
# textures
bind tn = st_get("tx_names", [])
bind out = list_push(out, lf_line("lm_", "tex_count", num_str(len(tn))))
bind t = 0.0
while t < len(tn) {
bind i = tx_id(t)
bind pre = "t" + num_str(t) + "_"
bind out = list_push(out, lf_line("lm_", pre + "name", "\"" + lf_esc(list_get(tn, t)) + "\""))
bind out = list_push(out, lf_line("lm_", pre + "type", "\"" + st_get(tk(i, "type"), "noise") + "\""))
bind out = list_push(out, lf_line("lm_", pre + "p", lf_nums(st_get(tk(i, "p"), []))))
bind out = list_push(out, lf_line("lm_", pre + "c", lf_nums(st_get(tk(i, "c"), []))))
bind out = list_push(out, lf_line("lm_", pre + "opts", lf_nums([st_get(tk(i, "size"), 128.0), st_get(tk(i, "anim"), 0.0), st_get(tk(i, "speed"), 1.0), st_get(tk(i, "seamless"), 1.0)])))
bind out = list_push(out, lf_line("lm_", pre + "path", "\"" + lf_esc(st_get(tk(i, "path"), "")) + "\""))
bind t = t + 1.0
}
# draw helpers for other Ling programs
bind out = list_push(out, "")
bind h = lf_helpers()
bind i = 0.0
while i < len(h) { bind out = list_push(out, list_get(h, i)) bind i = i + 1.0 }
bind out = list_push(out, "# draw one object: lit triangles in the current scene (ling's triangle3d + set_color)")
bind out = list_push(out, "fn lmesh_draw_obj(vx, vy, vz, fi, fs, fc, fcol, col, ox, oy, oz, s) {")
bind out = list_push(out, " bind f = 0.0")
bind out = list_push(out, " while f < len(fc) {")
bind out = list_push(out, " bind c = col")
bind out = list_push(out, " if f < len(fcol) { if list_get(fcol, f) >= 0.0 { bind c = list_get(fcol, f) } }")
bind out = list_push(out, " set_color(floor(c / 65536.0), floor(c / 256.0) % 256.0, c % 256.0)")
bind out = list_push(out, " bind st = list_get(fs, f)")
bind out = list_push(out, " bind a = list_get(fi, st)")
bind out = list_push(out, " bind k = 1.0")
bind out = list_push(out, " while k + 1.0 < list_get(fc, f) {")
bind out = list_push(out, " bind b = list_get(fi, st + k)")
bind out = list_push(out, " bind d = list_get(fi, st + k + 1.0)")
bind out = list_push(out, " triangle3d(ox + list_get(vx, a) * s, oy + list_get(vy, a) * s, oz + list_get(vz, a) * s, ox + list_get(vx, b) * s, oy + list_get(vy, b) * s, oz + list_get(vz, b) * s, ox + list_get(vx, d) * s, oy + list_get(vy, d) * s, oz + list_get(vz, d) * s)")
bind out = list_push(out, " bind k = k + 1.0")
bind out = list_push(out, " }")
bind out = list_push(out, " bind f = f + 1.0")
bind out = list_push(out, " }")
bind out = list_push(out, "}")
bind j = 0.0
while j < len(ids) {
bind o = list_get(ids, j)
bind pre = "lm_o" + num_str(j) + "_"
bind out = list_push(out, "fn draw_" + lf_ident(me_name(o)) + "(ox, oy, oz, s) { lmesh_draw_obj(" + pre + "vx(), " + pre + "vy(), " + pre + "vz(), " + pre + "fi(), " + pre + "fs(), " + pre + "fc(), " + pre + "fcol(), " + pre + "col(), ox + " + pre + "px() * s, oy + " + pre + "py() * s, oz + " + pre + "pz() * s, s) }")
bind j = j + 1.0
}
write_file(path, p_join(out, "\n") + "\n")
return true
}
fn is_list_val(v) {
# len() on a number errors in some runtimes, so compare against a known list form
return str_starts_with(num_or_list_str(v), "[")
}
fn num_or_list_str(v) { return "" + v }
fn lf_load_lmesh(path, merge) {
bind n = lf_read(path, "lm_")
if n < 0.0 { st_set("status", "Cannot read " + path) return false }
if lf_get("format", "") != "lmesh" { st_set("status", path_base(path) + " is not an .lmesh scene") return false }
bind count = lf_get("object_count", 0.0)
bind schema = lf_obj_schema()
bind j = 0.0
while j < count {
bind pre = "o" + num_str(j) + "_"
bind o = me_add_object(lf_get(pre + "name", "Object"), lf_get(pre + "vx", []), lf_get(pre + "vy", []), lf_get(pre + "vz", []), lf_get(pre + "fi", []), lf_get(pre + "fs", []), lf_get(pre + "fc", []))
bind q = 0.0
while q + 1.0 < len(schema) {
bind key = list_get(schema, q)
if key != "name" && st_has("lfv_" + pre + key) > 0.5 { st_set(mk(o, key), st_get("lfv_" + pre + key, 0.0)) }
bind q = q + 2.0
}
bind acts = list_new()
bind a = 0.0
while st_has("lfv_" + pre + "act_" + num_str(a)) > 0.5 { bind acts = list_push(acts, st_get("lfv_" + pre + "act_" + num_str(a), [])) bind a = a + 1.0 }
st_set(mk(o, "act_data"), acts)
# bone selection / pose lists sized to the bones
bind nb = len(st_get(mk(o, "bn_name"), []))
st_set(mk(o, "bn_sel"), me_zeros(nb))
bind pk = ["bp_rx", "bp_ry", "bp_rz", "bp_tx", "bp_ty", "bp_tz"]
bind q = 0.0
while q < 6.0 { if len(st_get(mk(o, list_get(pk, q)), [])) != nb { st_set(mk(o, list_get(pk, q)), me_zeros(nb)) } bind q = q + 1.0 }
bind pk = ["bp_sx", "bp_sy", "bp_sz"]
bind q = 0.0
while q < 3.0 { if len(st_get(mk(o, list_get(pk, q)), [])) != nb { st_set(mk(o, list_get(pk, q)), me_fill(nb, 1.0)) } bind q = q + 1.0 }
me_edges_dirty(o)
me_rebuild_edges(o)
st_set(mk(o, "osel"), 0.0)
ps_mark(o)
bind j = j + 1.0
}
if !merge {
bind c = lf_get("cursor", [0.0, 0.0, 0.0])
if len(c) > 2.5 { st_set("cursor_x", list_get(c, 0)) st_set("cursor_y", list_get(c, 1)) st_set("cursor_z", list_get(c, 2)) }
bind t = lf_get("timeline", [])
if len(t) > 2.5 { st_set("tl_start", list_get(t, 0)) st_set("tl_end", list_get(t, 1)) st_set("tl_fps", list_get(t, 2)) }
# textures replace the library
bind tc = lf_get("tex_count", 0.0 - 1.0)
if tc >= 0.0 {
st_set("tx_ids", []) st_set("tx_names", [])
bind t = 0.0
while t < tc {
bind pre = "t" + num_str(t) + "_"
bind pos = tx_create(lf_get(pre + "type", "noise"), lf_get(pre + "name", "Texture"))
bind i = tx_id(pos)
st_set(tk(i, "p"), lf_get(pre + "p", []))
st_set(tk(i, "c"), lf_get(pre + "c", []))
bind op = lf_get(pre + "opts", [128.0, 0.0, 1.0, 1.0])
st_set(tk(i, "size"), list_get(op, 0)) st_set(tk(i, "anim"), list_get(op, 1)) st_set(tk(i, "speed"), list_get(op, 2)) st_set(tk(i, "seamless"), list_get(op, 3))
bind ip = lf_get(pre + "path", "")
if lf_get(pre + "type", "") == "image" && ip != "" && p_has_images() { st_set(tk(i, "img"), p_img_load(ip)) st_set(tk(i, "path"), ip) }
bind t = t + 1.0
}
st_set("tx_cur", sel(tc > 0.5, 0.0, 0.0 - 1.0))
}
}
lf_clear()
tl_mark_dirty()
st_set("sel_o", me_first())
return true
}
# ── .ling (vector document) ──────────────────────────────────────────────────
fn lf_save_ling(path) {
bind out = list_new()
bind name = st_get("vc_name", "drawing")
bind out = list_push(out, "# LingModeler vector document (.ling) - valid Ling source. `use` it and call draw_" + lf_ident(name) + "(ox, oy, scale).")
bind out = list_push(out, "# Paths: 6 numbers per node (x y, in-handle x y, out-handle x y). Also the intermediary for SVG import / export.")
bind out = list_push(out, lf_line("lv_", "format", "\"lingvec\""))
bind out = list_push(out, lf_line("lv_", "version", "1"))
bind out = list_push(out, lf_line("lv_", "name", "\"" + lf_esc(name) + "\""))
bind out = list_push(out, lf_line("lv_", "size", lf_nums([st_get("vc_w", 512.0), st_get("vc_h", 512.0), st_get("vc_bg", 16777215.0)])))
bind out = list_push(out, lf_line("lv_", "timeline", lf_nums([st_get("tl_start", 0.0), st_get("tl_end", 48.0), st_get("tl_fps", 24.0)])))
bind out = list_push(out, lf_line("lv_", "layers", lf_strs(st_get("vc_layers", []))))
bind out = list_push(out, lf_line("lv_", "layer_vis", lf_nums(st_get("vc_lvis", []))))
bind out = list_push(out, lf_line("lv_", "layer_lock", lf_nums(st_get("vc_llock", []))))
bind ids = vc_ids()
bind out = list_push(out, lf_line("lv_", "item_count", num_str(len(ids))))
bind j = 0.0
while j < len(ids) {
bind k = list_get(ids, j)
bind pre = "i" + num_str(j) + "_"
bind out = list_push(out, lf_line("lv_", pre + "kind", "\"" + st_get(vk(k, "kind"), "path") + "\""))
bind out = list_push(out, lf_line("lv_", pre + "name", "\"" + lf_esc(st_get(vk(k, "name"), "")) + "\""))
bind out = list_push(out, lf_line("lv_", pre + "style", lf_nums([st_get(vk(k, "layer"), 0.0), st_get(vk(k, "closed"), 0.0), st_get(vk(k, "fill"), 0.0 - 1.0), st_get(vk(k, "stroke"), 0.0 - 1.0), st_get(vk(k, "sw"), 1.0), st_get(vk(k, "op"), 1.0), st_get(vk(k, "grp"), 0.0)])))
bind out = list_push(out, lf_line("lv_", pre + "xf", lf_nums([st_get(vk(k, "tx"), 0.0), st_get(vk(k, "ty"), 0.0), st_get(vk(k, "rot"), 0.0), st_get(vk(k, "sx"), 1.0), st_get(vk(k, "sy"), 1.0)])))
bind out = list_push(out, lf_line("lv_", pre + "pts", lf_nums(st_get(vk(k, "pts"), []))))
bind out = list_push(out, lf_line("lv_", pre + "flat", lf_nums(vc_flatten(k, 1.0))))
bind out = list_push(out, lf_line("lv_", pre + "keys", lf_nums(st_get(vk(k, "keys"), []))))
bind out = list_push(out, lf_line("lv_", pre + "skf", lf_nums(st_get(vk(k, "skf"), []))))
bind skp = st_get(vk(k, "skp"), [])
bind s = 0.0
while s < len(skp) { bind out = list_push(out, lf_line("lv_", pre + "sk_" + num_str(s), lf_nums(list_get(skp, s)))) bind s = s + 1.0 }
bind j = j + 1.0
}
bind out = list_push(out, "")
bind h = lf_helpers()
bind i = 0.0
while i < len(h) { bind out = list_push(out, list_get(h, i)) bind i = i + 1.0 }
bind out = list_push(out, "# draw one flattened item at (ox, oy) scaled: filled polygon + outline (ling's draw_poly / draw_line)")
bind out = list_push(out, "fn lvec_draw_item(flat, style, ox, oy, s) {")
bind out = list_push(out, " bind n = floor(len(flat) / 2.0)")
bind out = list_push(out, " if n < 2.0 { return 0.0 }")
bind out = list_push(out, " bind pts = list_new()")
bind out = list_push(out, " bind i = 0.0")
bind out = list_push(out, " while i < n { bind pts = list_push(pts, ox + list_get(flat, i * 2.0) * s) bind pts = list_push(pts, oy + list_get(flat, i * 2.0 + 1.0) * s) bind i = i + 1.0 }")
bind out = list_push(out, " bind fill = list_get(style, 2)")
bind out = list_push(out, " bind stroke = list_get(style, 3)")
bind out = list_push(out, " if list_get(style, 1) > 0.5 { if fill >= 0.0 { set_color(floor(fill / 65536.0), floor(fill / 256.0) % 256.0, fill % 256.0) draw_poly(pts) } }")
bind out = list_push(out, " if stroke >= 0.0 {")
bind out = list_push(out, " set_color(floor(stroke / 65536.0), floor(stroke / 256.0) % 256.0, stroke % 256.0)")
bind out = list_push(out, " bind segs = n - 1.0")
bind out = list_push(out, " if list_get(style, 1) > 0.5 { bind segs = n }")
bind out = list_push(out, " bind i = 0.0")
bind out = list_push(out, " while i < segs { bind j = (i + 1.0) % n draw_line(list_get(pts, i * 2.0), list_get(pts, i * 2.0 + 1.0), list_get(pts, j * 2.0), list_get(pts, j * 2.0 + 1.0)) bind i = i + 1.0 }")
bind out = list_push(out, " }")
bind out = list_push(out, "}")
bind out = list_push(out, "fn draw_" + lf_ident(name) + "(ox, oy, s) {")
bind j = 0.0
while j < len(ids) {
bind out = list_push(out, " lvec_draw_item(lv_i" + num_str(j) + "_flat(), lv_i" + num_str(j) + "_style(), ox, oy, s)")
bind j = j + 1.0
}
bind out = list_push(out, "}")
write_file(path, p_join(out, "\n") + "\n")
return true
}
fn lf_load_ling(path) {
bind n = lf_read(path, "lv_")
if n < 0.0 { st_set("status", "Cannot read " + path) return false }
if lf_get("format", "") != "lingvec" { st_set("status", path_base(path) + " is not a LingModeler vector document (Ling programs can still be run with ling)") lf_clear() return false }
vc_push()
bind sz = lf_get("size", [512.0, 512.0, 16777215.0])
vc_new_doc(list_get(sz, 0), list_get(sz, 1), st_get("tl_fps", 24.0))
st_set("vc_bg", list_get(sz, 2))
st_set("vc_name", lf_get("name", path_stem(path)))
bind t = lf_get("timeline", [])
if len(t) > 2.5 { st_set("tl_start", list_get(t, 0)) st_set("tl_end", list_get(t, 1)) st_set("tl_fps", list_get(t, 2)) st_set("an_fps", list_get(t, 2)) }
bind layers = lf_get("layers", [])
if len(layers) > 0.5 {
st_set("vc_layers", layers)
st_set("vc_lvis", lf_get("layer_vis", me_fill(len(layers), 1.0)))
st_set("vc_llock", lf_get("layer_lock", me_zeros(len(layers))))
}
bind count = lf_get("item_count", 0.0)
bind gmax = 0.0
bind j = 0.0
while j < count {
bind pre = "i" + num_str(j) + "_"
bind style = lf_get(pre + "style", [0.0, 1.0, 0.0, 0.0 - 1.0, 1.0, 1.0, 0.0])
bind k = vc_add_item(lf_get(pre + "kind", "path"), lf_get(pre + "pts", []), list_get(style, 1) > 0.5)
st_set(vk(k, "name"), lf_get(pre + "name", "item"))
st_set(vk(k, "layer"), list_get(style, 0))
st_set(vk(k, "fill"), list_get(style, 2)) st_set(vk(k, "stroke"), list_get(style, 3))
st_set(vk(k, "sw"), list_get(style, 4)) st_set(vk(k, "op"), list_get(style, 5))
st_set(vk(k, "grp"), list_get(style, 6))
bind gmax = max(gmax, list_get(style, 6))
bind xf = lf_get(pre + "xf", [0.0, 0.0, 0.0, 1.0, 1.0])
st_set(vk(k, "tx"), list_get(xf, 0)) st_set(vk(k, "ty"), list_get(xf, 1)) st_set(vk(k, "rot"), list_get(xf, 2)) st_set(vk(k, "sx"), list_get(xf, 3)) st_set(vk(k, "sy"), list_get(xf, 4))
st_set(vk(k, "keys"), lf_get(pre + "keys", []))
st_set(vk(k, "skf"), lf_get(pre + "skf", []))
bind skp = list_new()
bind s = 0.0
while st_has("lfv_" + pre + "sk_" + num_str(s)) > 0.5 { bind skp = list_push(skp, st_get("lfv_" + pre + "sk_" + num_str(s), [])) bind s = s + 1.0 }
st_set(vk(k, "skp"), skp)
bind j = j + 1.0
}
st_set("vc_gnext", gmax + 1.0)
lf_clear()
tl_mark_dirty()
return true
}