Skip to content

Scripting

The three examples the gallery lists under Scripting. Each block is what the gallery’s code panel shows beside that example, copied from the example itself: the lines that do it rather than the whole file, so it isn’t compiled here the way the guides’ code is. The file it came from is linked under each one.

Two interfaces written in .tsx, running in the engine, drawn by Flutter.

// script/hud.tsx — the whole of the interface. Compiled by `npm run build`
// and loaded into the engine's script host; nothing on the Dart side builds
// an element.
import { mount } from "orblit";
const state = { hull: 0.72, score: 1840, accent: "ember" };
/// A bar is two boxes: the track, and as much of it as is left. No progress
/// widget, and no second component set.
function Bar({ part }: { part: number }) {
return (
<box class="w-full h-2 rounded-full bg-slate-700 clip">
<box class={`h-2 rounded-full bg-${state.accent}-500`}
style={`width: ${Math.round(part * 224)}px`} />
</box>
);
}
function Hud() {
return (
<column class="p-5 gap-3 items-start">
<text class="text-lg font-semibold text-slate-100">Sector 12</text>
<Bar part={state.hull} />
<button class="px-3 py-2 rounded-md bg-ember-500 text-white"
key="repair"
onPressed={() => { state.hull = Math.min(1, state.hull + 0.12); }}>
Repair
</button>
</column>
);
}
mount(() => <Hud />);

From interface.dart. To open the gallery on it:

Terminal window
ORBLIT_EXAMPLE='an interface in typescript' flutter run -d macos

The same description, built directly, with no script in the way.

// The same description, written rather than sent. No engine, no script.
UiNode get description => UiNode(
type: 'column',
classes: 'gap-2 px-4 py-3 rounded-lg bg-slate-900 border border-slate-700',
children: [
UiNode(
type: 'text',
classes: 'text-xs uppercase text-slate-400',
text: 'Power',
),
// A bar is two boxes: the track, and as much of it as is left.
UiNode(
type: 'box',
classes: 'w-full h-2 rounded-full bg-slate-700 clip',
children: [
UiNode(
type: 'box',
classes: 'h-2 rounded-full bg-$accent-500',
css: 'width: ${(health * 224).round()}px',
),
],
),
],
);
// And then, exactly as in the TypeScript example:
UiBuilder().build(description)

From interface_native.dart. To open the gallery on it:

Terminal window
ORBLIT_EXAMPLE='an interface in dart' flutter run -d macos

Every object put there by TypeScript, and moved by it every frame.

// script/world.tsx — every object in the scene, and everything that moves.
import { spawn, all, clear } from "orblit/scene";
export const settings = { rings: 4, spin: 0.35, bob: true };
export function build() {
clear();
spawn({ id: "core", at: [0, 0.4, 0], size: [0.8, 2.4, 0.8],
colour: "#F2F4F7" });
for (let ring = 0; ring < settings.rings; ring++) {
const radius = 2.4 + ring * 1.9;
const many = 6 + ring * 4;
for (let i = 0; i < many; i++) {
const angle = (i / many) * Math.PI * 2;
spawn({
id: `r${ring}-${i}`,
at: [Math.cos(angle) * radius, -0.6, Math.sin(angle) * radius],
size: [0.5, 0.5 + ring * 0.25, 0.5],
turn: (angle * 180) / Math.PI,
colour: colours[(ring + i) % colours.length],
});
}
}
}
// The step. Everything that moves, moves here — the host only asks for a
// frame and draws whatever it is told.
export function step(seconds: number) {
for (const thing of all()) { /* ... */ }
}

From spawning.dart. To open the gallery on it:

Terminal window
ORBLIT_EXAMPLE='spawning from script' flutter run -d macos