@roomle/web-sdk 3.7.0 → 3.8.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/{BufferGeometry-BzmfTBQt.mjs → BufferGeometry-ltw0XkYt.mjs} +7 -4
- package/lib/BufferGeometry-ltw0XkYt.mjs.map +1 -0
- package/lib/ConfiguratorKernel.js +6 -6
- package/lib/ConfiguratorKernel.wasm +0 -0
- package/lib/{GLTFExporter-CyhgWPq0.mjs → GLTFExporter-BqjC9LhS.mjs} +9 -14
- package/lib/GLTFExporter-BqjC9LhS.mjs.map +1 -0
- package/lib/{Object3D-C3wqWk6O.mjs → Object3D-BZaiqQIE.mjs} +24 -12
- package/lib/Object3D-BZaiqQIE.mjs.map +1 -0
- package/lib/{PointLightHelper-DwIXACyT.mjs → PointLightHelper-AxCe6I00.mjs} +4 -4
- package/lib/PointLightHelper-AxCe6I00.mjs.map +1 -0
- package/lib/RoomleCore.js +8 -8
- package/lib/RoomleCore.wasm +0 -0
- package/lib/RoomleToolsCore.wasm +0 -0
- package/lib/{SpotLightHelper-CfLHM7LU.mjs → SpotLightHelper-DpMerFPv.mjs} +3 -3
- package/lib/{SpotLightHelper-CfLHM7LU.mjs.map → SpotLightHelper-DpMerFPv.mjs.map} +1 -1
- package/lib/{USDZExporter-kmxcTvnQ.mjs → USDZExporter-qUD2VgwK.mjs} +2 -2
- package/lib/{USDZExporter-kmxcTvnQ.mjs.map → USDZExporter-qUD2VgwK.mjs.map} +1 -1
- package/lib/{Vector4-DUqY3Egg.mjs → Vector4-BfZH1ecw.mjs} +7 -4
- package/lib/Vector4-BfZH1ecw.mjs.map +1 -0
- package/lib/{api-X1dDTDvL.mjs → api-CbHAzwVm.mjs} +2 -2
- package/lib/{api-X1dDTDvL.mjs.map → api-CbHAzwVm.mjs.map} +1 -1
- package/lib/asset-loader.worker-A7nEeQB4.mjs.map +1 -1
- package/lib/{banana-for-scale-Bpf8RfLi.mjs → banana-for-scale-DiBCpVNM.mjs} +3 -3
- package/lib/{banana-for-scale-Bpf8RfLi.mjs.map → banana-for-scale-DiBCpVNM.mjs.map} +1 -1
- package/lib/budgeteer.sw-CQWYbQSc.mjs.map +1 -1
- package/lib/{common-utils-DMI8Yuhe.mjs → common-utils-AB4Lnet3.mjs} +2 -2
- package/lib/{common-utils-DMI8Yuhe.mjs.map → common-utils-AB4Lnet3.mjs.map} +1 -1
- package/lib/{component-dimensioning-MtS9xiY-.mjs → component-dimensioning-LUnZnpqG.mjs} +5 -5
- package/lib/{component-dimensioning-MtS9xiY-.mjs.map → component-dimensioning-LUnZnpqG.mjs.map} +1 -1
- package/lib/{component-raycast-helper-C1qWqpRH.mjs → component-raycast-helper-Bl0mWPcj.mjs} +4 -4
- package/lib/{component-raycast-helper-C1qWqpRH.mjs.map → component-raycast-helper-Bl0mWPcj.mjs.map} +1 -1
- package/lib/configurator-BmJX0gB5.mjs +2 -0
- package/lib/configurator-CP80d0HI.mjs +45 -0
- package/lib/{configurator-Cg1a9XSL.mjs.map → configurator-CP80d0HI.mjs.map} +1 -1
- package/lib/{continuous-drawing-helper-CQx5Sbns.mjs → continuous-drawing-helper-BlRy7u2t.mjs} +3 -3
- package/lib/{continuous-drawing-helper-CQx5Sbns.mjs.map → continuous-drawing-helper-BlRy7u2t.mjs.map} +1 -1
- package/lib/dimensioning-helper-5xsc6I7Y.mjs +2 -0
- package/lib/{dimensioning-helper-GPn7Z8GE.mjs → dimensioning-helper-vPhGfHd-.mjs} +3 -3
- package/lib/{dimensioning-helper-GPn7Z8GE.mjs.map → dimensioning-helper-vPhGfHd-.mjs.map} +1 -1
- package/lib/{glb-viewer-tgKOPCaI.mjs → glb-viewer-B7pA8K_w.mjs} +71 -54
- package/lib/glb-viewer-B7pA8K_w.mjs.map +1 -0
- package/lib/glb-viewer-XFEP993c.mjs +2 -0
- package/lib/{highlight-coordinator-DRHeEU-E.mjs → highlight-coordinator-DeB46jQq.mjs} +9 -3
- package/lib/highlight-coordinator-DeB46jQq.mjs.map +1 -0
- package/lib/{homag-intelligence-D5mCTWgG.mjs → homag-intelligence-f1JD0An1.mjs} +3 -3
- package/lib/homag-intelligence-f1JD0An1.mjs.map +1 -0
- package/lib/{imos-ix-poc-export-helper-BKFs_Yhm.mjs → imos-ix-poc-export-helper-Vyv-uuNs.mjs} +3 -3
- package/lib/{imos-ix-poc-export-helper-BKFs_Yhm.mjs.map → imos-ix-poc-export-helper-Vyv-uuNs.mjs.map} +1 -1
- package/lib/kernel-C7YDLxq8.mjs.map +1 -1
- package/lib/{kernel-utils-B80amC-l.mjs → kernel-utils-BG1uqfT_.mjs} +2 -2
- package/lib/{kernel-utils-B80amC-l.mjs.map → kernel-utils-BG1uqfT_.mjs.map} +1 -1
- package/lib/{main-CJ5TNhBt.mjs → main-CuqGqemT.mjs} +2916 -2605
- package/lib/main-CuqGqemT.mjs.map +1 -0
- package/lib/{material-viewer-DCqZzMZN.mjs → material-viewer-Cij9aWpI.mjs} +23 -23
- package/lib/{material-viewer-DCqZzMZN.mjs.map → material-viewer-Cij9aWpI.mjs.map} +1 -1
- package/lib/packages-DALvuVA_.mjs +4 -0
- package/lib/planner-CVn2Lls0.mjs +2 -0
- package/lib/planner-DKbmQVSf.mjs +44 -0
- package/lib/{planner-CSboZram.mjs.map → planner-DKbmQVSf.mjs.map} +1 -1
- package/lib/{plugin-system-DD0Z9Jvt.mjs → plugin-system-BEZnFUyT.mjs} +2 -2
- package/lib/{plugin-system-DD0Z9Jvt.mjs.map → plugin-system-BEZnFUyT.mjs.map} +1 -1
- package/lib/{roomle-headless-setup-nsoGENQV.mjs → roomle-headless-setup-CMK-quZI.mjs} +131 -77
- package/lib/roomle-headless-setup-CMK-quZI.mjs.map +1 -0
- package/lib/roomle-headless.d.ts +333 -44
- package/lib/roomle-headless.js +196 -80
- package/lib/roomle-headless.js.map +1 -1
- package/lib/{roomle-renderer-BEJNPCKx.mjs → roomle-renderer-BgT28pfp.mjs} +2 -2
- package/lib/{roomle-renderer-BEJNPCKx.mjs.map → roomle-renderer-BgT28pfp.mjs.map} +1 -1
- package/lib/roomle-sdk.d.ts +168 -37
- package/lib/roomle-sdk.js +7 -7
- package/lib/roomle-webgpu-renderer-BdCItfH1.mjs +2243 -0
- package/lib/roomle-webgpu-renderer-BdCItfH1.mjs.map +1 -0
- package/lib/{scene-renderer-Dm1kij1z.mjs → scene-renderer-Bdl7umAf.mjs} +6 -6
- package/lib/{scene-renderer-Dm1kij1z.mjs.map → scene-renderer-Bdl7umAf.mjs.map} +1 -1
- package/lib/{script-loader-DqaDm1FG.mjs → script-loader-BtWHegD-.mjs} +2 -2
- package/lib/{script-loader-DqaDm1FG.mjs.map → script-loader-BtWHegD-.mjs.map} +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/package.json +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/configuratorCallback.d.ts +2 -2
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/configuratorCallback.js +2 -2
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/configuratorCallback.js.map +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/configuratorCoreInterface.d.ts +12 -3
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/configuratorCoreInterface.js +1 -0
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/configuratorCoreInterface.js.map +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/plannerCoreInterface.d.ts +43 -2
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/plannerCoreInterface.js +20 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/embind/plannerCoreInterface.js.map +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/loader/configurationLoader.d.ts +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/loader/configurationLoader.js +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/src/loader/configurationLoader.js.map +1 -1
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/wasm_modern/ConfiguratorKernel.js +6 -6
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/wasm_modern/ConfiguratorKernel.wasm +0 -0
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/wasm_modern/RoomleCore.js +8 -8
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/wasm_modern/RoomleCore.wasm +0 -0
- package/lib/static/roomle-core-hsc/node_modules/roomle-core-hsc/wasm_modern/RoomleToolsCore.wasm +0 -0
- package/lib/{stats-helper-D7a7oxnj.mjs → stats-helper-BvDfWWfq.mjs} +2 -2
- package/lib/{stats-helper-D7a7oxnj.mjs.map → stats-helper-BvDfWWfq.mjs.map} +1 -1
- package/lib/{three.core-BmQnspOL.mjs → three.core-K1JzUaep.mjs} +748 -706
- package/lib/three.core-K1JzUaep.mjs.map +1 -0
- package/lib/{three.module-DkrZwaid.mjs → three.module-Q2K9uyhi.mjs} +1022 -965
- package/lib/three.module-Q2K9uyhi.mjs.map +1 -0
- package/lib/{three.webgpu-DLZjhIYv.mjs → three.webgpu-7v7o6Pxs.mjs} +3804 -3481
- package/lib/three.webgpu-7v7o6Pxs.mjs.map +1 -0
- package/lib/three.webgpu-ChguPx4k.mjs +3 -0
- package/lib/{threejs-utils-CrK_gp1x.mjs → threejs-utils-BzXU2M3w.mjs} +67 -47
- package/lib/threejs-utils-BzXU2M3w.mjs.map +1 -0
- package/lib/{tools-core-CZWgXTFV.mjs → tools-core-BoxckhTR.mjs} +6 -6
- package/lib/{tools-core-CZWgXTFV.mjs.map → tools-core-BoxckhTR.mjs.map} +1 -1
- package/package.json +4 -4
- package/lib/BufferGeometry-BzmfTBQt.mjs.map +0 -1
- package/lib/GLTFExporter-CyhgWPq0.mjs.map +0 -1
- package/lib/Object3D-C3wqWk6O.mjs.map +0 -1
- package/lib/PointLightHelper-DwIXACyT.mjs.map +0 -1
- package/lib/Vector4-DUqY3Egg.mjs.map +0 -1
- package/lib/configurator-C5t3clCx.mjs +0 -2
- package/lib/configurator-Cg1a9XSL.mjs +0 -45
- package/lib/dimensioning-helper-Bfe0fImX.mjs +0 -2
- package/lib/glb-viewer-DIEpkrvY.mjs +0 -2
- package/lib/glb-viewer-tgKOPCaI.mjs.map +0 -1
- package/lib/highlight-coordinator-DRHeEU-E.mjs.map +0 -1
- package/lib/homag-intelligence-D5mCTWgG.mjs.map +0 -1
- package/lib/main-CJ5TNhBt.mjs.map +0 -1
- package/lib/packages-DuOz6rk6.mjs +0 -4
- package/lib/planner-CSboZram.mjs +0 -44
- package/lib/planner-CWPqJktz.mjs +0 -2
- package/lib/roomle-headless-setup-nsoGENQV.mjs.map +0 -1
- package/lib/roomle-webgpu-renderer-D5flithq.mjs +0 -1502
- package/lib/roomle-webgpu-renderer-D5flithq.mjs.map +0 -1
- package/lib/three.core-BmQnspOL.mjs.map +0 -1
- package/lib/three.module-DkrZwaid.mjs.map +0 -1
- package/lib/three.webgpu-DLZjhIYv.mjs.map +0 -1
- package/lib/three.webgpu-RkQxSIwG.mjs +0 -3
- package/lib/threejs-utils-CrK_gp1x.mjs.map +0 -1
package/lib/roomle-headless.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { i as e, t } from "./kernel-C7YDLxq8.mjs";
|
|
2
|
-
import { bi as n } from "./three.core-
|
|
3
|
-
import {
|
|
4
|
-
import { n as
|
|
5
|
-
import { t as
|
|
6
|
-
import { t as F } from "./planner-
|
|
7
|
-
import { n as I, t as L } from "./glb-viewer-
|
|
8
|
-
import { t as R } from "./api-
|
|
9
|
-
import "./packages-
|
|
10
|
-
import "./roomle-headless-setup-
|
|
2
|
+
import { bi as n } from "./three.core-K1JzUaep.mjs";
|
|
3
|
+
import { B as r, F as i, H as a, K as o, M as s, N as c, O as l, P as u, U as d, V as f, W as p, a as m, b as h, c as g, et as _, i as v, it as y, j as b, k as x, l as S, lt as C, n as w, nt as T, ot as E, s as D, st as O, tt as k, v as A, x as j, y as M, z as N } from "./main-CuqGqemT.mjs";
|
|
4
|
+
import { n as P } from "./script-loader-BtWHegD-.mjs";
|
|
5
|
+
import { t as ee } from "./configurator-CP80d0HI.mjs";
|
|
6
|
+
import { t as F } from "./planner-DKbmQVSf.mjs";
|
|
7
|
+
import { n as I, t as L } from "./glb-viewer-B7pA8K_w.mjs";
|
|
8
|
+
import { t as R } from "./api-CbHAzwVm.mjs";
|
|
9
|
+
import "./packages-DALvuVA_.mjs";
|
|
10
|
+
import "./roomle-headless-setup-CMK-quZI.mjs";
|
|
11
11
|
import { createRequire as z } from "module";
|
|
12
12
|
//#region packages/headless-core/src/headless-script-loader.ts
|
|
13
13
|
var B = z(import.meta.url), V = {}, H = [
|
|
@@ -62,7 +62,7 @@ var B = z(import.meta.url), V = {}, H = [
|
|
|
62
62
|
return Promise.all(t);
|
|
63
63
|
}
|
|
64
64
|
resolveKernelPaths(e) {
|
|
65
|
-
return
|
|
65
|
+
return P(e);
|
|
66
66
|
}
|
|
67
67
|
cleanUp() {
|
|
68
68
|
V = {};
|
|
@@ -161,16 +161,48 @@ var B = z(import.meta.url), V = {}, H = [
|
|
|
161
161
|
}
|
|
162
162
|
setAlwaysUseCache(e) {}
|
|
163
163
|
preFillAssetCache(e, t) {}
|
|
164
|
-
}, K = class
|
|
164
|
+
}, K = class extends D {
|
|
165
|
+
_getScriptLoaderKernelId(e) {
|
|
166
|
+
return e === x.PLANNER ? "kernel-planner" : "kernel";
|
|
167
|
+
}
|
|
168
|
+
}, q = class {
|
|
169
|
+
wrap(e) {
|
|
170
|
+
return new Proxy(e, { get(e, t) {
|
|
171
|
+
let n = e[t];
|
|
172
|
+
return typeof n == "function" ? function(...r) {
|
|
173
|
+
try {
|
|
174
|
+
return n.apply(e, r);
|
|
175
|
+
} catch (e) {
|
|
176
|
+
console.error(`[Headless] Kernel callback '${String(t)}' threw:`, e);
|
|
177
|
+
}
|
|
178
|
+
} : n;
|
|
179
|
+
} });
|
|
180
|
+
}
|
|
181
|
+
}, J = {
|
|
182
|
+
add(e) {
|
|
183
|
+
try {
|
|
184
|
+
e.end?.();
|
|
185
|
+
} catch {}
|
|
186
|
+
},
|
|
187
|
+
remove() {},
|
|
188
|
+
removeAll() {},
|
|
189
|
+
getAll() {
|
|
190
|
+
return [];
|
|
191
|
+
},
|
|
192
|
+
update() {}
|
|
193
|
+
}, Y = () => {
|
|
194
|
+
let e = window;
|
|
195
|
+
e.TWEEN = J;
|
|
196
|
+
}, X = (e) => e.split(":").length - 1 == 1, Z = (e) => e.split(":").length - 1 <= 0, Q = (e) => e ? e.startsWith("component@") : !1, $ = class e {
|
|
165
197
|
constructor() {
|
|
166
|
-
this._initialized = !1, this._width = 1024, this._height = 768;
|
|
198
|
+
this._initialized = !1, this._configuratorReady = !1, this._plannerReady = !1, this._glbViewerReady = !1, this._loadedConfigurationId = null, this._loadedPlanId = null, this._loadedStaticItemId = null, this._width = 1024, this._height = 768, this._loaderQueue = Promise.resolve(), this._onReadyForRenderArmed = null;
|
|
167
199
|
}
|
|
168
200
|
static async create(t) {
|
|
169
201
|
let n = new e();
|
|
170
202
|
return await n._init(t), n;
|
|
171
203
|
}
|
|
172
204
|
async _init(e) {
|
|
173
|
-
this._width = e.width ?? 1024, this._height = e.height ?? 768, this._registerHeadlessServices(this._width, this._height), await
|
|
205
|
+
this._width = e.width ?? 1024, this._height = e.height ?? 768, Y(), this._registerHeadlessServices(this._width, this._height), await S.setGlobalInitData({
|
|
174
206
|
configuratorId: e.configuratorId,
|
|
175
207
|
locale: e.locale,
|
|
176
208
|
tenant: e.tenant,
|
|
@@ -179,39 +211,24 @@ var B = z(import.meta.url), V = {}, H = [
|
|
|
179
211
|
}), this._initialized = !0;
|
|
180
212
|
}
|
|
181
213
|
_registerHeadlessServices(e, t) {
|
|
182
|
-
let n = new
|
|
214
|
+
let n = new _();
|
|
183
215
|
globalThis.__RML__DI__ = n;
|
|
184
|
-
class
|
|
216
|
+
class r extends W {
|
|
185
217
|
constructor(n) {
|
|
186
218
|
super(n, e, t);
|
|
187
219
|
}
|
|
188
220
|
}
|
|
189
|
-
let
|
|
190
|
-
new
|
|
191
|
-
new
|
|
192
|
-
new
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
return typeof r == "function" ? function(...t) {
|
|
201
|
-
try {
|
|
202
|
-
return r.apply(e, t);
|
|
203
|
-
} catch (e) {
|
|
204
|
-
console.error(`[Headless] Kernel callback '${String(n)}' threw:`, e);
|
|
205
|
-
}
|
|
206
|
-
} : r;
|
|
207
|
-
} });
|
|
208
|
-
}, n.addDependencyInjectionAssignments(C);
|
|
209
|
-
}
|
|
210
|
-
async loadConfiguration(e, t) {
|
|
211
|
-
this._ensureInitialized();
|
|
212
|
-
let n = await y.getConfigurator(t);
|
|
213
|
-
await n.boot(), this._configuratorMain = n, this._configurator = n.getApi();
|
|
214
|
-
let r = {
|
|
221
|
+
let i = [
|
|
222
|
+
new T("script-loader", U, k.CONTEXT, !0),
|
|
223
|
+
new T("dom-helper", r, k.CONTEXT, !0),
|
|
224
|
+
new T("data-syncer", G, k.GLOBAL, !0),
|
|
225
|
+
new T("planner-kernel-access", K, k.GLOBAL, !0),
|
|
226
|
+
new T("kernel-callback-guard", q, k.GLOBAL, !0)
|
|
227
|
+
];
|
|
228
|
+
n.addDependencyInjectionAssignments(v), n.addDependencyInjectionAssignments(i);
|
|
229
|
+
}
|
|
230
|
+
_makeStubElement() {
|
|
231
|
+
return {
|
|
215
232
|
clientWidth: this._width,
|
|
216
233
|
clientHeight: this._height,
|
|
217
234
|
appendChild() {},
|
|
@@ -219,21 +236,114 @@ var B = z(import.meta.url), V = {}, H = [
|
|
|
219
236
|
style: {},
|
|
220
237
|
classList: { add() {} }
|
|
221
238
|
};
|
|
222
|
-
await this._configurator.init(r), await this._configurator.loadConfigurableItemById(e);
|
|
223
239
|
}
|
|
224
|
-
async
|
|
240
|
+
async prewarmConfigurator(e) {
|
|
225
241
|
this._ensureInitialized();
|
|
226
|
-
let
|
|
227
|
-
await
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
await this._planner.
|
|
242
|
+
let t = await S.getConfigurator(e);
|
|
243
|
+
await t.boot(), this._configuratorMain = t, this._configurator = t.getApi(), await this._configurator.init(this._makeStubElement()), this._configuratorReady = !0;
|
|
244
|
+
}
|
|
245
|
+
async prewarmPlanner(e) {
|
|
246
|
+
this._ensureInitialized();
|
|
247
|
+
let t = await S.getPlanner({
|
|
248
|
+
moc: !0,
|
|
249
|
+
...e
|
|
250
|
+
});
|
|
251
|
+
if (e?.moc === !1) throw Error("HeadlessRoomleSdk: planner requires moc:true");
|
|
252
|
+
await t.boot(), this._plannerMain = t, this._planner = t.getApi(), await this._planner.init(this._makeStubElement()), this._plannerReady = !0;
|
|
253
|
+
}
|
|
254
|
+
async prewarmGlbViewer(e) {
|
|
255
|
+
this._ensureInitialized();
|
|
256
|
+
let t = await S.getGlbViewer(e);
|
|
257
|
+
await t.boot(), this._glbViewerMain = t, this._glbViewer = t.getApi(), await this._glbViewer.init(this._makeStubElement()), this._glbViewerReady = !0;
|
|
258
|
+
}
|
|
259
|
+
async loadConfiguration(e, t) {
|
|
260
|
+
return this._loadIntoConfigurator(e, (e) => this._configurator.loadConfigurationById(e), t);
|
|
261
|
+
}
|
|
262
|
+
async loadConfigurableItemById(e, t) {
|
|
263
|
+
return this._loadIntoConfigurator(e, (e) => this._configurator.loadConfigurableItemById(e), t);
|
|
264
|
+
}
|
|
265
|
+
async _loadIntoConfigurator(e, t, n) {
|
|
266
|
+
return this._ensureInitialized(), this._withLoader(async () => {
|
|
267
|
+
if (this._configuratorReady || await this.prewarmConfigurator(n), this._loadedConfigurationId === e) return;
|
|
268
|
+
let { pka: r, plannerVM: i } = this._plannerReady ? this._getPlannerListenerInfo() : {};
|
|
269
|
+
r && i && r.removeConfiguratorListener(i);
|
|
270
|
+
try {
|
|
271
|
+
await this._armOnReadyForRender(), await t(e), this._loadedConfigurationId = e, this._loadedPlanId = null, this._loadedStaticItemId = null, await this._settleScene();
|
|
272
|
+
} finally {
|
|
273
|
+
r && i && r.addConfiguratorListener(i);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
async loadStaticItem(e, t) {
|
|
278
|
+
return this._ensureInitialized(), this._withLoader(async () => {
|
|
279
|
+
this._glbViewerReady || await this.prewarmGlbViewer(t), this._loadedStaticItemId !== e && (await this._armOnReadyForRender(), await this._glbViewer.loadStaticItem(e), this._suppressGlbSelfShadowing(), this._loadedStaticItemId = e, this._loadedConfigurationId = null, this._loadedPlanId = null, await this._settleScene());
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
_suppressGlbSelfShadowing() {
|
|
283
|
+
let e = this._glbViewer.getSceneManager().getScene();
|
|
284
|
+
e && e.traverse((e) => {
|
|
285
|
+
e.isMesh && (e.castShadow = !1);
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
async loadObject(e, t) {
|
|
289
|
+
if (this._ensureInitialized(), Q(e)) throw Error(`HeadlessRoomleSdk: component ids ("${e}") are not supported. Use loadConfigurableItemById, loadConfiguration, or loadPlan directly.`);
|
|
290
|
+
return Z(e) ? this.loadPlan(e, t) : X(e) ? (await (await S.getRapiAccess()).getItem(e))?.configuration ? this.loadConfigurableItemById(e, t) : this.loadStaticItem(e, t) : this.loadConfiguration(e, t);
|
|
291
|
+
}
|
|
292
|
+
async loadPlan(e, t) {
|
|
293
|
+
return this._ensureInitialized(), this._withLoader(async () => {
|
|
294
|
+
if (this._plannerReady || await this.prewarmPlanner(t), this._loadedPlanId === e) return;
|
|
295
|
+
let { pka: n, configuratorVM: r } = this._configuratorReady ? this._getConfiguratorListenerInfo() : {};
|
|
296
|
+
n && r && n.removeConfiguratorListener(r);
|
|
297
|
+
try {
|
|
298
|
+
await this._armOnReadyForRender(), await this._planner.loadPlan(e), this._loadedPlanId = e, this._loadedConfigurationId = null, this._loadedStaticItemId = null, await this._settleScene();
|
|
299
|
+
} finally {
|
|
300
|
+
n && r && n.addConfiguratorListener(r);
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
_withLoader(e) {
|
|
305
|
+
let t = this._loaderQueue.then(e);
|
|
306
|
+
return this._loaderQueue = t.then(() => {}, () => {}), t;
|
|
307
|
+
}
|
|
308
|
+
async _settleScene() {
|
|
309
|
+
this._onReadyForRenderArmed &&= (await this._onReadyForRenderArmed, null);
|
|
310
|
+
}
|
|
311
|
+
async _armOnReadyForRender() {
|
|
312
|
+
let e = await S.callbacks;
|
|
313
|
+
if (!e) {
|
|
314
|
+
this._onReadyForRenderArmed = null;
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
let t = e.onReadyForRender;
|
|
318
|
+
this._onReadyForRenderArmed = new Promise((n) => {
|
|
319
|
+
e.onReadyForRender = () => {
|
|
320
|
+
try {
|
|
321
|
+
t?.();
|
|
322
|
+
} finally {
|
|
323
|
+
e.onReadyForRender = t, n();
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
_getPlannerListenerInfo() {
|
|
329
|
+
try {
|
|
330
|
+
return {
|
|
331
|
+
pka: globalThis.__RML__DI__?.lookup?.("planner-kernel-access"),
|
|
332
|
+
plannerVM: this._planner?.getSceneManager()?.viewModel
|
|
333
|
+
};
|
|
334
|
+
} catch {
|
|
335
|
+
return {};
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
_getConfiguratorListenerInfo() {
|
|
339
|
+
try {
|
|
340
|
+
return {
|
|
341
|
+
pka: globalThis.__RML__DI__?.lookup?.("planner-kernel-access"),
|
|
342
|
+
configuratorVM: this._configurator?.getSceneManager()?.viewModel
|
|
343
|
+
};
|
|
344
|
+
} catch {
|
|
345
|
+
return {};
|
|
346
|
+
}
|
|
237
347
|
}
|
|
238
348
|
async exportGLB(e) {
|
|
239
349
|
return this._export(e, "glb");
|
|
@@ -241,32 +351,38 @@ var B = z(import.meta.url), V = {}, H = [
|
|
|
241
351
|
async exportUSDZ(e) {
|
|
242
352
|
return this._export(e, "usdz");
|
|
243
353
|
}
|
|
354
|
+
_getActiveApi() {
|
|
355
|
+
if (this._loadedPlanId) return this._planner;
|
|
356
|
+
if (this._loadedConfigurationId) return this._configurator;
|
|
357
|
+
if (this._loadedStaticItemId) return this._glbViewer;
|
|
358
|
+
throw Error("HeadlessRoomleSdk: nothing loaded — call loadPlan(), loadConfiguration(), loadConfigurableItemById(), loadStaticItem() or loadObject() first");
|
|
359
|
+
}
|
|
360
|
+
_getActiveSceneManager() {
|
|
361
|
+
return this._loadedStaticItemId ? this._glbViewer.getSceneManager() : this._getActiveApi().getSceneManager();
|
|
362
|
+
}
|
|
244
363
|
async _export(e, t) {
|
|
245
364
|
this._ensureInitialized();
|
|
246
|
-
let n = this.
|
|
365
|
+
let n = this._getActiveSceneManager(), r = t === "glb" ? await n.createExportGLB() : await n.createUSDZExport();
|
|
247
366
|
if (!r) throw Error(`${t.toUpperCase()} export produced no data`);
|
|
248
367
|
let i = r instanceof ArrayBuffer ? r : r.buffer;
|
|
249
368
|
return e && (await import("fs")).writeFileSync(e, Buffer.from(i)), { buffer: i };
|
|
250
369
|
}
|
|
251
370
|
async exportScreenshot(e, t = {}) {
|
|
252
371
|
this._ensureInitialized();
|
|
253
|
-
let n = t.
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
let c = await i.exportCanvasScreenshot(n);
|
|
261
|
-
if (r > 1 && o && s && (i.getRoomleRenderer()?.setSize(o, s), c = await this._ssaaDownscale(c, o, s)), e) {
|
|
262
|
-
let t = await import("fs"), n = c.replace(/^data:image\/\w+;base64,/, "");
|
|
372
|
+
let n = t.ssaa ?? 2, r = t.size ?? 1024, i = r * n, a = (await this._getActiveApi().preparePerspectiveImage({
|
|
373
|
+
rotationY: t.rotationY,
|
|
374
|
+
size: i,
|
|
375
|
+
preserveSceneBackground: !0
|
|
376
|
+
})).image;
|
|
377
|
+
if (n > 1 && (a = await this._ssaaDownscale(a, r, r)), e) {
|
|
378
|
+
let t = await import("fs"), n = a.replace(/^data:image\/\w+;base64,/, "");
|
|
263
379
|
t.writeFileSync(e, Buffer.from(n, "base64"));
|
|
264
380
|
}
|
|
265
|
-
return { dataUrl:
|
|
381
|
+
return { dataUrl: a };
|
|
266
382
|
}
|
|
267
383
|
async exportPerspectiveImage(e, t = {}) {
|
|
268
384
|
this._ensureInitialized();
|
|
269
|
-
let n = t.ssaa ?? 2, r = t.size ?? 1024, i = r * n, a = await this.
|
|
385
|
+
let n = t.ssaa ?? 2, r = t.size ?? 1024, i = r * n, a = await this._getActiveApi().preparePerspectiveImage({
|
|
270
386
|
...t,
|
|
271
387
|
size: i
|
|
272
388
|
}), o = a.image, s = a.width, c = a.height;
|
|
@@ -281,24 +397,24 @@ var B = z(import.meta.url), V = {}, H = [
|
|
|
281
397
|
};
|
|
282
398
|
}
|
|
283
399
|
async exportTopImage(e, t = {}) {
|
|
284
|
-
this._ensureInitialized();
|
|
285
|
-
let n = t.ssaa ?? 2,
|
|
400
|
+
if (this._ensureInitialized(), this._loadedStaticItemId) throw Error("HeadlessRoomleSdk: exportTopImage is not supported for static items");
|
|
401
|
+
let n = this._getActiveApi(), r = t.ssaa ?? 2, i = await n.prepareTopImage({
|
|
286
402
|
...t,
|
|
287
|
-
size: (t.size ?? 1024) *
|
|
403
|
+
size: (t.size ?? 1024) * r,
|
|
288
404
|
showDimensions: t.showDimensions ?? !1
|
|
289
|
-
}),
|
|
290
|
-
if (
|
|
291
|
-
let e = Math.round(
|
|
292
|
-
|
|
405
|
+
}), a = i.image, o = i.width, s = i.height;
|
|
406
|
+
if (r > 1) {
|
|
407
|
+
let e = Math.round(o / r), t = Math.round(s / r);
|
|
408
|
+
a = await this._ssaaDownscale(a, e, t), o = e, s = t;
|
|
293
409
|
}
|
|
294
410
|
if (e) {
|
|
295
|
-
let t = await import("fs"), n =
|
|
411
|
+
let t = await import("fs"), n = a.replace(/^data:image\/\w+;base64,/, "");
|
|
296
412
|
t.writeFileSync(e, Buffer.from(n, "base64"));
|
|
297
413
|
}
|
|
298
414
|
return {
|
|
299
|
-
dataUrl:
|
|
300
|
-
width:
|
|
301
|
-
height:
|
|
415
|
+
dataUrl: a,
|
|
416
|
+
width: o,
|
|
417
|
+
height: s
|
|
302
418
|
};
|
|
303
419
|
}
|
|
304
420
|
async _ssaaDownscale(e, t, n) {
|
|
@@ -312,13 +428,13 @@ var B = z(import.meta.url), V = {}, H = [
|
|
|
312
428
|
return this._planner;
|
|
313
429
|
}
|
|
314
430
|
async destroy() {
|
|
315
|
-
this._configuratorMain && this._configuratorMain.destroy(), this._plannerMain && this._plannerMain.destroy();
|
|
431
|
+
this._configuratorMain && this._configuratorMain.destroy(), this._plannerMain && this._plannerMain.destroy(), this._glbViewerMain && this._glbViewerMain.destroy();
|
|
316
432
|
}
|
|
317
433
|
_ensureInitialized() {
|
|
318
434
|
if (!this._initialized) throw Error("HeadlessRoomleSdk not initialized. Call HeadlessRoomleSdk.create() first.");
|
|
319
435
|
}
|
|
320
436
|
};
|
|
321
437
|
//#endregion
|
|
322
|
-
export { t as CONFIGURATION_TYPE, e as CORE_PERMISSION_TO_DELETE,
|
|
438
|
+
export { t as CONFIGURATION_TYPE, e as CORE_PERMISSION_TO_DELETE, ee as Configurator, m as ConfiguratorUiCallbacks, b as FloorPlanElementViewModel, L as GlbViewer, o as GlobalCallback, N as HI_CONTEXT_ACTION, $ as HeadlessRoomleSdk, E as IdbManager, w as Main, j as MeasurementLinePlanElementViewModel, A as PLAN_ELEMENT_CHANGE_TYPES, i as PlanElementViewModel, u as PlanObjectViewModel, F as Planner, y as RapiAccess, R as RoomDesignerApi, l as RoomleConfigurator, I as RoomleGLBViewer, C as RoomleLightSource, g as RoomlePlanner, M as RoomlePlannerUiCallback, S as RoomleSdk, c as StaticPlanObjectViewModel, s as WallPlanElementViewModel, r as createExtObj, p as createExtObjId, O as getCatalogIdFromConfigurationHash, f as isExtObjId, a as isExternalObject, h as isSafari, d as removeExtObjIdPrefix };
|
|
323
439
|
|
|
324
440
|
//# sourceMappingURL=roomle-headless.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roomle-headless.js","names":[],"sources":["../../packages/headless-core/src/headless-script-loader.ts","../../packages/headless-core/src/stubs.ts","../../packages/headless-core/src/headless-dom-helper.ts","../../packages/headless-core/src/headless-data-syncer.ts","../../packages/headless-core/src/headless-sdk.ts"],"sourcesContent":["/**\n * Replaces the browser ScriptLoader for headless mode.\n * Instead of injecting <script> tags, directly imports the Emscripten JS modules.\n */\nimport { createRequire } from 'module';\nimport type { Context } from '../../common-core/src/di/context';\nimport { getHeadlessWasmPath } from '../../common-core/src/static-files/roomle-core';\n\n// createRequire is needed because the Emscripten kernel files are CommonJS\n// and must be loaded synchronously\nconst _require = createRequire(import.meta.url);\n\nlet _idCache: { [key: string]: boolean } = {};\n\n// Maps a .wasm filename found in the Emscripten factory's source to its global name.\n// Each Emscripten factory references its own .wasm file (e.g. ConfiguratorKernel.wasm).\nconst WASM_TO_GLOBAL: Array<\n [wasmFile: string, globalName: string, modulePath: string]\n> = [\n [\n 'ConfiguratorKernel.wasm',\n 'ConfiguratorKernel',\n 'roomle-core-hsc/wasm_modern/ConfiguratorKernel.js',\n ],\n [\n 'RoomleCore.wasm',\n 'RoomleCore',\n 'roomle-core-hsc/wasm_modern/RoomleCore.js',\n ],\n [\n 'RoomleToolsCore.wasm',\n 'RoomleToolsCore',\n 'roomle-core-hsc/wasm_modern/RoomleToolsCore.js',\n ],\n];\n\nexport default class HeadlessScriptLoader implements Context {\n public _creator_: string;\n\n constructor(creator: string) {\n this._creator_ = creator;\n }\n\n public async fetch(url: string, options: { id: string }) {\n if (_idCache[options.id]) {\n return;\n }\n\n // In Bun, Vite's ?no-inline?url imports resolve to the module's default\n // export (a function) rather than a URL string. Handle both cases.\n if (typeof url === 'function') {\n this._registerFactory(url);\n _idCache[options.id] = true;\n return;\n }\n\n const entry = this._resolveEntry(url);\n if (entry) {\n const [, globalName, modulePath] = entry;\n // If url is an absolute filesystem path (from getHeadlessWasmPath),\n // require it directly. Otherwise fall back to the module specifier\n // (works from source where roomle-core-hsc is in node_modules).\n const pathToLoad = url.startsWith('/') ? url : modulePath;\n const mod = _require(pathToLoad);\n (globalThis as any)[globalName] = mod.default || mod;\n _idCache[options.id] = true;\n }\n }\n\n // Identify an Emscripten factory function by checking its source for the\n // unique .wasm filename it references, then register it on globalThis\n // under the name the kernel-access classes expect (e.g. window.ConfiguratorKernel).\n private _registerFactory(factory: () => void) {\n const source = factory.toString();\n for (const [wasmFile, globalName] of WASM_TO_GLOBAL) {\n if (source.includes(wasmFile)) {\n (globalThis as any)[globalName] = factory;\n return;\n }\n }\n console.warn(\n 'HeadlessScriptLoader: Could not identify Emscripten factory function',\n );\n }\n\n private _resolveEntry(url: string) {\n for (const entry of WASM_TO_GLOBAL) {\n const [wasmFile, globalName] = entry;\n const baseName = globalName; // e.g. \"ConfiguratorKernel\"\n if (url.includes(baseName) || url.includes(wasmFile)) {\n return entry;\n }\n }\n // Fallback: looser matching for generic URLs\n if (url.includes('configurator')) {\n return WASM_TO_GLOBAL[0];\n }\n if (url.includes('planner')) {\n return WASM_TO_GLOBAL[1];\n }\n if (url.includes('tools')) {\n return WASM_TO_GLOBAL[2];\n }\n console.warn(\n `HeadlessScriptLoader: Could not resolve module for URL: ${url}`,\n );\n return null;\n }\n\n public loadScripts(scripts: Array<{ id: string; name: string }>) {\n const promises = scripts.map((script) =>\n this.fetch(script.name, { id: script.id }),\n );\n return Promise.all(promises);\n }\n\n public resolveKernelPaths(type: 'configurator' | 'planner' | 'tools'): {\n wasm: string;\n loader: string;\n } {\n return getHeadlessWasmPath(type);\n }\n\n public cleanUp() {\n _idCache = {};\n }\n}\n","export const noop = () => {};\n","/**\n * Stub DomHelper for headless mode.\n * Returns fixed dimensions since we don't render to a real canvas.\n */\nimport { Vector2 } from 'three';\nimport { noop } from './stubs';\nimport type {\n LifeCycleCallbacks,\n LifeCycleManager,\n} from '../../common-core/src/life-cycle-manager';\nimport type { Context } from '../../common-core/src/di/context';\n\nexport default class HeadlessDomHelper implements LifeCycleCallbacks, Context {\n public _creator_: string;\n\n // Manual DI lookup instead of @inject decorator (avoids legacy/TC39 decorator mismatch)\n private get _lifeCycleManager(): LifeCycleManager | undefined {\n return (globalThis as any).__RML__DI__?.lookup(\n 'life-cycle-manager',\n this._creator_,\n );\n }\n\n private _width: number;\n private _height: number;\n private _stubElement: any;\n\n get element(): any {\n return this._stubElement;\n }\n\n constructor(creator: string, width = 1024, height = 768) {\n this._creator_ = creator;\n this._width = width;\n this._height = height;\n\n const w = this._width;\n const h = this._height;\n this._stubElement = {\n clientWidth: w,\n clientHeight: h,\n appendChild() {},\n removeChild() {},\n style: {},\n classList: {\n add() {},\n remove() {},\n contains() {\n return false;\n },\n },\n setAttribute() {},\n getAttribute(): string | null {\n return null;\n },\n children: [] as any[],\n getBoundingClientRect() {\n return {\n x: 0,\n y: 0,\n width: w,\n height: h,\n top: 0,\n left: 0,\n bottom: h,\n right: w,\n };\n },\n addEventListener() {},\n removeEventListener() {},\n dispatchEvent() {\n return true;\n },\n offsetWidth: w,\n offsetHeight: h,\n scrollWidth: w,\n scrollHeight: h,\n contains() {\n return false;\n },\n };\n }\n\n public setDomElement(_element: any) {\n noop();\n }\n\n public getClientDimensions() {\n return new Vector2(this._width, this._height);\n }\n\n public getAspectRatio() {\n return this._width / this._height;\n }\n\n public ensureCanvasFocus() {}\n public reset() {}\n public pause() {}\n public resume() {}\n public destroy() {}\n}\n","/**\n * Replaces the Worker-based DataSyncer with a no-op for headless mode.\n * In headless mode, assets are loaded on-demand via RapiAccess rather than\n * being pre-synced with a Web Worker.\n */\nimport type { RapiId } from '@roomle/web-sdk';\nimport { noop } from './stubs';\nimport type { Context } from '../../common-core/src/di/context';\n\nexport default class HeadlessDataSyncer implements Context {\n public _creator_: string;\n\n constructor(creator: string) {\n this._creator_ = creator;\n }\n\n public start(_catalogId: RapiId) {\n return Promise.resolve();\n }\n\n public syncCatalog(_catalogId: RapiId): Promise<void> {\n return Promise.resolve();\n }\n\n public syncFloorTag(_tagId: RapiId) {\n return Promise.resolve();\n }\n\n public syncTypeChangeTag(_tagId: RapiId) {\n return Promise.resolve();\n }\n\n public _syncTypeChangeTag(_tagId: RapiId): Promise<any> {\n return Promise.resolve();\n }\n\n public getIsCatalogSynced(_catalogId: RapiId) {\n return false;\n }\n\n public onCommand(_command: number, _conversationId: number, _data: any) {\n noop();\n }\n\n public requestAsset(url: string, _urlAsFallback: boolean = false): string {\n return url;\n }\n\n public setAlwaysUseCache(_alwaysUseCache: boolean): void {\n noop();\n }\n\n public preFillAssetCache(_key: string, _url: string) {\n noop();\n }\n}\n","/**\n * Main entry point for the headless Roomle SDK.\n * Provides the ability to run the Roomle web-sdk in Node.js/Bun\n * for loading configurations/plans and exporting them to GLB/USDZ.\n */\nimport HeadlessScriptLoader from './headless-script-loader';\nimport HeadlessDomHelper from './headless-dom-helper';\nimport HeadlessDataSyncer from './headless-data-syncer';\nimport CommonKernelAccess from '../../common-core/src/services/common-kernel-access';\nimport type {\n RoomlePlanner,\n Planner,\n RoomleConfigurator,\n Configurator,\n InitDataDefinition,\n GlobalInitDataDefinition,\n RapiId,\n} from '../../index';\nimport { RoomleSdk } from '../../index';\nimport {\n Container,\n DependencyInjectionAssignment,\n DI_TYPE,\n} from '../../common-core/src/di/container';\nimport { INJECTABLES } from '../../common-core/src/di/injectables';\n\nexport interface HeadlessInitData\n extends Partial<InitDataDefinition>,\n Partial<GlobalInitDataDefinition> {\n configuratorId: string;\n /** Canvas width in pixels. Defaults to 1024. */\n width?: number;\n /** Canvas height in pixels. Defaults to 768. */\n height?: number;\n}\n\nexport interface ExportResult {\n buffer: ArrayBuffer;\n}\n\nexport interface ImageExportOptions {\n /** Supersampling anti-aliasing factor. Defaults to 2. */\n ssaa?: number;\n}\n\nexport interface ScreenshotExportOptions extends ImageExportOptions {\n /** JPEG quality (0–1). Defaults to 1. */\n quality?: number;\n}\n\nexport interface PerspectiveImageExportOptions extends ImageExportOptions {\n /** Output image size in pixels. Defaults to 1024. */\n size?: number;\n showDimensions?: boolean;\n rotationY?: number;\n}\n\nexport interface TopImageExportOptions extends ImageExportOptions {\n /** Output image size in pixels. Defaults to 1024. */\n size?: number;\n showDimensions?: boolean;\n}\n\nexport class HeadlessRoomleSdk {\n private _planner: RoomlePlanner;\n private _plannerMain: Planner;\n private _configurator: RoomleConfigurator;\n private _configuratorMain: Configurator;\n private _initialized = false;\n private _width = 1024;\n private _height = 768;\n\n static async create(initData: HeadlessInitData): Promise<HeadlessRoomleSdk> {\n const instance = new HeadlessRoomleSdk();\n await instance._init(initData);\n return instance;\n }\n\n private async _init(initData: HeadlessInitData) {\n this._width = initData.width ?? 1024;\n this._height = initData.height ?? 768;\n\n // Register headless service overrides BEFORE the DI container initializes.\n // This monkey-patches Container so that headless overrides always win,\n // even after boot() re-registers the default INJECTABLES.\n this._registerHeadlessServices(this._width, this._height);\n\n await RoomleSdk.setGlobalInitData({\n configuratorId: initData.configuratorId,\n locale: initData.locale,\n // @ts-ignore -- tenant is untyped, but we still need it.\n tenant: initData.tenant,\n overrideCountry: initData.overrideCountry,\n animateCamera: false,\n });\n\n this._initialized = true;\n }\n\n private _registerHeadlessServices(width: number, height: number) {\n // Create the DI container early. When roomle-dependency-injection.ts is\n // later loaded transitively, its _ensureContainer() checks if __RML__DI__\n // already exists and skips creating a new one — so we must register the\n // full INJECTABLES here ourselves.\n const container = new Container();\n (globalThis as any).__RML__DI__ = container;\n\n // Capture width/height in a subclass so the DI container instantiates\n // HeadlessDomHelper with the correct dimensions (DI only passes `creator`).\n class SizedHeadlessDomHelper extends HeadlessDomHelper {\n constructor(creator: string) {\n super(creator, width, height);\n }\n }\n\n const headlessOverrides = [\n new DependencyInjectionAssignment(\n 'script-loader',\n HeadlessScriptLoader,\n DI_TYPE.CONTEXT,\n ),\n new DependencyInjectionAssignment(\n 'dom-helper',\n SizedHeadlessDomHelper,\n DI_TYPE.CONTEXT,\n ),\n new DependencyInjectionAssignment('data-syncer', HeadlessDataSyncer),\n ];\n\n // Monkey-patch addDependencyInjectionAssignments so that every time\n // the SDK registers its default INJECTABLES (during boot()), our headless\n // overrides are re-applied on top. This ensures headless services always win.\n const originalAdd = Container.prototype.addDependencyInjectionAssignments;\n Container.prototype.addDependencyInjectionAssignments = function (\n injections: DependencyInjectionAssignment[],\n ) {\n originalAdd.call(this, injections);\n originalAdd.call(this, headlessOverrides);\n };\n\n // Wrap kernel callbacks with a safety Proxy so that exceptions thrown\n // from JS callbacks invoked by C++ (via Embind) are caught and logged\n // rather than propagating into C++ which would call std::terminate → abort().\n (CommonKernelAccess.prototype as any)._buildCallbackTarget = function () {\n const target = this;\n return new Proxy(target, {\n get(_, prop) {\n const val = (target as any)[prop];\n if (typeof val === 'function') {\n return function (...args: any[]) {\n try {\n return val.apply(target, args);\n } catch (e) {\n console.error(\n `[Headless] Kernel callback '${String(prop)}' threw:`,\n e,\n );\n }\n };\n }\n return val;\n },\n });\n };\n\n // Register all default INJECTABLES + headless overrides.\n // The monkey-patch ensures headless overrides are applied on top.\n container.addDependencyInjectionAssignments(INJECTABLES);\n }\n\n async loadConfiguration(\n configurationId: RapiId,\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n this._ensureInitialized();\n\n const configuratorModule = await RoomleSdk.getConfigurator(initData);\n await configuratorModule.boot();\n this._configuratorMain = configuratorModule;\n this._configurator = configuratorModule.getApi();\n\n const stubElement = {\n clientWidth: this._width,\n clientHeight: this._height,\n appendChild() {},\n removeChild() {},\n style: {},\n classList: { add() {} },\n };\n await this._configurator.init(stubElement as any);\n\n await this._configurator.loadConfigurableItemById(configurationId);\n }\n\n async loadPlan(\n planId: string,\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n this._ensureInitialized();\n\n const plannerModule = await RoomleSdk.getPlanner(initData);\n await plannerModule.boot();\n this._plannerMain = plannerModule;\n this._planner = plannerModule.getApi();\n\n const stubElement = {\n clientWidth: this._width,\n clientHeight: this._height,\n appendChild() {},\n removeChild() {},\n style: {},\n classList: { add() {} },\n };\n await this._planner.init(stubElement as any);\n\n await this._planner.loadPlan(planId);\n }\n\n async exportGLB(outputPath?: string): Promise<ExportResult> {\n return this._export(outputPath, 'glb');\n }\n\n async exportUSDZ(outputPath?: string): Promise<ExportResult> {\n return this._export(outputPath, 'usdz');\n }\n\n private async _export(\n outputPath: string | undefined,\n type: 'glb' | 'usdz',\n ): Promise<ExportResult> {\n this._ensureInitialized();\n\n const sm = this._configurator.getSceneManager();\n const buffer =\n type === 'glb' ? await sm.createExportGLB() : await sm.createUSDZExport();\n\n if (!buffer) {\n throw new Error(`${type.toUpperCase()} export produced no data`);\n }\n\n // The buffer is either ArrayBuffer (GLB) or Uint8Array (USDZ).\n // Extract the underlying ArrayBuffer in both cases.\n const arrayBuffer =\n buffer instanceof ArrayBuffer\n ? buffer\n : ((buffer as Uint8Array).buffer as ArrayBuffer);\n\n if (outputPath) {\n const fs = await import('fs');\n fs.writeFileSync(outputPath, Buffer.from(arrayBuffer));\n }\n\n return { buffer: arrayBuffer };\n }\n\n async exportScreenshot(\n outputPath?: string,\n options: ScreenshotExportOptions = {},\n ): Promise<{ dataUrl: string }> {\n this._ensureInitialized();\n\n const quality = options.quality ?? 1;\n const ssaa = options.ssaa ?? 2;\n const sm = this._configurator.getSceneManager();\n const renderer = sm.getRenderer();\n if (!renderer) {\n throw new Error('HeadlessRoomleSdk: renderer is not available');\n }\n\n let originalWidth: number | undefined;\n let originalHeight: number | undefined;\n\n // Temporarily resize renderer for SSAA supersampling\n if (ssaa > 1) {\n const roomleRenderer = sm.getRoomleRenderer();\n const canvas = renderer.domElement;\n originalWidth = canvas.width;\n originalHeight = canvas.height;\n roomleRenderer?.setSize(originalWidth! * ssaa, originalHeight! * ssaa);\n }\n\n let dataUrl: string = await sm.exportCanvasScreenshot(quality);\n\n // Restore original size and downscale\n if (ssaa > 1 && originalWidth && originalHeight) {\n sm.getRoomleRenderer()?.setSize(originalWidth, originalHeight);\n dataUrl = await this._ssaaDownscale(\n dataUrl,\n originalWidth,\n originalHeight,\n );\n }\n\n if (outputPath) {\n const fs = await import('fs');\n const base64 = dataUrl.replace(/^data:image\\/\\w+;base64,/, '');\n fs.writeFileSync(outputPath, Buffer.from(base64, 'base64'));\n }\n\n return { dataUrl };\n }\n\n async exportPerspectiveImage(\n outputPath?: string,\n options: PerspectiveImageExportOptions = {},\n ): Promise<{ dataUrl: string; width: number; height: number }> {\n this._ensureInitialized();\n\n const ssaa = options.ssaa ?? 2;\n const targetSize = options.size ?? 1024;\n const renderSize = targetSize * ssaa;\n\n const result = await this._configurator.preparePerspectiveImage({\n ...options,\n size: renderSize,\n });\n\n let finalDataUrl = result.image;\n let finalWidth = result.width;\n let finalHeight = result.height;\n\n // Downscale with SSAA if rendering at higher resolution, achieves antialiasing effect.\n if (ssaa > 1) {\n finalDataUrl = await this._ssaaDownscale(\n finalDataUrl,\n targetSize,\n targetSize,\n );\n finalWidth = targetSize;\n finalHeight = targetSize;\n }\n\n if (outputPath) {\n const fs = await import('fs');\n const base64 = finalDataUrl.replace(/^data:image\\/\\w+;base64,/, '');\n fs.writeFileSync(outputPath, Buffer.from(base64, 'base64'));\n }\n\n return { dataUrl: finalDataUrl, width: finalWidth, height: finalHeight };\n }\n\n async exportTopImage(\n outputPath?: string,\n options: TopImageExportOptions = {},\n ): Promise<{ dataUrl: string; width: number; height: number }> {\n this._ensureInitialized();\n\n const ssaa = options.ssaa ?? 2;\n const result = await this._configurator.prepareTopImage({\n ...options,\n size: (options.size ?? 1024) * ssaa,\n showDimensions: options.showDimensions ?? false,\n });\n\n let finalDataUrl = result.image;\n let finalWidth = result.width;\n let finalHeight = result.height;\n\n if (ssaa > 1) {\n const targetWidth = Math.round(finalWidth / ssaa);\n const targetHeight = Math.round(finalHeight / ssaa);\n finalDataUrl = await this._ssaaDownscale(\n finalDataUrl,\n targetWidth,\n targetHeight,\n );\n finalWidth = targetWidth;\n finalHeight = targetHeight;\n }\n\n if (outputPath) {\n const fs = await import('fs');\n const base64 = finalDataUrl.replace(/^data:image\\/\\w+;base64,/, '');\n fs.writeFileSync(outputPath, Buffer.from(base64, 'base64'));\n }\n\n return { dataUrl: finalDataUrl, width: finalWidth, height: finalHeight };\n }\n\n /** Downscale a data URL image to target dimensions using high-quality filtering. */\n private async _ssaaDownscale(\n dataUrl: string,\n targetWidth: number,\n targetHeight: number,\n ): Promise<string> {\n const { createCanvas, loadImage } = await import('@napi-rs/canvas');\n const imgBuffer = Buffer.from(\n dataUrl.replace(/^data:image\\/\\w+;base64,/, ''),\n 'base64',\n );\n const img = await loadImage(imgBuffer);\n const outCanvas = createCanvas(targetWidth, targetHeight);\n const ctx = outCanvas.getContext('2d');\n (ctx as any).imageSmoothingEnabled = true;\n (ctx as any).imageSmoothingQuality = 'high';\n ctx.drawImage(img, 0, 0, targetWidth, targetHeight);\n return outCanvas.toDataURL('image/png');\n }\n\n getConfiguratorApi() {\n return this._configurator;\n }\n\n getPlannerApi() {\n return this._planner;\n }\n\n async destroy() {\n if (this._configuratorMain) {\n this._configuratorMain.destroy();\n }\n if (this._plannerMain) {\n this._plannerMain.destroy();\n }\n }\n\n private _ensureInitialized() {\n if (!this._initialized) {\n throw new Error(\n 'HeadlessRoomleSdk not initialized. Call HeadlessRoomleSdk.create() first.',\n );\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"roomle-headless.js","names":[],"sources":["../../packages/headless-core/src/headless-script-loader.ts","../../packages/headless-core/src/stubs.ts","../../packages/headless-core/src/headless-dom-helper.ts","../../packages/headless-core/src/headless-data-syncer.ts","../../packages/headless-core/src/headless-planner-kernel-access.ts","../../packages/headless-core/src/headless-kernel-callback-guard.ts","../../packages/headless-core/src/headless-tween-stub.ts","../../../common/src/utils/id-inferrer.ts","../../packages/headless-core/src/headless-sdk.ts"],"sourcesContent":["/**\n * Replaces the browser ScriptLoader for headless mode.\n * Instead of injecting <script> tags, directly imports the Emscripten JS modules.\n */\nimport { createRequire } from 'module';\nimport type { Context } from '../../common-core/src/di/context';\nimport { getHeadlessWasmPath } from '../../common-core/src/static-files/roomle-core';\n\n// createRequire is needed because the Emscripten kernel files are CommonJS\n// and must be loaded synchronously\nconst _require = createRequire(import.meta.url);\n\nlet _idCache: { [key: string]: boolean } = {};\n\n// Maps a .wasm filename found in the Emscripten factory's source to its global name.\n// Each Emscripten factory references its own .wasm file (e.g. ConfiguratorKernel.wasm).\nconst WASM_TO_GLOBAL: Array<\n [wasmFile: string, globalName: string, modulePath: string]\n> = [\n [\n 'ConfiguratorKernel.wasm',\n 'ConfiguratorKernel',\n 'roomle-core-hsc/wasm_modern/ConfiguratorKernel.js',\n ],\n [\n 'RoomleCore.wasm',\n 'RoomleCore',\n 'roomle-core-hsc/wasm_modern/RoomleCore.js',\n ],\n [\n 'RoomleToolsCore.wasm',\n 'RoomleToolsCore',\n 'roomle-core-hsc/wasm_modern/RoomleToolsCore.js',\n ],\n];\n\nexport default class HeadlessScriptLoader implements Context {\n public _creator_: string;\n\n constructor(creator: string) {\n this._creator_ = creator;\n }\n\n public async fetch(url: string, options: { id: string }) {\n if (_idCache[options.id]) {\n return;\n }\n\n // In Bun, Vite's ?no-inline?url imports resolve to the module's default\n // export (a function) rather than a URL string. Handle both cases.\n if (typeof url === 'function') {\n this._registerFactory(url);\n _idCache[options.id] = true;\n return;\n }\n\n const entry = this._resolveEntry(url);\n if (entry) {\n const [, globalName, modulePath] = entry;\n // If url is an absolute filesystem path (from getHeadlessWasmPath),\n // require it directly. Otherwise fall back to the module specifier\n // (works from source where roomle-core-hsc is in node_modules).\n const pathToLoad = url.startsWith('/') ? url : modulePath;\n const mod = _require(pathToLoad);\n (globalThis as any)[globalName] = mod.default || mod;\n _idCache[options.id] = true;\n }\n }\n\n // Identify an Emscripten factory function by checking its source for the\n // unique .wasm filename it references, then register it on globalThis\n // under the name the kernel-access classes expect (e.g. window.ConfiguratorKernel).\n private _registerFactory(factory: () => void) {\n const source = factory.toString();\n for (const [wasmFile, globalName] of WASM_TO_GLOBAL) {\n if (source.includes(wasmFile)) {\n (globalThis as any)[globalName] = factory;\n return;\n }\n }\n console.warn(\n 'HeadlessScriptLoader: Could not identify Emscripten factory function',\n );\n }\n\n private _resolveEntry(url: string) {\n for (const entry of WASM_TO_GLOBAL) {\n const [wasmFile, globalName] = entry;\n const baseName = globalName; // e.g. \"ConfiguratorKernel\"\n if (url.includes(baseName) || url.includes(wasmFile)) {\n return entry;\n }\n }\n // Fallback: looser matching for generic URLs\n if (url.includes('configurator')) {\n return WASM_TO_GLOBAL[0];\n }\n if (url.includes('planner')) {\n return WASM_TO_GLOBAL[1];\n }\n if (url.includes('tools')) {\n return WASM_TO_GLOBAL[2];\n }\n console.warn(\n `HeadlessScriptLoader: Could not resolve module for URL: ${url}`,\n );\n return null;\n }\n\n public loadScripts(scripts: Array<{ id: string; name: string }>) {\n const promises = scripts.map((script) =>\n this.fetch(script.name, { id: script.id }),\n );\n return Promise.all(promises);\n }\n\n public resolveKernelPaths(type: 'configurator' | 'planner' | 'tools'): {\n wasm: string;\n loader: string;\n } {\n return getHeadlessWasmPath(type);\n }\n\n public cleanUp() {\n _idCache = {};\n }\n}\n","export const noop = () => {};\n","/**\n * Stub DomHelper for headless mode.\n * Returns fixed dimensions since we don't render to a real canvas.\n */\nimport { Vector2 } from 'three';\nimport { noop } from './stubs';\nimport type {\n LifeCycleCallbacks,\n LifeCycleManager,\n} from '../../common-core/src/life-cycle-manager';\nimport type { Context } from '../../common-core/src/di/context';\n\nexport default class HeadlessDomHelper implements LifeCycleCallbacks, Context {\n public _creator_: string;\n\n // Manual DI lookup instead of @inject decorator (avoids legacy/TC39 decorator mismatch)\n private get _lifeCycleManager(): LifeCycleManager | undefined {\n return (globalThis as any).__RML__DI__?.lookup(\n 'life-cycle-manager',\n this._creator_,\n );\n }\n\n private _width: number;\n private _height: number;\n private _stubElement: any;\n\n get element(): any {\n return this._stubElement;\n }\n\n constructor(creator: string, width = 1024, height = 768) {\n this._creator_ = creator;\n this._width = width;\n this._height = height;\n\n const w = this._width;\n const h = this._height;\n this._stubElement = {\n clientWidth: w,\n clientHeight: h,\n appendChild() {},\n removeChild() {},\n style: {},\n classList: {\n add() {},\n remove() {},\n contains() {\n return false;\n },\n },\n setAttribute() {},\n getAttribute(): string | null {\n return null;\n },\n children: [] as any[],\n getBoundingClientRect() {\n return {\n x: 0,\n y: 0,\n width: w,\n height: h,\n top: 0,\n left: 0,\n bottom: h,\n right: w,\n };\n },\n addEventListener() {},\n removeEventListener() {},\n dispatchEvent() {\n return true;\n },\n offsetWidth: w,\n offsetHeight: h,\n scrollWidth: w,\n scrollHeight: h,\n contains() {\n return false;\n },\n };\n }\n\n public setDomElement(_element: any) {\n noop();\n }\n\n public getClientDimensions() {\n return new Vector2(this._width, this._height);\n }\n\n public getAspectRatio() {\n return this._width / this._height;\n }\n\n public ensureCanvasFocus() {}\n public reset() {}\n public pause() {}\n public resume() {}\n public destroy() {}\n}\n","/**\n * Replaces the Worker-based DataSyncer with a no-op for headless mode.\n * In headless mode, assets are loaded on-demand via RapiAccess rather than\n * being pre-synced with a Web Worker.\n */\nimport type { RapiId } from '@roomle/web-sdk';\nimport { noop } from './stubs';\nimport type { Context } from '../../common-core/src/di/context';\n\nexport default class HeadlessDataSyncer implements Context {\n public _creator_: string;\n\n constructor(creator: string) {\n this._creator_ = creator;\n }\n\n public start(_catalogId: RapiId) {\n return Promise.resolve();\n }\n\n public syncCatalog(_catalogId: RapiId): Promise<void> {\n return Promise.resolve();\n }\n\n public syncFloorTag(_tagId: RapiId) {\n return Promise.resolve();\n }\n\n public syncTypeChangeTag(_tagId: RapiId) {\n return Promise.resolve();\n }\n\n public _syncTypeChangeTag(_tagId: RapiId): Promise<any> {\n return Promise.resolve();\n }\n\n public getIsCatalogSynced(_catalogId: RapiId) {\n return false;\n }\n\n public onCommand(_command: number, _conversationId: number, _data: any) {\n noop();\n }\n\n public requestAsset(url: string, _urlAsFallback: boolean = false): string {\n return url;\n }\n\n public setAlwaysUseCache(_alwaysUseCache: boolean): void {\n noop();\n }\n\n public preFillAssetCache(_key: string, _url: string) {\n noop();\n }\n}\n","/**\n * Headless override of `PlannerKernelAccess`.\n */\nimport { KERNEL_TYPE } from '../../common-core/src/services/common-kernel-access';\nimport PlannerKernelAccess from '../../planner-core/src/services/planner-kernel-access';\n\nexport default class HeadlessPlannerKernelAccess extends PlannerKernelAccess {\n protected _getScriptLoaderKernelId(kernelType: KERNEL_TYPE): string {\n return kernelType === KERNEL_TYPE.PLANNER ? 'kernel-planner' : 'kernel';\n }\n}\n","import type { KernelCallbackGuard } from '../../common-core/src/services/kernel-callback-guard';\n\n/**\n * Headless implementation: wraps the kernel callback target in a Proxy so that\n * any JS exception thrown inside a callback invoked from C++ (via Embind) is\n * caught and logged rather than propagating into C++, which would call\n * std::terminate and abort the process.\n */\nexport default class HeadlessKernelCallbackGuard\n implements KernelCallbackGuard\n{\n wrap<T extends object>(target: T): T {\n return new Proxy(target, {\n get(t: any, prop) {\n const val = t[prop];\n if (typeof val === 'function') {\n return function (...args: any[]) {\n try {\n return val.apply(t, args);\n } catch (e) {\n console.error(\n `[Headless] Kernel callback '${String(prop)}' threw:`,\n e,\n );\n }\n };\n }\n return val;\n },\n });\n }\n}\n","// Prevents tween effects from happening in headless mode, we don't ever want\n// things to fade in or out headlessly because it creates delays and causes\n// elements to show up white or half-visible as they tween in while taking a screenshot.\n\ninterface MinimalTween {\n end?: () => void;\n}\n\ninterface MinimalTweenGroup {\n add(tween: MinimalTween): void;\n remove(_tween: MinimalTween): void;\n removeAll(): void;\n getAll(): MinimalTween[];\n update(_time?: number): void;\n}\n\nconst noopGroup: MinimalTweenGroup = {\n add(tween) {\n // Synchronously fast-forward. Wrapped in try/catch so a single\n // misbehaving tween can't poison the whole queue — at worst that\n // tween silently doesn't apply, exactly as in browser mode if it\n // never advances.\n try {\n tween.end?.();\n } catch {\n // ignore\n }\n },\n remove() {},\n removeAll() {},\n getAll() {\n return [];\n },\n update() {},\n};\n\nexport const installHeadlessTweenStub = (): void => {\n const target = window as unknown as { TWEEN?: MinimalTweenGroup };\n // Always overwrite — if a previous SDK boot left the real Group here,\n // we want our noop in its place for the new instance.\n target.TWEEN = noopGroup;\n};\n","import type { RapiId, RapiPlanSnapshotId } from '@roomle/web-sdk';\n\nexport const isIdAnItem = (id: string) => id.split(':').length - 1 === 1;\n\nexport const isIdAPlan = (id: string) => id.split(':').length - 1 <= 0;\n\nexport const isIdAComponent = (id: string) =>\n id ? id.startsWith('component@') : false;\n\nexport const isIdAConfigurationString = (id: string) =>\n id.startsWith('{') && id.endsWith('}');\n\nexport const isPlanSnapshotId = (\n id: string | RapiId,\n): id is RapiPlanSnapshotId => id.startsWith('ps_');\n","/**\n * Main entry point for the headless Roomle SDK.\n * Provides the ability to run the Roomle web-sdk in Node.js/Bun\n * for loading configurations/plans and exporting them to GLB/USDZ.\n */\nimport HeadlessScriptLoader from './headless-script-loader';\nimport HeadlessDomHelper from './headless-dom-helper';\nimport HeadlessDataSyncer from './headless-data-syncer';\nimport HeadlessPlannerKernelAccess from './headless-planner-kernel-access';\nimport HeadlessKernelCallbackGuard from './headless-kernel-callback-guard';\nimport { installHeadlessTweenStub } from './headless-tween-stub';\nimport type {\n RoomlePlanner,\n Planner,\n RoomleConfigurator,\n Configurator,\n InitDataDefinition,\n GlobalInitDataDefinition,\n RapiId,\n GlbViewer,\n RoomleGLBViewer,\n} from '../../index';\nimport { RoomleSdk } from '../../index';\nimport {\n Container,\n DependencyInjectionAssignment,\n DI_TYPE,\n} from '../../common-core/src/di/container';\nimport { INJECTABLES } from '../../common-core/src/di/injectables';\nimport {\n isIdAComponent,\n isIdAPlan,\n isIdAnItem,\n} from '#/common/src/utils/id-inferrer';\nimport type { Mesh } from 'three';\n\nexport interface HeadlessInitData\n extends Partial<InitDataDefinition>,\n Partial<GlobalInitDataDefinition> {\n configuratorId: string;\n /** Canvas width in pixels. Defaults to 1024. */\n width?: number;\n /** Canvas height in pixels. Defaults to 768. */\n height?: number;\n}\n\nexport interface ExportResult {\n buffer: ArrayBuffer;\n}\n\nexport interface ImageExportOptions {\n /** Supersampling anti-aliasing factor. Defaults to 2. */\n ssaa?: number;\n /** Output image size in pixels. Defaults to 1024. */\n size?: number;\n}\n\n/** Mixin for image exports that frame the scene from a rotatable camera. */\nexport interface RotatableImageExportOptions {\n /** Camera rotation around the Y axis, in radians. */\n rotationY?: number;\n}\n\nexport interface ScreenshotExportOptions\n extends ImageExportOptions,\n RotatableImageExportOptions {\n /** JPEG quality (0–1). Defaults to 1. */\n quality?: number;\n}\n\nexport interface PerspectiveImageExportOptions\n extends ImageExportOptions,\n RotatableImageExportOptions {\n showDimensions?: boolean;\n}\n\nexport interface TopImageExportOptions extends ImageExportOptions {\n showDimensions?: boolean;\n}\n\nexport class HeadlessRoomleSdk {\n private _planner: RoomlePlanner;\n private _plannerMain: Planner;\n private _configurator: RoomleConfigurator;\n private _configuratorMain: Configurator;\n private _glbViewer: RoomleGLBViewer;\n private _glbViewerMain: GlbViewer;\n private _initialized = false;\n private _configuratorReady = false;\n private _plannerReady = false;\n private _glbViewerReady = false;\n private _loadedConfigurationId: RapiId | null = null;\n private _loadedPlanId: string | null = null;\n private _loadedStaticItemId: string | null = null;\n private _width = 1024;\n private _height = 768;\n private _loaderQueue: Promise<void> = Promise.resolve();\n\n /**\n * Create and initialize a headless SDK instance.\n * @param initData Configurator id plus optional canvas size and global init fields.\n * @returns Initialized SDK instance.\n */\n public static async create(\n initData: HeadlessInitData,\n ): Promise<HeadlessRoomleSdk> {\n const instance = new HeadlessRoomleSdk();\n await instance._init(initData);\n return instance;\n }\n\n private async _init(initData: HeadlessInitData) {\n this._width = initData.width ?? 1024;\n this._height = initData.height ?? 768;\n\n installHeadlessTweenStub();\n\n // Register headless service overrides BEFORE the DI container initializes.\n // This monkey-patches Container so that headless overrides always win,\n // even after boot() re-registers the default INJECTABLES.\n this._registerHeadlessServices(this._width, this._height);\n\n await RoomleSdk.setGlobalInitData({\n configuratorId: initData.configuratorId,\n locale: initData.locale,\n // @ts-ignore -- tenant is untyped, but we still need it.\n tenant: initData.tenant,\n overrideCountry: initData.overrideCountry,\n animateCamera: false,\n });\n\n this._initialized = true;\n }\n\n private _registerHeadlessServices(width: number, height: number) {\n // Create the DI container early. When roomle-dependency-injection.ts is\n // later loaded transitively, its _ensureContainer() checks if __RML__DI__\n // already exists and skips creating a new one — so we must register the\n // full INJECTABLES here ourselves.\n const container = new Container();\n (globalThis as any).__RML__DI__ = container;\n\n // Capture width/height in a subclass so the DI container instantiates\n // HeadlessDomHelper with the correct dimensions (DI only passes `creator`).\n class SizedHeadlessDomHelper extends HeadlessDomHelper {\n constructor(creator: string) {\n super(creator, width, height);\n }\n }\n\n // override: true marks each key so that subsequent boot() calls that\n // re-register the default INJECTABLES cannot overwrite these entries.\n const headlessOverrides = [\n new DependencyInjectionAssignment(\n 'script-loader',\n HeadlessScriptLoader,\n DI_TYPE.CONTEXT,\n true,\n ),\n new DependencyInjectionAssignment(\n 'dom-helper',\n SizedHeadlessDomHelper,\n DI_TYPE.CONTEXT,\n true,\n ),\n new DependencyInjectionAssignment(\n 'data-syncer',\n HeadlessDataSyncer,\n DI_TYPE.GLOBAL,\n true,\n ),\n new DependencyInjectionAssignment(\n 'planner-kernel-access',\n HeadlessPlannerKernelAccess,\n DI_TYPE.GLOBAL,\n true,\n ),\n new DependencyInjectionAssignment(\n 'kernel-callback-guard',\n HeadlessKernelCallbackGuard,\n DI_TYPE.GLOBAL,\n true,\n ),\n ];\n\n // Register defaults first, then overlay headless overrides.\n // The override: true flag on each headless entry prevents later boot() calls\n // from overwriting them when they re-register the default INJECTABLES.\n container.addDependencyInjectionAssignments(INJECTABLES);\n container.addDependencyInjectionAssignments(headlessOverrides);\n }\n\n private _makeStubElement() {\n return {\n clientWidth: this._width,\n clientHeight: this._height,\n appendChild() {},\n removeChild() {},\n style: {},\n classList: { add() {} },\n };\n }\n\n /**\n * Boot and initialize the configurator module ahead of first load.\n * @param initData Optional per-module init overrides.\n */\n public async prewarmConfigurator(\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n this._ensureInitialized();\n const configuratorModule = await RoomleSdk.getConfigurator(initData);\n await configuratorModule.boot();\n this._configuratorMain = configuratorModule;\n this._configurator = configuratorModule.getApi();\n await this._configurator.init(this._makeStubElement() as any);\n this._configuratorReady = true;\n }\n\n /**\n * Boot and initialize the planner module ahead of first load.\n * @param initData Optional per-module init overrides.\n */\n public async prewarmPlanner(\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n this._ensureInitialized();\n const plannerModule = await RoomleSdk.getPlanner({\n moc: true,\n ...initData,\n });\n if (initData?.moc === false) {\n throw new Error('HeadlessRoomleSdk: planner requires moc:true');\n }\n await plannerModule.boot();\n this._plannerMain = plannerModule;\n this._planner = plannerModule.getApi();\n await this._planner.init(this._makeStubElement() as any);\n this._plannerReady = true;\n }\n\n /**\n * Boot and initialize the GLB viewer module ahead of first load.\n * @param initData Optional per-module init overrides.\n */\n public async prewarmGlbViewer(\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n this._ensureInitialized();\n const glbModule = await RoomleSdk.getGlbViewer(initData);\n await glbModule.boot();\n this._glbViewerMain = glbModule;\n this._glbViewer = glbModule.getApi();\n await this._glbViewer.init(this._makeStubElement() as any);\n this._glbViewerReady = true;\n }\n\n /**\n * Load a saved configuration via the RAPI `/configurations/` endpoint.\n * @param configurationId Multi-segment id like `catalog:item:HASH`.\n * @param initData Optional per-module init overrides for prewarm.\n */\n public async loadConfiguration(\n configurationId: RapiId,\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n return this._loadIntoConfigurator(\n configurationId,\n (id) => this._configurator.loadConfigurationById(id),\n initData,\n );\n }\n\n /**\n * Load a configurable item via the RAPI `/items/` endpoint.\n * @param itemId Single-segment id like `catalog:item`.\n * @param initData Optional per-module init overrides for prewarm.\n */\n public async loadConfigurableItemById(\n itemId: RapiId,\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n return this._loadIntoConfigurator(\n itemId,\n (id) => this._configurator.loadConfigurableItemById(id),\n initData,\n );\n }\n\n private async _loadIntoConfigurator(\n id: RapiId,\n load: (id: RapiId) => Promise<unknown>,\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n this._ensureInitialized();\n return this._withLoader(async () => {\n if (!this._configuratorReady) {\n await this.prewarmConfigurator(initData);\n }\n if (this._loadedConfigurationId === id) {\n return;\n }\n // Temporarily remove the planner view model from PKA listeners so it\n // doesn't process configurator kernel callbacks (avoids listener\n // cross-contamination when both configurator and planner are pre-warmed).\n const { pka, plannerVM } = this._plannerReady\n ? this._getPlannerListenerInfo()\n : {};\n if (pka && plannerVM) {\n pka.removeConfiguratorListener(plannerVM);\n }\n try {\n await this._armOnReadyForRender();\n await load(id);\n this._loadedConfigurationId = id;\n this._loadedPlanId = null;\n this._loadedStaticItemId = null;\n await this._settleScene();\n } finally {\n if (pka && plannerVM) {\n pka.addConfiguratorListener(plannerVM);\n }\n }\n });\n }\n\n /**\n * Load a static (non-configurable) item via the GLB viewer.\n * @param staticItemId Catalog item id whose RAPI record has no `configuration`.\n * @param initData Optional per-module init overrides for prewarm.\n */\n public async loadStaticItem(\n staticItemId: string,\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n this._ensureInitialized();\n return this._withLoader(async () => {\n if (!this._glbViewerReady) {\n await this.prewarmGlbViewer(initData);\n }\n if (this._loadedStaticItemId === staticItemId) {\n return;\n }\n await this._armOnReadyForRender();\n await this._glbViewer.loadStaticItem(staticItemId);\n this._suppressGlbSelfShadowing();\n this._loadedStaticItemId = staticItemId;\n this._loadedConfigurationId = null;\n this._loadedPlanId = null;\n await this._settleScene();\n });\n }\n\n /**\n * Temporary workaround:\n * GLB-loaded scenes commonly contain hundreds of thousands of triangles\n * (high-poly furniture/cars). With the default 1024² shadow map those\n * triangles cast a self-shadow pattern back onto themselves that the\n * shadow comparison can't resolve cleanly — it appears as a dense\n * triangle/herringbone overlay covering every PBR-shaded surface\n * (visible on flat-coloured car bodies, wood slats, etc.). The\n * artifact is specific to headless's GL backend; in the browser the\n * same scene renders fine.\n *\n * Walking the freshly-loaded scene and clearing `castShadow` on every\n * mesh removes the cause of the acne while keeping `receiveShadow`,\n * so static items still pick up shadows from external casters and\n * full PBR direct-light shading is preserved.\n */\n private _suppressGlbSelfShadowing(): void {\n const sceneManager = this._glbViewer.getSceneManager();\n const root = sceneManager.getScene();\n\n if (!root) {\n return;\n }\n\n root.traverse((node) => {\n if ((node as Mesh).isMesh) {\n (node as Mesh).castShadow = false;\n }\n });\n }\n\n /**\n * Auto-dispatch by id shape using the shared id-inferrer utilities so\n * detection stays in lock-step with the UI's `SdkConnector.loadObject`:\n * - `component@…` → not supported in headless, throws\n * - 0 colons (plan id) → {@link loadPlan}\n * - 1 colon (item id) → {@link loadStaticItem} if RAPI says the\n * item has no `configuration`, otherwise\n * {@link loadConfigurableItemById}\n * - 2+ colons (config id) → {@link loadConfiguration}\n *\n * RAPI lookup failures during the item branch are propagated rather than\n * swallowed — a transient 5xx routing the call to the wrong loader would\n * surface as an unrelated downstream error.\n */\n async loadObject(\n id: string,\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n this._ensureInitialized();\n if (isIdAComponent(id)) {\n throw new Error(\n `HeadlessRoomleSdk: component ids (\"${id}\") are not supported. Use loadConfigurableItemById, loadConfiguration, or loadPlan directly.`,\n );\n }\n if (isIdAPlan(id)) {\n return this.loadPlan(id, initData);\n }\n if (isIdAnItem(id)) {\n const rapi = await RoomleSdk.getRapiAccess();\n const item = await rapi.getItem(id as RapiId);\n const isStatic = !item?.configuration;\n if (isStatic) {\n return this.loadStaticItem(id, initData);\n }\n return this.loadConfigurableItemById(id as RapiId, initData);\n }\n return this.loadConfiguration(id as RapiId, initData);\n }\n\n /**\n * Load a plan into the planner.\n * @param planId Plan id (no colons).\n * @param initData Optional per-module init overrides for prewarm.\n */\n async loadPlan(\n planId: string,\n initData?: Partial<InitDataDefinition>,\n ): Promise<void> {\n this._ensureInitialized();\n return this._withLoader(async () => {\n if (!this._plannerReady) {\n await this.prewarmPlanner(initData);\n }\n // Skip reload if the same plan is already loaded.\n if (this._loadedPlanId === planId) {\n return;\n }\n // Temporarily remove the configurator view model from PKA listeners so it\n // doesn't process planner kernel callbacks.\n const { pka, configuratorVM } = this._configuratorReady\n ? this._getConfiguratorListenerInfo()\n : {};\n if (pka && configuratorVM) {\n pka.removeConfiguratorListener(configuratorVM);\n }\n try {\n await this._armOnReadyForRender();\n await this._planner.loadPlan(planId);\n this._loadedPlanId = planId;\n // A freshly-loaded plan scene invalidates any previously-loaded configuration.\n this._loadedConfigurationId = null;\n this._loadedStaticItemId = null;\n await this._settleScene();\n } finally {\n if (pka && configuratorVM) {\n pka.addConfiguratorListener(configuratorVM);\n }\n }\n });\n }\n\n /**\n * Serialises concurrent load operations using a promise-chain queue.\n * Each call chains its task onto the previous queue tail so they run\n * one at a time — listener mutations never overlap across an await.\n * Errors in one task do not stall subsequent ones (the queue tail is\n * always advanced in a settled state).\n */\n private _withLoader<T>(task: () => Promise<T>): Promise<T> {\n const next = this._loaderQueue.then(task);\n // Advance the queue unconditionally so a failing task never blocks\n // future callers.\n this._loaderQueue = next.then(\n () => {},\n () => {},\n );\n return next;\n }\n\n /**\n * Wait for the active scene to fire its onReadyForRender callback —\n * fired by each scene manager once `_itemsLoaded` (planner) /\n * `loadConfiguration` (configurator) / `loadStaticItem` (GLB viewer)\n * has finished constructing the scene and queued its materials. The\n * callback is armed via {@link _armOnReadyForRender} *before* the load\n * begins so synchronous firings (the GLB viewer does this) are still\n * caught.\n */\n private async _settleScene(): Promise<void> {\n if (!this._onReadyForRenderArmed) {\n return;\n }\n await this._onReadyForRenderArmed;\n this._onReadyForRenderArmed = null;\n }\n\n /**\n * Pre-arms an onReadyForRender listener on the *global* callback (shared\n * across configurator/planner/GLB viewer) so that it captures even\n * synchronous firings during the upcoming load. Restores the previous\n * callback after firing. Using the global callback rather than each\n * module's api.callbacks is necessary because the GLB viewer only fires\n * the global one ([glb-viewer-scene-manager.ts:355](packages/web-sdk/packages/glb-viewer-core/src/webgl/glb-viewer-scene-manager.ts:355)).\n */\n private async _armOnReadyForRender(): Promise<void> {\n const globalCallback = (await RoomleSdk.callbacks) as unknown as {\n onReadyForRender?: () => void;\n };\n if (!globalCallback) {\n this._onReadyForRenderArmed = null;\n return;\n }\n const previous = globalCallback.onReadyForRender;\n this._onReadyForRenderArmed = new Promise<void>((resolve) => {\n globalCallback.onReadyForRender = () => {\n try {\n previous?.();\n } finally {\n globalCallback.onReadyForRender = previous;\n resolve();\n }\n };\n });\n }\n\n private _onReadyForRenderArmed: Promise<void> | null = null;\n\n private _getPlannerListenerInfo() {\n try {\n const pka = (globalThis as any).__RML__DI__?.lookup?.(\n 'planner-kernel-access',\n );\n const plannerVM = this._planner?.getSceneManager()?.viewModel;\n return { pka, plannerVM };\n } catch {\n return {};\n }\n }\n\n private _getConfiguratorListenerInfo() {\n try {\n const pka = (globalThis as any).__RML__DI__?.lookup?.(\n 'planner-kernel-access',\n );\n const configuratorVM = this._configurator?.getSceneManager()?.viewModel;\n return { pka, configuratorVM };\n } catch {\n return {};\n }\n }\n\n /**\n * Export the active scene as GLB.\n * @param outputPath Optional file path to write the buffer to.\n * @returns The GLB bytes as an ArrayBuffer.\n */\n async exportGLB(outputPath?: string): Promise<ExportResult> {\n return this._export(outputPath, 'glb');\n }\n\n /**\n * Export the active scene as USDZ.\n * @param outputPath Optional file path to write the buffer to.\n * @returns The USDZ bytes as an ArrayBuffer.\n */\n async exportUSDZ(outputPath?: string): Promise<ExportResult> {\n return this._export(outputPath, 'usdz');\n }\n\n /**\n * Returns the active top-level API (planner or configurator) based on what\n * was last loaded. `loadPlan()` and `loadConfiguration()` are mutually\n * exclusive — each one nulls the other's id — so this resolves cleanly.\n */\n private _getActiveApi():\n | RoomlePlanner\n | RoomleConfigurator\n | RoomleGLBViewer {\n if (this._loadedPlanId) {\n return this._planner;\n }\n if (this._loadedConfigurationId) {\n return this._configurator;\n }\n if (this._loadedStaticItemId) {\n return this._glbViewer;\n }\n throw new Error(\n 'HeadlessRoomleSdk: nothing loaded — call loadPlan(), loadConfiguration(), loadConfigurableItemById(), loadStaticItem() or loadObject() first',\n );\n }\n\n /**\n * Returns the scene manager of whichever module is active. All exporters\n * route through here so plan-mode and config-mode share a single code path.\n */\n private _getActiveSceneManager() {\n if (this._loadedStaticItemId) {\n // The GLB viewer doesn't expose a sceneManager getter; reach into the\n // private field. The methods we use here (createExportGLB,\n // createUSDZExport, exportCanvasScreenshot) are shared with the\n // configurator/planner scene managers.\n return this._glbViewer.getSceneManager();\n }\n return this._getActiveApi().getSceneManager();\n }\n\n private async _export(\n outputPath: string | undefined,\n type: 'glb' | 'usdz',\n ): Promise<ExportResult> {\n this._ensureInitialized();\n\n const activeSceneManager = this._getActiveSceneManager();\n const buffer =\n type === 'glb'\n ? await activeSceneManager.createExportGLB()\n : await activeSceneManager.createUSDZExport();\n\n if (!buffer) {\n throw new Error(`${type.toUpperCase()} export produced no data`);\n }\n\n // The buffer is either ArrayBuffer (GLB) or Uint8Array (USDZ).\n // Extract the underlying ArrayBuffer in both cases.\n const arrayBuffer =\n buffer instanceof ArrayBuffer\n ? buffer\n : ((buffer as Uint8Array).buffer as ArrayBuffer);\n\n if (outputPath) {\n const fs = await import('fs');\n fs.writeFileSync(outputPath, Buffer.from(arrayBuffer));\n }\n\n return { buffer: arrayBuffer };\n }\n\n /**\n * Render a perspective screenshot preserving the scene background.\n * @param outputPath Optional file path to write the PNG to.\n * @param options ssaa, size, quality, rotationY.\n * @returns Data URL of the rendered image.\n */\n public async exportScreenshot(\n outputPath?: string,\n options: ScreenshotExportOptions = {},\n ): Promise<{ dataUrl: string }> {\n this._ensureInitialized();\n\n // Reuse the deterministic preparePerspectiveImage pipeline — it clones\n // the live camera and frames it synchronously off the bounding box,\n // sidestepping the zoomToFitBounds tween race that the previous\n // exportCanvasScreenshot path suffered from. The only behavioural\n // difference vs. exportPerspectiveImage is preserveSceneBackground:true,\n // so the scene's sky/floor/skybox stays visible.\n const ssaa = options.ssaa ?? 2;\n const targetSize = options.size ?? 1024;\n const renderSize = targetSize * ssaa;\n\n const result = await this._getActiveApi().preparePerspectiveImage({\n rotationY: options.rotationY,\n size: renderSize,\n preserveSceneBackground: true,\n });\n\n let dataUrl = result.image;\n if (ssaa > 1) {\n dataUrl = await this._ssaaDownscale(dataUrl, targetSize, targetSize);\n }\n\n if (outputPath) {\n const fs = await import('fs');\n const base64 = dataUrl.replace(/^data:image\\/\\w+;base64,/, '');\n fs.writeFileSync(outputPath, Buffer.from(base64, 'base64'));\n }\n\n return { dataUrl };\n }\n\n /**\n * Render a framed perspective image of the scene.\n * @param outputPath Optional file path to write the PNG to.\n * @param options ssaa, size, showDimensions, rotationY.\n * @returns Data URL plus final image dimensions.\n */\n public async exportPerspectiveImage(\n outputPath?: string,\n options: PerspectiveImageExportOptions = {},\n ): Promise<{ dataUrl: string; width: number; height: number }> {\n this._ensureInitialized();\n\n const ssaa = options.ssaa ?? 2;\n const targetSize = options.size ?? 1024;\n const renderSize = targetSize * ssaa;\n\n const result = await this._getActiveApi().preparePerspectiveImage({\n ...options,\n size: renderSize,\n });\n\n let finalDataUrl = result.image;\n let finalWidth = result.width;\n let finalHeight = result.height;\n\n // Downscale with SSAA if rendering at higher resolution, achieves antialiasing effect.\n if (ssaa > 1) {\n finalDataUrl = await this._ssaaDownscale(\n finalDataUrl,\n targetSize,\n targetSize,\n );\n finalWidth = targetSize;\n finalHeight = targetSize;\n }\n\n if (outputPath) {\n const fs = await import('fs');\n const base64 = finalDataUrl.replace(/^data:image\\/\\w+;base64,/, '');\n fs.writeFileSync(outputPath, Buffer.from(base64, 'base64'));\n }\n\n return { dataUrl: finalDataUrl, width: finalWidth, height: finalHeight };\n }\n\n /**\n * Render a top-down image of the scene. Not supported for static items.\n * @param outputPath Optional file path to write the PNG to.\n * @param options ssaa, size, showDimensions.\n * @returns Data URL plus final image dimensions.\n */\n public async exportTopImage(\n outputPath?: string,\n options: TopImageExportOptions = {},\n ): Promise<{ dataUrl: string; width: number; height: number }> {\n this._ensureInitialized();\n\n if (this._loadedStaticItemId) {\n throw new Error(\n 'HeadlessRoomleSdk: exportTopImage is not supported for static items',\n );\n }\n const api = this._getActiveApi() as RoomlePlanner | RoomleConfigurator;\n\n const ssaa = options.ssaa ?? 2;\n const result = await api.prepareTopImage({\n ...options,\n size: (options.size ?? 1024) * ssaa,\n showDimensions: options.showDimensions ?? false,\n });\n\n let finalDataUrl = result.image;\n let finalWidth = result.width;\n let finalHeight = result.height;\n\n if (ssaa > 1) {\n const targetWidth = Math.round(finalWidth / ssaa);\n const targetHeight = Math.round(finalHeight / ssaa);\n finalDataUrl = await this._ssaaDownscale(\n finalDataUrl,\n targetWidth,\n targetHeight,\n );\n finalWidth = targetWidth;\n finalHeight = targetHeight;\n }\n\n if (outputPath) {\n const fs = await import('fs');\n const base64 = finalDataUrl.replace(/^data:image\\/\\w+;base64,/, '');\n fs.writeFileSync(outputPath, Buffer.from(base64, 'base64'));\n }\n\n return { dataUrl: finalDataUrl, width: finalWidth, height: finalHeight };\n }\n\n /** Downscale a data URL image to target dimensions using high-quality filtering. */\n private async _ssaaDownscale(\n dataUrl: string,\n targetWidth: number,\n targetHeight: number,\n ): Promise<string> {\n const { createCanvas, loadImage } = await import('@napi-rs/canvas');\n const imgBuffer = Buffer.from(\n dataUrl.replace(/^data:image\\/\\w+;base64,/, ''),\n 'base64',\n );\n const img = await loadImage(imgBuffer);\n const outCanvas = createCanvas(targetWidth, targetHeight);\n const ctx = outCanvas.getContext('2d');\n (ctx as any).imageSmoothingEnabled = true;\n (ctx as any).imageSmoothingQuality = 'high';\n ctx.drawImage(img, 0, 0, targetWidth, targetHeight);\n return outCanvas.toDataURL('image/png');\n }\n\n getConfiguratorApi() {\n return this._configurator;\n }\n\n getPlannerApi() {\n return this._planner;\n }\n\n /** Destroy any prewarmed configurator, planner, and GLB viewer modules. */\n public async destroy() {\n if (this._configuratorMain) {\n this._configuratorMain.destroy();\n }\n if (this._plannerMain) {\n this._plannerMain.destroy();\n }\n if (this._glbViewerMain) {\n this._glbViewerMain.destroy();\n }\n }\n\n private _ensureInitialized() {\n if (!this._initialized) {\n throw new Error(\n 'HeadlessRoomleSdk not initialized. Call HeadlessRoomleSdk.create() first.',\n );\n }\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { d as e } from "./three.core-
|
|
1
|
+
import { d as e } from "./three.core-K1JzUaep.mjs";
|
|
2
2
|
//#region packages/common-core/src/roomle-renderer.ts
|
|
3
3
|
var t = /* @__PURE__ */ function(e) {
|
|
4
4
|
return e[e.Mode3D = 0] = "Mode3D", e[e.Mode2D = 1] = "Mode2D", e;
|
|
@@ -46,4 +46,4 @@ var t = /* @__PURE__ */ function(e) {
|
|
|
46
46
|
//#endregion
|
|
47
47
|
export { n, t };
|
|
48
48
|
|
|
49
|
-
//# sourceMappingURL=roomle-renderer-
|
|
49
|
+
//# sourceMappingURL=roomle-renderer-BgT28pfp.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roomle-renderer-
|
|
1
|
+
{"version":3,"file":"roomle-renderer-BgT28pfp.mjs","names":[],"sources":["../../packages/common-core/src/roomle-renderer.ts"],"sourcesContent":["import type { Camera, Object3D, Scene, Vector2, WebGLRenderer } from 'three';\nimport { Box3 } from 'three';\nimport type { Enumify } from '#/common/src/utils/types';\nimport type { CAMERA_TYPE } from './cameracontrol/camera-type';\nimport type { WebGPURenderer } from 'three/webgpu';\nimport type {\n CustomShadingParameters,\n SceneShadingType,\n} from './webgl/renderer/shading-settings';\nimport type {\n LutImageDefinition,\n OutlineCustomParameters,\n QualityLevel,\n QualityMap,\n} from './webgl/renderer/scene-renderer';\n\nexport type GenericRoomleRenderer = RoomleRenderer<\n WebGLRenderer | WebGPURenderer\n>;\n\nexport enum PlannerRenderMode {\n Mode3D,\n Mode2D,\n}\n\nexport abstract class RoomleRenderer<\n RendererType extends WebGLRenderer | WebGPURenderer,\n> {\n public _creator_: string;\n public renderer: RendererType;\n protected isConfiguratorMode: boolean = true;\n protected isCameraMoving: boolean = false;\n protected cameraType: Enumify<typeof CAMERA_TYPE>;\n protected shadowNeedsUpdate: boolean = false;\n protected boundingBox: Box3 = new Box3();\n protected boundingBoxNeedsUpdate: boolean = false;\n\n protected constructor(creator: string, renderer: RendererType) {\n this._creator_ = creator;\n this.renderer = renderer;\n }\n\n public get isConfiguring(): boolean {\n return this.isConfiguratorMode;\n }\n\n public dispose(): void {\n this.renderer.dispose();\n }\n\n public setSize(width: number, height: number): void {\n this.renderer.setSize(width, height);\n }\n\n public getSize(target: Vector2): Vector2 {\n return this.renderer.getSize(target);\n }\n\n public setCameraType(cameraType: Enumify<typeof CAMERA_TYPE>) {\n this.cameraType = cameraType;\n }\n\n public movingCameraStarts(): void {\n this.isCameraMoving = true;\n }\n\n public movingCameraStops(): void {\n this.isCameraMoving = false;\n }\n\n public forceShadowUpdates(_updateBakedGroundShadow: boolean): void {\n this.shadowNeedsUpdate = true;\n }\n\n public clear() {\n this.renderer.clear();\n }\n\n public updateBounds(geometryBounds: Box3) {\n this.boundingBox.copy(geometryBounds);\n this.boundingBoxNeedsUpdate = true;\n }\n\n public switchToConfigurator(): void {\n this.isConfiguratorMode = true;\n }\n\n public switchToPlanner(_renderMode: PlannerRenderMode) {\n this.isConfiguratorMode = false;\n }\n\n public abstract setShadingType(shadingType: SceneShadingType): void;\n\n public abstract setAutoQuality(autoQuality: boolean): void;\n\n public abstract setQualityLevel(qualityLevel: QualityLevel): void;\n\n public abstract getQualityLevel(): QualityLevel;\n\n public abstract setQualityMap(qualityMap: QualityMap): void;\n\n public abstract setCustomShadingParameters(\n customShadingParameters?: CustomShadingParameters,\n customShadingParametersMoc?: CustomShadingParameters,\n ): void;\n\n public abstract setCustomOutlineParameters(\n outlineCustomParameters: OutlineCustomParameters,\n ): void;\n\n public abstract loadLutImages(luts: LutImageDefinition[]): void;\n\n public abstract render(scene: Scene, camera: Camera): void;\n\n public abstract showGUI(updateCallback: () => void): void;\n\n public abstract setOnQualityLevelChangeCallback(\n callback: (qualityLevel: QualityLevel) => void,\n ): void;\n\n public abstract clearCache(): void;\n\n public abstract highlightObjects(selectedMeshes: Object3D[]): void;\n\n public abstract setGroundShadow(enabled: boolean): void;\n\n public abstract enableUiInteractionMode(): void;\n\n public abstract disableUiInteractionMode(): void;\n}\n"],"mappings":";;AAoBA,IAAY,IAAL,yBAAA,GAAA;QACL,EAAA,EAAA,SAAA,KAAA,UACA,EAAA,EAAA,SAAA,KAAA;KACD,EAEqB,IAAtB,MAEE;CAUA,YAAsB,GAAiB,GAAwB;AAE7D,4BATsC,0BACJ,6BAEG,uBACT,IAAI,GAAM,gCACI,IAG1C,KAAK,YAAY,GACjB,KAAK,WAAW;;CAGlB,IAAW,gBAAyB;AAClC,SAAO,KAAK;;CAGd,UAAuB;AACrB,OAAK,SAAS,SAAS;;CAGzB,QAAe,GAAe,GAAsB;AAClD,OAAK,SAAS,QAAQ,GAAO,EAAO;;CAGtC,QAAe,GAA0B;AACvC,SAAO,KAAK,SAAS,QAAQ,EAAO;;CAGtC,cAAqB,GAAyC;AAC5D,OAAK,aAAa;;CAGpB,qBAAkC;AAChC,OAAK,iBAAiB;;CAGxB,oBAAiC;AAC/B,OAAK,iBAAiB;;CAGxB,mBAA0B,GAAyC;AACjE,OAAK,oBAAoB;;CAG3B,QAAe;AACb,OAAK,SAAS,OAAO;;CAGvB,aAAoB,GAAsB;AAExC,EADA,KAAK,YAAY,KAAK,EAAe,EACrC,KAAK,yBAAyB;;CAGhC,uBAAoC;AAClC,OAAK,qBAAqB;;CAG5B,gBAAuB,GAAgC;AACrD,OAAK,qBAAqB"}
|