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>
|
</div>
|
||||||
</fieldset>
|
</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>
|
<fieldset>
|
||||||
<legend>View</legend>
|
<legend>View</legend>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
@ -290,6 +304,8 @@
|
||||||
let isDrawing = false;
|
let isDrawing = false;
|
||||||
let drawButton = 0;
|
let drawButton = 0;
|
||||||
let lastPaintedCell = null;
|
let lastPaintedCell = null;
|
||||||
|
let brushSize = 1;
|
||||||
|
let brushShape = 'circle';
|
||||||
|
|
||||||
const canvas = document.getElementById('canvas');
|
const canvas = document.getElementById('canvas');
|
||||||
const ctx = canvas.getContext('2d', { willReadFrequently: true });
|
const ctx = canvas.getContext('2d', { willReadFrequently: true });
|
||||||
|
|
@ -425,6 +441,39 @@
|
||||||
renderCanvas();
|
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) {
|
function getGridCoords(event) {
|
||||||
const rect = canvas.getBoundingClientRect();
|
const rect = canvas.getBoundingClientRect();
|
||||||
const canvasX = (event.clientX - rect.left) * (canvas.width / rect.width);
|
const canvasX = (event.clientX - rect.left) * (canvas.width / rect.width);
|
||||||
|
|
@ -446,7 +495,7 @@
|
||||||
symbol = button === 0 ? symbols.m1 : symbols.m2;
|
symbol = button === 0 ? symbols.m1 : symbols.m2;
|
||||||
}
|
}
|
||||||
|
|
||||||
paintCell(x, y, symbol);
|
paintBrush(x, y, symbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveState() {
|
function saveState() {
|
||||||
|
|
@ -457,6 +506,8 @@
|
||||||
symbols: symbols,
|
symbols: symbols,
|
||||||
activeSlot: activeSlot,
|
activeSlot: activeSlot,
|
||||||
palette: palette,
|
palette: palette,
|
||||||
|
brushSize: brushSize,
|
||||||
|
brushShape: brushShape,
|
||||||
};
|
};
|
||||||
localStorage.setItem('map_editor_state', JSON.stringify(state));
|
localStorage.setItem('map_editor_state', JSON.stringify(state));
|
||||||
}
|
}
|
||||||
|
|
@ -480,6 +531,8 @@
|
||||||
if (state.symbols) symbols = state.symbols;
|
if (state.symbols) symbols = state.symbols;
|
||||||
if (state.activeSlot) activeSlot = state.activeSlot;
|
if (state.activeSlot) activeSlot = state.activeSlot;
|
||||||
if (state.palette) palette = state.palette;
|
if (state.palette) palette = state.palette;
|
||||||
|
if (state.brushSize !== undefined) brushSize = state.brushSize;
|
||||||
|
if (state.brushShape) brushShape = state.brushShape;
|
||||||
|
|
||||||
widthInput.value = gridWidth;
|
widthInput.value = gridWidth;
|
||||||
heightInput.value = gridHeight;
|
heightInput.value = gridHeight;
|
||||||
|
|
@ -487,6 +540,7 @@
|
||||||
m2Slot.textContent = symbols.m2;
|
m2Slot.textContent = symbols.m2;
|
||||||
updateActiveSlot();
|
updateActiveSlot();
|
||||||
updateSymbolSlotColors();
|
updateSymbolSlotColors();
|
||||||
|
updateBrushUI();
|
||||||
sizeCanvas();
|
sizeCanvas();
|
||||||
renderCanvas();
|
renderCanvas();
|
||||||
renderPalette();
|
renderPalette();
|
||||||
|
|
@ -600,6 +654,24 @@ ${paletteStr}"""
|
||||||
m2Slot.style.color = `rgb(${c2[0]},${c2[1]},${c2[2]})`;
|
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
|
// Palette manager functions
|
||||||
function loadPalettesFromStorage() {
|
function loadPalettesFromStorage() {
|
||||||
const saved = localStorage.getItem('map_editor_palettes');
|
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
|
// Symbol slot selection
|
||||||
m1Slot.addEventListener('click', () => {
|
m1Slot.addEventListener('click', () => {
|
||||||
activeSlot = 'm1';
|
activeSlot = 'm1';
|
||||||
|
|
@ -1001,6 +1092,7 @@ ${paletteStr}"""
|
||||||
if (!loadState()) {
|
if (!loadState()) {
|
||||||
renderPalette();
|
renderPalette();
|
||||||
updateSymbolSlotColors();
|
updateSymbolSlotColors();
|
||||||
|
updateBrushUI();
|
||||||
initGrid(100, 100, false);
|
initGrid(100, 100, false);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue