灵符lingfu

lingmodeler

↓ 0 downloads

LingModeler: 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

Windows · x86-64Linux · x86-64LingOS · x86-64LingOS · Pi 5 ARM64Web · WASM
Keywords 3d, modeling, vector, svg, gltf, obj, rigging, animation, textures, ling
lingfu install lingmodeler
LicenseApache-2.0 OR MIT
Authorsling-lin
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

Code / 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
}

← Back to index