fix(nds): wrong 3d click detection

This commit is contained in:
2026-02-12 18:24:13 +01:00
parent a751c1a150
commit 161b22259a

View File

@@ -274,12 +274,7 @@ const pressButton = (button: string) => {
window.dispatchEvent(new KeyboardEvent("keydown", { key: `NDS_${button}` }));
};
const handleClick = (event: MouseEvent) => {
if (!hasAnimated.value) {
animateIntro();
return;
}
const raycast = (event: MouseEvent) => {
const domElement = renderer.instance.domElement;
const rect = domElement.getBoundingClientRect();
@@ -293,32 +288,50 @@ const handleClick = (event: MouseEvent) => {
);
const intersects = raycaster.intersectObjects(model.children, true);
const intersection = intersects[0];
return intersects[0];
};
const getScreenCanvas = (name: string) => {
if (name === TOP_SCREEN) return props.topScreenCanvas;
if (name === BOTTOM_SCREEN) return props.bottomScreenCanvas;
return null;
};
const dispatchScreenEvent = (
type: string,
canvas: HTMLCanvasElement,
intersection: THREE.Intersection,
) => {
if (!intersection.uv) return;
const logicalX = (1 - intersection.uv.x) * LOGICAL_WIDTH;
const logicalY = (1 - intersection.uv.y) * LOGICAL_HEIGHT;
const rect = canvas.getBoundingClientRect();
canvas.dispatchEvent(
new MouseEvent(type, {
bubbles: true,
cancelable: true,
clientX: (logicalX / LOGICAL_WIDTH) * rect.width + rect.left,
clientY: (logicalY / LOGICAL_HEIGHT) * rect.height + rect.top,
}),
);
};
const handleMouseDown = (event: MouseEvent) => {
if (!hasAnimated.value) {
animateIntro();
return;
}
const intersection = raycast(event);
if (!intersection?.uv) return;
switch (intersection.object.name) {
case TOP_SCREEN:
case BOTTOM_SCREEN: {
const canvas =
intersection.object.name === TOP_SCREEN
? props.topScreenCanvas
: props.bottomScreenCanvas;
if (!canvas) break;
const logicalX = (1 - intersection.uv.x) * LOGICAL_WIDTH;
const logicalY = (1 - intersection.uv.y) * LOGICAL_HEIGHT;
const rect = canvas.getBoundingClientRect();
canvas.dispatchEvent(
new MouseEvent("click", {
bubbles: true,
cancelable: true,
clientX: (logicalX / LOGICAL_WIDTH) * rect.width + rect.left,
clientY: (logicalY / LOGICAL_HEIGHT) * rect.height + rect.top,
}),
);
const canvas = getScreenCanvas(intersection.object.name);
if (canvas) dispatchScreenEvent("mousedown", canvas, intersection);
break;
}
@@ -361,6 +374,16 @@ const handleClick = (event: MouseEvent) => {
}
};
const handleClick = (event: MouseEvent) => {
if (!hasAnimated.value) return;
const intersection = raycast(event);
if (!intersection?.uv) return;
const canvas = getScreenCanvas(intersection.object.name);
if (canvas) dispatchScreenEvent("click", canvas, intersection);
};
const handleMouseUp = () => {
if (mousePressedButton) {
physicalButtonsDown.delete(mousePressedButton);
@@ -377,14 +400,19 @@ onMounted(() => {
app.ready = true;
if (renderer) {
renderer.instance.domElement.addEventListener("mousedown", handleClick);
renderer.instance.domElement.addEventListener("mousedown", handleMouseDown);
renderer.instance.domElement.addEventListener("click", handleClick);
renderer.instance.domElement.addEventListener("mouseup", handleMouseUp);
}
});
onUnmounted(() => {
if (renderer) {
renderer.instance.domElement.removeEventListener("mousedown", handleClick);
renderer.instance.domElement.removeEventListener(
"mousedown",
handleMouseDown,
);
renderer.instance.domElement.removeEventListener("click", handleClick);
renderer.instance.domElement.removeEventListener("mouseup", handleMouseUp);
}
topScreenTexture?.dispose();