🚀 Auto-deploy: melhoria no snap e medição AR em 10/06/2026 23:57:45
This commit is contained in:
@@ -177,7 +177,10 @@ export function XRGrabbable({ allowScale = true, lockedActive = false, onGrabSta
|
|||||||
if (!dual.current) {
|
if (!dual.current) {
|
||||||
group.updateMatrixWorld();
|
group.updateMatrixWorld();
|
||||||
|
|
||||||
// Restrição: Apontar ambos os controles para a caixa delimitadora do modelo
|
// Se o usuário já estava segurando a peça com uma das mãos, transita para o modo dual imediatamente.
|
||||||
|
// Caso contrário (peça solta), exige que ambos os controles apontem para a bounding box da peça.
|
||||||
|
const wasSingleGrabbing = !!single.current;
|
||||||
|
|
||||||
const box = new THREE.Box3().setFromObject(group);
|
const box = new THREE.Box3().setFromObject(group);
|
||||||
const checkPointerCollision = (slot: typeof L) => {
|
const checkPointerCollision = (slot: typeof L) => {
|
||||||
const origin = new THREE.Vector3().setFromMatrixPosition(slot.gripWorld);
|
const origin = new THREE.Vector3().setFromMatrixPosition(slot.gripWorld);
|
||||||
@@ -187,7 +190,7 @@ export function XRGrabbable({ allowScale = true, lockedActive = false, onGrabSta
|
|||||||
return ray.intersectsBox(box);
|
return ray.intersectsBox(box);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (checkPointerCollision(L) && checkPointerCollision(R)) {
|
if (wasSingleGrabbing || (checkPointerCollision(L) && checkPointerCollision(R))) {
|
||||||
dual.current = {
|
dual.current = {
|
||||||
startGroupWorld: group.matrixWorld.clone(),
|
startGroupWorld: group.matrixWorld.clone(),
|
||||||
startMid: midNow.clone(),
|
startMid: midNow.clone(),
|
||||||
@@ -197,7 +200,7 @@ export function XRGrabbable({ allowScale = true, lockedActive = false, onGrabSta
|
|||||||
};
|
};
|
||||||
single.current = null;
|
single.current = null;
|
||||||
if (!everGrabbed.current) { everGrabbed.current = true; onGrabStart?.(); }
|
if (!everGrabbed.current) { everGrabbed.current = true; onGrabStart?.(); }
|
||||||
console.log('[XR][grab] ◆ TWO-HAND start (orbit+zoom) - bounding box hit');
|
console.log('[XR][grab] ◆ TWO-HAND start (orbit+zoom) - ' + (wasSingleGrabbing ? 'from active single grab' : 'bounding box hit'));
|
||||||
} else {
|
} else {
|
||||||
// Se não apontavam para o modelo, ignora e permite o pan de uma mão (da primeira mão a engajar)
|
// Se não apontavam para o modelo, ignora e permite o pan de uma mão (da primeira mão a engajar)
|
||||||
return;
|
return;
|
||||||
@@ -230,7 +233,12 @@ export function XRGrabbable({ allowScale = true, lockedActive = false, onGrabSta
|
|||||||
} else if (dual.current) {
|
} else if (dual.current) {
|
||||||
console.log('[XR][grab] ◆ TWO-HAND end');
|
console.log('[XR][grab] ◆ TWO-HAND end');
|
||||||
dual.current = null;
|
dual.current = null;
|
||||||
syncGrabToStore();
|
// Se a outra mão ainda estiver segurando, NÃO sincronizamos/resetamos o group local ainda.
|
||||||
|
// A transição de duas mãos para uma mão herdará o groupWorldPos correto de forma contínua.
|
||||||
|
const activeHand = lActive ? 'left' : rActive ? 'right' : null;
|
||||||
|
if (!activeHand) {
|
||||||
|
syncGrabToStore();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Modo de Uma Mão: Panorâmica Livre (Arrastar em 3D) ────────
|
// ─── Modo de Uma Mão: Panorâmica Livre (Arrastar em 3D) ────────
|
||||||
|
|||||||
Reference in New Issue
Block a user