bilca commited on
Commit
7f3416a
·
verified ·
1 Parent(s): bae1b70

Update js_scripts/index.js

Browse files
Files changed (1) hide show
  1. js_scripts/index.js +92 -33
js_scripts/index.js CHANGED
@@ -61,6 +61,7 @@ const currentScriptTag = document.currentScript;
61
  let viewerInitialized = false;
62
  let wheelHandlers = [];
63
  let resizeHandler = null;
 
64
 
65
  // Generate a unique identifier for this widget instance.
66
  const instanceId = Math.random().toString(36).substr(2, 8);
@@ -151,7 +152,7 @@ const currentScriptTag = document.currentScript;
151
  <img id="preview-image-${instanceId}" alt="Preview" crossorigin="anonymous">
152
  </div>
153
  <!-- Viewer Container -->
154
- <div id="viewer-container-${instanceId}" class="viewer-container">
155
  <canvas id="canvas-${instanceId}" class="ply-canvas"></canvas>
156
  <div id="progress-dialog-${instanceId}" class="progress-dialog">
157
  <progress id="progress-indicator-${instanceId}" max="100" value="0"></progress>
@@ -207,31 +208,46 @@ const currentScriptTag = document.currentScript;
207
  `;
208
  }
209
 
210
- // If a gif_url is provided, set the preview image.
211
- // Otherwise, hide the preview container, show the viewer immediately,
212
- // and hide the "close" button since there's no preview to return to.
213
  if (gifUrl) {
214
  previewImage.src = gifUrl;
215
- viewerContainer.style.display = 'none';
216
  gifPreview.style.display = 'block';
 
217
  } else {
218
  gifPreview.style.display = 'none';
219
  viewerContainer.style.display = 'block';
220
  closeBtn.style.display = 'none';
221
- initializeViewer();
 
 
 
222
  }
223
 
224
  // --- Button Event Handlers ---
225
  if (gifUrl) {
 
226
  gifPreview.addEventListener('click', function() {
 
227
  gifPreview.style.display = 'none';
228
  viewerContainer.style.display = 'block';
229
- initializeViewer();
 
 
 
 
230
  });
231
  }
232
 
233
- // Function to clean up the viewer
234
  function cleanupViewer() {
 
 
 
 
 
 
 
 
235
  // Remove wheel event listeners
236
  for (const handler of wheelHandlers) {
237
  const [element, func] = handler;
@@ -245,24 +261,31 @@ const currentScriptTag = document.currentScript;
245
  resizeHandler = null;
246
  }
247
 
 
 
 
 
 
 
 
 
 
 
 
 
248
  // Destroy PlayCanvas app if it exists
249
  if (app) {
250
- app.destroy();
 
 
 
 
251
  app = null;
252
  }
253
 
254
  // Reset entities
255
  cameraEntity = null;
256
  modelEntity = null;
257
- viewerInitialized = false;
258
-
259
- // Reset the canvas
260
- if (canvas) {
261
- const ctx = canvas.getContext('webgl2') || canvas.getContext('webgl');
262
- if (ctx) {
263
- ctx.getExtension('WEBGL_lose_context')?.loseContext();
264
- }
265
- }
266
 
267
  // Mark the viewer as not initialized
268
  viewerInitialized = false;
@@ -270,7 +293,10 @@ const currentScriptTag = document.currentScript;
270
  console.log("Viewer cleanup complete");
271
  }
272
 
 
273
  closeBtn.addEventListener('click', function() {
 
 
274
  // Handle fullscreen exit
275
  if (document.fullscreenElement === widgetContainer) {
276
  if (document.exitFullscreen) {
@@ -290,6 +316,7 @@ const currentScriptTag = document.currentScript;
290
  gifPreview.style.display = 'block';
291
  });
292
 
 
293
  fullscreenToggle.addEventListener('click', function() {
294
  if (isIOS) {
295
  if (!widgetContainer.classList.contains('fake-fullscreen')) {
@@ -333,6 +360,7 @@ const currentScriptTag = document.currentScript;
333
  }
334
  });
335
 
 
336
  helpToggle.addEventListener('click', function(e) {
337
  e.stopPropagation();
338
  menuContent.style.display = (menuContent.style.display === 'block') ? 'none' : 'block';
@@ -340,12 +368,18 @@ const currentScriptTag = document.currentScript;
340
 
341
  // --- Camera Reset Function ---
342
  function resetCamera() {
343
- if (!cameraEntity || !modelEntity || !app) return;
 
 
 
344
 
345
  try {
346
  // Get the orbit camera script
347
  const orbitCam = cameraEntity.script.orbitCamera;
348
- if (!orbitCam) return;
 
 
 
349
 
350
  // Store model position
351
  const modelPos = modelEntity.getPosition();
@@ -399,16 +433,20 @@ const currentScriptTag = document.currentScript;
399
  // Clean up
400
  tempEntity.destroy();
401
 
 
 
402
  } catch (error) {
403
  console.error("Error resetting camera:", error);
404
  }
405
  }
406
 
 
407
  resetCameraBtn.addEventListener('click', function() {
408
- console.log("Reset camera button clicked.");
409
  resetCamera();
410
  });
411
 
 
412
  document.addEventListener('keydown', function(e) {
413
  if (e.key === 'Escape' || e.key === 'Esc') {
414
  let wasFullscreen = false;
@@ -472,18 +510,21 @@ const currentScriptTag = document.currentScript;
472
  // Store handlers for later cleanup
473
  wheelHandlers.push([viewerContainer, handleWheel]);
474
  wheelHandlers.push([canvas, handleWheel]);
 
 
475
  }
476
 
477
  // --- Initialize the 3D PLY Viewer using PlayCanvas ---
478
  async function initializeViewer() {
479
  // Skip initialization if already initialized
480
- if (viewerInitialized) {
481
- console.log("Viewer already initialized, skipping");
482
  return;
483
  }
484
 
485
  console.log("Initializing PLY viewer...");
486
  progressDialog.style.display = 'block';
 
487
 
488
  // Initialize PlayCanvas
489
  const deviceType = "webgl2";
@@ -502,8 +543,8 @@ const currentScriptTag = document.currentScript;
502
  // Create app
503
  const createOptions = new pc.AppOptions();
504
  createOptions.graphicsDevice = device;
505
- createOptions.mouse = new pc.Mouse(canvas); // Use canvas, not document.body
506
- createOptions.touch = new pc.TouchDevice(canvas); // Use canvas, not document.body
507
  createOptions.componentSystems = [
508
  pc.RenderComponentSystem,
509
  pc.CameraComponentSystem,
@@ -539,9 +580,17 @@ const currentScriptTag = document.currentScript;
539
  // Store resize handler for cleanup
540
  resizeHandler = resize;
541
  window.addEventListener('resize', resizeHandler);
 
 
542
  app.on('destroy', () => {
543
- window.removeEventListener('resize', resizeHandler);
544
- resizeHandler = null;
 
 
 
 
 
 
545
  });
546
 
547
  // Load required assets
@@ -557,18 +606,27 @@ const currentScriptTag = document.currentScript;
557
  let lastProgress = 0;
558
  assets.model.on('load', (asset) => {
559
  progressDialog.style.display = 'none';
 
560
  });
561
 
562
  assets.model.on('error', (err) => {
563
  console.error("Error loading PLY file:", err);
564
  progressDialog.innerHTML = `<p style="color: red">Error loading model: ${err}</p>`;
 
565
  });
566
 
567
  // Set up progress monitoring
568
  const checkProgress = () => {
 
 
 
 
 
 
569
  if (app && assets.model.resource) {
570
  progressIndicator.value = 100;
571
  clearInterval(progressChecker);
 
572
  progressDialog.style.display = 'none';
573
  } else if (assets.model.loading) {
574
  // Increment progress for visual feedback
@@ -578,15 +636,15 @@ const currentScriptTag = document.currentScript;
578
  }
579
  };
580
 
581
- const progressChecker = setInterval(checkProgress, 100);
582
-
583
- // Store the interval for cleanup
584
- app.once('destroy', () => {
585
- clearInterval(progressChecker);
586
- });
587
 
588
  // Load assets and set up scene
589
  assetListLoader.load(() => {
 
 
 
 
 
590
  app.start();
591
 
592
  // Create model entity
@@ -693,6 +751,7 @@ const currentScriptTag = document.currentScript;
693
  console.error("Error initializing PlayCanvas viewer:", error);
694
  progressDialog.innerHTML = `<p style="color: red">Error loading viewer: ${error.message}</p>`;
695
  viewerInitialized = false;
 
696
  }
697
  }
698
  })();
 
61
  let viewerInitialized = false;
62
  let wheelHandlers = [];
63
  let resizeHandler = null;
64
+ let progressChecker = null;
65
 
66
  // Generate a unique identifier for this widget instance.
67
  const instanceId = Math.random().toString(36).substr(2, 8);
 
152
  <img id="preview-image-${instanceId}" alt="Preview" crossorigin="anonymous">
153
  </div>
154
  <!-- Viewer Container -->
155
+ <div id="viewer-container-${instanceId}" class="viewer-container" style="display: none;">
156
  <canvas id="canvas-${instanceId}" class="ply-canvas"></canvas>
157
  <div id="progress-dialog-${instanceId}" class="progress-dialog">
158
  <progress id="progress-indicator-${instanceId}" max="100" value="0"></progress>
 
208
  `;
209
  }
210
 
211
+ // Handle GIF configuration
 
 
212
  if (gifUrl) {
213
  previewImage.src = gifUrl;
 
214
  gifPreview.style.display = 'block';
215
+ viewerContainer.style.display = 'none';
216
  } else {
217
  gifPreview.style.display = 'none';
218
  viewerContainer.style.display = 'block';
219
  closeBtn.style.display = 'none';
220
+ // Initialize the viewer only when needed
221
+ setTimeout(() => {
222
+ initializeViewer();
223
+ }, 100);
224
  }
225
 
226
  // --- Button Event Handlers ---
227
  if (gifUrl) {
228
+ // Add click event to the GIF container
229
  gifPreview.addEventListener('click', function() {
230
+ console.log("GIF preview clicked, showing 3D viewer");
231
  gifPreview.style.display = 'none';
232
  viewerContainer.style.display = 'block';
233
+
234
+ // Make sure we're not initializing again if already done
235
+ if (!viewerInitialized) {
236
+ initializeViewer();
237
+ }
238
  });
239
  }
240
 
241
+ // Function to clean up the viewer completely
242
  function cleanupViewer() {
243
+ console.log("Starting viewer cleanup...");
244
+
245
+ // Clear any running intervals
246
+ if (progressChecker) {
247
+ clearInterval(progressChecker);
248
+ progressChecker = null;
249
+ }
250
+
251
  // Remove wheel event listeners
252
  for (const handler of wheelHandlers) {
253
  const [element, func] = handler;
 
261
  resizeHandler = null;
262
  }
263
 
264
+ // Reset the canvas context
265
+ if (canvas) {
266
+ const ctx = canvas.getContext('webgl2') || canvas.getContext('webgl');
267
+ if (ctx && ctx.getExtension('WEBGL_lose_context')) {
268
+ try {
269
+ ctx.getExtension('WEBGL_lose_context').loseContext();
270
+ } catch (e) {
271
+ console.error("Error releasing WebGL context:", e);
272
+ }
273
+ }
274
+ }
275
+
276
  // Destroy PlayCanvas app if it exists
277
  if (app) {
278
+ try {
279
+ app.destroy();
280
+ } catch (e) {
281
+ console.error("Error destroying PlayCanvas app:", e);
282
+ }
283
  app = null;
284
  }
285
 
286
  // Reset entities
287
  cameraEntity = null;
288
  modelEntity = null;
 
 
 
 
 
 
 
 
 
289
 
290
  // Mark the viewer as not initialized
291
  viewerInitialized = false;
 
293
  console.log("Viewer cleanup complete");
294
  }
295
 
296
+ // Close button event handler
297
  closeBtn.addEventListener('click', function() {
298
+ console.log("Close button clicked");
299
+
300
  // Handle fullscreen exit
301
  if (document.fullscreenElement === widgetContainer) {
302
  if (document.exitFullscreen) {
 
316
  gifPreview.style.display = 'block';
317
  });
318
 
319
+ // Fullscreen toggle handler
320
  fullscreenToggle.addEventListener('click', function() {
321
  if (isIOS) {
322
  if (!widgetContainer.classList.contains('fake-fullscreen')) {
 
360
  }
361
  });
362
 
363
+ // Help toggle button
364
  helpToggle.addEventListener('click', function(e) {
365
  e.stopPropagation();
366
  menuContent.style.display = (menuContent.style.display === 'block') ? 'none' : 'block';
 
368
 
369
  // --- Camera Reset Function ---
370
  function resetCamera() {
371
+ if (!cameraEntity || !modelEntity || !app) {
372
+ console.log("Cannot reset camera - missing entities or app");
373
+ return;
374
+ }
375
 
376
  try {
377
  // Get the orbit camera script
378
  const orbitCam = cameraEntity.script.orbitCamera;
379
+ if (!orbitCam) {
380
+ console.log("Cannot reset camera - missing orbit camera script");
381
+ return;
382
+ }
383
 
384
  // Store model position
385
  const modelPos = modelEntity.getPosition();
 
433
  // Clean up
434
  tempEntity.destroy();
435
 
436
+ console.log("Camera reset complete");
437
+
438
  } catch (error) {
439
  console.error("Error resetting camera:", error);
440
  }
441
  }
442
 
443
+ // Reset camera button event handler
444
  resetCameraBtn.addEventListener('click', function() {
445
+ console.log("Reset camera button clicked");
446
  resetCamera();
447
  });
448
 
449
+ // Escape key handler for fullscreen exit
450
  document.addEventListener('keydown', function(e) {
451
  if (e.key === 'Escape' || e.key === 'Esc') {
452
  let wasFullscreen = false;
 
510
  // Store handlers for later cleanup
511
  wheelHandlers.push([viewerContainer, handleWheel]);
512
  wheelHandlers.push([canvas, handleWheel]);
513
+
514
+ console.log("Wheel handlers set up");
515
  }
516
 
517
  // --- Initialize the 3D PLY Viewer using PlayCanvas ---
518
  async function initializeViewer() {
519
  // Skip initialization if already initialized
520
+ if (viewerInitialized || app) {
521
+ console.log("Viewer already initialized or app exists, skipping initialization");
522
  return;
523
  }
524
 
525
  console.log("Initializing PLY viewer...");
526
  progressDialog.style.display = 'block';
527
+ progressIndicator.value = 0;
528
 
529
  // Initialize PlayCanvas
530
  const deviceType = "webgl2";
 
543
  // Create app
544
  const createOptions = new pc.AppOptions();
545
  createOptions.graphicsDevice = device;
546
+ createOptions.mouse = new pc.Mouse(canvas);
547
+ createOptions.touch = new pc.TouchDevice(canvas);
548
  createOptions.componentSystems = [
549
  pc.RenderComponentSystem,
550
  pc.CameraComponentSystem,
 
580
  // Store resize handler for cleanup
581
  resizeHandler = resize;
582
  window.addEventListener('resize', resizeHandler);
583
+
584
+ // Add cleanup when app is destroyed
585
  app.on('destroy', () => {
586
+ if (resizeHandler) {
587
+ window.removeEventListener('resize', resizeHandler);
588
+ resizeHandler = null;
589
+ }
590
+ if (progressChecker) {
591
+ clearInterval(progressChecker);
592
+ progressChecker = null;
593
+ }
594
  });
595
 
596
  // Load required assets
 
606
  let lastProgress = 0;
607
  assets.model.on('load', (asset) => {
608
  progressDialog.style.display = 'none';
609
+ console.log("Model loaded successfully");
610
  });
611
 
612
  assets.model.on('error', (err) => {
613
  console.error("Error loading PLY file:", err);
614
  progressDialog.innerHTML = `<p style="color: red">Error loading model: ${err}</p>`;
615
+ viewerInitialized = false;
616
  });
617
 
618
  // Set up progress monitoring
619
  const checkProgress = () => {
620
+ if (!app) {
621
+ clearInterval(progressChecker);
622
+ progressChecker = null;
623
+ return;
624
+ }
625
+
626
  if (app && assets.model.resource) {
627
  progressIndicator.value = 100;
628
  clearInterval(progressChecker);
629
+ progressChecker = null;
630
  progressDialog.style.display = 'none';
631
  } else if (assets.model.loading) {
632
  // Increment progress for visual feedback
 
636
  }
637
  };
638
 
639
+ progressChecker = setInterval(checkProgress, 100);
 
 
 
 
 
640
 
641
  // Load assets and set up scene
642
  assetListLoader.load(() => {
643
+ if (!app) {
644
+ console.log("App was destroyed during asset loading");
645
+ return;
646
+ }
647
+
648
  app.start();
649
 
650
  // Create model entity
 
751
  console.error("Error initializing PlayCanvas viewer:", error);
752
  progressDialog.innerHTML = `<p style="color: red">Error loading viewer: ${error.message}</p>`;
753
  viewerInitialized = false;
754
+ app = null;
755
  }
756
  }
757
  })();