灵符lingfu

lingdev

↓ 0 下载

LingDev: a Godot / Unity-style game editor written in Ling. 2-D and 3-D scenes, Flash-style timeline and cutscenes, HUDs over 3-D, Ling scripting, audio / music / MIDI, builds for Windows, Linux, macOS, web, Raspberry Pi and LingOS. Ships with Ling Agent (an N64-style spy FPS), Ling Breaker (a 3-D breakout) and Moko's Picture Book (a kawaii storybook platformer).

Windows · x86-64Linux · x86-64LingOS · x86-64LingOS · Pi 5 ARM64Web · WASM
关键词 game-engine, editor, 3d, 2d, cutscene, timeline, ling, lingos, raspberry-pi
lingfu install lingdev
许可证Apache-2.0 OR MIT
作者ling-lin
README代码 / 文件版本依赖关系图依赖此包的项目安全构建设置

代码 / 文件 (136)

ling/view2d.ling
# view2d.ling - the canvas for 2-D scenes (menus, HUDs): the design frame, nodes drawn as in
# the game, selection with resize handles, drag to move, wheel to zoom, middle-drag to pan.

fn view2d(x, y, w, h) {
    bind t = st_get("tl_t", 0.0)
    g_rect(x, y, w, h, C_VIEW_BG)
    u_clip(x, y, w, h)
    bind cw = sc_get("cw", 1280.0)
    bind ch = sc_get("ch", 720.0)
    bind zoom = st_get("c2_zoom", 1.0)
    bind s = min((w - 48.0) / cw, (h - 48.0) / ch) * zoom
    bind ox = x + (w - cw * s) * 0.5 + st_get("c2_ox", 0.0)
    bind oy = y + (h - ch * s) * 0.5 + st_get("c2_oy", 0.0)
    bind hot = u_hot(x, y, w, h) && st_get("bar_busy", 0.0) < 0.5
    # canvas
    g_rect_a(ox + 4.0, oy + 6.0, cw * s, ch * s, 0.0, 0.4)
    g_rect(ox, oy, cw * s, ch * s, sc_get("bg", 1776411.0))
    bind bg3 = sc_ex("bg3d", "")
    if bg3 != "" { g_text(ox + 8.0, oy + ch * s - 18.0, 10.0, C_TEXT_DIM, "3D background: " + bg3) }
    if st_get("view_grid", 1.0) > 0.5 {
        bind g = 40.0
        bind k = g
        while k < cw {
            px_line(ox + k * s, oy, ox + k * s, oy + ch * s, C_GRID_MIN, 0.5)
            bind k = k + g
        }
        bind k = g
        while k < ch {
            px_line(ox, oy + k * s, ox + cw * s, oy + k * s, C_GRID_MIN, 0.5)
            bind k = k + g
        }
    }
    g_frame(ox - 1.0, oy - 1.0, cw * s + 2.0, ch * s + 2.0, C_LINE)
    hud_draw(t, ox, oy, s, false)
    # selection
    bind sidx = sel_index()
    bind hover_h = ""
    if sidx >= 0.0 && nd_is_2d(nd_get(sidx, "kind")) {
        bind r = hud_rect(sidx, t)
        bind rx = ox + list_get(r, 0) * s
        bind ry = oy + list_get(r, 1) * s
        bind rw = list_get(r, 2) * s
        bind rh = list_get(r, 3) * s
        g_frame(rx - 1.0, ry - 1.0, rw + 2.0, rh + 2.0, C_GIZMO)
        bind hs = ["tl", "tc", "tr", "cl", "cr", "bl", "bc", "br"]
        bind k = 0.0
        while k < 8.0 {
            bind hn = list_get(hs, k)
            bind hx = rx + anchor_fx(hn) * rw
            bind hy = ry + anchor_fy(hn) * rh
            bind hh = hot && abs(u_mx() - hx) < 6.0 && abs(u_my() - hy) < 6.0
            if hh { bind hover_h = hn }
            g_rect(hx - 4.0, hy - 4.0, 8.0, 8.0, sel(hh, C_WHITE, C_GIZMO))
            bind k = k + 1.0
        }
        g_text(rx, ry - 14.0, 10.0, C_GIZMO, nd_get(sidx, "name") + "  " + num_str(floor(list_get(r, 2))) + "x" + num_str(floor(list_get(r, 3))))
    }
    # input
    if hot {
        if u_scroll() != 0.0 && st_get("wheel_used", 0.0) < 0.5 {
            st_set("c2_zoom", clampf(zoom * pow(1.12, u_scroll()), 0.2, 6.0))
            st_set("wheel_used", 1.0)
        }
        if u_mpressed() { u_set_active("c2_pan") }
        if u_pressed() && u_active() == "" {
            if hover_h != "" && sidx >= 0.0 {
                u_set_active("c2_resize")
                st_set("c2_handle", hover_h)
                st_set("c2_id", nd_id(sidx))
                undo_push()
                st_set("c2_v0", [nd_get(sidx, "px"), nd_get(sidx, "py"), nd_get(sidx, "w"), nd_get(sidx, "h"), u_mx(), u_my()])
            } else {
                bind pi = view2d_pick(ox, oy, s, t)
                if pi >= 0.0 {
                    bind id = nd_id(pi)
                    if u_ctrl() { sel_toggle(id) } else if !sel_has(id) { sel_set(id) }
                    if u_double() {
                        bind k = nd_get(pi, "kind")
                        if k == "label" || k == "button" { st_set("insp_field", "txt")  modal_text("Text", "node_field", nd_get(pi, "txt")) }
                    } else if !u_ctrl() {
                        u_set_active("c2_move")
                        st_set("c2_id", id)
                        undo_push()
                        st_set("c2_v0", [nd_get(pi, "px"), nd_get(pi, "py"), nd_get(pi, "w"), nd_get(pi, "h"), u_mx(), u_my()])
                    }
                } else if !u_ctrl() { sel_clear() }
            }
        }
        if u_rpressed() {
            st_set("drop_cx", (u_mx() - ox) / s)
            st_set("drop_cy", (u_my() - oy) / s)
            ctx_open("canvas", "", u_mx(), u_my())
        }
    }
    if u_active() == "c2_pan" {
        if u_mdown() { st_set("c2_ox", st_get("c2_ox", 0.0) + u_dx())  st_set("c2_oy", st_get("c2_oy", 0.0) + u_dy()) } else { u_set_active("") }
    }
    if u_active() == "c2_move" || u_active() == "c2_resize" {
        bind i = nd_find(st_get("c2_id", 0.0))
        bind v0 = st_get("c2_v0", [])
        if !u_down() || i < 0.0 || len(v0) < 6.0 { u_set_active("") }
        else {
            bind dx = (u_mx() - list_get(v0, 4)) / s
            bind dy = (u_my() - list_get(v0, 5)) / s
            bind sn = st_get("snap_on", 1.0) > 0.5 && !u_ctrl()
            if u_active() == "c2_move" {
                bind nx = list_get(v0, 0) + dx
                bind ny = list_get(v0, 1) + dy
                if sn { bind nx = round(nx / 8.0) * 8.0  bind ny = round(ny / 8.0) * 8.0 }
                set_prop(i, "px", nx)
                set_prop(i, "py", ny)
            } else {
                bind hn = st_get("c2_handle", "br")
                bind fx = anchor_fx(hn)
                bind fy = anchor_fy(hn)
                bind nw = list_get(v0, 2)
                bind nh = list_get(v0, 3)
                bind nx = list_get(v0, 0)
                bind ny = list_get(v0, 1)
                if fx > 0.75 { bind nw = max(4.0, list_get(v0, 2) + dx) }
                if fx < 0.25 { bind nw = max(4.0, list_get(v0, 2) - dx)  bind nx = list_get(v0, 0) + (list_get(v0, 2) - nw) }
                if fy > 0.75 { bind nh = max(4.0, list_get(v0, 3) + dy) }
                if fy < 0.25 { bind nh = max(4.0, list_get(v0, 3) - dy)  bind ny = list_get(v0, 1) + (list_get(v0, 3) - nh) }
                if sn { bind nw = round(nw / 8.0) * 8.0  bind nh = round(nh / 8.0) * 8.0 }
                set_prop(i, "w", nw)
                set_prop(i, "h", nh)
                set_prop(i, "px", nx)
                set_prop(i, "py", ny)
            }
        }
    }
    # drops
    if st_get("drop_path", "") != "" && u_in(x, y, w, h) {
        st_set("drop_cx", (u_mx() - ox) / s)
        st_set("drop_cy", (u_my() - oy) / s)
        asset_add_to_scene(st_get("drop_path", ""), true)
        st_set("drop_path", "")
    }
    g_text(x + 12.0, y + 10.0, 11.0, C_TEXT_DIM, sc_get("name", "") + "   2D CANVAS " + num_str(cw) + "x" + num_str(ch) + "   zoom " + fmt1(zoom) + "   " + st_get("tool", "move"))
    if nd_count() < 0.5 { g_text_c(x + w * 0.5, y + h * 0.5 - 8.0, 14.0, C_TEXT_DIM, "Empty menu - Scene > Add 2D Control, or drag an image here") }
    u_unclip()
}

fn view2d_pick(ox, oy, s, t) {
    bind n = nd_count()
    bind i = n - 1.0
    while i >= 0.0 {
        if nd_is_2d(nd_get(i, "kind")) && nd_get(i, "vis") > 0.5 && nd_get(i, "lock") < 0.5 {
            bind r = hud_rect(i, t)
            bind rx = ox + list_get(r, 0) * s
            bind ry = oy + list_get(r, 1) * s
            if u_in(rx, ry, list_get(r, 2) * s, list_get(r, 3) * s) { return i }
        }
        bind i = i - 1.0
    }
    return 0.0 - 1.0
}

← 返回索引