"use strict"; const SCALABLE_TOOLS = new Set(scalableToolIds()); const TEXT_ICON_TOOL_IDS = new Set(["poke", "pinch", "water_hose", "rope", "rod", "reciprocator", "copy", "undo", "redo", "area_delete", "clear_tool"]); function applyToolTextIcon(btn, def, toolId) { if (!btn || !def?.iconText || !TEXT_ICON_TOOL_IDS.has(toolId)) return false; btn.classList.add("tool-emoji-icon"); btn.style.setProperty("--tool-emoji", JSON.stringify(String(def.iconText))); return true; } function cssToolIconPath(path) { const raw = String(path || "").trim(); if (!raw) return ""; if (/^(?:[a-z]+:|data:|\/)/i.test(raw)) return raw; if (raw.startsWith("../")) return raw; if (raw.startsWith("./assets/")) return `../${raw.slice(2)}`; if (raw.startsWith("assets/")) return `../${raw}`; return raw; } function applyToolImageIcon(btn, def) { if (!btn || !def?.icon) return false; const iconPath = cssToolIconPath(def.icon); if (!iconPath) return false; btn.style.setProperty("--tool-icon", `url(${JSON.stringify(iconPath)})`); return true; } const SIZE_ORDER = window.TarinaiItemToolMetadata?.TOOL_SIZE_ORDER || ["small", "medium", "large"]; const SIZE_LABELS = window.TarinaiItemToolMetadata?.TOOL_SIZE_LABELS || { small: "\u5c0f", medium: "\u4e2d", large: "\u5927" }; function renderToolPalette() { if (!ui?.toolPalette || typeof toolCategories !== "function") return; ui.toolPalette.innerHTML = ""; const frag = document.createDocumentFragment(); for (const category of toolCategories()) { const section = document.createElement("section"); section.className = `tool-category ${category.themeClass || ""}`.trim(); section.dataset.toolCategory = category.id; const mobileCompact = Boolean(window.TarinaiInputMode.classification?.touchFirst || document.body.classList.contains("touch-mobile-ui")); const initiallyCollapsed = mobileCompact && category.id !== "operate"; if (initiallyCollapsed) section.classList.add("collapsed"); const toggle = document.createElement("button"); toggle.className = "tool-category-toggle"; toggle.type = "button"; toggle.setAttribute("aria-expanded", initiallyCollapsed ? "false" : "true"); toggle.textContent = category.label || category.id; const body = document.createElement("div"); body.className = "tool-grid tool-category-body"; for (const toolId of category.toolIds || []) { const def = toolDefinition(toolId); if (!def || def.simulationOnly || toolId === "observe") continue; const btn = document.createElement("button"); btn.className = "tool"; const hasTextIcon = applyToolTextIcon(btn, def, toolId); if (!hasTextIcon) applyToolImageIcon(btn, def); btn.dataset.tool = toolId; btn.dataset.toolCategory = category.id || ""; const label = document.createElement("span"); label.className = "tool-label"; label.textContent = def.label || toolId; btn.setAttribute("aria-label", label.textContent); btn.removeAttribute("title"); btn.appendChild(label); attachToolSpritePreview(btn, def, toolId); if (toolId === world?.tool) btn.classList.add("selected"); body.appendChild(btn); } section.append(toggle, body); frag.appendChild(section); } ui.toolPalette.appendChild(frag); } function drawToolPreviewCanvas(canvas, itemType, { watermark = false } = {}) { if (!canvas || !itemType) return false; const ctx = canvas.getContext("2d"); if (!ctx) return false; ctx.clearRect(0, 0, canvas.width, canvas.height); if (typeof window.drawToolItemPreview !== "function") return false; return window.drawToolItemPreview(ctx, itemType, { width: canvas.width, height: canvas.height, compact: true, watermark }) !== false; } function createToolPreviewCanvas(className, size = 96) { const canvas = document.createElement("canvas"); canvas.className = className; canvas.width = size; canvas.height = size; canvas.setAttribute("aria-hidden", "true"); return canvas; } function attachToolSpritePreview(btn, def, toolId) { const itemType = def?.itemType || toolId; if (!btn || !itemType || !def?.placeable || TEXT_ICON_TOOL_IDS.has(toolId)) return; if (toolId === "reciprocator") return; if (toolId === "ball" || itemType === "ball") return; if (typeof window.drawToolItemPreview !== "function") return; const iconCanvas = createToolPreviewCanvas("tool-sprite-preview", 160); const iconDrawn = drawToolPreviewCanvas(iconCanvas, itemType); if (!iconDrawn) return; btn.classList.add("tool-has-canvas-icon"); btn.prepend(iconCanvas); } function toolSizeFor(tool) { if (!SCALABLE_TOOLS.has(tool)) return ""; return normalizedToolSizeFor(world, tool); } function cycleToolSize(tool) { if (!SCALABLE_TOOLS.has(tool)) return false; const result = window.TarinaiCommands.dispatch(world, { type: "tool.size.cycle", toolId: tool, order: SIZE_ORDER }); if (!result?.ok) return false; syncToolSizeBadges(); showToast(`\u30b5\u30a4\u30ba: ${SIZE_LABELS[result.size] || result.size}`); return true; } function syncToolSizeBadges() { for (const btn of uiCache.toolButtons || []) { const tool = btn.dataset.tool || ""; const old = btn.querySelector(".tool-size-badge"); if (!SCALABLE_TOOLS.has(tool)) { if (old) old.remove(); continue; } const size = toolSizeFor(tool); let badge = old; if (!badge) { badge = document.createElement("b"); badge.className = "tool-size-badge"; btn.appendChild(badge); } badge.textContent = SIZE_LABELS[size] || size; } }