feat(utils): useButtonNavigation now exposes pressed button
This commit is contained in:
@@ -3,6 +3,7 @@ const canvas = useTemplateRef("canvas");
|
|||||||
|
|
||||||
const renderCallbacks = new Map<RenderCallback, number>();
|
const renderCallbacks = new Map<RenderCallback, number>();
|
||||||
const screenClickCallbacks = new Set<ScreenClickCallback>();
|
const screenClickCallbacks = new Set<ScreenClickCallback>();
|
||||||
|
const screenMouseDownCallbacks = new Set<ScreenClickCallback>();
|
||||||
const screenMouseWheelCallbacks = new Set<ScreenMouseWheelCallback>();
|
const screenMouseWheelCallbacks = new Set<ScreenMouseWheelCallback>();
|
||||||
|
|
||||||
let ctx: CanvasRenderingContext2D | null = null;
|
let ctx: CanvasRenderingContext2D | null = null;
|
||||||
@@ -20,6 +21,11 @@ const registerScreenClickCallback = (callback: ScreenClickCallback) => {
|
|||||||
return () => screenClickCallbacks.delete(callback);
|
return () => screenClickCallbacks.delete(callback);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const registerScreenMouseDownCallback = (callback: ScreenClickCallback) => {
|
||||||
|
screenMouseDownCallbacks.add(callback);
|
||||||
|
return () => screenMouseDownCallbacks.delete(callback);
|
||||||
|
};
|
||||||
|
|
||||||
const registerScreenMouseWheelCallback = (
|
const registerScreenMouseWheelCallback = (
|
||||||
callback: ScreenMouseWheelCallback,
|
callback: ScreenMouseWheelCallback,
|
||||||
) => {
|
) => {
|
||||||
@@ -42,6 +48,21 @@ const handleCanvasClick = (event: MouseEvent) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCanvasMouseDown = (event: MouseEvent) => {
|
||||||
|
if (!canvas.value) return;
|
||||||
|
|
||||||
|
const rect = canvas.value.getBoundingClientRect();
|
||||||
|
const scaleX = LOGICAL_WIDTH / rect.width;
|
||||||
|
const scaleY = LOGICAL_HEIGHT / rect.height;
|
||||||
|
|
||||||
|
const x = (event.clientX - rect.left) * scaleX;
|
||||||
|
const y = (event.clientY - rect.top) * scaleY;
|
||||||
|
|
||||||
|
for (const callback of screenMouseDownCallbacks) {
|
||||||
|
callback(x, y);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleCanvasWheel = (event: WheelEvent) => {
|
const handleCanvasWheel = (event: WheelEvent) => {
|
||||||
for (const callback of screenMouseWheelCallbacks) {
|
for (const callback of screenMouseWheelCallbacks) {
|
||||||
callback(event.deltaY, event.deltaX);
|
callback(event.deltaY, event.deltaX);
|
||||||
@@ -87,6 +108,7 @@ const renderFrame = (timestamp: number) => {
|
|||||||
|
|
||||||
provide("registerRenderCallback", registerRenderCallback);
|
provide("registerRenderCallback", registerRenderCallback);
|
||||||
provide("registerScreenClickCallback", registerScreenClickCallback);
|
provide("registerScreenClickCallback", registerScreenClickCallback);
|
||||||
|
provide("registerScreenMouseDownCallback", registerScreenMouseDownCallback);
|
||||||
provide("registerScreenMouseWheelCallback", registerScreenMouseWheelCallback);
|
provide("registerScreenMouseWheelCallback", registerScreenMouseWheelCallback);
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
@@ -98,6 +120,7 @@ onMounted(() => {
|
|||||||
ctx.imageSmoothingEnabled = false;
|
ctx.imageSmoothingEnabled = false;
|
||||||
|
|
||||||
canvas.value.addEventListener("click", handleCanvasClick);
|
canvas.value.addEventListener("click", handleCanvasClick);
|
||||||
|
canvas.value.addEventListener("mousedown", handleCanvasMouseDown);
|
||||||
canvas.value.addEventListener("wheel", handleCanvasWheel, { passive: true });
|
canvas.value.addEventListener("wheel", handleCanvasWheel, { passive: true });
|
||||||
|
|
||||||
animationFrameId = requestAnimationFrame(renderFrame);
|
animationFrameId = requestAnimationFrame(renderFrame);
|
||||||
@@ -110,6 +133,7 @@ onUnmounted(() => {
|
|||||||
|
|
||||||
if (canvas.value) {
|
if (canvas.value) {
|
||||||
canvas.value.removeEventListener("click", handleCanvasClick);
|
canvas.value.removeEventListener("click", handleCanvasClick);
|
||||||
|
canvas.value.removeEventListener("mousedown", handleCanvasMouseDown);
|
||||||
canvas.value.removeEventListener("wheel", handleCanvasWheel);
|
canvas.value.removeEventListener("wheel", handleCanvasWheel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -187,7 +187,40 @@ export const useButtonNavigation = <T extends Record<string, Rect>>({
|
|||||||
selectedButton.value = targetButton;
|
selectedButton.value = targetButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
const { onClick } = useScreen();
|
const { onClick, onMouseDown } = useScreen();
|
||||||
|
|
||||||
|
const pressedButton = ref<Entry | null>(null);
|
||||||
|
let lastPressedButton: Entry | null = null;
|
||||||
|
|
||||||
|
onMouseDown((x: number, y: number) => {
|
||||||
|
if (blockInteractions.value) return;
|
||||||
|
|
||||||
|
for (const [buttonName, buttonRect] of Object.entries(buttons) as [
|
||||||
|
Entry,
|
||||||
|
Rect,
|
||||||
|
][]) {
|
||||||
|
const [sx, sy, sw, sh] = buttonRect;
|
||||||
|
if (x >= sx && x <= sx + sw && y >= sy && y <= sy + sh) {
|
||||||
|
if (canClickButton && !canClickButton(buttonName)) continue;
|
||||||
|
|
||||||
|
pressedButton.value = buttonName;
|
||||||
|
lastPressedButton = buttonName;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleMouseUp = () => {
|
||||||
|
pressedButton.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
document.addEventListener("mouseup", handleMouseUp);
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
document.removeEventListener("mouseup", handleMouseUp);
|
||||||
|
});
|
||||||
|
|
||||||
onClick((x: number, y: number) => {
|
onClick((x: number, y: number) => {
|
||||||
if (blockInteractions.value) return;
|
if (blockInteractions.value) return;
|
||||||
@@ -200,6 +233,9 @@ export const useButtonNavigation = <T extends Record<string, Rect>>({
|
|||||||
if (x >= sx && x <= sx + sw && y >= sy && y <= sy + sh) {
|
if (x >= sx && x <= sx + sw && y >= sy && y <= sy + sh) {
|
||||||
if (canClickButton && !canClickButton(buttonName)) continue;
|
if (canClickButton && !canClickButton(buttonName)) continue;
|
||||||
|
|
||||||
|
if (lastPressedButton !== buttonName) break;
|
||||||
|
lastPressedButton = null;
|
||||||
|
|
||||||
if (selectedButton.value === buttonName) {
|
if (selectedButton.value === buttonName) {
|
||||||
onActivate?.(buttonName);
|
onActivate?.(buttonName);
|
||||||
} else {
|
} else {
|
||||||
@@ -328,6 +364,7 @@ export const useButtonNavigation = <T extends Record<string, Rect>>({
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
selected: readonly(selectedButton),
|
selected: readonly(selectedButton),
|
||||||
|
pressed: readonly(pressedButton),
|
||||||
selectorPosition,
|
selectorPosition,
|
||||||
select,
|
select,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ export const useScreen = () => {
|
|||||||
const registerClick = inject<(cb: ScreenClickCallback) => () => void>(
|
const registerClick = inject<(cb: ScreenClickCallback) => () => void>(
|
||||||
"registerScreenClickCallback",
|
"registerScreenClickCallback",
|
||||||
);
|
);
|
||||||
|
const registerMouseDown = inject<(cb: ScreenClickCallback) => () => void>(
|
||||||
|
"registerScreenMouseDownCallback",
|
||||||
|
);
|
||||||
const registerWheel = inject<(cb: ScreenMouseWheelCallback) => () => void>(
|
const registerWheel = inject<(cb: ScreenMouseWheelCallback) => () => void>(
|
||||||
"registerScreenMouseWheelCallback",
|
"registerScreenMouseWheelCallback",
|
||||||
);
|
);
|
||||||
@@ -37,6 +40,15 @@ export const useScreen = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onMouseDown = (callback: ScreenClickCallback) => {
|
||||||
|
onMounted(() => {
|
||||||
|
if (!registerMouseDown)
|
||||||
|
throw new Error("useScreen must be used within a Screen component");
|
||||||
|
const unregister = registerMouseDown(callback);
|
||||||
|
onUnmounted(unregister);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const onMouseWheel = (callback: ScreenMouseWheelCallback) => {
|
const onMouseWheel = (callback: ScreenMouseWheelCallback) => {
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
if (!registerWheel)
|
if (!registerWheel)
|
||||||
@@ -46,5 +58,5 @@ export const useScreen = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return { onRender, onClick, onMouseWheel };
|
return { onRender, onClick, onMouseDown, onMouseWheel };
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user