Add brush size slider and circle/square brush shapes
This commit is contained in:
parent
a746c6c0ee
commit
ce49530ff4
1 changed files with 93 additions and 1 deletions
|
|
@ -205,6 +205,20 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>Brush</legend>
|
||||
<div class="form-group">
|
||||
<label for="brushSize">Size:</label>
|
||||
<input type="range" id="brushSize" min="1" max="8" value="1" style="width: 100px; vertical-align: middle;">
|
||||
<span id="brushSizeValue">1</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Shape:</label>
|
||||
<button id="brushCircle" style="width: 30px; height: 30px; margin-right: 0.25rem; border: 2px solid;">○</button>
|
||||
<button id="brushSquare" style="width: 30px; height: 30px; border: 2px solid;">□</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset>
|
||||
<legend>View</legend>
|
||||
<div class="form-group">
|
||||
|
|
@ -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);
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in a new issue