This commit is contained in:
33333-33333 2026-07-10 16:40:06 +09:00
commit 2636d580a8
75 changed files with 3890 additions and 1084 deletions

View file

@ -154,18 +154,39 @@ function bindUI() {
ui.temperatureSlider?.addEventListener("input", applyTemperatureSlider);
ui.temperatureSlider?.addEventListener("change", applyTemperatureSlider);
const applyColonyLimit = (kind) => {
const colonyLimitControls = (kind) => kind === "tarinai"
? { slider: ui.tarinaiPopulationLimitSlider, input: ui.tarinaiPopulationLimitInput }
: { slider: ui.objectLimitSlider, input: ui.objectLimitInput };
const syncColonyLimitControls = (kind, value) => {
const { slider, input } = colonyLimitControls(kind);
const limit = Math.max(0, Math.floor(Number(value || 0) || 0));
if (input && document.activeElement !== input) input.value = limit > 0 ? String(limit) : "";
if (slider && document.activeElement !== slider) {
const max = Math.max(0, Number(slider.max || 0) || 0);
slider.value = String(max > 0 ? Math.min(limit, max) : limit);
slider.setAttribute("aria-valuetext", limit > 0 ? String(limit) : "\u4e0a\u9650\u306a\u3057");
}
};
window.syncColonyLimitControls = syncColonyLimitControls;
const applyColonyLimit = (kind, source = "number") => {
if (!world) return;
const input = kind === "tarinai" ? ui.tarinaiPopulationLimitInput : ui.objectLimitInput;
if (!input) return;
const value = input.value.trim() === "" ? 0 : Number(input.value);
const { slider, input } = colonyLimitControls(kind);
const sourceEl = String(source).startsWith("slider") ? slider : input;
if (!sourceEl) return;
const raw = sourceEl.value?.trim?.() === "" ? 0 : Number(sourceEl.value);
const value = Math.max(0, Math.floor(Number(raw) || 0));
if (kind === "tarinai") world.setTarinaiPopulationLimit?.(value);
else world.setObjectLimit?.(value);
audio.uiClick?.();
syncColonyLimitControls(kind, value);
if (source !== "slider-live") audio.uiClick?.();
renderStats?.();
};
ui.tarinaiPopulationLimitInput?.addEventListener("change", () => applyColonyLimit("tarinai"));
ui.objectLimitInput?.addEventListener("change", () => applyColonyLimit("object"));
ui.tarinaiPopulationLimitSlider?.addEventListener("input", () => applyColonyLimit("tarinai", "slider-live"));
ui.tarinaiPopulationLimitSlider?.addEventListener("change", () => applyColonyLimit("tarinai", "slider"));
ui.objectLimitSlider?.addEventListener("input", () => applyColonyLimit("object", "slider-live"));
ui.objectLimitSlider?.addEventListener("change", () => applyColonyLimit("object", "slider"));
ui.tarinaiPopulationLimitInput?.addEventListener("change", () => applyColonyLimit("tarinai", "number"));
ui.objectLimitInput?.addEventListener("change", () => applyColonyLimit("object", "number"));
ui.panel?.addEventListener("scroll", () => {
const panel = ui.panel;
@ -335,6 +356,24 @@ function bindUI() {
uiCache.lastChartDraw = "";
renderStats();
});
const toggleChartSeries = (target) => {
const icon = target?.closest?.("i[data-series-key]");
if (!icon) return false;
const key = String(icon.dataset.seriesKey || "");
if (!key) return false;
if (!(uiCache.chartHiddenSeries instanceof Set)) uiCache.chartHiddenSeries = new Set();
if (uiCache.chartHiddenSeries.has(key)) uiCache.chartHiddenSeries.delete(key);
else uiCache.chartHiddenSeries.add(key);
uiCache.lastChartDraw = "";
audio.uiClick?.();
renderStats();
return true;
};
ui.colonyChartLegend?.addEventListener("click", (e) => toggleChartSeries(e.target));
ui.colonyChartLegend?.addEventListener("keydown", (e) => {
if (e.key !== "Enter" && e.key !== " ") return;
if (toggleChartSeries(e.target)) e.preventDefault();
});
ui.logPushEnabled?.addEventListener("change", () => {
uiCache.logPushEnabled = Boolean(ui.logPushEnabled.checked);
audio.notify?.();
@ -546,6 +585,34 @@ function bindUI() {
showToast("\u5bb6\u7cfb\u56f3\u3092\u30ea\u30bb\u30c3\u30c8\u3057\u307e\u3057\u305f\u3002");
});
const TOOL_SHORTCUTS = window.TarinaiItemToolMetadata?.TOOL_SHORTCUTS || {};
const TOOL_BY_SHORTCUT = Object.freeze(Object.fromEntries(Object.entries(TOOL_SHORTCUTS).map(([tool, key]) => [String(key), tool])));
const isKeyboardTypingTarget = (target) => {
const tag = String(target?.tagName || "").toLowerCase();
return tag === "input" || tag === "textarea" || tag === "select" || Boolean(target?.isContentEditable);
};
function activateControlTool(tool) {
if (!tool || !world) return false;
audio.uiClick?.();
if (tool === "undo" || tool === "redo") {
const result = window.TarinaiCommands.dispatch(world, { type: tool === "undo" ? "history.undo" : "history.redo" });
showToast(result?.ok ? (tool === "undo" ? "Undo" : "Redo") : (tool === "undo" ? "Nothing to undo" : "Nothing to redo"));
renderStats();
return true;
}
if (tool === "clear_tool") {
world.pendingLinkEndpoint = null;
world.copyBuffer = null;
selectTool("observe");
for (const b of uiCache.toolButtons || []) b.classList.remove("selected");
showToast("\u9053\u5177\u9078\u629E\u3092\u89E3\u9664\u3057\u307E\u3057\u305F\u3002");
return true;
}
if (world.tool === tool && cycleToolSize(tool)) return true;
selectTool(tool);
return true;
}
ui.toolPalette?.addEventListener("click", (e) => {
const toggle = e.target.closest(".tool-category-toggle");
if (toggle) {
@ -564,24 +631,16 @@ function bindUI() {
e.stopPropagation();
return;
}
const tool = btn.dataset.tool;
audio.uiClick?.();
if (tool === "undo" || tool === "redo") {
const result = window.TarinaiCommands.dispatch(world, { type: tool === "undo" ? "history.undo" : "history.redo" });
showToast(result?.ok ? (tool === "undo" ? "\u623b\u3057\u307e\u3057\u305f\u3002" : "\u9032\u3081\u307e\u3057\u305f\u3002") : (tool === "undo" ? "\u623b\u305b\u308b\u64cd\u4f5c\u304c\u3042\u308a\u307e\u305b\u3093\u3002" : "\u9032\u3081\u308b\u64cd\u4f5c\u304c\u3042\u308a\u307e\u305b\u3093\u3002"));
renderStats();
return;
}
if (tool === "clear_tool") {
world.pendingLinkEndpoint = null;
world.copyBuffer = null;
selectTool("observe");
for (const b of uiCache.toolButtons || []) b.classList.remove("selected");
showToast("\u9053\u5177\u9078\u629E\u3092\u89E3\u9664\u3057\u307E\u3057\u305F\u3002");
return;
}
if (world.tool === tool && cycleToolSize(tool)) return;
selectTool(tool);
activateControlTool(btn.dataset.tool);
});
window.addEventListener("keydown", (e) => {
if (e.defaultPrevented || e.ctrlKey || e.metaKey || e.altKey || e.isComposing) return;
if (isKeyboardTypingTarget(e.target)) return;
const tool = TOOL_BY_SHORTCUT[String(e.key || "")];
if (!tool) return;
e.preventDefault();
activateControlTool(tool);
});
const normalizedWheelDeltaY = (e) => {