kubexr
v0.3.0
Published
Neux kubexr
Readme
kubexr
Creative-mode authoring primitives for XR Voyage plugins. Wraps Babylon.js
with a small scene/object/gizmo/editor stack so plugins can spawn instances
(xrcube, xrimage, …), click them to get a property editor, and persist
their layout into the owning panel's inputs.
- npm:
kubexr - Source:
gitlab.com/neux/kubexr - Plugin author guide:
GUIDE.md - Changelog:
CHANGELOG.md
Install
yarn add kubexr
# peer deps you probably already have in an XR Voyage plugin host:
# @babylonjs/core @babylonjs/gui lil-guiQuick start (inside an XR Voyage plugin)
class XrVoyagePlugin {
public constructor() {
// storage persists instance params to panel.inputs on Save
const storage = new kubexr.XRStorage();
storage.loadFromPanelInputs(this.panel.data.object.inputs);
// creates creative-mode infrastructure; edit mode starts OFF (v0.2+)
const sceneManager = new kubexr.SceneManager(storage, this.scene, true);
// turn edit mode on to enable click → bounding-box gizmo + lil-gui editor
sceneManager.setEditMode(true);
// spawn buttons (top-center 2D HUD)
const buttons = new kubexr.Buttons(this.scene);
buttons.addButton('xrcube', (type) => sceneManager.createInstance(type));
buttons.addButton('xrimage', (type) => sceneManager.createInstance(type));
}
// Panel ingress handler — fired when the user clicks Save inside the editor
@kubexr.kubexrIngress('kubexr.instance.save')
public handleInstanceSave(payload: Record<string, any>) {
this.panel.inputs.merge({ instances: [payload] });
}
}Public API (brief)
kubexr.SceneManager(storage, scene, isCreativeMode)— orchestrates handlers,CreativeMode, click-selection, gizmos, editor. Loads persisted instances fromstorage.storage.instances.setEditMode(on: boolean)— gate for click→select. OFF = instances render, clicks are ignored. ON = full click→bounding-box gizmo + property editor flow. Added in v0.2.isEditMode(): booleancreateInstance(type: 'xrcube' | 'xrimage' | …)onSaveInstance(cb)— fires when the editor's Save button is clicked.
kubexr.XRStorage— in-memory instance catalogue; serialises to the panelinputsshape vialoadFromPanelInputs()/saveInstance().kubexr.Buttons(scene)— thin wrapper over Babylon GUIStackPanelfor the top-center spawn HUD.kubexr.XRCubeHandler,kubexr.XRImageHandler— mesh factories for the built-in instance types. Both honour the samecreateInstanceMesh/updateInstanceMeshprotocol fromXRHandlerBase, so custom handlers can plug intoSceneManagerthe same way.kubexr.storageXrCube,kubexr.storageXrImage— declarative schemas for the property editor. Each listsgui_folderswithparams;GuiManagerwalks them to build the lil-gui controls.kubexr.GuiManager,kubexr.GizmoManager,kubexr.CreativeMode— internal; accessible if you want to wire a bespoke editor.- Decorators —
kubexr.kubexrIngress(eventType),kubexr.kubexrEgress(eventType)for wiring decorated class methods into the XR Voyage event bus.
Registering your own construct type (v0.3)
Third-party plugins can bolt arbitrary Babylon.js-backed constructs
onto kubexr's click → gizmo + lil-gui editor machinery via the
type registry. Full walk-through in GUIDE.md.
kubexr.defineType({
id: 'xrsphere',
name: 'Sphere',
params: [
{ param: 'diameter', min: 0.1, max: 10, step: 0.1, default: 1 },
],
createMesh: (instance, scene) =>
BabylonjsCore.MeshBuilder.CreateSphere(
instance.id, { diameter: instance.params.diameter }, scene,
),
});
// Hook a spawn button onto the 2D HUD
buttons.addButton('xrsphere', (t) => sceneManager.createInstance(t));The resulting instance gets Position/Rotation/Scale sliders, a type-specific "Sphere" folder with the diameter control, and Save / Delete buttons — all auto-composed from the schema. Edit-mode selection, bounding-box gizmo, reload-rehydrate-from-panel-inputs all work identically to the built-in xrcube / xrimage types.
Lower-level API: kubexr.registerType({ schema, factory, handlers })
for authors who need a custom folder layout. See
GUIDE.md.
Edit-mode gate (v0.2)
Prior versions exposed the click→select flow unconditionally — every scene
with a SceneManager reacted to pointer events. That made it hard to ship
a plugin where spawned instances should just render unless the user
explicitly enters an authoring view.
As of v0.2:
CreativeModeholds aprivate editMode = falseflag.scene.onPointerObservableearly-returns wheneditMode === false.- Plugins opt in via
sceneManager.setEditMode(true), opt out at any time. - Applies symmetrically to every handler (xrcube, xrimage, future types).
Recommended pattern: render a small Edit Mode toggle button (inside
your plugin's HUD) that calls sceneManager.setEditMode(on).
XrImage fallback + default URL (v0.2)
XRImageHandler:
createInstanceMeshno longer constructs a texture whenimage_urlis falsy/0/empty. The plane is spawned with a solid tinteddiffuseColor+emissiveColorandbackFaceCulling = falseso it is visible from any camera angle.updateInstanceMeshdisposes the diffuseTexture cleanly when the user clears the URL, so the fallback colour comes back through.storageXrImage.image_urlnow has adefaultpointing at an envoy-served PNG (/xrdesigns/level-001/xr-voyage-horizontal-v2.pngin the reference stack), so freshly spawned planes render a real texture out of the box.
The updateImage onFinishChange path is unchanged — typing a URL still
triggers instance.updateParam → updateInstanceMesh.
Development
# tsc + rollup produces dist/index.js (cjs), dist/index.mjs (esm), .d.ts
yarn install
yarn build
# iterate against a consuming app via yarn link
yarn link # in this repo
yarn link kubexr # in the consumerRelease
main and any issue/** branch trigger the publish_npm CI job. Version
comes from git describe --tags via git_semver.sh, so tagging v0.3 on
an empty-diff commit produces exactly 0.3 on npm; otherwise the commit
count is appended (e.g. 0.2.12).
License
MIT. See LICENSE.
