RemoteArKotlinJs.kt
src/jvmMain/kotlin/afield/lang/remotejs/RemoteArKotlinJs.kt · 612 lines
package afield.lang.remotejs
import afield.geometry.path.FLine
import afield.geometry.path.div
import afield.geometry.path.length
import afield.geometry.path.minus
import afield.geometry.path.plus
import afield.geometry.path.scale
import afield.geometry.path.times
import afield.graphics.three.three
The Kotlin/JS declarations a box sees when it runs Kotlin in the browser RemoteAR head.
RemoteArKotlinJs describes the THREE globals the extensions/remote_ar head installs
(scene objects, vectors, FLine construction, the stage proxy and the animation task loop) with
jsBinding. From that one description it produces RemoteArKotlinJs.declarations, the
external declarations the Kotlin/JS compiler sees, and RemoteArKotlinJs.completionDeclarations,
the stub model the completion sidecar analyses on the JVM. It also adds FLine operators
(fline + rotate(0.5), fline * 2.0) and named scene slots (SCENEname= obj).
object RemoteArKotlinJs
Typed Kotlin/JS view of the stable, useful core of the browser RemoteAR head.
The surface is described ONCE via jsBinding; the compiler-facing external declarations and the
JVM-analysis-safe completion mirror are both generated from it (see KotlinJsBinding), so they
cannot drift (no more var vs val mismatches or completion offering members compilation rejects).
Add THREE classes / helpers here without touching marker parsing, routing, or compilation.
Deliberately smaller than the complete THREE universe — these are the globals Field actually
installs in extensions/remote_ar (scene objects, vectors, FLine construction, the stage proxy,
and the animation task loop). The richer real head (transforms, scene search, object-creation
helpers, XR) is bound incrementally on top of this spine.
const val surfaceId: String = "remoteAR"
source — 566 lines, from line 39
private val binding = jsBinding {
obj("THREE") {
valProp("REVISION", "String")
cls("Object3D") {
open()
varProp("name", "String")
valProp("position", "Vector3")
valProp("rotation", "Euler")
valProp("scale", "Vector3")
valProp("children", "Array<Object3D>")
// ---- richer standard Object3D surface (three.js Object3D) ----
valProp("up", "Vector3")
valProp("quaternion", "Quaternion")
valProp("matrix", "Matrix4")
varProp("visible", "Boolean", completionInit = "true")
varProp("castShadow", "Boolean", completionInit = "false")
varProp("receiveShadow", "Boolean", completionInit = "false")
varProp("renderOrder", "Double", completionInit = "0.0")
varProp("frustumCulled", "Boolean", completionInit = "true")
varProp("userData", JsType.DYNAMIC)
varProp("parent", JsType("dynamic", "Object3D?"))
fn("add", "Object3D") { vararg("objects", "Object3D") }
fn("remove", "Object3D") { vararg("objects", "Object3D") }
fn("lookAt", "Unit") { param("x", "Double"); param("y", "Double"); param("z", "Double") }
fn("lookAt", "Unit") { param("target", "Vector3") }
fn("applyMatrix4", "Unit") { param("matrix", "Matrix4") }
fn("applyQuaternion", "Object3D") { param("q", "Quaternion") }
fn("translateX", "Object3D") { param("distance", "Double") }
fn("translateY", "Object3D") { param("distance", "Double") }
fn("translateZ", "Object3D") { param("distance", "Double") }
fn("rotateX", "Object3D") { param("angle", "Double") }
fn("rotateY", "Object3D") { param("angle", "Double") }
fn("rotateZ", "Object3D") { param("angle", "Double") }
fn("rotateOnAxis", "Object3D") { param("axis", "Vector3"); param("angle", "Double") }
fn("getObjectByName", "Object3D?") { param("name", "String") }
fn("traverse", "Unit") { param("callback", JsType("(o: dynamic) -> Unit", "(o: Object3D) -> Unit")) }
fn("updateMatrix", "Unit")
fn("updateMatrixWorld", "Unit") { param("force", "Boolean", "false") }
fn("clone", "Object3D") { param("recursive", "Boolean", "true") }
}
cls("Scene") {
extends("Object3D")
// Field replaces three.js's `attach(object)` method with a named-index proxy
// (graphics.js): `SCENE.attach[name] = obj`. dynamic for the compiler, indexer for completion.
valProp("attach", JsType("dynamic", "AttachProxy"))
// `SCENE[name] = obj` / `SCENE[name]` — the named-scene-slot operators declared below
// delegate to these compiler-only raw members (installed on the scene in graphics.js),
// which route straight through the `attach` proxy so assigning replaces whatever object
// currently occupies the slot. Kept out of completion like FLine's `__PLUS__`.
compilerFn("__attachSet", "Unit") { param("name", "String"); param("value", JsType.DYNAMIC) }
compilerFn("__attachGet", JsType.DYNAMIC) { param("name", "String") }
}
cls("Camera") { open(); extends("Object3D") }
cls("Vector2") {
field("x", "Double", "0.0")
field("y", "Double", "0.0")
fn("set", "Vector2") { param("x", "Double"); param("y", "Double") }
fn("clone", "Vector2")
fn("add", "Vector2") { param("other", "Vector2") }
fn("sub", "Vector2") { param("other", "Vector2") }
fn("multiplyScalar", "Vector2") { param("value", "Double") }
}
cls("Vector3") {
field("x", "Double", "0.0")
field("y", "Double", "0.0")
field("z", "Double", "0.0")
fn("set", "Vector3") { param("x", "Double"); param("y", "Double"); param("z", "Double") }
fn("clone", "Vector3")
fn("add", "Vector3") { param("other", "Vector3") }
fn("sub", "Vector3") { param("other", "Vector3") }
fn("multiplyScalar", "Vector3") { param("value", "Double") }
fn("normalize", "Vector3")
fn("length", "Double")
}
cls("Euler") {
field("x", "Double", "0.0")
field("y", "Double", "0.0")
field("z", "Double", "0.0")
field("order", "String", "\"XYZ\"")
fn("set", "Euler") {
param("x", "Double"); param("y", "Double"); param("z", "Double")
param("order", "String", "\"XYZ\"")
}
}
cls("BufferGeometry") { open() }
cls("BoxGeometry") {
extends("BufferGeometry")
ctor { param("width", "Double"); param("height", "Double"); param("depth", "Double") }
}
cls("SphereGeometry") {
extends("BufferGeometry")
ctor { param("radius", "Double"); param("widthSegments", "Int", "32"); param("heightSegments", "Int", "16") }
}
// ---- richer geometries (super-three r0.184.0; all re-exported on the THREE global) ----
cls("PlaneGeometry") {
extends("BufferGeometry")
ctor {
param("width", "Double", "1.0"); param("height", "Double", "1.0")
param("widthSegments", "Int", "1"); param("heightSegments", "Int", "1")
}
}
cls("CylinderGeometry") {
extends("BufferGeometry")
ctor {
param("radiusTop", "Double", "1.0"); param("radiusBottom", "Double", "1.0")
param("height", "Double", "1.0"); param("radialSegments", "Int", "32")
}
}
cls("ConeGeometry") {
extends("BufferGeometry")
ctor { param("radius", "Double", "1.0"); param("height", "Double", "1.0"); param("radialSegments", "Int", "32") }
}
cls("TorusGeometry") {
extends("BufferGeometry")
ctor {
param("radius", "Double", "1.0"); param("tube", "Double", "0.4")
param("radialSegments", "Int", "12"); param("tubularSegments", "Int", "48")
}
}
cls("TorusKnotGeometry") {
extends("BufferGeometry")
ctor {
param("radius", "Double", "1.0"); param("tube", "Double", "0.4")
param("tubularSegments", "Int", "64"); param("radialSegments", "Int", "8")
}
}
cls("CircleGeometry") {
extends("BufferGeometry")
ctor { param("radius", "Double", "1.0"); param("segments", "Int", "32") }
}
cls("RingGeometry") {
extends("BufferGeometry")
ctor { param("innerRadius", "Double", "0.5"); param("outerRadius", "Double", "1.0"); param("thetaSegments", "Int", "32") }
}
cls("Material") {
open()
varProp("transparent", "Boolean", completionInit = "false")
varProp("opacity", "Double", completionInit = "1.0")
varProp("visible", "Boolean", completionInit = "true")
varProp("side", "Int", completionInit = "0")
varProp("depthTest", "Boolean", completionInit = "true")
varProp("depthWrite", "Boolean", completionInit = "true")
varProp("needsUpdate", "Boolean", completionInit = "false")
}
cls("MeshBasicMaterial") {
extends("Material")
ctor { param("parameters", JsType.DYNAMIC, "null") }
valProp("color", "Color")
varProp("map", JsType("dynamic", "Texture?"))
varProp("wireframe", "Boolean", completionInit = "false")
}
// ---- lit materials (three.js; used by addPlane/addBox/loaders — all on the THREE global) ----
cls("MeshStandardMaterial") {
extends("Material")
ctor { param("parameters", JsType.DYNAMIC, "null") }
valProp("color", "Color")
valProp("emissive", "Color")
varProp("roughness", "Double", completionInit = "1.0")
varProp("metalness", "Double", completionInit = "0.0")
varProp("wireframe", "Boolean", completionInit = "false")
varProp("map", JsType("dynamic", "Texture?"))
}
cls("MeshLambertMaterial") {
extends("Material")
ctor { param("parameters", JsType.DYNAMIC, "null") }
valProp("color", "Color")
valProp("emissive", "Color")
varProp("wireframe", "Boolean", completionInit = "false")
varProp("map", JsType("dynamic", "Texture?"))
}
cls("MeshPhongMaterial") {
extends("Material")
ctor { param("parameters", JsType.DYNAMIC, "null") }
valProp("color", "Color")
valProp("emissive", "Color")
valProp("specular", "Color")
varProp("shininess", "Double", completionInit = "30.0")
varProp("wireframe", "Boolean", completionInit = "false")
varProp("map", JsType("dynamic", "Texture?"))
}
cls("MeshNormalMaterial") {
extends("Material")
ctor { param("parameters", JsType.DYNAMIC, "null") }
varProp("wireframe", "Boolean", completionInit = "false")
}
cls("PointsMaterial") {
extends("Material")
ctor { param("parameters", JsType.DYNAMIC, "null") }
valProp("color", "Color")
varProp("size", "Double", completionInit = "1.0")
varProp("sizeAttenuation", "Boolean", completionInit = "true")
varProp("vertexColors", "Boolean", completionInit = "false")
varProp("map", JsType("dynamic", "Texture?"))
}
cls("LineBasicMaterial") {
extends("Material")
ctor { param("parameters", JsType.DYNAMIC, "null") }
valProp("color", "Color")
varProp("linewidth", "Double", completionInit = "1.0")
}
cls("Mesh") {
extends("Object3D")
// ctor args that are also mutable properties → present + mutable in BOTH renderings.
field("geometry", "BufferGeometry")
field("material", "Material")
}
// ---- core THREE math types (standard three.js) ----
cls("Vector4") {
field("x", "Double", "0.0"); field("y", "Double", "0.0")
field("z", "Double", "0.0"); field("w", "Double", "0.0")
fn("set", "Vector4") { param("x", "Double"); param("y", "Double"); param("z", "Double"); param("w", "Double") }
fn("clone", "Vector4")
fn("add", "Vector4") { param("other", "Vector4") }
fn("sub", "Vector4") { param("other", "Vector4") }
fn("multiplyScalar", "Vector4") { param("value", "Double") }
fn("length", "Double")
}
cls("Quaternion") {
field("x", "Double", "0.0"); field("y", "Double", "0.0")
field("z", "Double", "0.0"); field("w", "Double", "1.0")
fn("set", "Quaternion") { param("x", "Double"); param("y", "Double"); param("z", "Double"); param("w", "Double") }
fn("setFromEuler", "Quaternion") { param("euler", "Euler") }
fn("setFromAxisAngle", "Quaternion") { param("axis", "Vector3"); param("angle", "Double") }
fn("multiply", "Quaternion") { param("other", "Quaternion") }
fn("normalize", "Quaternion")
fn("clone", "Quaternion")
}
cls("Matrix4") {
fn("identity", "Matrix4")
fn("clone", "Matrix4")
fn("multiply", "Matrix4") { param("other", "Matrix4") }
fn("premultiply", "Matrix4") { param("other", "Matrix4") }
fn("makeTranslation", "Matrix4") { param("x", "Double"); param("y", "Double"); param("z", "Double") }
fn("makeScale", "Matrix4") { param("x", "Double"); param("y", "Double"); param("z", "Double") }
fn("makeRotationFromQuaternion", "Matrix4") { param("q", "Quaternion") }
}
cls("Color") {
// `new THREE.Color(r, g, b)` — components are 0..1 and mutable.
field("r", "Double", "1.0"); field("g", "Double", "1.0"); field("b", "Double", "1.0")
fn("set", "Color") { param("value", "Int") }
fn("setRGB", "Color") { param("r", "Double"); param("g", "Double"); param("b", "Double") }
fn("setHex", "Color") { param("hex", "Int") }
fn("getHex", "Int")
fn("clone", "Color")
}
cls("PointLight") {
extends("Object3D")
ctor { param("color", "Int", "0xffffff"); param("intensity", "Double", "1.0"); param("distance", "Double", "0.0") }
valProp("color", "Color")
varProp("intensity", "Double")
varProp("distance", "Double")
}
// ---- more lights (three.js; on the THREE global) ----
cls("DirectionalLight") {
extends("Object3D")
ctor { param("color", "Int", "0xffffff"); param("intensity", "Double", "1.0") }
valProp("color", "Color")
varProp("intensity", "Double")
valProp("target", "Object3D")
}
cls("AmbientLight") {
extends("Object3D")
ctor { param("color", "Int", "0xffffff"); param("intensity", "Double", "1.0") }
valProp("color", "Color")
varProp("intensity", "Double")
}
cls("HemisphereLight") {
extends("Object3D")
ctor { param("skyColor", "Int", "0xffffff"); param("groundColor", "Int", "0xffffff"); param("intensity", "Double", "1.0") }
valProp("color", "Color")
varProp("intensity", "Double")
}
cls("SpotLight") {
extends("Object3D")
ctor {
param("color", "Int", "0xffffff"); param("intensity", "Double", "1.0")
param("distance", "Double", "0.0"); param("angle", "Double", "1.047")
param("penumbra", "Double", "0.0")
}
valProp("color", "Color")
varProp("intensity", "Double")
varProp("distance", "Double")
varProp("angle", "Double")
varProp("penumbra", "Double")
valProp("target", "Object3D")
}
// ---- scene-graph containers + renderable object types ----
cls("Group") { extends("Object3D") }
cls("Points") {
extends("Object3D")
field("geometry", "BufferGeometry")
field("material", "Material")
}
cls("Line") {
extends("Object3D")
field("geometry", "BufferGeometry")
field("material", "Material")
}
// ---- textures (loadTexture / addImagePlane return these) ----
cls("Texture") {
open()
varProp("needsUpdate", "Boolean", completionInit = "false")
varProp("wrapS", "Int", completionInit = "1000")
varProp("wrapT", "Int", completionInit = "1000")
valProp("repeat", "Vector2")
valProp("offset", "Vector2")
varProp("flipY", "Boolean", completionInit = "true")
}
cls("TextureLoader") {
fn("load", "Texture") { param("url", "String") }
}
}
cls("FLine") {
varProp("stroked", "Boolean", completionInit = "true")
varProp("filled", "Boolean", completionInit = "false")
varProp("pointed", "Boolean", completionInit = "false")
fn("moveTo", "FLine") { param("x", "Double"); param("y", "Double"); param("z", "Double", "0.0") }
fn("moveTo", "FLine") { param("point", "THREE.Vector3") }
fn("moveTo", "FLine") { param("point", "THREE.Vector2") }
fn("lineTo", "FLine") { param("x", "Double"); param("y", "Double"); param("z", "Double", "0.0") }
fn("lineTo", "FLine") { param("point", "THREE.Vector3") }
fn("lineTo", "FLine") { param("point", "THREE.Vector2") }
// cubicTo: 3 control vectors, 6 numbers (2D), or 9 numbers (3D).
fn("cubicTo", "FLine") { param("a", "THREE.Vector3"); param("b", "THREE.Vector3"); param("c", "THREE.Vector3") }
fn("cubicTo", "FLine") {
param("c1x", "Double"); param("c1y", "Double"); param("c2x", "Double"); param("c2y", "Double")
param("x", "Double"); param("y", "Double")
}
fn("cubicTo", "FLine") {
param("c1x", "Double"); param("c1y", "Double"); param("c1z", "Double")
param("c2x", "Double"); param("c2y", "Double"); param("c2z", "Double")
param("x", "Double"); param("y", "Double"); param("z", "Double")
}
fn("uv", "FLine") { param("u", "Double"); param("v", "Double") }
fn("vcolor", "FLine") { param("r", "Double"); param("g", "Double"); param("b", "Double"); param("a", "Double") }
// Public transform: apply a per-point map `(x,y,z) -> [x,y,z]`, returning a new FLine
// (fline.js:458). The callback returns a 3-element array of coordinates.
fn(
"byTransforming", "FLine",
) {
param(
"transform",
JsType(
"(x: Double, y: Double, z: Double) -> Array<Double>",
"(x: Double, y: Double, z: Double) -> Array<Double>",
),
)
}
// Raw runtime transform ops (fline.js:492–578) — compiler-only; the public `+`/`-`/`*`/`/`
// operator extensions below delegate to these, so they stay OUT of completion.
compilerFn("__PLUS__", "FLine") { param("v", JsType.DYNAMIC) }
compilerFn("__MINUS__", "FLine") { param("v", JsType.DYNAMIC) }
compilerFn("__MULTIPLY__", "FLine") { param("v", JsType.DYNAMIC) }
compilerFn("__DIVIDE__", "FLine") { param("v", JsType.DYNAMIC) }
// Pointer-event registries: `fline.mouseDown[name] = { event -> … }` (Proxy-over-Map).
valProp("mouseDown", JsType("dynamic", "PointerCallbacks"))
valProp("mouseUp", JsType("dynamic", "PointerCallbacks"))
valProp("mouseMove", JsType("dynamic", "PointerCallbacks"))
valProp("dblClick", JsType("dynamic", "PointerCallbacks"))
}
// The runtime `stage` is a dynamic Map proxy (`fline.js`): `stage[name] = fline`,
// `stage.name = fline`, `stage.add/remove`. Typing it as `dynamic` for the compiler keeps all
// of that permissive; a completion-only `Stage` type gives `stage.add|` / `stage.remove|` and
// `stage["…"]` completion without constraining the JS target. (To clear the scene use the free
// `clearAll()` — the proxy's Map.clear would bypass scene removal.)
completionCls("Stage") {
fn("add", "Unit") { param("item", "Any?") }
fn("remove", "Boolean") { param("item", "Any?") }
operatorFn("get", JsType.of("Any?")) { param("name", "String") }
operatorFn("set", JsType.of("Unit")) { param("name", "String"); param("value", "Any?") }
}
// `SCENE.attach[name] = obj` — Field's named-index proxy (compiler sees `dynamic`).
completionCls("AttachProxy") {
operatorFn("get", JsType.of("THREE.Object3D?")) { param("name", "String") }
operatorFn("set", JsType.of("Unit")) { param("name", "String"); param("value", "Any?") }
}
// Completion shapes for the dynamic result objects the helpers return (compiler sees `dynamic`).
completionCls("CameraPose") {
valProp("position", "THREE.Vector3"); valProp("forward", "THREE.Vector3"); valProp("up", "THREE.Vector3")
}
completionCls("PlacedMesh") {
valProp("mesh", "THREE.Mesh"); valProp("material", "THREE.Material"); valProp("mouseDown", "PointerCallbacks")
}
completionCls("ImagePlane") {
valProp("mesh", "THREE.Mesh"); valProp("material", "THREE.Material")
valProp("texture", "Any?"); valProp("mouseDown", "PointerCallbacks")
}
completionCls("VideoPlane") {
valProp("mesh", "THREE.Mesh"); valProp("material", "THREE.Material")
valProp("video", "Any?"); valProp("texture", "Any?"); valProp("mouseDown", "PointerCallbacks")
}
// ---- asset-loader callback payloads (files.js) — the loader hands each `callback` a runtime
// object; `dynamic` for the compiler, these typed shapes for completion inside the lambda. The
// animation methods (`play`/`stop`/`apply`) drive the auto-created XR AnimationMixer via
// `mixer.clipAction(clip)` under the hood (files.js:396+, webxr.js:76). ----
completionCls("GltfAsset") {
// Array-valued fields are raw JS arrays (the payload is `dynamic` for the compiler, so member
// names are emitted verbatim — a JS array's length is `.length`, not Kotlin's `.size`); keep
// them `Any?` so completion doesn't suggest a `.size` that resolves to `undefined` at runtime.
valProp("meshes", "Any?") // Array<THREE.Object3D> at runtime (use [i] / .length)
valProp("animations", "Any?") // Array<THREE.AnimationClip> at runtime
valProp("scene", "THREE.Object3D")
valProp("scenes", "Any?")
valProp("cameras", "Any?")
valProp("asset", "Any?")
fn("play", "Unit") // clipAction(clip).play() on every clip
fn("stop", "Unit")
fn("apply", "Unit") { param("time", "Double") } // scrub: seek every clip to `time`
}
completionCls("FbxAsset") {
// NB: loadFBX THROWS unless a FBXLoader is vendored in the head (files.js:129); prefer glTF.
valProp("animations", "Any?") // raw JS array at runtime (use [i] / .length)
valProp("objects", "Any?") // raw JS array at runtime (use [i] / .length)
fn("play", "Unit") { param("looping", "Boolean", "true") }
fn("stop", "Unit")
fn("pause", "Unit")
fn("currentTime", "Double")
fn("apply", "Unit") { param("time", "Double") }
}
completionCls("PlyAsset") {
valProp("mesh", "THREE.Object3D")
}
// Pointer-event registry: `target.mouseDown[name] = { event -> … }`. dynamic for the compiler,
// a named-index callback registry for completion. The event object is head-dependent (dynamic).
completionCls("PointerCallbacks") {
operatorFn("set", JsType.of("Unit")) { param("name", "String"); param("callback", JsType.of("(event: Any?) -> Unit")) }
operatorFn("get", JsType.of("Any?")) { param("name", "String") }
}
// WebXR hit (position + world matrix), returned by `xrHit()` / passed to onXRHit callbacks.
completionCls("XRHit") {
valProp("position", "THREE.Vector3")
valProp("matrix", "Array<Double>")
}
externalVal("SCENE", "THREE.Scene")
externalVal("CAMERA", "THREE.Camera")
externalVal("stage", JsType("dynamic", "Stage"))
computedVal("scene", "THREE.Scene", compiler = "SCENE")
computedVal("camera", "THREE.Camera", compiler = "CAMERA")
// `vec(…)` builds a THREE vector sized by arity (fline.js); `clearAll()` empties the scene.
externalFun("vec", "THREE.Vector2") { param("x", "Double"); param("y", "Double") }
externalFun("vec", "THREE.Vector3") { param("x", "Double"); param("y", "Double"); param("z", "Double") }
externalFun("vec", "THREE.Vector4") { param("x", "Double"); param("y", "Double"); param("z", "Double"); param("w", "Double") }
externalFun("clearAll", "Unit")
// ---- transforms (fline.js) — each builds a THREE.Matrix4 ----
externalFun("rotate", "THREE.Matrix4") { param("angle", "Double") }
externalFun("rotate", "THREE.Matrix4") { param("angle", "Double"); param("pivotX", "Double"); param("pivotY", "Double") }
externalFun("scale", "THREE.Matrix4") { param("s", "Double") }
externalFun("scale", "THREE.Matrix4") { param("x", "Double"); param("y", "Double"); param("z", "Double") }
externalFun("translate", "THREE.Matrix4") { param("x", "Double", "0.0"); param("y", "Double", "0.0"); param("z", "Double", "0.0") }
externalFun("rotate3", "THREE.Matrix4") { param("axis", "THREE.Vector3"); param("angle", "Double") }
// ---- scene search + camera pose (fline.js) ----
externalFun("findByName", "THREE.Object3D?") { param("name", "String") }
externalFun("findBySearchingFor", "THREE.Object3D?") { param("name", "String") }
externalFun("findBySearchingPathFor", "THREE.Object3D?") { param("name", "String") }
externalFun("getCurrentCamera", JsType("dynamic", "CameraPose"))
externalFun("addTextureTo", "Unit") { param("url", "String"); param("target", JsType.DYNAMIC) }
// ---- object-creation helpers (files.js) — return dynamic result objects (typed for completion) ----
externalFun("addBox", JsType("dynamic", "PlacedMesh")) { param("name", "String"); param("size", "Double", "1.0") }
externalFun("addPlane", JsType("dynamic", "PlacedMesh")) { param("name", "String"); param("size", "Double", "1.0") }
externalFun("addImagePlane", JsType("dynamic", "ImagePlane")) { param("url", "String"); param("name", "String"); param("size", "Double", "1.0") }
externalFun("addVideoPlane", JsType("dynamic", "VideoPlane")) { param("url", "String"); param("name", "String"); param("size", "Double", "1.0") }
externalFun("addPointLight", "THREE.PointLight") { param("name", "String") }
// ---- asset & animation loaders (files.js) — async/callback-based; the callback receives a
// runtime payload (dynamic for the compiler, typed for completion). The loaded object is also
// installed as a head global under `name`. ----
externalFun("loadGLTF", "Unit") {
param("url", "String"); param("name", "String")
param("callback", JsType("(loaded: dynamic) -> Unit", "(loaded: GltfAsset) -> Unit"))
}
externalFun("loadPointCloudPLY", "Unit") {
param("url", "String"); param("name", "String")
param("callback", JsType("(loaded: dynamic) -> Unit", "(loaded: PlyAsset) -> Unit"))
}
// loadFBX THROWS unless the head vendors a FBXLoader (files.js:129) — bound for completeness;
// convert assets to glTF and use loadGLTF instead.
externalFun("loadFBX", "Unit") {
param("url", "String"); param("name", "String")
param("callback", JsType("(loaded: dynamic) -> Unit", "(loaded: FbxAsset) -> Unit"))
}
externalFun("loadJSONScene", "Unit") { param("url", "String"); param("name", "String") }
// A THREE.Texture (dynamic for the compiler; typed for completion).
externalFun("loadTexture", JsType("dynamic", "THREE.Texture")) { param("url", "String") }
// Expose an on-disk directory over the Field server: mapDirectory("/abs/assets", "/assets").
externalFun("mapDirectory", "Unit") { param("onDiskPath", "String"); param("servedAs", "String") }
// ---- WebXR interaction (webxr.js) — on* return an unsubscribe () -> Unit ----
externalFun("onXRHit", JsType.CALLBACK) { param("callback", JsType("(hit: dynamic) -> Unit", "(hit: Any?) -> Unit")) }
externalFun("onXRSelect", JsType.CALLBACK) { param("callback", JsType("(hit: dynamic) -> Unit", "(hit: Any?) -> Unit")) }
externalFun("xrHit", JsType("dynamic", "XRHit"))
function("log", ret = JsType.of("Unit"), compilerBody = "__remoteArLog(value)") {
param("value", "Any?")
}
operator("THREE.Vector2", "plus", "THREE.Vector2", "clone().add(other)") { param("other", "THREE.Vector2") }
operator("THREE.Vector2", "minus", "THREE.Vector2", "clone().sub(other)") { param("other", "THREE.Vector2") }
operator("THREE.Vector2", "times", "THREE.Vector2", "clone().multiplyScalar(value)") { param("value", "Double") }
operator("THREE.Vector3", "plus", "THREE.Vector3", "clone().add(other)") { param("other", "THREE.Vector3") }
operator("THREE.Vector3", "minus", "THREE.Vector3", "clone().sub(other)") { param("other", "THREE.Vector3") }
operator("THREE.Vector3", "times", "THREE.Vector3", "clone().multiplyScalar(value)") { param("value", "Double") }
operator("THREE.Vector4", "plus", "THREE.Vector4", "clone().add(other)") { param("other", "THREE.Vector4") }
operator("THREE.Vector4", "minus", "THREE.Vector4", "clone().sub(other)") { param("other", "THREE.Vector4") }
operator("THREE.Vector4", "times", "THREE.Vector4", "clone().multiplyScalar(value)") { param("value", "Double") }
// ---- FLine transform operators (fline.js:492–578) — `fline + rotate(0.5)`, `fline + vec(1,0,0)`,
// `fline * 2.0`, `fline - translate(…)`. Each delegates to the compiler-only raw member above.
// Grounded overloads: +/- take a Matrix4 or a promotable vector; */÷ also take a scalar.
operator("FLine", "plus", "FLine", "__PLUS__(m)") { param("m", "THREE.Matrix4") }
operator("FLine", "plus", "FLine", "__PLUS__(v)") { param("v", "THREE.Vector3") }
operator("FLine", "plus", "FLine", "__PLUS__(v)") { param("v", "THREE.Vector2") }
operator("FLine", "minus", "FLine", "__MINUS__(m)") { param("m", "THREE.Matrix4") }
operator("FLine", "minus", "FLine", "__MINUS__(v)") { param("v", "THREE.Vector3") }
operator("FLine", "minus", "FLine", "__MINUS__(v)") { param("v", "THREE.Vector2") }
operator("FLine", "times", "FLine", "__MULTIPLY__(m)") { param("m", "THREE.Matrix4") }
operator("FLine", "times", "FLine", "__MULTIPLY__(v)") { param("v", "THREE.Vector3") }
operator("FLine", "times", "FLine", "__MULTIPLY__(s)") { param("s", "Double") }
operator("FLine", "div", "FLine", "__DIVIDE__(m)") { param("m", "THREE.Matrix4") }
operator("FLine", "div", "FLine", "__DIVIDE__(v)") { param("v", "THREE.Vector3") }
operator("FLine", "div", "FLine", "__DIVIDE__(s)") { param("s", "Double") }
// ---- named scene slots — `SCENE[name] = obj` / `val obj = SCENE[name]` (graphics.js). Assigning
// REPLACES whatever object already occupies that slot; reading returns the object in it (or null).
// Value is typed `THREE.Object3D` and the receiver stays `THREE.Scene` (not `dynamic`), so SCENE
// keeps its full member autocomplete. Delegates to the compiler-only members on Scene above.
operator("THREE.Scene", "set", "Unit", "__attachSet(name, value)") {
param("name", "String"); param("value", "THREE.Object3D")
}
operator("THREE.Scene", "get", "THREE.Object3D?", "__attachGet(name)") {
param("name", "String")
}
rawCompiler(
"""
@kotlin.js.JsName("log")
private external fun __remoteArLog(value: Any?)
""".trimIndent(),
)
}
val declarations: String = binding.compilerDeclarations
Compiler-facing external declarations, generated from binding.
val completionDeclarations: String = binding.completionDeclarations
JVM-analysis-safe model used by the out-of-process completion sidecar, generated from binding.