@preference-sl/pref-viewer 2.1.1 → 2.1.3
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/package.json +1 -1
- package/src/index.js +45 -27
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
* viewer.setAttribute("model", "https://example.com/models/anotherModel.glb");
|
|
37
37
|
*
|
|
38
38
|
* -----------------------------------------------------------------------------
|
|
39
|
-
* Implementation code below with
|
|
39
|
+
* Implementation code below with updated preprocessUrl
|
|
40
40
|
* -----------------------------------------------------------------------------
|
|
41
41
|
*/
|
|
42
42
|
|
|
@@ -60,14 +60,17 @@ class PrefViewer extends HTMLElement {
|
|
|
60
60
|
this._createCanvas();
|
|
61
61
|
this._wrapCanvas();
|
|
62
62
|
|
|
63
|
-
//
|
|
63
|
+
// These will be set in _initializeBabylon()
|
|
64
64
|
this.engine = null;
|
|
65
65
|
this.scene = null;
|
|
66
66
|
this.camera = null;
|
|
67
67
|
this.hemiLight = null;
|
|
68
68
|
this.dirLight = null;
|
|
69
|
-
this.modelUrl = null;
|
|
70
69
|
this._onWindowResize = null;
|
|
70
|
+
|
|
71
|
+
// modelUrl might be provided via attribute before connectedCallback
|
|
72
|
+
this.modelUrl = null;
|
|
73
|
+
this._hasInitialized = false;
|
|
71
74
|
}
|
|
72
75
|
|
|
73
76
|
static get observedAttributes() {
|
|
@@ -75,17 +78,20 @@ class PrefViewer extends HTMLElement {
|
|
|
75
78
|
}
|
|
76
79
|
|
|
77
80
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
78
|
-
console.log(`PrefViewer: attributeChangedCallback - ${name}
|
|
81
|
+
console.log(`PrefViewer: attributeChangedCallback - ${name} -> ${newValue}`);
|
|
79
82
|
if (name === "model" && newValue) {
|
|
80
83
|
this.modelUrl = newValue;
|
|
81
84
|
console.log(`PrefViewer: modelUrl set to ${this.modelUrl}`);
|
|
82
|
-
|
|
85
|
+
// Only reload if initialization has already happened
|
|
86
|
+
if (this._hasInitialized) {
|
|
87
|
+
this._reloadModel();
|
|
88
|
+
}
|
|
83
89
|
}
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
connectedCallback() {
|
|
87
93
|
console.log("PrefViewer: connectedCallback");
|
|
88
|
-
//
|
|
94
|
+
// 1) Determine modelUrl now that element is connected
|
|
89
95
|
if (!this.hasAttribute("model")) {
|
|
90
96
|
this.modelUrl = new URL("./models/patata.gltf", import.meta.url).href;
|
|
91
97
|
console.log(`PrefViewer: no model attribute, defaulting to ${this.modelUrl}`);
|
|
@@ -93,7 +99,15 @@ class PrefViewer extends HTMLElement {
|
|
|
93
99
|
this.modelUrl = this.getAttribute("model");
|
|
94
100
|
console.log(`PrefViewer: model attribute present, using ${this.modelUrl}`);
|
|
95
101
|
}
|
|
102
|
+
|
|
103
|
+
// 2) Initialize Babylon (engine + scene + camera + lights + hooks)
|
|
96
104
|
this._initializeBabylon();
|
|
105
|
+
|
|
106
|
+
// 3) Mark that initialization is done
|
|
107
|
+
this._hasInitialized = true;
|
|
108
|
+
|
|
109
|
+
// 4) Load whatever modelUrl we have
|
|
110
|
+
this._reloadModel();
|
|
97
111
|
}
|
|
98
112
|
|
|
99
113
|
disconnectedCallback() {
|
|
@@ -127,28 +141,39 @@ class PrefViewer extends HTMLElement {
|
|
|
127
141
|
|
|
128
142
|
_initializeBabylon() {
|
|
129
143
|
console.log("PrefViewer: _initializeBabylon - creating engine and scene");
|
|
130
|
-
|
|
144
|
+
|
|
145
|
+
// 1) Create the Babylon engine & scene
|
|
131
146
|
this.engine = new Engine(this.canvas, true, { alpha: true });
|
|
132
147
|
this.scene = new Scene(this.engine);
|
|
133
148
|
this.scene.clearColor = new Color4(1, 1, 1, 1);
|
|
134
149
|
|
|
135
|
-
// 2) Hook into Babylon’s GLTF loader so
|
|
150
|
+
// 2) Hook into Babylon’s GLTF loader so that any URIs starting with "blob:…"
|
|
151
|
+
// get stripped off before we check for an absolute "https://".
|
|
136
152
|
console.log("PrefViewer: Adding preprocessUrl hook");
|
|
137
153
|
SceneLoader.OnPluginActivatedObservable.add((plugin) => {
|
|
138
154
|
console.log(`PrefViewer: Plugin activated - ${plugin.name}`);
|
|
139
155
|
if (plugin.name === "gltf" || plugin.name === "gltf2") {
|
|
140
156
|
plugin.preprocessUrl = (url) => {
|
|
141
|
-
//
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
157
|
+
// a) If the loader already prepended "blob:…", strip it out.
|
|
158
|
+
// Regex explanation: ^blob:(?:file|https?|ftp):\/\/[^\/]+\/(.*)
|
|
159
|
+
// basically removes the entire "blob:http://localhost:3000/" prefix.
|
|
160
|
+
const stripped = url.replace(
|
|
161
|
+
/^blob:(?:http|https|file):\/\/[^\/]+\/(.+)/i,
|
|
162
|
+
"$1"
|
|
163
|
+
);
|
|
164
|
+
// b) Normalize backslashes "\" → forward slashes "/"
|
|
165
|
+
const fixedSlashes = stripped.replace(/\\/g, "/");
|
|
166
|
+
console.log(
|
|
167
|
+
`PrefViewer: preprocessUrl received "${url}", stripped to "${stripped}", normalized to "${fixedSlashes}"`
|
|
168
|
+
);
|
|
169
|
+
// c) If it now starts with "http://" or "https://", return it as an absolute URL:
|
|
170
|
+
if (/^https?:\/\//i.test(fixedSlashes)) {
|
|
171
|
+
console.log(`PrefViewer: preprocessUrl returning absolute URL "${fixedSlashes}"`);
|
|
172
|
+
return fixedSlashes;
|
|
148
173
|
}
|
|
149
|
-
// Otherwise,
|
|
150
|
-
console.log(`PrefViewer: preprocessUrl returning relative URL "${
|
|
151
|
-
return
|
|
174
|
+
// d) Otherwise, return the relative path (Babylon will resolve it relative to the blob if needed)
|
|
175
|
+
console.log(`PrefViewer: preprocessUrl returning relative URL "${fixedSlashes}"`);
|
|
176
|
+
return fixedSlashes;
|
|
152
177
|
};
|
|
153
178
|
}
|
|
154
179
|
});
|
|
@@ -158,11 +183,11 @@ class PrefViewer extends HTMLElement {
|
|
|
158
183
|
this._createCamera();
|
|
159
184
|
this._createLights();
|
|
160
185
|
|
|
161
|
-
// 4) Hook up input/event handlers
|
|
186
|
+
// 4) Hook up input/event handlers (e.g. wheel-to-zoom)
|
|
162
187
|
console.log("PrefViewer: _setupEventListeners");
|
|
163
188
|
this._setupEventListeners();
|
|
164
189
|
|
|
165
|
-
// 5) Start render loop
|
|
190
|
+
// 5) Start Babylon’s render loop
|
|
166
191
|
console.log("PrefViewer: Starting render loop");
|
|
167
192
|
this.engine.runRenderLoop(() => {
|
|
168
193
|
if (this.scene) {
|
|
@@ -174,10 +199,6 @@ class PrefViewer extends HTMLElement {
|
|
|
174
199
|
this.engine.resize();
|
|
175
200
|
};
|
|
176
201
|
window.addEventListener("resize", this._onWindowResize);
|
|
177
|
-
|
|
178
|
-
// 6) Load the initial model (if modelUrl is already set)
|
|
179
|
-
console.log("PrefViewer: _initializeBabylon calling _reloadModel");
|
|
180
|
-
this._reloadModel();
|
|
181
202
|
}
|
|
182
203
|
|
|
183
204
|
_createCamera() {
|
|
@@ -196,7 +217,6 @@ class PrefViewer extends HTMLElement {
|
|
|
196
217
|
|
|
197
218
|
_createLights() {
|
|
198
219
|
console.log("PrefViewer: _createLights");
|
|
199
|
-
// Simple hemispheric + directional as a starting point
|
|
200
220
|
this.hemiLight = new HemisphericLight(
|
|
201
221
|
"hemiLight",
|
|
202
222
|
new Vector3(0, 1, 0),
|
|
@@ -218,7 +238,6 @@ class PrefViewer extends HTMLElement {
|
|
|
218
238
|
// Zoom toward point-of-interest on wheel scroll
|
|
219
239
|
this.canvas.addEventListener("wheel", (evt) => {
|
|
220
240
|
if (!this.scene || !this.camera) return;
|
|
221
|
-
|
|
222
241
|
const pickResult = this.scene.pick(
|
|
223
242
|
this.scene.pointerX,
|
|
224
243
|
this.scene.pointerY
|
|
@@ -226,7 +245,6 @@ class PrefViewer extends HTMLElement {
|
|
|
226
245
|
const pivotPoint = pickResult.hit
|
|
227
246
|
? pickResult.pickedPoint.clone()
|
|
228
247
|
: this.camera.target.clone();
|
|
229
|
-
|
|
230
248
|
this.camera.target = pivotPoint;
|
|
231
249
|
this.camera.inertialRadiusOffset +=
|
|
232
250
|
evt.deltaY * this.camera.wheelPrecision * 0.01;
|