diff --git a/scripts/map_editor.html b/scripts/map_editor.html index c5b8fb3..8b54680 100644 --- a/scripts/map_editor.html +++ b/scripts/map_editor.html @@ -205,6 +205,20 @@ +
+ Brush +
+ + + 1 +
+
+ + + +
+
+
View
@@ -290,6 +304,8 @@ let isDrawing = false; let drawButton = 0; let lastPaintedCell = null; + let brushSize = 1; + let brushShape = 'circle'; const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d', { willReadFrequently: true }); @@ -425,6 +441,39 @@ renderCanvas(); } + function paintBrush(x, y, symbol) { + if (brushSize === 1) { + paintCell(x, y, symbol); + return; + } + + // Temporarily disable single-cell tracking for brush painting + const oldLastPainted = lastPaintedCell; + lastPaintedCell = null; + + for (let dy = -(brushSize - 1); dy < brushSize; dy++) { + for (let dx = -(brushSize - 1); dx < brushSize; dx++) { + const nx = x + dx; + const ny = y + dy; + + if (nx < 0 || nx >= gridWidth || ny < 0 || ny >= gridHeight) continue; + + if (brushShape === 'circle') { + if (dx * dx + dy * dy < brushSize * brushSize) { + grid[ny][nx] = symbol; + } + } else { // square + if (Math.abs(dx) < brushSize && Math.abs(dy) < brushSize) { + grid[ny][nx] = symbol; + } + } + } + } + + lastPaintedCell = `${x},${y}`; + renderCanvas(); + } + function getGridCoords(event) { const rect = canvas.getBoundingClientRect(); const canvasX = (event.clientX - rect.left) * (canvas.width / rect.width); @@ -446,7 +495,7 @@ symbol = button === 0 ? symbols.m1 : symbols.m2; } - paintCell(x, y, symbol); + paintBrush(x, y, symbol); } function saveState() { @@ -457,6 +506,8 @@ symbols: symbols, activeSlot: activeSlot, palette: palette, + brushSize: brushSize, + brushShape: brushShape, }; localStorage.setItem('map_editor_state', JSON.stringify(state)); } @@ -480,6 +531,8 @@ if (state.symbols) symbols = state.symbols; if (state.activeSlot) activeSlot = state.activeSlot; if (state.palette) palette = state.palette; + if (state.brushSize !== undefined) brushSize = state.brushSize; + if (state.brushShape) brushShape = state.brushShape; widthInput.value = gridWidth; heightInput.value = gridHeight; @@ -487,6 +540,7 @@ m2Slot.textContent = symbols.m2; updateActiveSlot(); updateSymbolSlotColors(); + updateBrushUI(); sizeCanvas(); renderCanvas(); renderPalette(); @@ -600,6 +654,24 @@ ${paletteStr}""" m2Slot.style.color = `rgb(${c2[0]},${c2[1]},${c2[2]})`; } + function updateBrushUI() { + const slider = document.getElementById('brushSize'); + const valueDisplay = document.getElementById('brushSizeValue'); + const circleBtn = document.getElementById('brushCircle'); + const squareBtn = document.getElementById('brushSquare'); + + slider.value = brushSize; + valueDisplay.textContent = brushSize; + + if (brushShape === 'circle') { + circleBtn.style.borderWidth = '4px'; + squareBtn.style.borderWidth = '2px'; + } else { + circleBtn.style.borderWidth = '2px'; + squareBtn.style.borderWidth = '4px'; + } + } + // Palette manager functions function loadPalettesFromStorage() { const saved = localStorage.getItem('map_editor_palettes'); @@ -911,6 +983,25 @@ ${paletteStr}""" }); }); + // Brush controls + document.getElementById('brushSize').addEventListener('input', (e) => { + brushSize = parseInt(e.target.value); + document.getElementById('brushSizeValue').textContent = brushSize; + saveState(); + }); + + document.getElementById('brushCircle').addEventListener('click', () => { + brushShape = 'circle'; + updateBrushUI(); + saveState(); + }); + + document.getElementById('brushSquare').addEventListener('click', () => { + brushShape = 'square'; + updateBrushUI(); + saveState(); + }); + // Symbol slot selection m1Slot.addEventListener('click', () => { activeSlot = 'm1'; @@ -1001,6 +1092,7 @@ ${paletteStr}""" if (!loadState()) { renderPalette(); updateSymbolSlotColors(); + updateBrushUI(); initGrid(100, 100, false); }