fix(nds): wrong 3d click detection

This commit is contained in:
2026-02-12 18:24:13 +01:00
parent 0bc8378bcb
commit a5be493b54

View File

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