MikaFil commited on
Commit
ee74538
·
verified ·
1 Parent(s): 0f3e0b7

Update viewer_ar.js

Browse files
Files changed (1) hide show
  1. viewer_ar.js +58 -38
viewer_ar.js CHANGED
@@ -278,68 +278,81 @@
278
  });
279
  });
280
 
281
- // --- Interactions ---
282
- let isDragging = false; // déplacement du modèle
283
- let rotateMode = false; // rotation 2 doigts (tactile) ou souris
284
- let multiTouchActive = false; // >= 2 doigts
 
 
285
  let lastMouseX = 0;
286
 
287
- // ===== MODIF: paramètres rotation 2 doigts (angle) =====
288
- let rotationBaseY = 0; // Y du modèle au démarrage du geste
289
- let lastTwoFingerAngle = 0; // angle entre les 2 doigts (radians)
 
 
 
 
 
 
 
 
 
290
  const RAD2DEG = 180 / Math.PI;
291
 
292
- // Déplacement (input XR : maintien/drag) — désactivé si 2 doigts
293
  app.xr.input.on("add", (inputSource) => {
294
  inputSource.on("selectstart", () => {
295
- if (!placedOnce || !modelLoaded || multiTouchActive) return; // <-- MODIF: bloque drag si 2 doigts
296
  inputSource.hitTestStart({
297
  entityTypes: [pc.XRTRACKABLE_POINT, pc.XRTRACKABLE_PLANE],
298
  callback: (err, transientSource) => {
299
  if (err) return;
300
  isDragging = true;
 
301
 
302
  transientSource.on("result", (pos /*, rot */) => {
303
- if (!isDragging || rotateMode || multiTouchActive) return; // <-- MODIF: pas de déplacement si rotation en cours
 
304
  modelRoot.setPosition(pos);
305
  });
306
 
307
  transientSource.once("remove", () => {
308
- isDragging = false;
 
309
  });
310
  }
311
  });
312
  });
313
 
314
  inputSource.on("selectend", () => {
315
- isDragging = false;
 
316
  });
317
  });
318
 
319
- // ===== MODIF: Rotation tactile (2 doigts par angle, sans déplacement) =====
320
  if (app.touch) {
321
  const touches = new Map(); // id -> {x,y}
322
 
323
- const calcTwoFingerAngle = () => {
324
  if (touches.size < 2) return null;
325
  const it = touches.values();
326
- const t1 = it.next().value;
327
- const t2 = it.next().value;
328
- return Math.atan2(t2.y - t1.y, t2.x - t1.x); // radians
329
  };
330
 
331
  app.touch.on("touchstart", (e) => {
332
  for (const t of e.touches) touches.set(t.id, { x: t.x, y: t.y });
333
 
334
  if (touches.size >= 2) {
335
- multiTouchActive = true; // <-- MODIF
336
- rotateMode = true; // on passe en mode rotation
337
- isDragging = false; // on annule tout drag en cours
338
- const ang = calcTwoFingerAngle();
339
- if (ang !== null) {
340
- lastTwoFingerAngle = ang;
341
- rotationBaseY = modelRoot.getEulerAngles().y; // point de départ
342
- }
343
  }
344
  });
345
 
@@ -348,29 +361,32 @@
348
  if (touches.has(t.id)) touches.set(t.id, { x: t.x, y: t.y });
349
  }
350
 
 
351
  if (rotateMode && multiTouchActive && modelRoot.enabled && touches.size >= 2) {
352
- const ang = calcTwoFingerAngle();
353
- if (ang !== null) {
354
- const deltaRad = ang - lastTwoFingerAngle;
355
- // On ne “snap” pas le lastTwoFingerAngle : on garde une base stable et on applique delta total
356
- // => pour lisser, cumuler sur la base :
357
- const newY = rotationBaseY + deltaRad * RAD2DEG;
358
- const euler = modelRoot.getEulerAngles();
359
- modelRoot.setEulerAngles(euler.x, newY, euler.z);
 
 
 
 
360
  }
361
  }
362
  });
363
 
364
  app.touch.on("touchend", (e) => {
365
  for (const t of e.changedTouches) touches.delete(t.id);
 
366
  if (touches.size < 2) {
367
- // fin du geste 2 doigts
368
- if (rotateMode && multiTouchActive) {
369
- // fige la base à la rotation actuelle pour le prochain geste
370
- rotationBaseY = modelRoot.getEulerAngles().y;
371
- }
372
  rotateMode = false;
373
  multiTouchActive = false;
 
374
  }
375
  });
376
 
@@ -378,6 +394,8 @@
378
  touches.clear();
379
  rotateMode = false;
380
  multiTouchActive = false;
 
 
381
  });
382
  }
383
 
@@ -428,6 +446,8 @@
428
  isDragging = false;
429
  rotateMode = false;
430
  multiTouchActive = false;
 
 
431
  });
432
 
433
  app.xr.on(`available:${pc.XRTYPE_AR}`, (available) => {
 
278
  });
279
  });
280
 
281
+ // =========================
282
+ // --- Interactions (MODIF)
283
+ // =========================
284
+ let isDragging = false; // déplacement du modèle
285
+ let rotateMode = false; // rotation 2 doigts (tactile) ou souris
286
+ let multiTouchActive = false; // >= 2 doigts
287
  let lastMouseX = 0;
288
 
289
+ // Nouveaux états pour gérer/annuler les hit-tests transitoires démarrés par le 1er doigt
290
+ const activeTransientSources = new Set(); // XRHitTestSource
291
+ function cancelAllTransientHitTests() {
292
+ activeTransientSources.forEach(src => {
293
+ try { src.remove && src.remove(); } catch(_) {}
294
+ });
295
+ activeTransientSources.clear();
296
+ isDragging = false;
297
+ }
298
+
299
+ // ===== Rotation 2 doigts (incrémentale) =====
300
+ let lastTwoFingerAngle = null; // radians
301
  const RAD2DEG = 180 / Math.PI;
302
 
303
+ // Déplacement (input XR) — ne démarre que si pas de 2 doigts
304
  app.xr.input.on("add", (inputSource) => {
305
  inputSource.on("selectstart", () => {
306
+ if (!placedOnce || !modelLoaded || multiTouchActive) return;
307
  inputSource.hitTestStart({
308
  entityTypes: [pc.XRTRACKABLE_POINT, pc.XRTRACKABLE_PLANE],
309
  callback: (err, transientSource) => {
310
  if (err) return;
311
  isDragging = true;
312
+ activeTransientSources.add(transientSource);
313
 
314
  transientSource.on("result", (pos /*, rot */) => {
315
+ // Pas de translation si rotation 2 doigts ou multitouch
316
+ if (!isDragging || rotateMode || multiTouchActive) return;
317
  modelRoot.setPosition(pos);
318
  });
319
 
320
  transientSource.once("remove", () => {
321
+ activeTransientSources.delete(transientSource);
322
+ if (activeTransientSources.size === 0) isDragging = false;
323
  });
324
  }
325
  });
326
  });
327
 
328
  inputSource.on("selectend", () => {
329
+ // Libère seulement si plus de sources actives
330
+ cancelAllTransientHitTests();
331
  });
332
  });
333
 
334
+ // ===== Gestes tactiles =====
335
  if (app.touch) {
336
  const touches = new Map(); // id -> {x,y}
337
 
338
+ const twoFingerAngle = () => {
339
  if (touches.size < 2) return null;
340
  const it = touches.values();
341
+ const a = it.next().value;
342
+ const b = it.next().value;
343
+ return Math.atan2(b.y - a.y, b.x - a.x);
344
  };
345
 
346
  app.touch.on("touchstart", (e) => {
347
  for (const t of e.touches) touches.set(t.id, { x: t.x, y: t.y });
348
 
349
  if (touches.size >= 2) {
350
+ multiTouchActive = true;
351
+ rotateMode = true;
352
+ // cancel toute translation issue d'un 1er doigt déjà actif
353
+ cancelAllTransientHitTests();
354
+ // initialise l'angle de référence
355
+ lastTwoFingerAngle = twoFingerAngle();
 
 
356
  }
357
  });
358
 
 
361
  if (touches.has(t.id)) touches.set(t.id, { x: t.x, y: t.y });
362
  }
363
 
364
+ // Rotation à 2 doigts : appliquer delta d'angle incrémental
365
  if (rotateMode && multiTouchActive && modelRoot.enabled && touches.size >= 2) {
366
+ const ang = twoFingerAngle();
367
+ if (ang !== null && lastTwoFingerAngle !== null) {
368
+ let delta = ang - lastTwoFingerAngle; // radians
369
+ // normaliser (-PI, PI) pour éviter les sauts
370
+ if (delta > Math.PI) delta -= 2 * Math.PI;
371
+ if (delta < -Math.PI) delta += 2 * Math.PI;
372
+
373
+ const eul = modelRoot.getEulerAngles();
374
+ modelRoot.setEulerAngles(eul.x, eul.y + delta * RAD2DEG, eul.z);
375
+
376
+ // mise à jour incrémentale
377
+ lastTwoFingerAngle = ang;
378
  }
379
  }
380
  });
381
 
382
  app.touch.on("touchend", (e) => {
383
  for (const t of e.changedTouches) touches.delete(t.id);
384
+
385
  if (touches.size < 2) {
386
+ // fin du geste 2 doigts : sortir proprement du mode rotation
 
 
 
 
387
  rotateMode = false;
388
  multiTouchActive = false;
389
+ lastTwoFingerAngle = null;
390
  }
391
  });
392
 
 
394
  touches.clear();
395
  rotateMode = false;
396
  multiTouchActive = false;
397
+ lastTwoFingerAngle = null;
398
+ cancelAllTransientHitTests();
399
  });
400
  }
401
 
 
446
  isDragging = false;
447
  rotateMode = false;
448
  multiTouchActive = false;
449
+ lastTwoFingerAngle = null;
450
+ cancelAllTransientHitTests();
451
  });
452
 
453
  app.xr.on(`available:${pc.XRTYPE_AR}`, (available) => {