isokit: engine core, theme and Rhai scene runtime with prefab library

This commit is contained in:
grabowski committed 2026-10-22 15:09:46 +07:00
commit 95c80ec6b1
32 files changed
+5896

No files matched your search

+154
View File
@@ -0,0 +1,154 @@
// isokit/ground: site plate, paved and green areas, roads, parking, walls,
// fences and lamps. Ground surfaces go to the unsorted "ground" layer in
// document order (later objects lie on top).
fn ground_materials() {
["g-grass", "g-grass2", "g-green", "g-garden", "g-asph", "g-conc", "g-pad", "g-path", "g-sand", "g-court", "dirt"]
}
fn meta_site() {
#{ label: "Site ground", category: "Ground", icon: "▭",
help: "The ground plate: a surface with earth sides. Frames the view.",
props: [
#{ key: "w", type: "float", def: 60.0, min: 4.0, max: 1000.0, step: 1.0, label: "Width (m)" },
#{ key: "d", type: "float", def: 40.0, min: 4.0, max: 1000.0, step: 1.0, label: "Depth (m)" },
#{ key: "mat", type: "material", def: "g-grass", choices: ground_materials(), label: "Surface" },
#{ key: "base", type: "float", def: 1.6, min: 0.2, max: 10.0, step: 0.1, label: "Earth depth (m)" },
] }
}
fn prefab_site(o) {
let p = o.p;
let w = p.w / 2.0;
let d = p.d / 2.0;
layer("ground");
sprite().box(-w, -d, w, d, -p.base, 0.0, "dirt", #{ top: p.mat });
bounds(-w, -d, w, d, -p.base);
}
fn meta_area() {
#{ label: "Area", category: "Ground", icon: "▱",
help: "A paved or planted area lying on the ground.",
props: [
#{ key: "w", type: "float", def: 10.0, min: 0.5, max: 1000.0, step: 0.5, label: "Width (m)" },
#{ key: "d", type: "float", def: 6.0, min: 0.5, max: 1000.0, step: 0.5, label: "Depth (m)" },
#{ key: "mat", type: "material", def: "g-conc", choices: ground_materials(), label: "Surface" },
] }
}
fn prefab_area(o) {
let p = o.p;
layer("ground");
let s = sprite();
if o.pts != () && o.pts.len() >= 3 {
s.flat(o.pts, 0.006, p.mat + " t");
} else {
s.flat(rect(-p.w / 2.0, -p.d / 2.0, p.w / 2.0, p.d / 2.0), 0.006, p.mat + " t");
}
}
fn meta_road() {
#{ label: "Road", category: "Ground", icon: "═",
help: "A straight road along its length, with a dashed centre line.",
props: [
#{ key: "w", type: "float", def: 40.0, min: 2.0, max: 2000.0, step: 1.0, label: "Length (m)" },
#{ key: "d", type: "float", def: 6.0, min: 2.0, max: 40.0, step: 0.5, label: "Width (m)" },
#{ key: "dashed", type: "bool", def: true, label: "Centre line" },
#{ key: "kerb", type: "bool", def: true, label: "Kerb lines" },
] }
}
fn prefab_road(o) {
let p = o.p;
let w = p.w / 2.0;
let d = p.d / 2.0;
layer("ground");
let s = sprite();
s.flat(rect(-w, -d, w, d), 0.007, "g-asph t");
if p.dashed { s.lines([[-w, 0.0, w, 0.0]], 0.012, "dash"); }
if p.kerb { s.lines([[-w, -d, w, -d], [-w, d, w, d]], 0.012, "kerb"); }
}
fn meta_parking() {
#{ label: "Parking bays", category: "Ground", icon: "P",
props: [
#{ key: "n", type: "int", def: 6, min: 1, max: 60, step: 1, label: "Bays" },
#{ key: "bay_w", type: "float", def: 2.5, min: 2.0, max: 4.0, step: 0.1, label: "Bay width (m)" },
#{ key: "bay_d", type: "float", def: 5.0, min: 4.0, max: 7.0, step: 0.1, label: "Bay depth (m)" },
] }
}
fn prefab_parking(o) {
let p = o.p;
let w = p.n * p.bay_w / 2.0;
let d = p.bay_d / 2.0;
layer("ground");
let s = sprite();
s.flat(rect(-w, -d, w, d), 0.008, "g-pad t");
let segs = [];
for i in 0..(p.n + 1) {
let x = -w + i * p.bay_w;
segs.push([x, -d, x, d]);
}
s.lines(segs, 0.014, "bayline");
}
fn meta_wall() {
#{ label: "Wall", category: "Site", icon: "▬",
props: [
#{ key: "w", type: "float", def: 20.0, min: 0.5, max: 500.0, step: 0.5, label: "Length (m)" },
#{ key: "h", type: "float", def: 2.2, min: 0.3, max: 8.0, step: 0.1, label: "Height (m)" },
#{ key: "t", type: "float", def: 0.24, min: 0.1, max: 1.0, step: 0.02, label: "Thickness (m)" },
] }
}
fn prefab_wall(o) {
// long walls in pieces of at most 30 m, each its own sprite for the depth sort
let p = o.p;
let n = (p.w / 30.0).ceiling().to_int();
let L = p.w / n;
for i in 0..n {
let x0 = -p.w / 2.0 + i * L;
sprite().box(x0, -p.t / 2.0, x0 + L, p.t / 2.0, 0.0, p.h, "wallp", #{ top: "wallt" });
}
}
fn meta_fence() {
#{ label: "Fence", category: "Site", icon: "┼",
props: [
#{ key: "w", type: "float", def: 20.0, min: 1.0, max: 500.0, step: 0.5, label: "Length (m)" },
#{ key: "h", type: "float", def: 1.8, min: 0.5, max: 4.0, step: 0.1, label: "Height (m)" },
] }
}
fn prefab_fence(o) {
let p = o.p;
let n = (p.w / 30.0).ceiling().to_int();
let L = p.w / n;
for i in 0..n {
let x0 = -p.w / 2.0 + i * L;
let s = sprite();
s.box(x0, -0.03, x0 + L, 0.03, 0.0, p.h, "fence");
let k = (L / 2.5).floor().to_int();
for j in 0..(k + 1) {
let x = x0 + j * L / fmax(k, 1);
s.box(x - 0.04, -0.04, x + 0.04, 0.04, 0.0, p.h + 0.05, "steel");
}
}
}
fn meta_lamp() {
#{ label: "Street lamp", category: "Site", icon: "†",
help: "Keep lamps on verges and kerbs, not on drive areas.",
props: [ #{ key: "h", type: "float", def: 5.0, min: 2.0, max: 12.0, step: 0.5, label: "Height (m)" } ] }
}
fn prefab_lamp(o) {
let s = sprite();
s.box(-0.07, -0.07, 0.07, 0.07, 0.0, o.p.h, "lampost", #{ no_top: true });
s.circle(0.0, 0.0, o.p.h + 0.1, 1.2, "lamp");
}
fn meta_marker() {
#{ label: "Marker", category: "Site", icon: "⚑",
help: "A pin with a label: set the label in Tag and the tooltip in Info.",
props: [ #{ key: "h", type: "float", def: 1.5, min: 0.3, max: 20.0, step: 0.1, label: "Height (m)" } ] }
}
fn prefab_marker(o) {
let s = sprite();
s.box(-0.05, -0.05, 0.05, 0.05, 0.0, o.p.h, "steel", #{ no_top: true });
s.circle(0.0, 0.0, o.p.h, 2.0, "led ledo");
}