Use consistent drawing behavior in the editor; add shift, ctrl pencil modifiers

This commit is contained in:
Eevee (Evelyn Woods) 2020-11-28 11:59:57 -07:00
parent dff3081194
commit 4218657c28
2 changed files with 70 additions and 19 deletions

View File

@ -34,6 +34,8 @@ class MouseOperation {
this.editor = editor; this.editor = editor;
this.target = target; this.target = target;
this.button_mask = MOUSE_BUTTON_MASKS[ev.button]; this.button_mask = MOUSE_BUTTON_MASKS[ev.button];
this.modifier = null; // or 'shift' or 'ctrl' (ctrl takes precedent)
this._update_modifier(ev);
// Client coordinates of the initial click // Client coordinates of the initial click
this.mx0 = ev.clientX; this.mx0 = ev.clientX;
@ -56,13 +58,14 @@ class MouseOperation {
} }
cell(gx, gy) { cell(gx, gy) {
return this.editor.stored_level.cells[Math.floor(gy)][Math.floor(gx)]; return this.editor.cell(Math.floor(gx), Math.floor(gy));
} }
do_mousemove(ev) { do_mousemove(ev) {
let [gxf, gyf] = this.editor.renderer.real_cell_coords_from_event(ev); let [gxf, gyf] = this.editor.renderer.real_cell_coords_from_event(ev);
let gx = Math.floor(gxf); let gx = Math.floor(gxf);
let gy = Math.floor(gyf); let gy = Math.floor(gyf);
this._update_modifier(ev);
this.step(ev.clientX, ev.clientY, gxf, gyf, gx, gy); this.step(ev.clientX, ev.clientY, gxf, gyf, gx, gy);
@ -74,6 +77,18 @@ class MouseOperation {
this.gy1 = gy; this.gy1 = gy;
} }
_update_modifier(ev) {
if (ev.ctrlKey) {
this.modifier = 'ctrl';
}
else if (ev.shiftKey) {
this.modifier = 'shift';
}
else {
this.modifier = null;
}
}
do_commit() { do_commit() {
this.commit(); this.commit();
this.cleanup(); this.cleanup();
@ -118,10 +133,44 @@ class DrawOperation extends MouseOperation {
class PencilOperation extends DrawOperation { class PencilOperation extends DrawOperation {
start() { start() {
this.editor.place_in_cell(this.gx1, this.gy1, this.editor.palette_selection); this.handle_cell(this.gx0, this.gy0);
} }
step(mx, my, gxf, gyf) { step(mx, my, gxf, gyf, gx, gy) {
for (let [x, y] of this.iter_touched_cells(gxf, gyf)) { if (this.modifier === 'ctrl') {
this.handle_cell(gx, gy);
}
else {
for (let [x, y] of this.iter_touched_cells(gxf, gyf)) {
this.handle_cell(x, y);
}
}
}
handle_cell(x, y) {
if (this.modifier === 'ctrl') {
let cell = this.cell(x, y);
if (cell) {
// FIXME the selected tile should actually be a template
// FIXME this doesn't update the ui
this.editor.palette_selection = cell[cell.length - 1].type.name;
}
}
else if (this.modifier === 'shift') {
// Aggressive mode: erase whatever's already in the cell
let cell = this.cell(x, y);
cell.length = 0;
let type = TILE_TYPES[this.editor.palette_selection];
if (type.draw_layer !== 0) {
cell.push({type: TILE_TYPES.floor});
}
let direction;
if (type.is_actor) {
direction = 'south';
}
cell.push({type, direction});
}
else {
// Default operation: only erase whatever's on the same layer
this.editor.place_in_cell(x, y, this.editor.palette_selection); this.editor.place_in_cell(x, y, this.editor.palette_selection);
} }
} }
@ -193,6 +242,7 @@ class ForceFloorOperation extends DrawOperation {
// Tiles the "adjust" tool will turn into each other // Tiles the "adjust" tool will turn into each other
const ADJUST_TOGGLES = { const ADJUST_TOGGLES = {
// TODO shouldn't this convert regular walls into regular floors then?
floor_custom_green: 'wall_custom_green', floor_custom_green: 'wall_custom_green',
floor_custom_pink: 'wall_custom_pink', floor_custom_pink: 'wall_custom_pink',
floor_custom_yellow: 'wall_custom_yellow', floor_custom_yellow: 'wall_custom_yellow',
@ -589,7 +639,6 @@ export class Editor extends PrimaryView {
} }
else if (ev.button === 1) { else if (ev.button === 1) {
// Middle button: always pan // Middle button: always pan
console.log("middle button!");
this.mouse_op = new PanOperation(this, ev); this.mouse_op = new PanOperation(this, ev);
ev.preventDefault(); ev.preventDefault();
@ -788,6 +837,15 @@ export class Editor extends PrimaryView {
return 0 <= x && x < this.stored_level.size_x && 0 <= y && y < this.stored_level.size_y; return 0 <= x && x < this.stored_level.size_x && 0 <= y && y < this.stored_level.size_y;
} }
cell(x, y) {
if (this.is_in_bounds(x, y)) {
return this.stored_level.cells[y][x];
}
else {
return null;
}
}
place_in_cell(x, y, name) { place_in_cell(x, y, name) {
// TODO weird api? // TODO weird api?
if (! name) if (! name)
@ -799,23 +857,16 @@ export class Editor extends PrimaryView {
direction = 'south'; direction = 'south';
} }
let cell = this.stored_level.cells[y][x]; let cell = this.stored_level.cells[y][x];
// For terrain tiles, erase the whole cell. For other tiles, only // Replace whatever's on the same layer
// replace whatever's on the same layer
// TODO probably not the best heuristic yet, since i imagine you can // TODO probably not the best heuristic yet, since i imagine you can
// combine e.g. the tent with thin walls // combine e.g. the tent with thin walls
if (type.draw_layer === 0) { for (let i = cell.length - 1; i >= 0; i--) {
cell.length = 0; if (cell[i].type.draw_layer === type.draw_layer) {
cell.push({type, direction}); cell.splice(i, 1);
}
else {
for (let i = cell.length - 1; i >= 0; i--) {
if (cell[i].type.draw_layer === type.draw_layer) {
cell.splice(i, 1);
}
} }
cell.push({type, direction});
cell.sort((a, b) => a.type.draw_layer - b.type.draw_layer);
} }
cell.push({type, direction});
cell.sort((a, b) => a.type.draw_layer - b.type.draw_layer);
} }
cancel_mouse_operation() { cancel_mouse_operation() {

View File

@ -885,7 +885,6 @@ main.--has-demo .demo-controls {
#editor .editor-canvas { #editor .editor-canvas {
grid-area: level; grid-area: level;
position: relative;
overflow: auto; overflow: auto;
/* Flex layout to center the canvas and overlay together */ /* Flex layout to center the canvas and overlay together */
display: flex; display: flex;
@ -897,6 +896,7 @@ main.--has-demo .demo-controls {
border: 0.125em solid black; border: 0.125em solid black;
} }
#editor .editor-canvas .-container { #editor .editor-canvas .-container {
position: relative;
/* Give the canvas/overlay a bit of a margin; it has to be a border because, due to some quirk /* Give the canvas/overlay a bit of a margin; it has to be a border because, due to some quirk
* of overflowing flexboxes I guess, padding and margins won't extend the scroll area on the * of overflowing flexboxes I guess, padding and margins won't extend the scroll area on the
* right and bottom */ * right and bottom */