isokit: project layer, Studio GUI, MCP server, viewer, CLI, demo project and docs

This commit is contained in:
grabowski committed 2026-10-22 15:29:07 +07:00
1 parent 95c80ec6b1
commit 564aeb75f6
47 files changed
+5978 -366

No files matched your search

+38
View File
@@ -0,0 +1,38 @@
# isokit demo: a small works site. Open it with `isokit studio examples/demo`.
title = "isokit demo works"
note = "Demo scene for isokit. Drag to pan, Ctrl + wheel or pinch to zoom, tap anything for details; GF and 1F cut the building open."
default_level = "site"
default_rotation = 1
prelude = ["lib/kiosk.rhai"]
theme = ["theme.toml"]
[[level]]
id = "site"
label = "Site"
title = "Closed buildings and roofs"
[[level]]
id = "gf"
label = "GF"
title = "Ground floor, cut open"
[[level]]
id = "1f"
label = "1F"
title = "First floor, cut open"
[[param]]
name = "labels"
type = "bool"
default = true
label = "Labels"
[[param]]
name = "running"
type = "bool"
default = true
label = "Animation"
[build]
out = "dist/index.html"
budget = 4000
+27
View File
@@ -0,0 +1,27 @@
// A project prefab: shows up as "Gate kiosk" in the Studio palette.
fn meta_kiosk() {
#{ label: "Gate kiosk", category: "Site", icon: "⌂",
help: "A small kiosk with a boom barrier (project prefab, lib/kiosk.rhai).",
props: [
#{ key: "h", type: "float", def: 2.8, min: 2.2, max: 4.0, step: 0.1, label: "Height (m)" },
#{ key: "boom", type: "bool", def: true, label: "Boom barrier" },
#{ key: "boom_len", type: "float", def: 5.0, min: 2.0, max: 8.0, step: 0.5, label: "Boom length (m)" },
] }
}
fn prefab_kiosk(o) {
let p = o.p;
let s = sprite();
s.box(-1.5, -1.2, 1.5, 1.2, 0.0, 0.2, "plinth");
s.box(-1.4, -1.1, 1.4, 1.1, 0.2, p.h, "brick", #{ top: "roof3" });
let sd = sides(-1.4, -1.1, 1.4, 1.1);
s.open(sd.S[0], sd.S[1], [[0.3, 1.5, 1.1, 2.0]], "glass");
s.open(sd.E[0], sd.E[1], [[0.6, 1.4, 0.2, 2.3]], "door2");
if p.boom {
// the boom is its own sprite so cars and people sort around it
let b = sprite();
b.box(1.7, -1.5, 1.95, -1.25, 0.0, 1.0, "boom");
b.box(1.75, -1.5 - p.boom_len, 1.9, -1.45, 0.9, 1.0, "boom");
}
}
+29
View File
@@ -0,0 +1,29 @@
{
"version": 1,
"objects": [
{ "id": "site", "type": "site", "name": "Site", "x": 0, "y": 0, "props": { "w": 70, "d": 46 }, "info": "70 x 46 m plot", "locked": true },
{ "id": "road", "type": "road", "name": "Access road", "x": 0, "y": -19.5, "props": { "w": 70, "d": 6 } },
{ "id": "yard", "type": "area", "name": "Service yard", "x": 14, "y": 4, "props": { "w": 24, "d": 18, "mat": "g-conc" } },
{ "id": "parking", "type": "parking", "name": "Staff parking", "x": -20, "y": -12, "props": { "n": 8 } },
{ "id": "hall", "type": "building", "name": "Workshop and offices", "x": -12, "y": 6, "props": { "w": 24, "d": 12, "floors": 2, "pv": true }, "tag": "Workshop", "info": "Two storeys, 24 x 12 m, solar on the roof" },
{ "id": "carport", "type": "carport", "name": "Carport", "x": 14, "y": -10, "props": { "w": 12, "cars": 4, "pv": true }, "info": "Four bays with solar on the canopy" },
{ "id": "tank", "type": "tank", "name": "Water tank", "x": 22, "y": 9, "props": { "r": 2.2, "h": 6, "mat": "water" }, "tag": "Water", "info": "90 m3 process water" },
{ "id": "genset", "type": "generator", "name": "Standby generator", "x": 8, "y": 10, "props": { "running": true } },
{ "id": "stack", "type": "chimney", "name": "Boiler stack", "x": 30, "y": 12, "props": { "h": 14, "smoke": "puff" } },
{ "id": "truck", "type": "truck", "name": "Delivery truck", "x": 15, "y": 1 },
{ "id": "kiosk", "type": "kiosk", "name": "Gate kiosk", "x": -30, "y": -4, "tag": "Gate" },
{ "id": "crowd", "type": "crowd", "name": "Visitors", "x": -12, "y": -3, "props": { "n": 5 } },
{ "id": "car-1", "type": "car", "x": -28.75, "y": -12, "rot": 90, "props": { "colour": "car1" } },
{ "id": "car-2", "type": "car", "x": -23.75, "y": -12, "rot": 90, "props": { "colour": "car3" } },
{ "id": "car-3", "type": "car", "x": -16.25, "y": -12, "rot": 90, "props": { "colour": "car4" } },
{ "id": "bus", "type": "car", "name": "Passing car", "x": -25, "y": -18, "props": { "colour": "car2", "moving": true, "travel": 45, "dur": 12 } },
{ "id": "trees-north", "type": "tree_row", "name": "Tree belt", "x": 0, "y": 19.5, "props": { "w": 62, "spacing": 7 } },
{ "id": "tree-1", "type": "tree", "x": 30, "y": -2, "props": { "r": 2.0 } },
{ "id": "tree-2", "type": "tree", "x": -31, "y": 8 },
{ "id": "fence-east", "type": "fence", "name": "East fence", "x": 34.6, "y": 0, "rot": 90, "props": { "w": 40 } },
{ "id": "lamp-1", "type": "lamp", "x": -25, "y": -15.6 },
{ "id": "lamp-2", "type": "lamp", "x": -5, "y": -15.6 },
{ "id": "lamp-3", "type": "lamp", "x": 15, "y": -15.6 },
{ "id": "assembly", "type": "marker", "name": "Assembly point", "x": 30, "y": -14.5, "tag": "Assembly point", "info": "Fire assembly point" }
]
}
+11
View File
@@ -0,0 +1,11 @@
// Optional script, drawn before the objects of scene.json.
// Everything placed in the Studio lives in scene.json; use this file for
// things that are easier to code (repeats, data-driven layouts).
let s = sprite("sign");
s.box(-34.0, -15.7, -33.85, -15.55, 0.0, 2.4, "steel", #{ no_top: true });
s.box(-34.6, -15.75, -33.25, -15.5, 1.5, 2.5, "brick");
info("sign", "Site sign", "Drawn by scene.rhai, not by the Studio");
// open the view on the workshop on small screens
focus(-12.0, 6.0, 0.0);
+9
View File
@@ -0,0 +1,9 @@
# Demo theme: adds a brick material on top of the built-in theme.
[palette.dark]
brick = "#8a4f3e"
[palette.light]
brick = "#b8664c"
[materials]
brick = "brick"