MikaFil commited on
Commit
2af0591
·
verified ·
1 Parent(s): 1a2b495

Update viewer.js

Browse files
Files changed (1) hide show
  1. viewer.js +62 -30
viewer.js CHANGED
@@ -17,8 +17,7 @@ async function loadImageAsTexture(url, app) {
17
  img.onerror = reject;
18
  img.src = url;
19
  });
20
- }
21
-
22
 
23
  // --- Patch all window.Image to force crossOrigin="anonymous" ---
24
  (function() {
@@ -26,7 +25,6 @@ async function loadImageAsTexture(url, app) {
26
  window.Image = function(...args) {
27
  const img = new OriginalImage(...args);
28
  img.crossOrigin = "anonymous";
29
- // Optionally log image loading for debugging
30
  return img;
31
  };
32
  })();
@@ -103,7 +101,7 @@ export async function initializeViewer(config, instanceId) {
103
 
104
  presentoirScaleX = (config.presentoirScaleX !== undefined) ? parseFloat(config.presentoirScaleX) : 0;
105
  presentoirScaleY = (config.presentoirScaleY !== undefined) ? parseFloat(config.presentoirScaleY) : 0;
106
- presentoirScaleZ = (config.presentoirScaleZ !== undefined) ? parseFloat(config.presentoirScaleZ) : 0;
107
 
108
  const cameraX = (config.cameraX !== undefined) ? parseFloat(config.cameraX) : 0;
109
  const cameraY = (config.cameraY !== undefined) ? parseFloat(config.cameraY) : 2;
@@ -146,6 +144,39 @@ export async function initializeViewer(config, instanceId) {
146
  canvas.addEventListener('touchstart', e => { if (e.touches.length > 1) e.preventDefault(); }, { passive: false });
147
  canvas.addEventListener('wheel', (e) => { e.preventDefault(); }, { passive: false });
148
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  progressDialog.style.display = 'block';
150
 
151
  if (!pc) {
@@ -166,7 +197,7 @@ export async function initializeViewer(config, instanceId) {
166
  opts.graphicsDevice = device;
167
  opts.mouse = new pc.Mouse(canvas);
168
  opts.touch = new pc.TouchDevice(canvas);
169
- opts.keyboard = new pc.Keyboard(canvas);
170
  opts.componentSystems = [
171
  pc.RenderComponentSystem,
172
  pc.CameraComponentSystem,
@@ -195,9 +226,19 @@ export async function initializeViewer(config, instanceId) {
195
  resizeObserver.observe(viewerContainer);
196
 
197
  window.addEventListener('resize', () => app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight));
 
 
198
  app.on('destroy', () => {
199
  resizeObserver.disconnect();
200
- if (opts.keyboard) opts.keyboard.detach && opts.keyboard.detach();
 
 
 
 
 
 
 
 
201
  });
202
 
203
  // Assets after app exists
@@ -205,20 +246,16 @@ export async function initializeViewer(config, instanceId) {
205
  sogs: new pc.Asset('gsplat', 'gsplat', { url: sogsUrl }),
206
  orbit: new pc.Asset('script', 'script', { url: "https://mikafil-viewer-sgos.static.hf.space/orbit-camera.js" }),
207
  glb: new pc.Asset('glb', 'container', { url: glbUrl }),
208
- presentoir: new pc.Asset('presentoir', 'container', {url: presentoirUrl}),
209
  };
210
 
211
-
212
- // /!\ ======================================== /!\
213
- //const grilleTex = await loadImageAsTexture('https://huggingface.co/datasets/MikaFil/viewer_gs/resolve/main/ressources/textures/grille_cadrillee_4k.jpg', app);
214
- // /!\ ======================================== /!\
215
  for (const key in assets) app.assets.add(assets[key]);
216
 
217
- const loader = new pc.AssetListLoader(Object.values(assets), app.assets);
218
  loader.load(() => {
219
  app.start();
220
  progressDialog.style.display = 'none';
221
-
222
  modelEntity = new pc.Entity('model');
223
  modelEntity.addComponent('gsplat', { asset: assets.sogs });
224
  modelEntity.setLocalPosition(modelX, modelY, modelZ);
@@ -229,24 +266,22 @@ export async function initializeViewer(config, instanceId) {
229
  const glbEntity = assets.glb.resource.instantiateRenderEntity();
230
  app.root.addChild(glbEntity);
231
 
232
- const presentoirEntity =assets.presentoir.resource.instantiateRenderEntity();
233
  presentoirEntity.setLocalScale(presentoirScaleX, presentoirScaleY, presentoirScaleZ);
234
  app.root.addChild(presentoirEntity);
235
 
236
- if(!espace_expo_bool){
237
-
238
  let matSol = new pc.StandardMaterial();
239
  matSol.blendType = pc.BLEND_NONE;
240
  matSol.emissive = new pc.Color(color_bg);
241
  matSol.emissiveIntensity = 1;
242
- //matSol.emissiveMap = grilleTex;
243
  matSol.useLighting = false;
244
  matSol.update();
245
 
246
  traverse(presentoirEntity, node => {
247
  if (node.render && node.render.meshInstances) {
248
  for (let mi of node.render.meshInstances) {
249
- mi.material = matSol;
250
  }
251
  }
252
  });
@@ -254,15 +289,16 @@ export async function initializeViewer(config, instanceId) {
254
  traverse(glbEntity, node => {
255
  if (node.render && node.render.meshInstances) {
256
  for (let mi of node.render.meshInstances) {
257
- mi.material = matSol;
258
  }
259
  }
260
  });
261
  }
262
-
263
  cameraEntity = new pc.Entity('camera');
264
- cameraEntity.addComponent('camera',
265
- { clearColor: new pc.Color(color_bg),
 
266
  nearClip: 0.001,
267
  farClip: 100
268
  });
@@ -287,10 +323,8 @@ export async function initializeViewer(config, instanceId) {
287
  cameraEntity.script.create('orbitCameraInputTouch');
288
  cameraEntity.script.create('orbitCameraInputKeyboard', {
289
  attributes: {
290
- forwardSpeed: 1.2, // vitesses relatives à la distance
291
- strafeSpeed: 1.2,
292
- fastMultiplier: 2.5, // Shift
293
- slowMultiplier: 0.5 // Ctrl
294
  }
295
  });
296
  app.root.addChild(cameraEntity);
@@ -310,12 +344,10 @@ export async function initializeViewer(config, instanceId) {
310
  defaultVisible: !!config.showTooltipsDefault,
311
  moveDuration: config.tooltipMoveDuration || 0.6
312
  });
313
- }).catch(e => {
314
- // Tooltips optional: fail silently if missing
315
- });
316
  }
317
  } catch (e) {
318
- // Tooltips optional, fail silently
319
  }
320
 
321
  viewerInitialized = true;
 
17
  img.onerror = reject;
18
  img.src = url;
19
  });
20
+ }
 
21
 
22
  // --- Patch all window.Image to force crossOrigin="anonymous" ---
23
  (function() {
 
25
  window.Image = function(...args) {
26
  const img = new OriginalImage(...args);
27
  img.crossOrigin = "anonymous";
 
28
  return img;
29
  };
30
  })();
 
101
 
102
  presentoirScaleX = (config.presentoirScaleX !== undefined) ? parseFloat(config.presentoirScaleX) : 0;
103
  presentoirScaleY = (config.presentoirScaleY !== undefined) ? parseFloat(config.presentoirScaleY) : 0;
104
+ presentoirScaleZ = (config.presentoirScaleZ !== undefined) ? parseFloat(config.presentoirScaleZ) : 0;
105
 
106
  const cameraX = (config.cameraX !== undefined) ? parseFloat(config.cameraX) : 0;
107
  const cameraY = (config.cameraY !== undefined) ? parseFloat(config.cameraY) : 2;
 
144
  canvas.addEventListener('touchstart', e => { if (e.touches.length > 1) e.preventDefault(); }, { passive: false });
145
  canvas.addEventListener('wheel', (e) => { e.preventDefault(); }, { passive: false });
146
 
147
+ // --- Clavier : empêcher le scroll de la page quand le pointeur est au-dessus du viewer ---
148
+ const scrollKeys = new Set([
149
+ 'ArrowUp','ArrowDown','ArrowLeft','ArrowRight',
150
+ 'PageUp','PageDown','Home','End',' ','Space','Spacebar'
151
+ ]);
152
+ let isPointerOverCanvas = false;
153
+
154
+ const focusCanvas = () => canvas.focus({ preventScroll: true });
155
+ const onPointerEnter = () => { isPointerOverCanvas = true; focusCanvas(); };
156
+ const onPointerLeave = () => { isPointerOverCanvas = false; };
157
+
158
+ canvas.addEventListener('pointerenter', onPointerEnter);
159
+ canvas.addEventListener('pointerleave', onPointerLeave);
160
+ canvas.addEventListener('mousedown', focusCanvas);
161
+ canvas.addEventListener('touchstart', () => { focusCanvas(); }, { passive: false });
162
+
163
+ // Capture au niveau fenêtre pour bloquer le scroll, mais laisser PlayCanvas recevoir l'event
164
+ const onKeyDownCapture = (e) => {
165
+ if (!isPointerOverCanvas) return;
166
+ if (scrollKeys.has(e.key) || scrollKeys.has(e.code)) {
167
+ e.preventDefault(); // bloque le scroll page
168
+ // ne pas stopPropagation: PlayCanvas doit recevoir les touches
169
+ }
170
+ };
171
+ window.addEventListener('keydown', onKeyDownCapture, true);
172
+
173
+ // Ceinture et bretelles: si le canvas a le focus, on bloque ici aussi
174
+ const onCanvasKey = (e) => {
175
+ if (scrollKeys.has(e.key) || scrollKeys.has(e.code)) e.preventDefault();
176
+ };
177
+ canvas.addEventListener('keydown', onCanvasKey);
178
+ canvas.addEventListener('keyup', onCanvasKey);
179
+
180
  progressDialog.style.display = 'block';
181
 
182
  if (!pc) {
 
197
  opts.graphicsDevice = device;
198
  opts.mouse = new pc.Mouse(canvas);
199
  opts.touch = new pc.TouchDevice(canvas);
200
+ opts.keyboard = new pc.Keyboard(canvas);
201
  opts.componentSystems = [
202
  pc.RenderComponentSystem,
203
  pc.CameraComponentSystem,
 
226
  resizeObserver.observe(viewerContainer);
227
 
228
  window.addEventListener('resize', () => app.resizeCanvas(viewerContainer.clientWidth, viewerContainer.clientHeight));
229
+
230
+ // Nettoyage complet à la destruction
231
  app.on('destroy', () => {
232
  resizeObserver.disconnect();
233
+ if (opts.keyboard && opts.keyboard.detach) opts.keyboard.detach();
234
+
235
+ window.removeEventListener('keydown', onKeyDownCapture, true);
236
+ canvas.removeEventListener('pointerenter', onPointerEnter);
237
+ canvas.removeEventListener('pointerleave', onPointerLeave);
238
+ canvas.removeEventListener('mousedown', focusCanvas);
239
+ canvas.removeEventListener('touchstart', focusCanvas);
240
+ canvas.removeEventListener('keydown', onCanvasKey);
241
+ canvas.removeEventListener('keyup', onCanvasKey);
242
  });
243
 
244
  // Assets after app exists
 
246
  sogs: new pc.Asset('gsplat', 'gsplat', { url: sogsUrl }),
247
  orbit: new pc.Asset('script', 'script', { url: "https://mikafil-viewer-sgos.static.hf.space/orbit-camera.js" }),
248
  glb: new pc.Asset('glb', 'container', { url: glbUrl }),
249
+ presentoir: new pc.Asset('presentoir', 'container', { url: presentoirUrl }),
250
  };
251
 
 
 
 
 
252
  for (const key in assets) app.assets.add(assets[key]);
253
 
254
+ const loader = new pc.AssetListLoader(Object.values(assets), app.assets);
255
  loader.load(() => {
256
  app.start();
257
  progressDialog.style.display = 'none';
258
+
259
  modelEntity = new pc.Entity('model');
260
  modelEntity.addComponent('gsplat', { asset: assets.sogs });
261
  modelEntity.setLocalPosition(modelX, modelY, modelZ);
 
266
  const glbEntity = assets.glb.resource.instantiateRenderEntity();
267
  app.root.addChild(glbEntity);
268
 
269
+ const presentoirEntity = assets.presentoir.resource.instantiateRenderEntity();
270
  presentoirEntity.setLocalScale(presentoirScaleX, presentoirScaleY, presentoirScaleZ);
271
  app.root.addChild(presentoirEntity);
272
 
273
+ if (!espace_expo_bool) {
 
274
  let matSol = new pc.StandardMaterial();
275
  matSol.blendType = pc.BLEND_NONE;
276
  matSol.emissive = new pc.Color(color_bg);
277
  matSol.emissiveIntensity = 1;
 
278
  matSol.useLighting = false;
279
  matSol.update();
280
 
281
  traverse(presentoirEntity, node => {
282
  if (node.render && node.render.meshInstances) {
283
  for (let mi of node.render.meshInstances) {
284
+ mi.material = matSol;
285
  }
286
  }
287
  });
 
289
  traverse(glbEntity, node => {
290
  if (node.render && node.render.meshInstances) {
291
  for (let mi of node.render.meshInstances) {
292
+ mi.material = matSol;
293
  }
294
  }
295
  });
296
  }
297
+
298
  cameraEntity = new pc.Entity('camera');
299
+ cameraEntity.addComponent('camera',
300
+ {
301
+ clearColor: new pc.Color(color_bg),
302
  nearClip: 0.001,
303
  farClip: 100
304
  });
 
323
  cameraEntity.script.create('orbitCameraInputTouch');
324
  cameraEntity.script.create('orbitCameraInputKeyboard', {
325
  attributes: {
326
+ forwardSpeed: 1.2, // vitesses relatives à la distance (vertical)
327
+ strafeSpeed: 1.2 // gauche/droite
 
 
328
  }
329
  });
330
  app.root.addChild(cameraEntity);
 
344
  defaultVisible: !!config.showTooltipsDefault,
345
  moveDuration: config.tooltipMoveDuration || 0.6
346
  });
347
+ }).catch(() => { /* optional */ });
 
 
348
  }
349
  } catch (e) {
350
+ // optional
351
  }
352
 
353
  viewerInitialized = true;