The Data created by the Studio. Holds all data models.
ReadonlyeventsPer-Studio event hub — currently just onError / onWarning.
Mirrors the *.events shape on Scene, Data, Viewer, and
WebGLRenderer; the !issuesPanel.IssuesPanel | IssuesPanel
subscribes here alongside those four to surface Studio-side
failures in the same list.
Registry of model-format loaders consulted by loadModel. Populated from StudioConfig.loaders or createDefaultLoaderRegistry.
Resolves the default URL for a (modelId, format) pair when
loadModel is called without an explicit src. Populated
from StudioConfig.locator or DefaultModelLocator.
Base directory for loading models, relative to the HTML page.
ReadonlypanelsSingle dispatch point for opening, hiding, and toggling every
built-in panel and tool — studio.panels.open("modelsPanel"),
studio.panels.toggle("navCube", {view}), etc. Replaces the
40 dedicated openX/hideX/toggleX methods that used to
live directly on Studio.
Register custom panels with studio.panels.register("myId", ...)
and augment PanelMap from your own module so the call
sites stay typed.
Owns the unified pick strategy and the BVH-backed
SceneCollisionIndex. Lazy-built — demos that never pick
pay for neither.
Direct picks: studio.picking.picker.pick({...}).
AABB queries: studio.picking.collisionIndex.getSceneAABB().
ViewController adapter: studio.picking.pickForViewController(view, params).
The WebGLRenderer created by the Studio.
The Scene created by the Studio. Holds all 3D objects.
Statistics about the demo, available after calling finished().
The Viewer created by the Studio.
Owns the lifecycle of every View created through Studio — the
views map (records of view, cameraFlight, viewController),
auto-canvas layout, and floating ViewPanels for floating: true.
Read access: studio.viewManager.views[id].cameraFlight.
Create / destroy: studio.viewManager.createView(...) /
studio.viewManager.destroyView(view).
Mount the TransformControls on view (creating them on first call), attach them to target, and switch to mode when supplied.
pivotWorld is the world-space anchor the handles render
around — typically the surface point the picker returned from
the click that triggered the attach.
Optionalmode: TransformControlsModeOptionalpivotWorld: Vec3Lazily creates a ScenePhysics system, attaches every
SceneObject of sceneModel (or every SceneObject of every
SceneModel if no model is passed) as a dynamic Rapier body, and
applies a downward gravity so the parts drop and "demolish"
themselves.
"Downward" is derived from Scene.coordinateSystem.worldUp
— gravity points in -worldUp, which makes the demolition look
the same regardless of whether the scene is Y-up, Z-up, or any
other orientation. SceneModels with their own coordinate-system
basis still fall the right way because Rapier bodies live in
world space and the SceneModel's coordinateSystemMatrix has
already mapped them there.
The physics system, Rapier WASM module, and per-frame step()
loop are only created on the first call — demos that never
demolish anything pay nothing. Gravity is locked in at that first
call from the Scene's worldUp; later calls don't re-derive it.
Each object gets a small randomised initial angular + lateral velocity so the disassembly looks chaotic instead of monolithic.
OptionalsceneModel: SceneModelSceneModel whose objects should be turned into dynamic bodies. When omitted, every SceneModel currently in the Scene is demolished.
SDKResult — ok: false if Rapier failed to load.
Destroys both the SceneModel and the DataModel
that share modelId (when each exists). Either side may be
absent — a model loaded via loadModel with no
dataModel argument leaves the data side empty, and a model
loaded with datamodel only leaves the scene side empty —
and the call succeeds whichever combination is found.
Pairs with how loadDataset mints SceneModel +
DataModel under the same id so a "delete this model"
action in the UI is the natural inverse: one call wipes
both halves without the caller having to know which loader
path produced them.
The ID shared by the SceneModel / DataModel
to destroy (typically SceneModel.id from the active
selection).
A small report of what was actually destroyed — useful when the caller wants to log/announce only the sides that existed.
Detach the TransformControls on view if mounted. Leaves the controls live so the next attachTransformControls call reuses the same instance.
Finalizes the demo setup, gathering statistics and signaling completion.
Provenance for modelId, or undefined if none was recorded.
Initializes the Studio by creating the Scene, Data, Viewer, WebGLRenderer, and optional initial View.
Configuration options for initialization.
A promise that resolves when initialization is complete.
Replace the helper's Scene + Data contents with a single
named dataset from the demo model catalog
(models/index.json). Loads formats sequentially into a
fresh SceneModel + DataModel pair and frames the camera on the result.
Optionalclear?: booleanWhen true (default), every existing SceneModel + DataModel in the helper's Scene / Data is destroyed before the new one is created. Pass false to load alongside whatever's already there.
OptionalyieldIntervalMs?: numberOptional override for the cooperative-yield throttle, in
milliseconds. See
yieldIntervalMs
— passed through to every per-format loadModel call so a
single override applies across the whole dataset load.
Raise above the 16ms default for noticeably faster large
loads at the cost of less-frequent progress updates.
The newly-created SceneModel + DataModel on success, or an SDK error result if any phase fails.
Loads a model into the Scene and/or Data layers using a format-specific loader.
This method:
params.src or a default path derived from modelIdparams.formatSupported formats:
"xgf" → XGFLoader (binary)"ifc" → IFCLoader (binary)"gltf" → GLTFLoader (binary, .glb)"metamodel" → MetaModelLoader (JSON, data-only)"datamodel" → DataModelParamsLoader (JSON, data-only)"scenemodel" → SceneModelParamsLoader (JSON, scene-only)Default source resolution:
If params.src is not provided, the source path is inferred as:
../../models/{modelId}/{format}/model.{ext}
Model creation behavior:
sceneModel is not provided, a new one is created via this.scene.createModel()dataModel is not provided, a new one is created via this.data.createModel()modelId when availableConfiguration for loading the model
OptionaldataModel?: DataModelOptional existing DataModel to populate
Model format determining which loader to use
OptionalmodelId?: stringOptional identifier used for default paths and generated model IDs
OptionalsceneModel?: SceneModelOptional existing SceneModel to populate
Optionalsrc?: stringOptional explicit source URL/path for the model file
Loader-specific options passed through to the underlying loader
A promise resolving to an SDKResult containing the loader result
Open the floating per-example info panel. Single-instance: a second call destroys the previously-opened panel before constructing a fresh one, so an example always has at most one info card on screen. The caller gets the panel handle back and uses its imperative builders to populate it:
const info = studio.openInfoPanel({
id: "viewing_sectionPlane_duplex",
title: "Section Caps — Duplex",
description: "<p>Drag the slider to move the cut plane.</p>",
});
info.addToggle({ label: "Section plane", value: true,
onChange: v => sp.active = v });
info.addSlider({ label: "Cut Z (m)", min: 0, max: 5,
value: 2.6, onChange: rebuildCaps });
info.addStat ({ id: "caps", label: "Cap meshes" });
// …later:
info.setStat("caps", String(result.numCapMeshes));
Layout / chrome notes:
localStorage slot via InfoPanelParams.id.Open an InfoPanel pre-populated from the example's own
index.json metadata. Single line for every example:
const info = await studio.openInfoPanelFromMeta();
info.addToggle({...}); // optional — chain controls if needed
Fetches ./index.json (relative to the current page URL) and
uses its id, title, and description fields to build the
panel. If the fetch fails or the JSON is malformed, the
promise still resolves with a generic panel rather than
rejecting — examples never break because of a missing
metadata file.
Callers that need richer descriptions or want to override
the metadata can pass override props that win over
the fetched fields.
Record where a freshly-loaded model came from. The ModelsPanel reads this back via getModelOrigin to surface "loaded via …" details. Cleared by destroyModel.
Dispatch an error through this Studio's StudioEvents.onError
channel. The !issuesPanel.IssuesPanel | IssuesPanel
is the canonical subscriber — every dispatch lands as a row in
its log, with severity = "error". Panels and host code use
this in place of throw / console.error so the IssuesPanel
is the single place to surface Studio-side failures.
Accepts either an SDKResult<any> (an ok: false outcome
coming back from a downstream call) or a plain message string.
For the string form, the dispatched payload synthesises an
SDKResult<void> shape with the supplied type (defaulting
to SDKErrorType.InvalidOperation).
Optionaltype: SDKErrorTypeDispatch a recoverable warning through this Studio's
StudioEvents.onWarning channel. Same payload shape and
routing as reportError; the IssuesPanel surfaces these
with severity = "warning".
Optionaltype: SDKErrorTypeToggle the AngleMeasurementsTool's mouse control on view,
ensuring the tool exists first. Returns the
MouseAngleMeasurementsControl after the toggle.
Toggle the DistanceMeasurementTool's mouse control on view,
ensuring the tool exists first. Returns the
MouseDistanceMeasurementsControl after the toggle.
This is a domain operation — not a panel open/hide — so it stays as a direct method rather than going through panels.
Helper class to set up a basic 3D demo with a Scene, Data, Viewer, WebGLRenderer, and View.
See @xeokit/sdk/demo for usage.