'use strict'; const fs = require('fs'); const path = require('path'); const { pathToFileURL } = require('url'); /** 需要贴图预览的表单字段 id */ const HUD_ICON_KEYS = [ 'navigation', 'revert', 'speed1', 'speed2', 'speed4', 'zoomIn', 'zoomOut', 'audioOn', 'audioOff', ]; const PREVIEW_INPUT_IDS = [ 'tc-background', ...['playerFront', 'playerBack', 'vehicleNorth', 'vehicleEast', 'vehicleSouth', 'vehicleWest', 'prop', 'propGround'].map((k) => `tc-ent-${k}`), ...['Baseblock', 'JumpBlock', 'WallBlock', 'borderDecor'].map((k) => `tc-tile-${k}`), ...HUD_ICON_KEYS.map((k) => `tc-hud-${k}`), ]; function textureFsPath(projectRoot, texRel) { const normalized = String(texRel || '').trim(); if (!normalized) return null; let base = normalized.replace(/\\/g, '/'); if (base.startsWith('assets/resources/')) base = base.slice('assets/resources/'.length); if (base.endsWith('.png')) base = base.slice(0, -4); if (!base.startsWith('textures/')) base = `textures/${base}`; return path.join(projectRoot, 'assets/resources', `${base}.png`); } function updatePreviewBox(previewEl, texRel, projectRoot) { if (!previewEl) return; let img = previewEl.querySelector('img'); let empty = previewEl.querySelector('.tc-preview-empty'); const fsPath = textureFsPath(projectRoot, texRel); if (!fsPath || !fs.existsSync(fsPath)) { previewEl.classList.add('empty'); if (img) { img.style.display = 'none'; img.removeAttribute('src'); } if (empty) empty.style.display = 'flex'; previewEl.title = texRel ? `未找到: ${fsPath || texRel}` : ''; return; } previewEl.classList.remove('empty'); if (!img) { img = document.createElement('img'); img.alt = ''; previewEl.appendChild(img); } if (!empty) { empty = document.createElement('span'); empty.className = 'tc-preview-empty'; empty.textContent = '无图'; previewEl.appendChild(empty); } empty.style.display = 'none'; img.style.display = 'block'; img.src = `${pathToFileURL(fsPath).href}?v=${fs.statSync(fsPath).mtimeMs}`; previewEl.title = fsPath; } function refreshAllPreviews(formRoot, projectRoot) { if (!formRoot) return; for (const id of PREVIEW_INPUT_IDS) { const input = formRoot.querySelector(`#${id}`); const preview = formRoot.querySelector(`#${id}-preview`); if (preview && input) { updatePreviewBox(preview, input.value, projectRoot); } } } function bindPreviewInputs(formRoot, projectRoot, onRefresh) { if (!formRoot) return; for (const id of PREVIEW_INPUT_IDS) { const input = formRoot.querySelector(`#${id}`); if (!input || input._tcPreviewBound) continue; input._tcPreviewBound = true; const handler = () => { const preview = formRoot.querySelector(`#${id}-preview`); updatePreviewBox(preview, input.value, projectRoot); if (onRefresh) onRefresh(); }; input.addEventListener('change', handler); input.addEventListener('blur', handler); } } module.exports = { PREVIEW_INPUT_IDS, textureFsPath, updatePreviewBox, refreshAllPreviews, bindPreviewInputs, };