Ajustou grid à face inferior
X-Lovable-Edit-ID: edt-9adbb18a-f106-4dcf-a001-1173b3d4655d Co-authored-by: Reifonas <211114984+Reifonas@users.noreply.github.com>
This commit is contained in:
@@ -1035,25 +1035,27 @@ function GridLayer() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Computes min Y of all visible models and updates store gridY when auto-follow is on. */
|
/** Continuously aligns the grid Y to the bottom of all visible models so the
|
||||||
|
* piece always looks like it is sitting on the grid — including after
|
||||||
|
* calibration, fine-tuning, repositioning or scale changes. */
|
||||||
function GridAutoFollower() {
|
function GridAutoFollower() {
|
||||||
const models = useModelStore((s) => s.models);
|
|
||||||
const { scene } = useThree();
|
const { scene } = useThree();
|
||||||
useEffect(() => {
|
const lastY = useRef<number>(Number.NaN);
|
||||||
|
const acc = useRef(0);
|
||||||
|
useFrame((_, dt) => {
|
||||||
const auto = useModelStore.getState().gridAutoFollow;
|
const auto = useModelStore.getState().gridAutoFollow;
|
||||||
if (!auto) return;
|
if (!auto) return;
|
||||||
// Defer to next tick so models have rendered/positioned
|
// Throttle to ~10 Hz to keep this cheap.
|
||||||
const id = setTimeout(() => {
|
acc.current += dt;
|
||||||
if (!useModelStore.getState().gridAutoFollow) return;
|
if (acc.current < 0.1) return;
|
||||||
|
acc.current = 0;
|
||||||
const box = new THREE.Box3();
|
const box = new THREE.Box3();
|
||||||
let has = false;
|
let has = false;
|
||||||
scene.traverse((obj) => {
|
scene.traverse((obj) => {
|
||||||
if (obj instanceof THREE.Mesh && obj.geometry) {
|
if (obj instanceof THREE.Mesh && obj.geometry) {
|
||||||
// Skip helpers (markers, rings)
|
|
||||||
if (obj.geometry instanceof THREE.SphereGeometry) return;
|
if (obj.geometry instanceof THREE.SphereGeometry) return;
|
||||||
if (obj.geometry instanceof THREE.RingGeometry) return;
|
if (obj.geometry instanceof THREE.RingGeometry) return;
|
||||||
if (obj.userData.__edgeLine) return;
|
if (obj.userData.__edgeLine) return;
|
||||||
obj.updateWorldMatrix(true, false);
|
|
||||||
const b = new THREE.Box3().setFromObject(obj);
|
const b = new THREE.Box3().setFromObject(obj);
|
||||||
if (isFinite(b.min.y)) {
|
if (isFinite(b.min.y)) {
|
||||||
if (!has) { box.copy(b); has = true; }
|
if (!has) { box.copy(b); has = true; }
|
||||||
@@ -1061,12 +1063,13 @@ function GridAutoFollower() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (has) {
|
if (!has) return;
|
||||||
useModelStore.setState({ gridY: box.min.y - 0.005 });
|
const target = box.min.y - 0.005;
|
||||||
|
if (!Number.isFinite(lastY.current) || Math.abs(target - lastY.current) > 1e-4) {
|
||||||
|
lastY.current = target;
|
||||||
|
useModelStore.setState({ gridY: target });
|
||||||
}
|
}
|
||||||
}, 100);
|
});
|
||||||
return () => clearTimeout(id);
|
|
||||||
}, [models, scene]);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user