This commit is contained in:
33333-33333 2026-06-26 19:04:32 +09:00
commit 077d4ab9ac
71 changed files with 2905 additions and 1063 deletions

View file

@ -107,13 +107,6 @@
return true;
}
function isClientOverFrozenPanel(clientX, clientY) {
const panel = document.getElementById("frozenPanel");
if (!panel) return false;
const r = panel.getBoundingClientRect();
return clientX >= r.left && clientX <= r.right && clientY >= r.top && clientY <= r.bottom;
}
function rememberGrabOrigin(target) {
if (!target || uiCache.grabKind !== "tarinai") return;
uiCache.grabOrigin = { x: target.x, y: target.y, vx: target.vx || 0, vy: target.vy || 0 };
@ -121,11 +114,7 @@
function finishTarinaiGrab(target, clientX, clientY) {
if (!target || uiCache.grabKind !== "tarinai") return false;
if (isClientOverFrozenPanel(clientX, clientY) && global.TarinaiFreezeSystem?.freezeTarinai) {
global.TarinaiFreezeSystem.freezeTarinai(target, world);
uiCache.grabOrigin = null;
return true;
}
const p = screenToWorldClient(clientX, clientY);
if (!p.inside && uiCache.grabOrigin) {
target.x = uiCache.grabOrigin.x;
@ -165,6 +154,7 @@
if (options.notifyNoTarget) showToast("\u3064\u307e\u3081\u308b\u5bfe\u8c61\u304c\u3042\u308a\u307e\u305b\u3093\u3002");
return false;
}
global.TarinaiHistory?.capture?.(world, "pinch");
audio.grab?.();
uiCache.grabbing = true;
uiCache.grabMoved = false;
@ -202,6 +192,8 @@
const dy = p.y - (uiCache.grabLastWorldY ?? p.y);
uiCache.grabLastWorldX = p.x;
uiCache.grabLastWorldY = p.y;
const beforeX = Number(target.x || 0) || 0;
const beforeY = Number(target.y || 0) || 0;
const pad = target.radius || target.r || 16;
if (uiCache.grabKind === "tarinai" && !p.inside) {
const raw = clientToWorldRaw(clientX, clientY);
@ -211,6 +203,14 @@
target.x = clamp(p.x, CONFIG.worldPadding + pad * 0.15, world.w - CONFIG.worldPadding - pad * 0.15);
target.y = clamp(p.y, CONFIG.worldPadding + pad * 0.15, world.h - CONFIG.worldPadding - pad * 0.15);
}
const movedX = (Number(target.x || 0) || 0) - beforeX;
const movedY = (Number(target.y || 0) || 0) - beforeY;
if (uiCache.grabKind === "item" && target.type === "reciprocator") {
target.reciprocatorAnchorX = (Number(target.reciprocatorAnchorX || beforeX) || beforeX) + movedX;
target.reciprocatorAnchorY = (Number(target.reciprocatorAnchorY || beforeY) || beforeY) + movedY;
target.prevX = target.x;
target.prevY = target.y;
}
target.vx = clamp(dx * 16, -160, 160);
target.vy = clamp(dy * 16, -160, 160);
if (uiCache.grabKind === "tarinai") {
@ -266,6 +266,7 @@
}
function beginHose(p, clientX, clientY, options = {}) {
global.TarinaiHistory?.capture?.(world, "water-hose");
audio.waterHose?.();
uiCache.hosing = true;
uiCache.hoseMoved = false;
@ -273,13 +274,16 @@
uiCache.hoseLastWorldY = p.y;
uiCache.hoseStartX = clientX;
uiCache.hoseStartY = clientY;
world.applyWaterHose?.(p.x, p.y, 0, 0, 0.10);
uiCache.hoseLastApplyAt = global.performance?.now?.() || Date.now();
world.applyWaterHose?.(p.x, p.y, 0, 0, 0.18);
if (options.touchMode) uiCache.touchMode = options.touchMode;
render();
return true;
}
function moveHose(p, clientX, clientY, options = {}) {
uiCache.hoseLastClientX = clientX;
uiCache.hoseLastClientY = clientY;
const dx = p.x - (uiCache.hoseLastWorldX ?? p.x);
const dy = p.y - (uiCache.hoseLastWorldY ?? p.y);
uiCache.hoseLastWorldX = p.x;
@ -289,7 +293,12 @@
uiCache.hoseMoved = true;
if (options.touch) uiCache.touchMoved = true;
}
if (p.inside) world.applyWaterHose?.(p.x, p.y, dx, dy, 0.10);
if (p.inside) {
const now = global.performance?.now?.() || Date.now();
const elapsed = Math.max(0.06, Math.min(0.22, (now - (uiCache.hoseLastApplyAt || now)) / 1000));
uiCache.hoseLastApplyAt = now;
world.applyWaterHose?.(p.x, p.y, dx, dy, elapsed);
}
canvas.style.cursor = "crosshair";
render();
}
@ -297,12 +306,57 @@
function endHose() {
if (!uiCache.hosing) return false;
uiCache.hosing = false;
uiCache.hoseLastApplyAt = 0;
canvas.style.cursor = cursorForTool(world.tool);
world.rebuildSpatial?.();
renderStats();
return true;
}
function beginAreaDelete(p, clientX, clientY, options = {}) {
global.TarinaiHistory?.capture?.(world, "area-delete");
uiCache.areaDeleting = true;
uiCache.areaDeleteMoved = false;
uiCache.areaDeleteStartX = clientX;
uiCache.areaDeleteStartY = clientY;
uiCache.areaDeleteLastWorldX = p.x;
uiCache.areaDeleteLastWorldY = p.y;
world._areaDeleteDragRemoved = 0;
if (p.inside) world.deleteItemsInArea?.(p.x, p.y, { silentEmpty: true, silentLog: true, drag: true });
if (options.touchMode) uiCache.touchMode = options.touchMode;
render();
return true;
}
function moveAreaDelete(p, clientX, clientY, options = {}) {
const totalMove = Math.hypot(clientX - (uiCache.areaDeleteStartX || clientX), clientY - (uiCache.areaDeleteStartY || clientY));
if (totalMove > 3) {
uiCache.areaDeleteMoved = true;
if (options.touch) uiCache.touchMoved = true;
}
if (p.inside) world.deleteItemsInArea?.(p.x, p.y, { silentEmpty: true, silentLog: true, drag: true });
canvas.style.cursor = "crosshair";
render();
return true;
}
function endAreaDelete() {
if (!uiCache.areaDeleting) return false;
uiCache.areaDeleting = false;
const removed = world._areaDeleteDragRemoved || 0;
world._areaDeleteDragRemoved = 0;
canvas.style.cursor = cursorForTool(world.tool);
world.rebuildSpatial?.();
renderStats();
if (removed > 0) {
world.log?.(`範囲削除で${removed}個消した。`, "observe");
showToast(`${removed}個消しました。`);
}
return true;
}
function beginPan(clientX, clientY, button = null) {
uiCache.panning = true;
uiCache.panMoved = false;
@ -354,6 +408,8 @@
uiCache.touchMode = "";
uiCache.touchMoved = false;
uiCache.hosing = false;
if (uiCache.hoseHoldTimer) { clearInterval(uiCache.hoseHoldTimer); uiCache.hoseHoldTimer = null; }
uiCache.areaDeleting = false;
uiCache.grabbing = false;
uiCache.grabTarget = null;
uiCache.grabKind = "";
@ -382,6 +438,9 @@
beginHose,
moveHose,
endHose,
beginAreaDelete,
moveAreaDelete,
endAreaDelete,
beginPan,
movePan,
endPan,