Add support for subtracting from the selection
This commit is contained in:
parent
eaa3bf6965
commit
ed5f76221b
@ -41,7 +41,7 @@ export const TOOLS = {
|
||||
select_box: {
|
||||
icon: 'icons/tool-select-box.png',
|
||||
name: "Box select",
|
||||
desc: "Select and manipulate rectangles.\n\n[mouse1] Select rectangle\n[shift] [mouse1] Add to selection\n\n[mouse1] Move selection\n[ctrl] [mouse1] Clone selection",
|
||||
desc: "Select and manipulate rectangles.\n\n[mouse1] Select rectangle\n[shift] [mouse1] Add to selection\n[ctrl] [mouse1] Remove from selection\n\n[mouse1] Move selection\n[ctrl] [mouse1] Clone selection",
|
||||
affects_selection: true,
|
||||
op1: mouseops.SelectOperation,
|
||||
shortcut: 'm',
|
||||
|
||||
@ -33,8 +33,9 @@ export class SVGConnection {
|
||||
|
||||
|
||||
export class PendingRectangularSelection {
|
||||
constructor(owner) {
|
||||
constructor(owner, mode) {
|
||||
this.owner = owner;
|
||||
this.mode = mode ?? 'new'; // new, add, subtract
|
||||
this.element = mk_svg('rect.overlay-pending-selection');
|
||||
this.size_text = mk_svg('text.overlay-edit-tip');
|
||||
this.owner.svg_group.append(this.element, this.size_text);
|
||||
@ -54,7 +55,16 @@ export class PendingRectangularSelection {
|
||||
}
|
||||
|
||||
commit() {
|
||||
if (this.mode === 'new') {
|
||||
this.owner.clear();
|
||||
this.owner.add_rect(this.rect);
|
||||
}
|
||||
else if (this.mode === 'add') {
|
||||
this.owner.add_rect(this.rect);
|
||||
}
|
||||
else if (this.mode === 'subtract') {
|
||||
this.owner.subtract_rect(this.rect);
|
||||
}
|
||||
this.element.remove();
|
||||
this.size_text.remove();
|
||||
}
|
||||
@ -116,8 +126,8 @@ export class Selection {
|
||||
return this.cells.has(this.editor.stored_level.coords_to_scalar(x, y));
|
||||
}
|
||||
|
||||
create_pending() {
|
||||
return new PendingRectangularSelection(this);
|
||||
create_pending(mode) {
|
||||
return new PendingRectangularSelection(this, mode);
|
||||
}
|
||||
|
||||
add_rect(rect) {
|
||||
@ -154,18 +164,36 @@ export class Selection {
|
||||
Math.max(this.bbox.bottom, rect.bottom) - this.bbox.y);
|
||||
}
|
||||
|
||||
// XXX wait what the hell is this doing here? why would we set_from_rect while floating, vs
|
||||
// stamping it first?
|
||||
if (this.floated_element) {
|
||||
console.log("what the hell is this doing here");
|
||||
let tileset = this.editor.renderer.tileset;
|
||||
this.floated_canvas.width = this.bbox.width * tileset.size_x;
|
||||
this.floated_canvas.height = this.bbox.height * tileset.size_y;
|
||||
let foreign_obj = this.floated_element.querySelector('foreignObject');
|
||||
foreign_obj.setAttribute('width', this.floated_canvas.width);
|
||||
foreign_obj.setAttribute('height', this.floated_canvas.height);
|
||||
this._update_outline();
|
||||
}
|
||||
|
||||
subtract_rect(rect) {
|
||||
let old_cells = this.cells;
|
||||
this.cells = new Set(this.cells);
|
||||
|
||||
this.editor._do(
|
||||
() => this._subtract_rect(rect),
|
||||
() => {
|
||||
this._set_from_set(old_cells);
|
||||
},
|
||||
false,
|
||||
);
|
||||
}
|
||||
|
||||
_subtract_rect(rect) {
|
||||
if (this.is_empty)
|
||||
// Nothing to do
|
||||
return;
|
||||
|
||||
let stored_level = this.editor.stored_level;
|
||||
for (let y = rect.top; y < rect.bottom; y++) {
|
||||
for (let x = rect.left; x < rect.right; x++) {
|
||||
this.cells.delete(stored_level.coords_to_scalar(x, y));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO shrink bbox? i guess i only have to check along the edges that the rect intersects?
|
||||
|
||||
this._update_outline();
|
||||
}
|
||||
|
||||
|
||||
@ -525,13 +525,21 @@ export class FillOperation extends MouseOperation {
|
||||
|
||||
// TODO also, delete
|
||||
// FIXME i broke transforms
|
||||
// FIXME need to subtract from selection too
|
||||
// FIXME don't show the overlay text until has_moved
|
||||
// FIXME hide the god damn cursor
|
||||
export class SelectOperation extends MouseOperation {
|
||||
handle_press() {
|
||||
if (this.shift) {
|
||||
this.mode = 'select';
|
||||
if (this.ctrl) {
|
||||
// Subtract from selection (the normal way is ctrl, but ctrl-shift works even to
|
||||
// start dragging inside an existing selection)
|
||||
this.pending_selection = this.editor.selection.create_pending('subtract');
|
||||
}
|
||||
else {
|
||||
// Extend selection
|
||||
this.mode = 'extend';
|
||||
this.pending_selection = this.editor.selection.create_pending();
|
||||
this.pending_selection = this.editor.selection.create_pending('add');
|
||||
}
|
||||
this.update_pending_selection();
|
||||
}
|
||||
else if (! this.editor.selection.is_empty &&
|
||||
@ -541,10 +549,16 @@ export class SelectOperation extends MouseOperation {
|
||||
this.mode = 'float';
|
||||
this.make_copy = this.ctrl;
|
||||
}
|
||||
else {
|
||||
this.mode = 'select';
|
||||
if (this.ctrl) {
|
||||
// Subtract from selection (must initiate click outside selection, or it'll float)
|
||||
this.pending_selection = this.editor.selection.create_pending('subtract');
|
||||
}
|
||||
else {
|
||||
// Create new selection
|
||||
this.mode = 'create';
|
||||
this.pending_selection = this.editor.selection.create_pending();
|
||||
this.pending_selection = this.editor.selection.create_pending('new');
|
||||
}
|
||||
this.update_pending_selection();
|
||||
}
|
||||
this.has_moved = false;
|
||||
@ -598,9 +612,6 @@ export class SelectOperation extends MouseOperation {
|
||||
// commit it before doing anything else
|
||||
this.editor.selection.commit_floating();
|
||||
|
||||
if (this.mode === 'create') {
|
||||
this.editor.selection.clear();
|
||||
}
|
||||
this.pending_selection.commit();
|
||||
}
|
||||
else {
|
||||
|
||||
@ -2244,6 +2244,7 @@ svg.level-editor-overlay path.overlay-selection-background {
|
||||
svg.level-editor-overlay path.overlay-selection {
|
||||
stroke: hsla(var(--selected-hue), 10%, 10%, 0.75);
|
||||
fill: hsla(var(--selected-hue), 50%, 75%, 0.375);
|
||||
fill-rule: evenodd;
|
||||
stroke-width: calc(0.125px / var(--scale));
|
||||
stroke-dasharray: calc(0.125px / var(--scale)), calc(0.125px / var(--scale));
|
||||
animation: marching-ants 0.5s linear infinite;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user