Make mouse operations always exist, not only while clicking
This allows for multi-eyedrop (where right-clicking the same cell cycles through everything in that cell) to finally work. Also fixes #72, I think.
This commit is contained in:
parent
933d20d559
commit
bef5550a95
@ -210,6 +210,7 @@ export class Editor extends PrimaryView {
|
||||
|
||||
// Level canvas and mouse handling
|
||||
this.mouse_coords = null;
|
||||
this.mouse_ops = [null, new mouseops.PanOperation(this, 1), null]; // left, middle, right
|
||||
this.mouse_op = null;
|
||||
this.viewport_el.addEventListener('mousedown', ev => {
|
||||
this.mouse_coords = [ev.clientX, ev.clientY];
|
||||
@ -223,36 +224,10 @@ export class Editor extends PrimaryView {
|
||||
button = 0;
|
||||
}
|
||||
|
||||
let op_type = null;
|
||||
if (button === 0) {
|
||||
// Left button: activate tool
|
||||
op_type = TOOLS[this.current_tool].op1;
|
||||
}
|
||||
else if (button === 1) {
|
||||
// Middle button: always pan
|
||||
op_type = mouseops.PanOperation;
|
||||
// TODO how should this impact the hover?
|
||||
}
|
||||
else if (button === 2) {
|
||||
// Right button: activate tool's alt mode
|
||||
op_type = TOOLS[this.current_tool].op2;
|
||||
}
|
||||
|
||||
if (! op_type)
|
||||
return;
|
||||
|
||||
if (this.mouse_op && this.mouse_op instanceof op_type &&
|
||||
this.mouse_op.physical_button === button)
|
||||
{
|
||||
// Don't replace with the same operation!
|
||||
}
|
||||
else {
|
||||
this.set_mouse_button(button);
|
||||
if (this.mouse_op) {
|
||||
this.mouse_op.do_destroy();
|
||||
}
|
||||
this.mouse_op = new op_type(this, ev.clientX, ev.clientY, ev.button, button);
|
||||
}
|
||||
this.mouse_op.do_press(ev);
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
@ -284,9 +259,9 @@ export class Editor extends PrimaryView {
|
||||
this.statusbar_cursor.textContent = `—`;
|
||||
}
|
||||
|
||||
if (! this.mouse_op)
|
||||
return;
|
||||
if (this.mouse_op) {
|
||||
this.mouse_op.do_move(ev);
|
||||
}
|
||||
});
|
||||
this.actual_viewport_el.addEventListener('mouseleave', () => {
|
||||
if (this.mouse_op) {
|
||||
@ -302,10 +277,7 @@ export class Editor extends PrimaryView {
|
||||
ev.preventDefault();
|
||||
|
||||
this.mouse_op.do_commit();
|
||||
// If this was an op for a different button, switch back to the primary
|
||||
if (this.mouse_op.physical_button !== 0) {
|
||||
this.init_default_mouse_op();
|
||||
}
|
||||
this.set_mouse_button(0);
|
||||
});
|
||||
// Disable context menu, which interferes with right-click tools
|
||||
this.viewport_el.addEventListener('contextmenu', ev => {
|
||||
@ -1167,17 +1139,31 @@ export class Editor extends PrimaryView {
|
||||
}
|
||||
this.current_tool = tool;
|
||||
this.tool_button_els[this.current_tool].classList.add('-selected');
|
||||
this.init_default_mouse_op();
|
||||
|
||||
// Left button: activate tool
|
||||
this._init_mouse_op(0, this.current_tool && TOOLS[this.current_tool].op1);
|
||||
// Right button: activate tool's alt mode
|
||||
this._init_mouse_op(2, this.current_tool && TOOLS[this.current_tool].op2);
|
||||
|
||||
this.set_mouse_button(0);
|
||||
}
|
||||
_init_mouse_op(button, op_type) {
|
||||
if (this.mouse_ops[button] && op_type && this.mouse_ops[button] instanceof op_type)
|
||||
// Don't recreate the same type of mouse operation
|
||||
return;
|
||||
|
||||
if (this.mouse_ops[button]) {
|
||||
this.mouse_ops[button].do_destroy();
|
||||
this.mouse_ops[button] = null;
|
||||
}
|
||||
|
||||
init_default_mouse_op() {
|
||||
if (this.mouse_op) {
|
||||
this.mouse_op.do_destroy();
|
||||
this.mouse_op = null;
|
||||
if (op_type) {
|
||||
this.mouse_ops[button] = new op_type(this, button);
|
||||
}
|
||||
if (this.current_tool && TOOLS[this.current_tool].op1) {
|
||||
this.mouse_op = new TOOLS[this.current_tool].op1(this, ...(this.mouse_coords ?? [0, 0]), 0); // FIXME?
|
||||
}
|
||||
|
||||
set_mouse_button(button) {
|
||||
this.mouse_op = this.mouse_ops[button];
|
||||
}
|
||||
|
||||
show_palette_tooltip(key) {
|
||||
@ -1330,8 +1316,10 @@ export class Editor extends PrimaryView {
|
||||
ctx.clearRect(0, 0, this.fg_tile_el.width, this.fg_tile_el.height);
|
||||
this.renderer.draw_single_tile_type(
|
||||
this.fg_tile.type.name, this.fg_tile, this.fg_tile_el);
|
||||
if (this.mouse_op) {
|
||||
this.mouse_op.handle_tile_updated();
|
||||
for (let mouse_op of this.mouse_ops) {
|
||||
if (mouse_op) {
|
||||
mouse_op.handle_tile_updated();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1340,8 +1328,10 @@ export class Editor extends PrimaryView {
|
||||
ctx.clearRect(0, 0, this.bg_tile_el.width, this.bg_tile_el.height);
|
||||
this.renderer.draw_single_tile_type(
|
||||
this.bg_tile.type.name, this.bg_tile, this.bg_tile_el);
|
||||
if (this.mouse_op) {
|
||||
this.mouse_op.handle_tile_updated(true);
|
||||
for (let mouse_op of this.mouse_ops) {
|
||||
if (mouse_op) {
|
||||
mouse_op.handle_tile_updated(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,28 +10,23 @@ import { TILES_WITH_PROPS } from './tile-overlays.js';
|
||||
|
||||
const MOUSE_BUTTON_MASKS = [1, 4, 2]; // MouseEvent.button/buttons are ordered differently
|
||||
export class MouseOperation {
|
||||
constructor(editor, client_x, client_y, physical_button) {
|
||||
constructor(editor, physical_button) {
|
||||
this.editor = editor;
|
||||
this.is_held = false;
|
||||
this.physical_button = physical_button;
|
||||
this.alt_mode = physical_button !== 0;
|
||||
this.ctrl = false;
|
||||
this.shift = false;
|
||||
//this._update_modifiers(ev); // FIXME how do i get this initially??
|
||||
|
||||
let [frac_cell_x, frac_cell_y] = this.editor.renderer.real_cell_coords_from_event({clientX: client_x, clientY: client_y});
|
||||
let cell_x = Math.floor(frac_cell_x);
|
||||
let cell_y = Math.floor(frac_cell_y);
|
||||
|
||||
// Client coordinates of the previous mouse event
|
||||
this.prev_client_x = client_x;
|
||||
this.prev_client_y = client_y;
|
||||
this.prev_client_x = null;
|
||||
this.prev_client_y = null;
|
||||
// Cell coordinates
|
||||
this.prev_cell_x = cell_x;
|
||||
this.prev_cell_y = cell_y;
|
||||
this.prev_cell_x = null;
|
||||
this.prev_cell_y = null;
|
||||
// Fractional cell coordinates
|
||||
this.prev_frac_cell_x = frac_cell_x;
|
||||
this.prev_frac_cell_y = frac_cell_y;
|
||||
this.prev_frac_cell_x = null;
|
||||
this.prev_frac_cell_y = null;
|
||||
|
||||
// Same as above, but for the most recent click (so drag ops know where they started)
|
||||
this.click_client_x = null;
|
||||
@ -40,10 +35,6 @@ export class MouseOperation {
|
||||
this.click_cell_y = null;
|
||||
this.click_frac_cell_x = null;
|
||||
this.click_frac_cell_y = null;
|
||||
|
||||
// Start out with a hover effect
|
||||
// FIXME no good, subclass hasn't finished setting itself up yet
|
||||
//this.do_move({clientX: client_x, clientY: client_y});
|
||||
}
|
||||
|
||||
cell(x, y) {
|
||||
@ -207,6 +198,8 @@ export class PanOperation extends MouseOperation {
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME handle moving the mouse while the button is down; should continuously eyedrop
|
||||
// (seems like that /should/ work...)
|
||||
export class EyedropOperation extends MouseOperation {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
@ -296,10 +289,13 @@ export class PencilOperation extends MouseOperation {
|
||||
handle_press(x, y) {
|
||||
this.draw_in_cell(x, y);
|
||||
}
|
||||
handle_drag(client_x, client_y, frac_cell_x, frac_cell_y, _cell_x, _cell_y) {
|
||||
handle_drag(client_x, client_y, frac_cell_x, frac_cell_y, cell_x, cell_y) {
|
||||
for (let [x, y] of this.iter_touched_cells(frac_cell_x, frac_cell_y)) {
|
||||
this.draw_in_cell(x, y);
|
||||
}
|
||||
|
||||
// Also update the preview tile position
|
||||
this.handle_hover(client_x, client_y, frac_cell_x, frac_cell_y, cell_x, cell_y);
|
||||
}
|
||||
|
||||
draw_in_cell(x, y) {
|
||||
@ -346,6 +342,8 @@ export class PencilOperation extends MouseOperation {
|
||||
// toggled)
|
||||
// - right-click to pick, same logic as pencil (which needs improving)
|
||||
// - ctrl-click to erase
|
||||
// - wait, no. ctrl to like, fill the terrain layer regardless of the current tile's layer? atm
|
||||
// you can't flood with an item usefully, it just fills the whole level
|
||||
// - reset the preview after a fill? is that ever necessary?
|
||||
export class FillOperation extends MouseOperation {
|
||||
constructor(...args) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user