灵符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/fileio.ling
# ━━━ fileio.ling — open / save / import / export routing by extension ━━━

fn fi_new() {
    me_new_scene()
    v3_init()
    st_set("mode", 0.0)
    st_set("status", "New scene")
}

fn fi_open() {
    bind p = p_dlg_open("Open scene or asset", "lmesh,ling,obj,gltf,svg")
    if p == "" { return 0.0 }
    fi_open_path(p)
}

# open replaces the scene for scene formats; vector formats go to the Vector document
fn fi_open_path(p) {
    if !file_exists(p) { st_set("status", "File not found: " + p) return 0.0 }
    bind e = path_ext(p)
    if e == "lmesh" {
        me_new_scene()
        if lf_load_lmesh(p, false) {
            st_set("scene_path", p)
            st_set("scene_name", path_stem(p))
            st_set("dirty", 0.0)
            settings_recent_add(p)
            v3_frame(true)
            st_set("status", "Opened " + path_base(p))
        }
        return 0.0
    }
    if e == "ling" {
        if lf_load_ling(p) { settings_recent_add(p) set_mode(5.0) st_set("status", "Opened vector document " + path_base(p)) }
        return 0.0
    }
    if e == "svg" {
        if sv_import(p) { settings_recent_add(p) set_mode(5.0) st_set("status", "Imported " + path_base(p)) }
        return 0.0
    }
    if e == "obj" || e == "gltf" || e == "glb" {
        me_new_scene()
        fi_open_path_merge(p)
        st_set("scene_name", path_stem(p))
        st_set("dirty", 0.0)
        return 0.0
    }
    st_set("status", "Unknown file type: " + e)
}

# import into the current scene (merge)
fn fi_open_path_merge(p) {
    if !file_exists(p) { st_set("status", "File not found: " + p) return 0.0 }
    bind e = path_ext(p)
    me_undo_push()
    bind before = me_count()
    bind okv = false
    if e == "obj" { bind okv = ob_import(p) }
    else if e == "gltf" { bind okv = gl_import(p) }
    else if e == "glb" { st_set("status", "Binary .glb import is not supported here - export as .gltf (embedded) or convert with `ling convert model.glb`") return 0.0 }
    else if e == "lmesh" { bind okv = lf_load_lmesh(p, true) }
    else if e == "svg" { bind okv = sv_import(p) if okv { set_mode(5.0) } }
    else if e == "ling" { bind okv = lf_load_ling(p) if okv { set_mode(5.0) } }
    else if e == "png" || e == "jpg" || e == "jpeg" { bind okv = tx_import_image(p) if okv { set_mode(7.0) } }
    if okv {
        settings_recent_add(p)
        if me_count() > before { v3_frame(true) }
        st_set("status", "Imported " + path_base(p) + sel(me_count() > before, " (" + num_str(me_count() - before) + " objects)", ""))
    }
}

fn fi_save() {
    bind p = st_get("scene_path", "")
    if p == "" { fi_save_as() return 0.0 }
    fi_save_path(p)
}
fn fi_save_as() {
    bind p = p_dlg_save("Save scene as .lmesh", "lmesh", st_get("scene_name", "untitled") + ".lmesh")
    if p == "" { return 0.0 }
    fi_save_path(p)
}
fn fi_save_path(p) {
    if lf_save_lmesh(p) {
        st_set("scene_path", p)
        st_set("scene_name", path_stem(p))
        st_set("dirty", 0.0)
        settings_recent_add(p)
        st_set("status", "Saved " + path_base(p))
    }
}

fn fi_import(kind) {
    bind exts = kind
    if kind == "gltf" { bind exts = "gltf" }
    if kind == "png" { bind exts = "png,jpg,jpeg" }
    bind p = p_dlg_open("Import " + kind, exts)
    if p == "" { return 0.0 }
    fi_open_path_merge(p)
}

fn fi_export(kind) {
    bind base = st_get("scene_name", "untitled")
    if kind == "obj" { bind p = p_dlg_save("Export OBJ", "obj", base + ".obj") if p != "" { fi_export_path(p) } return 0.0 }
    if kind == "gltf" { bind p = p_dlg_save("Export glTF 2.0", "gltf", base + ".gltf") if p != "" { fi_export_path(p) } return 0.0 }
    if kind == "glb" { bind p = p_dlg_save("Export glTF binary", "glb", base + ".glb") if p != "" { fi_export_path(p) } return 0.0 }
    if kind == "svg" { bind p = p_dlg_save("Export SVG", "svg", st_get("vc_name", "drawing") + ".svg") if p != "" { fi_export_path(p) } return 0.0 }
    if kind == "svganim" { bind p = p_dlg_save("Export animated SVG", "svg", st_get("vc_name", "drawing") + "_anim.svg") if p != "" { st_set("svg_anim", 1.0) fi_export_path(p) st_set("svg_anim", 0.0) } return 0.0 }
    if kind == "ling" { bind p = p_dlg_save("Save vector document (.ling)", "ling", st_get("vc_name", "drawing") + ".ling") if p != "" { fi_export_path(p) } return 0.0 }
    if kind == "png" { bind p = p_dlg_save("Export texture PNG", "png", tx_cur_name() + ".png") if p != "" { tx_export(p) } return 0.0 }
    if kind == "normal" { bind p = p_dlg_save("Export normal map PNG", "png", tx_cur_name() + "_normal.png") if p != "" { tx_export_normal(p) } return 0.0 }
}

fn fi_export_path(p) {
    bind e = path_ext(p)
    bind okv = false
    if e == "obj" { bind okv = ob_export(p) }
    else if e == "gltf" { bind okv = gl_export(p, false) }
    else if e == "glb" { bind okv = gl_export(p, true) }
    else if e == "svg" { bind okv = sv_export(p, st_get("svg_anim", 0.0) > 0.5) }
    else if e == "ling" { bind okv = lf_save_ling(p) }
    else if e == "lmesh" { bind okv = lf_save_lmesh(p) }
    else if e == "png" { bind okv = tx_export(p) }
    if okv { settings_recent_add(p) st_set("status", "Exported " + path_base(p)) }
}

← Back to index