Update viewer_ar_ios.js
Browse files- viewer_ar_ios.js +88 -59
viewer_ar_ios.js
CHANGED
|
@@ -4,12 +4,13 @@
|
|
| 4 |
- Android/Desktop : WebXR AR (horizontaux uniquement) + slider yaw + blob shadow
|
| 5 |
- Éclairage PBR par défaut (sans WebXR light estimation)
|
| 6 |
- Monté dans un conteneur choisi (data-mount="#ar-mount") pour Squarespace
|
|
|
|
|
|
|
| 7 |
*/
|
| 8 |
|
| 9 |
(function () {
|
| 10 |
-
// ============ Utils: script tag / config / platform ============
|
| 11 |
function getCurrentScript() {
|
| 12 |
-
// robuste même si currentScript n'est pas dispo
|
| 13 |
return document.currentScript || (function () {
|
| 14 |
var scripts = document.getElementsByTagName('script');
|
| 15 |
return scripts[scripts.length - 1] || null;
|
|
@@ -46,6 +47,18 @@
|
|
| 46 |
}
|
| 47 |
}
|
| 48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
// ============ PlayCanvas version fixée (Android/Desktop) ============
|
| 50 |
var PC_VERSION = "2.11.7";
|
| 51 |
var PC_URLS = {
|
|
@@ -105,27 +118,7 @@
|
|
| 105 |
}
|
| 106 |
}
|
| 107 |
|
| 108 |
-
// ============
|
| 109 |
-
var css = [
|
| 110 |
-
".pc-ar-msg{position:fixed;left:50%;transform:translateX(-50%);bottom:16px;z-index:10002;padding:10px 14px;background:rgba(0,0,0,.65);color:#fff;border-radius:12px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;font-size:14px;line-height:1.3;text-align:center;max-width:min(90vw,640px);box-shadow:0 6px 20px rgba(0,0,0,.25);backdrop-filter:blur(4px);pointer-events:none}",
|
| 111 |
-
"#xr-overlay-root{position:fixed;inset:0;z-index:10001;pointer-events:none}",
|
| 112 |
-
|
| 113 |
-
".ar-ui{position:absolute;right:12px;top:50%;transform:translateY(-50%);background:rgba(0,0,0,0.55);color:#fff;padding:12px 10px;border-radius:16px;width:56px;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;pointer-events:auto;display:flex;flex-direction:column;align-items:center;gap:8px;box-shadow:0 6px 18px rgba(0,0,0,.25);backdrop-filter:blur(6px);touch-action:none}",
|
| 114 |
-
".ar-ui .label{font-size:12px;text-align:center;opacity:.95}",
|
| 115 |
-
".rotY-wrap{position:relative;width:48px;height:200px;display:flex;align-items:center;justify-content:center;touch-action:none;overflow:visible;pointer-events:auto}",
|
| 116 |
-
".rotY-rail{position:absolute;left:50%;transform:translateX(-50%);width:4px;height:100%;background:rgba(255,255,255,.35);border-radius:2px;pointer-events:none}",
|
| 117 |
-
".rotY-knob{position:absolute;left:50%;width:22px;height:22px;border-radius:50%;background:#fff;box-shadow:0 2px 8px rgba(0,0,0,.35);transform:translate(-50%,-50%);top:50%;will-change:top;touch-action:none;pointer-events:none}",
|
| 118 |
-
".ar-ui input[type=\"range\"].rotY{position:absolute;opacity:0;pointer-events:none;width:0;height:0}",
|
| 119 |
-
".ar-ui .val{font-size:12px;opacity:.95}",
|
| 120 |
-
|
| 121 |
-
/* iOS Quick Look button */
|
| 122 |
-
"#ios-quicklook-btn{position:fixed;left:50%;transform:translateX(-50%);bottom:16px;z-index:10003;display:inline-block;pointer-events:auto}",
|
| 123 |
-
"#ios-quicklook-btn img{display:block;height:44px;width:auto}"
|
| 124 |
-
].join("\n");
|
| 125 |
-
var styleTag = document.createElement("style");
|
| 126 |
-
styleTag.textContent = css;
|
| 127 |
-
document.head.appendChild(styleTag);
|
| 128 |
-
|
| 129 |
function ensureOverlayRoot() {
|
| 130 |
var r = document.getElementById("xr-overlay-root");
|
| 131 |
if (!r) {
|
|
@@ -161,43 +154,21 @@
|
|
| 161 |
}
|
| 162 |
}
|
| 163 |
|
| 164 |
-
|
| 165 |
-
var btn = document.getElementById("ios-quicklook-btn");
|
| 166 |
-
if (btn) return btn;
|
| 167 |
-
|
| 168 |
-
var anchor = document.createElement("a");
|
| 169 |
-
anchor.id = "ios-quicklook-btn";
|
| 170 |
-
anchor.setAttribute("rel", "ar");
|
| 171 |
-
anchor.setAttribute("href", buildQuickLookHref(USDZ_URL));
|
| 172 |
-
|
| 173 |
-
var img = document.createElement("img");
|
| 174 |
-
img.alt = "Voir en AR";
|
| 175 |
-
img.src =
|
| 176 |
-
"data:image/svg+xml;charset=utf-8," +
|
| 177 |
-
encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="160" height="44"><rect rx="8" ry="8" width="160" height="44" fill="black"/><text x="80" y="28" font-size="14" text-anchor="middle" fill="white" font-family="system-ui, -apple-system, Segoe UI, Roboto">Voir en AR</text></svg>');
|
| 178 |
-
|
| 179 |
-
anchor.appendChild(img);
|
| 180 |
-
document.body.appendChild(anchor);
|
| 181 |
-
return anchor;
|
| 182 |
-
}
|
| 183 |
-
|
| 184 |
-
// ============ Canvas monté dans un conteneur contrôlé (Squarespace) ============
|
| 185 |
function ensureCanvas() {
|
| 186 |
var scriptEl = getCurrentScript();
|
| 187 |
var mountSel = scriptEl && scriptEl.getAttribute('data-mount');
|
| 188 |
var desiredHeight = (scriptEl && scriptEl.getAttribute('data-height')) || '70vh';
|
| 189 |
|
| 190 |
-
// Trouve le conteneur cible
|
| 191 |
var mountEl = null;
|
| 192 |
if (mountSel) mountEl = document.querySelector(mountSel);
|
| 193 |
if (!mountEl) {
|
| 194 |
-
// fallback : tout en haut du body (pour éviter "sous le footer")
|
| 195 |
mountEl = document.createElement('div');
|
| 196 |
mountEl.id = 'ar-mount-fallback';
|
| 197 |
document.body.insertBefore(mountEl, document.body.firstChild);
|
| 198 |
}
|
| 199 |
|
| 200 |
-
//
|
| 201 |
var mountStyle = mountEl.style;
|
| 202 |
if (!mountStyle.position) mountStyle.position = 'relative';
|
| 203 |
mountStyle.width = mountStyle.width || '100%';
|
|
@@ -205,7 +176,6 @@
|
|
| 205 |
mountStyle.touchAction = mountStyle.touchAction || 'manipulation';
|
| 206 |
mountStyle.webkitTapHighlightColor = 'transparent';
|
| 207 |
|
| 208 |
-
// Réutilise ou crée le canvas
|
| 209 |
var canvas = mountEl.querySelector('#application-canvas');
|
| 210 |
if (!canvas) {
|
| 211 |
canvas = document.createElement('canvas');
|
|
@@ -213,7 +183,7 @@
|
|
| 213 |
mountEl.appendChild(canvas);
|
| 214 |
}
|
| 215 |
|
| 216 |
-
//
|
| 217 |
var cs = canvas.style;
|
| 218 |
cs.position = 'absolute';
|
| 219 |
cs.left = '0';
|
|
@@ -222,7 +192,6 @@
|
|
| 222 |
cs.height = '100%';
|
| 223 |
cs.display = 'block';
|
| 224 |
|
| 225 |
-
// Optionnel : ramener le viewport sur le viewer
|
| 226 |
try {
|
| 227 |
mountEl.scrollIntoView({ behavior: 'instant', block: 'start' });
|
| 228 |
} catch (_) {}
|
|
@@ -247,8 +216,41 @@
|
|
| 247 |
return p;
|
| 248 |
}
|
| 249 |
|
| 250 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 251 |
(async function () {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 252 |
var cfgUrl = findConfigUrl();
|
| 253 |
var cfg = await loadConfigJson(cfgUrl);
|
| 254 |
var GLB_URL = (cfg && typeof cfg.glb_url === "string" && cfg.glb_url) ?
|
|
@@ -258,28 +260,50 @@
|
|
| 258 |
cfg.usdz_url :
|
| 259 |
null;
|
| 260 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
if (isIOS()) {
|
| 262 |
if (USDZ_URL) {
|
| 263 |
-
|
| 264 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 265 |
} else {
|
| 266 |
message("iOS détecté, mais aucun 'usdz_url' dans config.json.");
|
|
|
|
|
|
|
| 267 |
}
|
| 268 |
return;
|
| 269 |
}
|
| 270 |
|
|
|
|
| 271 |
try {
|
| 272 |
await loadPlayCanvasRobust({ esmFirst: true, loadTimeoutMs: 15000 });
|
| 273 |
} catch (e) {
|
| 274 |
console.error("Chargement PlayCanvas échoué ->", e);
|
| 275 |
message("Impossible de charger PlayCanvas (réseau/CDN). Réessaie plus tard.");
|
|
|
|
|
|
|
| 276 |
return;
|
| 277 |
}
|
| 278 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 279 |
})();
|
| 280 |
|
| 281 |
// ============ App Android/Desktop (WebXR) ============
|
| 282 |
-
function initARApp(GLB_URL) {
|
| 283 |
var pc = window.pc;
|
| 284 |
var canvas = ensureCanvas();
|
| 285 |
var ui = ensureSliderUI();
|
|
@@ -395,7 +419,7 @@
|
|
| 395 |
return e;
|
| 396 |
}
|
| 397 |
|
| 398 |
-
// Euler de base
|
| 399 |
var baseEulerX = 0, baseEulerZ = 0;
|
| 400 |
|
| 401 |
// Rotation via slider (0..360, 360 en haut / 0 en bas)
|
|
@@ -448,7 +472,7 @@
|
|
| 448 |
baseEulerX = initE.x; baseEulerZ = initE.z;
|
| 449 |
|
| 450 |
modelLoaded = true;
|
| 451 |
-
message("Modèle chargé.
|
| 452 |
});
|
| 453 |
|
| 454 |
if (!app.xr.supported) { message("WebXR n’est pas supporté sur cet appareil."); return; }
|
|
@@ -502,7 +526,7 @@
|
|
| 502 |
document.addEventListener("pointerup", endDrag, { capture: true, passive: false });
|
| 503 |
document.addEventListener("pointercancel", endDrag, { capture: true, passive: false });
|
| 504 |
|
| 505 |
-
// --- Démarrage AR (Android/Desktop)
|
| 506 |
function activateAR() {
|
| 507 |
if (!app.xr.isAvailable(pc.XRTYPE_AR)) { message("AR immersive indisponible sur cet appareil."); return; }
|
| 508 |
if (!app.xr.domOverlay) app.xr.domOverlay = {};
|
|
@@ -518,6 +542,11 @@
|
|
| 518 |
}
|
| 519 |
});
|
| 520 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 521 |
app.mouse.on("mousedown", function () { if (!app.xr.active && !uiInteracting) activateAR(); });
|
| 522 |
if (app.touch) {
|
| 523 |
app.touch.on("touchend", function (evt) {
|
|
@@ -640,7 +669,7 @@
|
|
| 640 |
app.xr.on("available:" + pc.XRTYPE_AR, function (a) {
|
| 641 |
if (!a) message("AR immersive indisponible.");
|
| 642 |
else if (!app.xr.hitTest.supported) message("AR Hit Test non supporté.");
|
| 643 |
-
else message(modelLoaded ? "Touchez l’écran
|
| 644 |
});
|
| 645 |
|
| 646 |
if (!app.xr.isAvailable(pc.XRTYPE_AR)) message("AR immersive indisponible.");
|
|
|
|
| 4 |
- Android/Desktop : WebXR AR (horizontaux uniquement) + slider yaw + blob shadow
|
| 5 |
- Éclairage PBR par défaut (sans WebXR light estimation)
|
| 6 |
- Monté dans un conteneur choisi (data-mount="#ar-mount") pour Squarespace
|
| 7 |
+
- Bouton "Lancer l’AR" (Android & iOS)
|
| 8 |
+
- CSS externalisé : https://huggingface.co/spaces/MikaFil/VR/resolve/main/css/style.css
|
| 9 |
*/
|
| 10 |
|
| 11 |
(function () {
|
| 12 |
+
// ============ Utils: script tag / config / platform / CSS ============
|
| 13 |
function getCurrentScript() {
|
|
|
|
| 14 |
return document.currentScript || (function () {
|
| 15 |
var scripts = document.getElementsByTagName('script');
|
| 16 |
return scripts[scripts.length - 1] || null;
|
|
|
|
| 47 |
}
|
| 48 |
}
|
| 49 |
|
| 50 |
+
// Charge un CSS externe une seule fois
|
| 51 |
+
function ensureCssLink(href) {
|
| 52 |
+
if (!href) return;
|
| 53 |
+
var existing = Array.prototype.slice.call(document.querySelectorAll('link[rel="stylesheet"]'))
|
| 54 |
+
.some(function (link) { return link.href === href; });
|
| 55 |
+
if (existing) return;
|
| 56 |
+
var linkEl = document.createElement('link');
|
| 57 |
+
linkEl.rel = 'stylesheet';
|
| 58 |
+
linkEl.href = href;
|
| 59 |
+
document.head.appendChild(linkEl);
|
| 60 |
+
}
|
| 61 |
+
|
| 62 |
// ============ PlayCanvas version fixée (Android/Desktop) ============
|
| 63 |
var PC_VERSION = "2.11.7";
|
| 64 |
var PC_URLS = {
|
|
|
|
| 118 |
}
|
| 119 |
}
|
| 120 |
|
| 121 |
+
// ============ Overlay commun (structure DOM) ============
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
function ensureOverlayRoot() {
|
| 123 |
var r = document.getElementById("xr-overlay-root");
|
| 124 |
if (!r) {
|
|
|
|
| 154 |
}
|
| 155 |
}
|
| 156 |
|
| 157 |
+
// Canvas monté dans un conteneur (Squarespace-friendly)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 158 |
function ensureCanvas() {
|
| 159 |
var scriptEl = getCurrentScript();
|
| 160 |
var mountSel = scriptEl && scriptEl.getAttribute('data-mount');
|
| 161 |
var desiredHeight = (scriptEl && scriptEl.getAttribute('data-height')) || '70vh';
|
| 162 |
|
|
|
|
| 163 |
var mountEl = null;
|
| 164 |
if (mountSel) mountEl = document.querySelector(mountSel);
|
| 165 |
if (!mountEl) {
|
|
|
|
| 166 |
mountEl = document.createElement('div');
|
| 167 |
mountEl.id = 'ar-mount-fallback';
|
| 168 |
document.body.insertBefore(mountEl, document.body.firstChild);
|
| 169 |
}
|
| 170 |
|
| 171 |
+
// Styles minimaux structurels (pas de "design", laissé au CSS externe)
|
| 172 |
var mountStyle = mountEl.style;
|
| 173 |
if (!mountStyle.position) mountStyle.position = 'relative';
|
| 174 |
mountStyle.width = mountStyle.width || '100%';
|
|
|
|
| 176 |
mountStyle.touchAction = mountStyle.touchAction || 'manipulation';
|
| 177 |
mountStyle.webkitTapHighlightColor = 'transparent';
|
| 178 |
|
|
|
|
| 179 |
var canvas = mountEl.querySelector('#application-canvas');
|
| 180 |
if (!canvas) {
|
| 181 |
canvas = document.createElement('canvas');
|
|
|
|
| 183 |
mountEl.appendChild(canvas);
|
| 184 |
}
|
| 185 |
|
| 186 |
+
// Positionne le canvas en plein dans son conteneur
|
| 187 |
var cs = canvas.style;
|
| 188 |
cs.position = 'absolute';
|
| 189 |
cs.left = '0';
|
|
|
|
| 192 |
cs.height = '100%';
|
| 193 |
cs.display = 'block';
|
| 194 |
|
|
|
|
| 195 |
try {
|
| 196 |
mountEl.scrollIntoView({ behavior: 'instant', block: 'start' });
|
| 197 |
} catch (_) {}
|
|
|
|
| 216 |
return p;
|
| 217 |
}
|
| 218 |
|
| 219 |
+
// Bouton "Lancer l'AR" + (iOS) ancre rel=ar cachée
|
| 220 |
+
function ensureLaunchControls(USDZ_URL) {
|
| 221 |
+
var btn = document.getElementById('ar-launch-btn');
|
| 222 |
+
if (!btn) {
|
| 223 |
+
btn = document.createElement('button');
|
| 224 |
+
btn.id = 'ar-launch-btn';
|
| 225 |
+
btn.type = 'button';
|
| 226 |
+
btn.textContent = 'Lancer l’AR';
|
| 227 |
+
// Ne laisse pas le bouton déclencher des interactions scène
|
| 228 |
+
btn.addEventListener('pointerdown', function (e) { e.stopPropagation(); }, { passive: true });
|
| 229 |
+
btn.addEventListener('click', function (e) { e.stopPropagation(); }, false);
|
| 230 |
+
document.body.appendChild(btn);
|
| 231 |
+
}
|
| 232 |
+
|
| 233 |
+
var anchor = document.getElementById('ios-quicklook-anchor');
|
| 234 |
+
if (isIOS()) {
|
| 235 |
+
if (!anchor) {
|
| 236 |
+
anchor = document.createElement('a');
|
| 237 |
+
anchor.id = 'ios-quicklook-anchor';
|
| 238 |
+
anchor.setAttribute('rel', 'ar');
|
| 239 |
+
document.body.appendChild(anchor);
|
| 240 |
+
}
|
| 241 |
+
if (USDZ_URL) {
|
| 242 |
+
anchor.setAttribute('href', buildQuickLookHref(USDZ_URL));
|
| 243 |
+
}
|
| 244 |
+
}
|
| 245 |
+
return { btn: btn, anchor: anchor || null };
|
| 246 |
+
}
|
| 247 |
+
|
| 248 |
+
// ============ Boot : charge CSS, config, route iOS vs Android/Desktop ============
|
| 249 |
(async function () {
|
| 250 |
+
// CSS externe
|
| 251 |
+
ensureCssLink("https://huggingface.co/spaces/MikaFil/VR/resolve/main/css/style.css");
|
| 252 |
+
|
| 253 |
+
// Config
|
| 254 |
var cfgUrl = findConfigUrl();
|
| 255 |
var cfg = await loadConfigJson(cfgUrl);
|
| 256 |
var GLB_URL = (cfg && typeof cfg.glb_url === "string" && cfg.glb_url) ?
|
|
|
|
| 260 |
cfg.usdz_url :
|
| 261 |
null;
|
| 262 |
|
| 263 |
+
// Bouton (Android & iOS) + ancre QuickLook (iOS)
|
| 264 |
+
var controls = ensureLaunchControls(USDZ_URL);
|
| 265 |
+
var launchBtn = controls.btn;
|
| 266 |
+
var iosAnchor = controls.anchor;
|
| 267 |
+
|
| 268 |
if (isIOS()) {
|
| 269 |
if (USDZ_URL) {
|
| 270 |
+
message("iOS détecté : appuyez sur « Lancer l’AR » pour ouvrir Quick Look.");
|
| 271 |
+
launchBtn.onclick = function (e) {
|
| 272 |
+
e.preventDefault();
|
| 273 |
+
e.stopPropagation();
|
| 274 |
+
if (iosAnchor && iosAnchor.href) iosAnchor.click();
|
| 275 |
+
};
|
| 276 |
} else {
|
| 277 |
message("iOS détecté, mais aucun 'usdz_url' dans config.json.");
|
| 278 |
+
launchBtn.disabled = true;
|
| 279 |
+
launchBtn.style.opacity = '0.5';
|
| 280 |
}
|
| 281 |
return;
|
| 282 |
}
|
| 283 |
|
| 284 |
+
// Android / Desktop : charger PlayCanvas et initialiser l’app
|
| 285 |
try {
|
| 286 |
await loadPlayCanvasRobust({ esmFirst: true, loadTimeoutMs: 15000 });
|
| 287 |
} catch (e) {
|
| 288 |
console.error("Chargement PlayCanvas échoué ->", e);
|
| 289 |
message("Impossible de charger PlayCanvas (réseau/CDN). Réessaie plus tard.");
|
| 290 |
+
launchBtn.disabled = true;
|
| 291 |
+
launchBtn.style.opacity = '0.5';
|
| 292 |
return;
|
| 293 |
}
|
| 294 |
+
|
| 295 |
+
var activateARRef = { fn: null };
|
| 296 |
+
initARApp(GLB_URL, activateARRef);
|
| 297 |
+
|
| 298 |
+
launchBtn.onclick = function (e) {
|
| 299 |
+
e.preventDefault();
|
| 300 |
+
e.stopPropagation();
|
| 301 |
+
if (typeof activateARRef.fn === 'function') activateARRef.fn();
|
| 302 |
+
};
|
| 303 |
})();
|
| 304 |
|
| 305 |
// ============ App Android/Desktop (WebXR) ============
|
| 306 |
+
function initARApp(GLB_URL, activateARRef) {
|
| 307 |
var pc = window.pc;
|
| 308 |
var canvas = ensureCanvas();
|
| 309 |
var ui = ensureSliderUI();
|
|
|
|
| 419 |
return e;
|
| 420 |
}
|
| 421 |
|
| 422 |
+
// Euler de base
|
| 423 |
var baseEulerX = 0, baseEulerZ = 0;
|
| 424 |
|
| 425 |
// Rotation via slider (0..360, 360 en haut / 0 en bas)
|
|
|
|
| 472 |
baseEulerX = initE.x; baseEulerZ = initE.z;
|
| 473 |
|
| 474 |
modelLoaded = true;
|
| 475 |
+
message("Modèle chargé. Appuyez sur « Lancer l’AR » pour démarrer.");
|
| 476 |
});
|
| 477 |
|
| 478 |
if (!app.xr.supported) { message("WebXR n’est pas supporté sur cet appareil."); return; }
|
|
|
|
| 526 |
document.addEventListener("pointerup", endDrag, { capture: true, passive: false });
|
| 527 |
document.addEventListener("pointercancel", endDrag, { capture: true, passive: false });
|
| 528 |
|
| 529 |
+
// --- Démarrage AR (Android/Desktop) — exposé via activateARRef.fn et bouton
|
| 530 |
function activateAR() {
|
| 531 |
if (!app.xr.isAvailable(pc.XRTYPE_AR)) { message("AR immersive indisponible sur cet appareil."); return; }
|
| 532 |
if (!app.xr.domOverlay) app.xr.domOverlay = {};
|
|
|
|
| 542 |
}
|
| 543 |
});
|
| 544 |
}
|
| 545 |
+
if (activateARRef && typeof activateARRef === 'object') {
|
| 546 |
+
activateARRef.fn = activateAR;
|
| 547 |
+
}
|
| 548 |
+
|
| 549 |
+
// Tap écran (optionnel, on le conserve)
|
| 550 |
app.mouse.on("mousedown", function () { if (!app.xr.active && !uiInteracting) activateAR(); });
|
| 551 |
if (app.touch) {
|
| 552 |
app.touch.on("touchend", function (evt) {
|
|
|
|
| 669 |
app.xr.on("available:" + pc.XRTYPE_AR, function (a) {
|
| 670 |
if (!a) message("AR immersive indisponible.");
|
| 671 |
else if (!app.xr.hitTest.supported) message("AR Hit Test non supporté.");
|
| 672 |
+
else message(modelLoaded ? "Touchez l’écran ou « Lancer l’AR »." : "Chargement du modèle…");
|
| 673 |
});
|
| 674 |
|
| 675 |
if (!app.xr.isAvailable(pc.XRTYPE_AR)) message("AR immersive indisponible.");
|