"use strict"; // Shared pointer action router for mouse and touch. Keeps long-hold timers, // drag movement thresholds, and tap suppression consistent across input types. (function (global) { const DRAG_THRESHOLD = 3; function createPointerActionManager(ctx) { if (!ctx?.canvas || !ctx?.world || !ctx?.uiCache) return null; const { canvas, world, uiCache } = ctx; function clearHoseHoldTimer() { if (uiCache.hoseHoldTimer) { clearInterval(uiCache.hoseHoldTimer); uiCache.hoseHoldTimer = null; } } function ensureHoseHoldTimer(clientX, clientY, options = {}) { clearHoseHoldTimer(); uiCache.hoseHoldTimer = setInterval(() => { if (!uiCache.hosing) { clearHoseHoldTimer(); return; } const cx = uiCache.hoseLastClientX || uiCache.touchLastX || clientX; const cy = uiCache.hoseLastClientY || uiCache.touchLastY || clientY; const hp = ctx.screenToWorldClient(cx, cy); ctx.moveHose(hp, cx, cy, { touch: Boolean(options.touch) }); }, 90); } function beginToolAt(p, clientX, clientY, options = {}) { if (!p?.inside) return false; const tool = String(world.tool || ""); if (tool === "area_delete") { return Boolean(ctx.beginAreaDelete(p, clientX, clientY, options)); } if (tool === "water_hose") { const started = Boolean(ctx.beginHose(p, clientX, clientY, options)); if (started) ensureHoseHoldTimer(clientX, clientY, options); return started; } if (tool === "shoot") { return Boolean(ctx.beginShoot(p, clientX, clientY, options)); } if (tool === "pinch") { const started = Boolean(ctx.beginGrab(p, clientX, clientY, options)); if (started) canvas.style.cursor = "grabbing"; return started; } return false; } function moveActive(p, clientX, clientY, options = {}) { if (uiCache.areaDeleting) return Boolean(ctx.moveAreaDelete(p, clientX, clientY, options) || true); if (uiCache.hosing) return Boolean(ctx.moveHose(p, clientX, clientY, options) || true); if (uiCache.shooting) return Boolean(ctx.moveShoot(p, clientX, clientY, options)); if (uiCache.grabbing) { const sx = uiCache.grabStartX || clientX; const sy = uiCache.grabStartY || clientY; if (Math.hypot(clientX - sx, clientY - sy) > DRAG_THRESHOLD) { uiCache.grabMoved = true; if (options.touch) uiCache.touchMoved = true; } return Boolean(ctx.moveGrab(p, clientX, clientY, options)); } return false; } function endActive(clientX = 0, clientY = 0) { if (ctx.endAreaDelete()) return true; if (ctx.endHose()) { clearHoseHoldTimer(); return true; } if (ctx.endShoot()) return true; if (ctx.endGrab(clientX, clientY)) return true; return false; } function shouldSuppressClick() { const flags = ["areaDeleteMoved", "hoseMoved", "grabMoved", "shootSuppressClick", "panMoved"]; for (const key of flags) { if (uiCache[key]) { uiCache[key] = false; return true; } } return false; } function dispatchTapAt(p) { if (!p?.inside) return false; global.TarinaiCommands.dispatch(world, { type: "pointer.primary", x: p.x, y: p.y }); global.renderStats?.(); return true; } function dispatchTapClient(clientX, clientY) { return dispatchTapAt(ctx.screenToWorldClient(clientX, clientY)); } function cancel() { clearHoseHoldTimer(); ctx.cancelPointerActions?.(); } return Object.freeze({ beginToolAt, moveActive, endActive, shouldSuppressClick, dispatchTapAt, dispatchTapClient, cancel, }); } global.TarinaiPointerActionSystem = Object.freeze({ create: createPointerActionManager }); })(typeof window !== "undefined" ? window : globalThis);