🌐
index2.html
Back
📝 Html ⚡ Executable Ctrl+S: Save • Ctrl+R: Run • Ctrl+F: Find
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Tile Map Editor</title> <style> body { margin: 0; font-family: sans-serif; background: #121212; color: #eee; } .topbar { display: flex; justify-content: space-around; align-items: center; background: #1f1f1f; padding: 0.5rem; position: sticky; top: 0; z-index: 100; } .btn { font-size: 1.5rem; background: transparent; border: none; color: #eee; padding: 0.5rem; border-radius: 12px; cursor: pointer; } .btn.active, .btn:hover { background: #333; } .section { display: none; padding: 1rem; } .section.active { display: block; } .scroll-x { display: flex; overflow-x: auto; gap: 0.5rem; padding: 0.5rem 0; } .folder, .image { flex: 0 0 auto; width: 80px; height: 80px; border-radius: 12px; display: flex; align-items: center; justify-content: center; text-align: center; font-size: 0.8rem; cursor: pointer; } .folder { background: #2a2a4a; color: #ccc; } .image { background: #333; overflow: hidden; border: 2px solid transparent; } .image img { width: 100%; height: 100%; object-fit: cover; border-radius: 12px; } .image.selected { border-color: #6cf; } .breadcrumb { margin-bottom: 0.5rem; } .breadcrumb span { cursor: pointer; color: #6cf; margin-right: 0.25rem; } .breadcrumb span::after { content: ' /'; } .breadcrumb span:last-child::after { content: ''; } #preview { margin-top: 1rem; text-align: center; } #preview img { max-width: 90%; max-height: 200px; border-radius: 12px; border: 2px solid #6cf; background: #000; cursor: pointer; } /* Overlay */ #overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.95); color: #fff; z-index: 200; padding: 1rem; overflow: hidden; } #overlayContent { margin-top: 2.5rem; text-align: center; height: calc(100% - 3rem); display: flex; flex-direction: column; } #overlayClose { position: absolute; top: 0.5rem; right: 0.5rem; font-size: 1.5rem; background: #333; border: none; border-radius: 8px; color: #eee; cursor: pointer; padding: 0.25rem 0.5rem; } /* Tabs */ #groupTabs { display: flex; justify-content: center; gap: 0.5rem; margin-bottom: 0.5rem; } #groupTabs button { background: #333; border: none; color: #eee; padding: 0.25rem 0.75rem; border-radius: 6px; cursor: pointer; } #groupTabs button.active { background: #6cf; color: #000; } #pickedImages { display: flex; gap: 0.5rem; margin-bottom: 0.5rem; flex-wrap: wrap; justify-content: center; } .pickedTile { position: relative; display: inline-block; } .pickedTile canvas { border: 2px solid #6cf; border-radius: 8px; background: #000; } .pickedTile span { position: absolute; bottom: -14px; left: 50%; transform: translateX(-50%); font-size: 10px; color: #fff; background: rgba(0,0,0,0.6); padding: 1px 4px; border-radius: 4px; } .removeBtn { position: absolute; top: -8px; right: -8px; background: #f33; color: #fff; border: none; border-radius: 50%; font-size: 0.8rem; cursor: pointer; width: 18px; height: 18px; line-height: 16px; padding: 0; } #tileViewport { flex: 1; overflow: auto; border: 2px solid #444; background: #000; } #tileContainer { position: relative; display: inline-block; } #tileContainer img { display: block; border-radius: 12px; border: 2px solid #6cf; } .grid-cell { position: absolute; border: 1px solid rgba(255,255,255,0.3); box-sizing: border-box; cursor: pointer; font-size: 10px; color: #fff; } .grid-cell span { position: absolute; top: 2px; left: 2px; background: rgba(0,0,0,0.5); padding: 0 2px; border-radius: 3px; font-size: 9px; } .grid-cell:hover { background: rgba(255,255,255,0.1); } </style> </head> <body> <div class="topbar"> <button class="btn" data-target="files">📂</button> <button class="btn" data-overlay="tiles">🧩</button> <button class="btn" data-overlay="map">🗺️</button> <button class="btn" data-overlay="game">🎮</button> </div> <div id="files" class="section"> <h2>Files 📂</h2> <div class="breadcrumb"></div> <div class="scroll-x" id="fileList"></div> <div id="preview"></div> </div> <!-- Shared Overlay --> <div id="overlay"> <button id="overlayClose">✖️</button> <div id="overlayContent"></div> </div> <script> let selectedImage = null; let selectedImageName = null; let selectedImageDiv = null; let selectedTileSize = null; // Groups let groups = [{ id: 0, url: null, tiles: [] }]; let currentGroup = 0; let nextUniqueId = 1; // start at 1 (0 = "no object") // -------- BUTTON HANDLING -------- document.querySelectorAll('.btn').forEach(btn => { btn.addEventListener('click', () => { if (btn.dataset.target) { document.querySelectorAll('.btn').forEach(b => b.classList.remove('active')); document.querySelectorAll('.section').forEach(sec => sec.classList.remove('active')); btn.classList.add('active'); document.getElementById(btn.dataset.target).classList.add('active'); if (btn.dataset.target === 'files') loadFiles(''); } else if (btn.dataset.overlay) { openOverlay(btn.dataset.overlay); } }); }); document.querySelectorAll('.btn')[0].click(); // -------- FILE BROWSER -------- const fileList = document.getElementById('fileList'); const breadcrumb = document.querySelector('.breadcrumb'); const preview = document.getElementById('preview'); function loadFiles(sub) { fetch('media.php?sub=' + encodeURIComponent(sub)) .then(r => r.json()) .then(data => { renderBreadcrumb(data.breadcrumb); renderFiles(data); }) .catch(err => console.error(err)); } function renderBreadcrumb(crumbs) { breadcrumb.innerHTML = ''; crumbs.forEach(c => { const span = document.createElement('span'); span.textContent = c.label; span.onclick = () => loadFiles(c.sub); breadcrumb.appendChild(span); }); } function renderFiles(data) { fileList.innerHTML = ''; preview.innerHTML = ''; // Folders data.folders.forEach(f => { const div = document.createElement('div'); div.className = 'folder'; div.textContent = f.name; div.onclick = () => { if (/^\d+$/.test(f.name)) { selectedTileSize = parseInt(f.name, 10); loadFiles(f.sub); } else { loadFiles(f.sub); } }; fileList.appendChild(div); }); // Images data.images.forEach(img => { const div = document.createElement('div'); div.className = 'image'; const im = document.createElement('img'); im.src = img.url; im.alt = img.name; div.appendChild(im); div.onclick = () => { if (selectedImageDiv) selectedImageDiv.classList.remove('selected'); div.classList.add('selected'); selectedImageDiv = div; selectedImage = img.url; selectedImageName = img.name; showPreview(img); }; fileList.appendChild(div); }); } function showPreview(img) { preview.innerHTML = ` <h3>Selected: ${img.name}</h3> <img id="previewImg" src="${img.url}" alt="${img.name}"> `; // Click big preview → tile picker document.getElementById('previewImg').onclick = () => openOverlay('tiles'); } // -------- OVERLAY -------- const overlay = document.getElementById('overlay'); const overlayContent = document.getElementById('overlayContent'); document.getElementById('overlayClose').onclick = () => { overlay.style.display = 'none'; }; function openOverlay(type) { overlayContent.innerHTML = ''; overlay.style.display = 'block'; if (type === 'tiles') { if (selectedImage && selectedTileSize) { overlayContent.innerHTML = ` <h2>Tile Picker 🧩</h2> <p>Tile size: ${selectedTileSize}</p> <div id="groupTabs"></div> <div id="pickedImages"></div> <div id="tileViewport"> <div id="tileContainer"> <img id="tileImage" src="${selectedImage}" alt="${selectedImageName}"> </div> </div> `; renderTabs(); renderPicked(); const imgEl = document.getElementById('tileImage'); imgEl.onload = () => { const container = document.getElementById('tileContainer'); const w = imgEl.naturalWidth; const h = imgEl.naturalHeight; imgEl.style.width = w + "px"; imgEl.style.height = h + "px"; container.style.width = w + "px"; container.style.height = h + "px"; container.querySelectorAll('.grid-cell').forEach(c => c.remove()); const cols = Math.floor(w / selectedTileSize); for (let y = 0; y < h; y += selectedTileSize) { for (let x = 0; x < w; x += selectedTileSize) { const cell = document.createElement('div'); cell.className = 'grid-cell'; cell.style.left = x + 'px'; cell.style.top = y + 'px'; cell.style.width = selectedTileSize + 'px'; cell.style.height = selectedTileSize + 'px'; const row = Math.floor(y / selectedTileSize); const col = Math.floor(x / selectedTileSize); const tileIndex = row * cols + col + 1; const label = document.createElement('span'); label.textContent = tileIndex; cell.appendChild(label); cell.onclick = () => pickTile(imgEl, x, y, selectedTileSize, selectedImage); container.appendChild(cell); } } }; } else { overlayContent.innerHTML = `<h2>Tile Picker 🧩</h2><p>Select an image and a numeric folder first.</p>`; } } } // -------- TABS + GROUPS -------- function renderTabs() { const tabBar = document.getElementById('groupTabs'); tabBar.innerHTML = ''; groups.forEach((g, idx) => { const btn = document.createElement('button'); btn.textContent = "Group " + (idx+1); if (idx === currentGroup) btn.classList.add('active'); btn.onclick = () => { currentGroup = idx; renderTabs(); renderPicked(); }; tabBar.appendChild(btn); }); const addBtn = document.createElement('button'); addBtn.textContent = "+"; addBtn.onclick = () => { groups.push({ id: groups.length, url: null, tiles: [] }); currentGroup = groups.length - 1; renderTabs(); renderPicked(); }; tabBar.appendChild(addBtn); } function renderPicked() { const container = document.getElementById('pickedImages'); container.innerHTML = ''; const group = groups[currentGroup]; group.tiles.forEach((tile, idx) => { const wrapper = document.createElement('div'); wrapper.className = 'pickedTile'; const canvas = document.createElement('canvas'); canvas.width = tile.size; canvas.height = tile.size; const ctx = canvas.getContext('2d'); ctx.putImageData(tile.data, 0, 0); const removeBtn = document.createElement('button'); removeBtn.className = 'removeBtn'; removeBtn.textContent = "×"; removeBtn.onclick = () => { group.tiles.splice(idx, 1); renderPicked(); }; const idLabel = document.createElement('span'); idLabel.textContent = `ID ${tile.uniqueId}`; wrapper.appendChild(canvas); wrapper.appendChild(removeBtn); wrapper.appendChild(idLabel); container.appendChild(wrapper); }); } // -------- PICK TILE -------- function pickTile(imgEl, x, y, size, url) { const group = groups[currentGroup]; if (group.url && group.url !== url) { alert("This group already uses a different image. Make a new group."); return; } group.url = url; const canvas = document.createElement('canvas'); canvas.width = size; canvas.height = size; const ctx = canvas.getContext('2d'); ctx.drawImage(imgEl, x, y, size, size, 0, 0, size, size); const data = ctx.getImageData(0, 0, size, size); group.tiles.push({ size, data, uniqueId: nextUniqueId++ }); renderPicked(); } </script> </body> </html>