灵符lingfu

lingdev

↓ 0 downloads

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
Keywords game-engine, editor, 3d, 2d, cutscene, timeline, ling, lingos, raspberry-pi
lingfu install lingdev
LicenseApache-2.0 OR MIT
Authorsling-lin
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

Code / Files (136)

ling/plat_desktop.ling
# plat_desktop.ling - what the desktop runtime (ling run / ling build win|lin|mac) can do.
# Every plat_* function has a twin in plat_os.ling with the same name and arguments, so the editor
# and exported games call these and never a native builtin that one runtime lacks.

fn plat_name() { return "desktop" }
fn plat_has_3d() { return true }
fn plat_has_audio() { return true }
fn plat_has_models() { return true }
fn plat_has_images() { return true }
fn plat_has_net() { return true }
fn plat_has_ai() { return true }
fn plat_can_write() { return true }
fn plat_has_dialogs() { return true }
fn plat_has_midi() { return true }

# ── files ────────────────────────────────────────────────────────────────────
fn plat_reveal(path) { fs_reveal(path) }
fn plat_dlg_open(title, exts, start) { return dlg_open(title, exts, start) }
fn plat_dlg_save(title, exts, name, start) { return dlg_save(title, exts, name, start) }
fn plat_dlg_folder(title, start) { return dlg_folder(title, start) }
# run a generated .bat / .sh through the shell's "open" (Windows runs it; elsewhere it opens the folder)
fn plat_launch(path) { fs_reveal(path) }

# ── images ───────────────────────────────────────────────────────────────────
fn plat_image_load(path) { return image_load(path) }
fn plat_image_w(id) { return image_width(id) }
fn plat_image_h(id) { return image_height(id) }
fn plat_image_draw(id, x, y, w, h) { image_draw(id, x, y, w, h) }

# ── models (glb / gltf through gltf_*, .lmesh through mesh_*) ────────────────
# handle = index * 2 + kind (0 = gltf, 1 = lmesh); -1 when it failed to load
fn plat_model_load(path) {
    bind e = p_ext(path)
    if e == "lmesh" {
        bind m = mesh_load(path)
        if m < 0.0 { return 0.0 - 1.0 }
        return m * 2.0 + 1.0
    }
    if e == "glb" || e == "gltf" {
        bind g = gltf_load(path)
        if g < 0.0 { return 0.0 - 1.0 }
        return g * 2.0
    }
    return 0.0 - 1.0
}
fn plat_model_draw(h, x, y, z, scale, yaw) {
    if h < 0.0 { return 0.0 }
    bind kind = h % 2.0
    bind id = floor(h / 2.0)
    if kind > 0.5 { mesh_draw(id, x, y, z, scale, yaw, 0.0, 0.0, 0.0, 0.0, 0.0) }
    else { gltf_draw(id, x, y, z, scale, yaw) }
    return 0.0
}
fn plat_model_anim_count(h) {
    if h < 0.0 || h % 2.0 > 0.5 { return 0.0 }
    return gltf_anim_count(floor(h / 2.0))
}
fn plat_model_anim_name(h, i) {
    if h < 0.0 || h % 2.0 > 0.5 { return "" }
    return gltf_anim_name(floor(h / 2.0), i)
}
fn plat_model_anim_dur(h, i) {
    if h < 0.0 || h % 2.0 > 0.5 { return 0.0 }
    return gltf_anim_dur(floor(h / 2.0), i)
}
fn plat_model_tris(h) {
    if h < 0.0 { return 0.0 }
    if h % 2.0 > 0.5 { return 0.0 }
    return gltf_tris(floor(h / 2.0))
}

# ── 3-D (native renderer) ────────────────────────────────────────────────────
fn plat_3d_begin(ambient) {
    set_ambient(ambient)
    clear_lights()
    clear_depth()
}
fn plat_light(x, y, z, r, g, b, intensity, radius) { add_light(x, y, z, r / 255.0, g / 255.0, b / 255.0, intensity, radius) }
fn plat_color(c) { set_color(c_r(c), c_g(c), c_b(c)) }
# kind: box sphere cylinder cone capsule torus plane; mode 0 filled 1 wire 2 both
fn plat_shape(kind, cx, cy, cz, sx, sy, sz, rx, ry, rz, mode) {
    if kind == "box" || kind == "trigger" { cube(cx, cy, cz, sx, sy, sz, rx, ry, rz, mode) }
    else if kind == "sphere" { sphere(cx, cy, cz, sx, sy, sz, rx, ry, rz, mode) }
    else if kind == "cylinder" { cylinder(cx, cy, cz, sx, sy, sz, rx, ry, rz, mode) }
    else if kind == "cone" { cone(cx, cy, cz, sx, sy, sz, rx, ry, rz, mode) }
    else if kind == "capsule" { capsule(cx, cy, cz, sx, sy, sz, rx, ry, rz, mode) }
    else if kind == "torus" { torus(cx, cy, cz, sx, sy, sz, rx, ry, rz, mode) }
    else if kind == "plane" { cube(cx, cy, cz, sx, 0.02, sz, rx, ry, rz, mode) }
    return 0.0
}
fn plat_3d_flush() { flush_3d() }
# flush the 3-D queue and run the toon post chain now, so 2-D HUD drawn afterwards stays crisp
fn plat_post_now() { flush_post() }
fn plat_fog(r, g, b, near, far) { set_fog(r, g, b, near, far) }
fn plat_shade(mode, rim, c) {
    set_shade_mode(mode)
    set_rim(rim, c_r(c), c_g(c), c_b(c))
}
fn plat_mesh_hue(h, gain) { mesh_hue(h, gain) }
fn plat_blend(mode) { set_blend(mode) }

# ── audio ────────────────────────────────────────────────────────────────────
fn plat_sample_load(path) { return audio_sample_load(path) }
fn plat_sample_play(id, x, y, z, w, vol, loop) { return audio_sample_play(id, x, y, z, w, vol, loop) }
fn plat_sample_play_flat(id, vol, loop) { return audio_sample_play_flat(id, vol, loop, 1.0) }
fn plat_sample_stop(v) { audio_sample_stop(v) }
fn plat_sample_duration(id) { return audio_sample_duration(id) }
fn plat_listener(cy, sy, cp, sp) { audio_listener(cy, sy, cp, sp) }
fn plat_volume(v) { audio_volume(v) }
fn plat_sfx(x, y, z, w, freq, amp, dur, wave) { audio_sfx(x, y, z, w, freq, amp, dur, wave) }
fn plat_music_load(path) { return music_load(path) }
fn plat_music_play(id) { music_play(id) }
fn plat_music_stop() { music_stop() }
fn plat_music_pause() { music_pause() }
fn plat_music_seek(sec) { music_seek(sec) }
fn plat_music_pos() { return music_pos() }
fn plat_music_volume(v) { music_volume(v) }
fn plat_music_duration(id) { return music_duration(id) }
fn plat_music_fft(id, n) { return music_fft(id, n) }
fn plat_midi_load(path) { return music_midi_load(path) }
fn plat_midi_bars(id) { return music_midi_bars(id) }
fn plat_midi_count(id) { return music_midi_count(id) }
fn plat_patch_load(path) { return music_patch(path) }
fn plat_note(inst, midi, dur, vel) { music_note(inst, music_note_name(music_hz(midi)), dur, vel) }
fn plat_ui_sound(name) { ui_sound(name) }

# ── networking (TCP two-peer co-op + LAN discovery) ──────────────────────────
fn plat_net_host(port) { net_host(port) }
fn plat_net_join(ip, port) { net_join(ip, port) }
fn plat_net_send(s) { net_send(s) }
fn plat_net_recv() { return net_recv() }
fn plat_net_status() { return net_status() }
fn plat_net_events() { return net_events() }
fn plat_net_close() { net_close() }
fn plat_net_clients() { return net_client_count() }

# ── game AI (behaviour trees) ────────────────────────────────────────────────
fn plat_bt_build(src) { return bt_build(src) }
fn plat_bt_set(h, k, v) { bt_set(h, k, v) }
fn plat_bt_tick(h) { return bt_tick(h) }

# ── misc ─────────────────────────────────────────────────────────────────────
fn plat_screenshot(name) { screenshot(name) }
fn plat_set_fps(f) { set_fps(f) }
fn plat_close() { close_window() }
fn plat_args() { return get_args() }
fn plat_cwd() { return fs_cwd() }
fn plat_home() { return fs_home() }
fn plat_mkdir(p) { return fs_mkdir(p) }
fn plat_copy(a, b) { return fs_copy(a, b) }
fn plat_delete(p) { return fs_delete(p) }
fn plat_list(p) { return fs_list(p) }
fn plat_is_dir(p) { return fs_is_dir(p) }
fn plat_write(path, text) { write_file(path, text)  return true }
fn plat_read(path) {
    if !file_exists(path) { return "" }
    return read_file(path)
}
fn plat_text_fill(id, x, y, px, s) { font_text_fill(id, x, y, px, s) }
fn plat_gamepad_poll() { pad_poll() }
fn plat_gamepad_connected() { return pad_connected(0.0) }
fn plat_gamepad_lx() { return pad_lx(0.0) }
fn plat_gamepad_ly() { return pad_ly(0.0) }
# buttons by number: 0 A, 1 B, 2 X, 3 Y, 4 LB, 5 RB, 6 Back, 7 Start (the engine wants names)
fn plat_gamepad_button(b) { return pad_button(0.0, list_get(["a", "b", "x", "y", "lb", "rb", "select", "start"], clampf(floor(b), 0.0, 7.0))) }
fn plat_gamepad_rx() { return pad_rx(0.0) }
fn plat_gamepad_ry() { return pad_ry(0.0) }
fn plat_gamepad_rt() { return pad_rt(0.0) }
fn plat_capture_mouse() { capture_mouse() }
fn plat_release_mouse() { release_mouse() }

# ── game 3-D extras (engine tm_* / coll_* / pfx_* builtins) ──────────────────
fn plat_has_g3d() { return true }
fn plat_sample_play_pitch(id, vol, pitch) { return audio_sample_play_flat(id, vol, 0.0, pitch) }
# depth buffer, FXAA, ink outlines (width px, colour), bloom strength
fn plat_post(depth, fxaa, ink, inkcol, bloom) {
    set_depth_test(depth)
    set_fxaa(fxaa)
    toon_outlines(ink, inkcol, 0.05)
    set_bloom(bloom, 0.72)
}
fn plat_frame_blur(a) { set_frame_blur(a) }
fn plat_tex_load(path, size) { return tm_tex_load(path, size) }
fn plat_tm_load(path) { return tm_load(path) }
fn plat_tm_group(m, name) { return tm_group(m, name) }
fn plat_tm_bounds(m, g) { return tm_bounds(m, g) }
fn plat_tm_draw(m, g, tex, x, y, z, s, rot, tint, a, uo, vo, us, vs, shade, blend, cull) { return tm_draw(m, g, tex, x, y, z, s, rot, tint, a, uo, vo, us, vs, shade, blend, cull) }
fn plat_tm_hole(x, y, z, r) { tm_hole(x, y, z, r) }
fn plat_tm_fov(deg, vw) { tm_fov(deg, vw) }
fn plat_tm_sprite(tex, cx, cy, w, h, rot, tint, a, blend) { tm_sprite(tex, cx, cy, w, h, rot, tint, a, blend) }
fn plat_tm_billboard(tex, x, y, z, size, rot, tint, a, blend) { tm_billboard(tex, x, y, z, size, rot, tint, a, blend) }
fn plat_coll_build(m, g, x, y, z, s, rot, cell) { return coll_build(m, g, x, y, z, s, rot, cell) }
fn plat_coll_sphere(id, x, y, z, r) { return coll_sphere(id, x, y, z, r) }
fn plat_coll_ray(id, ox, oy, oz, dx, dy, dz, maxt) { return coll_ray(id, ox, oy, oz, dx, dy, dz, maxt) }
fn plat_pfx_emit(x, y, z, vx, vy, vz, life, s0, s1, c0, c1, kind, tex, grav, a) { pfx_emit(x, y, z, vx, vy, vz, life, s0, s1, c0, c1, kind, tex, grav, a) }
fn plat_pfx_burst(x, y, z, n, speed, life, s0, s1, c0, c1, kind, grav, vx, vy, vz) { pfx_burst(x, y, z, n, speed, life, s0, s1, c0, c1, kind, grav, vx, vy, vz) }
fn plat_pfx_rain(x0, z0, x1, z1, y, n, vy, life, s0, s1, tex0, ntex, a, col, yspread) { pfx_rain(x0, z0, x1, z1, y, n, vy, life, s0, s1, tex0, ntex, a, col, yspread) }
fn plat_pfx_step(dt, g, drag, floor, bounce) { pfx_step(dt, g, drag, floor, bounce) }
fn plat_pfx_draw() { pfx_draw() }
fn plat_pfx_clear() { pfx_clear() }
fn plat_pfx_count() { return pfx_count() }
fn plat_pfx_max(n) { pfx_max(n) }
fn plat_depth(on) { set_depth_test(on) }
fn plat_tm_edges(m, g, mx) { return tm_edges(m, g, mx) }
fn plat_voice(v, vol, pitch) { tm_voice(v, vol, pitch) }
fn plat_font_load(path) { return font_load(path) }
fn plat_text3d(f, x, y, z, ux, uy, uz, vx, vy, vz, size, s) { font_text_3d(f, x, y, z, ux, uy, uz, vx, vy, vz, size, s) }
fn plat_tm_draw_lit(m, g, tex, x, y, z, s, rot, tint, a, uo, vo, us, vs, shade, blend, cull, amb) { return tm_draw(m, g, tex, x, y, z, s, rot, tint, a, uo, vo, us, vs, shade, blend, cull, amb) }
fn plat_tm_wall_spots(m, g, spacing, up) { return tm_wall_spots(m, g, spacing, up) }
fn plat_outline_threshold(t) { toon_outlines(1.4, 6043206.0, t) }
fn plat_sphere_lod(cx, cy, cz, sx, sy, sz, seg, rings) { sphere(cx, cy, cz, sx, sy, sz, 0.0, 0.0, 0.0, 0.0, seg, rings) }

← Back to index