Give the adjust tool a live preview (still rough)
This commit is contained in:
parent
e7903d5895
commit
5da2cf14db
@ -276,6 +276,9 @@ export class MouseOperation {
|
|||||||
handle_tile_updated(is_bg = false) {}
|
handle_tile_updated(is_bg = false) {}
|
||||||
// Called when the mouse leaves the level or viewport while the button is NOT held down
|
// Called when the mouse leaves the level or viewport while the button is NOT held down
|
||||||
handle_leave() {}
|
handle_leave() {}
|
||||||
|
// Called when any hover state should be thrown away, due to some external change, just before
|
||||||
|
// handle_drag or handle_hover is called
|
||||||
|
handle_refresh() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PanOperation extends MouseOperation {
|
export class PanOperation extends MouseOperation {
|
||||||
@ -800,10 +803,18 @@ export class ForceFloorOperation extends MouseOperation {
|
|||||||
// fix it if it wasn't there?
|
// fix it if it wasn't there?
|
||||||
// TODO gonna need an ice tool too, so maybe i can merge all three with some base thing that tracks
|
// TODO gonna need an ice tool too, so maybe i can merge all three with some base thing that tracks
|
||||||
// the directions the mouse is moving? or is FF tool too different?
|
// the directions the mouse is moving? or is FF tool too different?
|
||||||
|
// TODO would be nice if i could add or remove individual tracks with a single click, too.
|
||||||
|
// and/or pop open the track editor bubble thing?
|
||||||
export class TrackOperation extends MouseOperation {
|
export class TrackOperation extends MouseOperation {
|
||||||
handle_press() {
|
handle_press() {
|
||||||
// Do nothing to start; we only lay track when the mouse leaves a cell
|
// Do nothing to start; we only lay track when the mouse leaves a cell
|
||||||
this.entry_direction = null;
|
this.entry_direction = null;
|
||||||
|
|
||||||
|
// ...unless...
|
||||||
|
let tri_x = Math.floor((this.click_frac_cell_x - this.click_cell_x) * 3);
|
||||||
|
let tri_y = Math.floor((this.click_frac_cell_y - this.click_cell_y) * 3);
|
||||||
|
// TODO add or remove track on the edge clicked here? hover preview?
|
||||||
|
// TODO ctrl-mouse2 for the popup?
|
||||||
}
|
}
|
||||||
handle_drag(client_x, client_y, frac_cell_x, frac_cell_y) {
|
handle_drag(client_x, client_y, frac_cell_x, frac_cell_y) {
|
||||||
// Walk the mouse movement and, for every tile we LEAVE, add a railroad track matching the
|
// Walk the mouse movement and, for every tile we LEAVE, add a railroad track matching the
|
||||||
@ -1314,6 +1325,26 @@ export class RotateOperation extends MouseOperation {
|
|||||||
cy: 0.5,
|
cy: 0.5,
|
||||||
r: 0.75,
|
r: 0.75,
|
||||||
}));
|
}));
|
||||||
|
// TODO better preview
|
||||||
|
/*
|
||||||
|
let renderer = this.editor.renderer;
|
||||||
|
this.canvas = mk('canvas', {
|
||||||
|
width: renderer.tileset.size_x,
|
||||||
|
height: renderer.tileset.size_y,
|
||||||
|
});
|
||||||
|
// Need an extra <g> here so the translate transform doesn't clobber the scale on the
|
||||||
|
// foreignObject
|
||||||
|
this.set_cursor_element(mk_svg('g.overlay-transient',
|
||||||
|
mk_svg('foreignObject', {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: this.canvas.width,
|
||||||
|
height: this.canvas.height,
|
||||||
|
transform: `scale(${1/renderer.tileset.size_x} ${1/renderer.tileset.size_y})`,
|
||||||
|
opacity: 0.75,
|
||||||
|
}, this.canvas),
|
||||||
|
));
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
_find_target_tile(cell) {
|
_find_target_tile(cell) {
|
||||||
@ -1621,10 +1652,34 @@ export class AdjustOperation extends MouseOperation {
|
|||||||
this.hovered_layer = null;
|
this.hovered_layer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_find_target_tile(cell) {
|
// The real work happens on hover, since we need to actually adjust the tile in order to preview
|
||||||
|
// it anyway; clicking just commits it.
|
||||||
|
handle_hover(client_x, client_y, frac_cell_x, frac_cell_y, cell_x, cell_y) {
|
||||||
|
// TODO hrmm if we undo without moving the mouse then this becomes wrong (even without the
|
||||||
|
// stuff here)
|
||||||
|
// TODO uhhh that's true for all kinds of kb shortcuts actually, even for pressing/releasing
|
||||||
|
// ctrl or shift to change the target. dang
|
||||||
|
if (cell_x === this.prev_cell_x && cell_y === this.prev_cell_y &&
|
||||||
|
(! this.hovered_edge || this.hovered_edge === this.get_tile_edge()) &&
|
||||||
|
! this.hover_stale)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cell = this.cell(cell_x, cell_y);
|
||||||
|
|
||||||
|
// Find our target tile, and in most cases, adjust it
|
||||||
|
this.hover_stale = false;
|
||||||
|
this.adjusted_tile = null;
|
||||||
|
this.hovered_edge = null;
|
||||||
let top_layer = LAYERS.MAX - 1;
|
let top_layer = LAYERS.MAX - 1;
|
||||||
let bottom_layer = 0;
|
let bottom_layer = 0;
|
||||||
if (this.ctrl) {
|
if (this.ctrl && this.shift) {
|
||||||
|
// ctrl-shift: explicitly target item
|
||||||
|
top_layer = LAYERS.item;
|
||||||
|
bottom_layer = LAYERS.item;
|
||||||
|
}
|
||||||
|
else if (this.ctrl) {
|
||||||
// ctrl: explicitly target terrain
|
// ctrl: explicitly target terrain
|
||||||
top_layer = LAYERS.terrain;
|
top_layer = LAYERS.terrain;
|
||||||
bottom_layer = LAYERS.terrain;
|
bottom_layer = LAYERS.terrain;
|
||||||
@ -1640,39 +1695,55 @@ export class AdjustOperation extends MouseOperation {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
// This is kind of like documentation for everything the adjust tool can do I guess
|
// This is kind of like documentation for everything the adjust tool can do I guess
|
||||||
if (TILE_TYPES['transmogrifier']._mogrifications[tile.type.name]) {
|
|
||||||
// Toggle between related tile types
|
|
||||||
return [layer, "Mogrify"];
|
|
||||||
}
|
|
||||||
if (ADJUST_TILE_TYPES[tile.type.name]) {
|
if (ADJUST_TILE_TYPES[tile.type.name]) {
|
||||||
// Toggle between related tile types
|
// Toggle between related tile types
|
||||||
return [layer, ADJUST_TILE_TYPES[tile.type.name].verb];
|
let adjustment = ADJUST_TILE_TYPES[tile.type.name];
|
||||||
|
//verb = adjustment.verb;
|
||||||
|
this.adjusted_tile = {...tile, type: TILE_TYPES[adjustment.next]};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (tile.type.name === 'logic_gate' && ADJUST_GATE_TYPES[tile.gate_type]) {
|
if (tile.type.name === 'logic_gate' && ADJUST_GATE_TYPES[tile.gate_type]) {
|
||||||
// Also toggle between related logic gate types
|
// Also toggle between related logic gate types
|
||||||
return [layer, "Change"];
|
//verb = "Change";
|
||||||
|
this.adjusted_tile = {...tile, gate_type: ADJUST_GATE_TYPES[tile.gate_type].next};
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (tile.type.name === 'logic_gate' && tile.gate_type === 'counter') {
|
let behavior = SPECIAL_TILE_BEHAVIOR[tile.type.name];
|
||||||
// Adjust the starting number on a logic gate
|
if (behavior && behavior.adjust_forward) {
|
||||||
return [layer, "Count"];
|
// Do faux-rotation, which includes incrementing counter gates
|
||||||
|
//verb = "Adjust";
|
||||||
|
this.adjusted_tile = {...tile};
|
||||||
|
behavior.adjust_forward(this.adjusted_tile);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (layer === LAYERS.thin_wall) {
|
if (layer === LAYERS.thin_wall) {
|
||||||
// Place or delete individual thin walls
|
// Place or delete individual thin walls
|
||||||
return [layer, "Place"];
|
let edge = this.get_tile_edge();
|
||||||
|
this.hovered_edge = edge;
|
||||||
|
this.adjusted_tile = {...tile};
|
||||||
|
this.adjusted_tile.edges ^= DIRECTIONS[edge].bit;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (tile.type.name === 'frame block') {
|
if (tile.type.name === 'frame_block') {
|
||||||
// Place or delete individual frame block arrows
|
// Place or delete individual frame block arrows
|
||||||
return [layer, "Place"];
|
// TODO this kinda obviates the need for a frame block editor
|
||||||
|
this.adjusted_tile = {...tile, arrows: new Set(tile.arrows)};
|
||||||
|
let edge = this.get_tile_edge();
|
||||||
|
this.hovered_edge = edge;
|
||||||
|
if (this.adjusted_tile.arrows.has(edge)) {
|
||||||
|
this.adjusted_tile.arrows.delete(edge);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.adjusted_tile.arrows.add(edge);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are
|
// These are
|
||||||
// TODO need a single-click thing to do for
|
// TODO need a single-click thing to do for
|
||||||
let behavior = SPECIAL_TILE_BEHAVIOR[tile.type.name];
|
|
||||||
if (behavior && behavior.adjust_forward) {
|
|
||||||
//
|
|
||||||
return [layer, "Adjust"];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// TODO hmm. what do i do with these
|
||||||
|
/*
|
||||||
if (TILES_WITH_PROPS[tile.type.name]) {
|
if (TILES_WITH_PROPS[tile.type.name]) {
|
||||||
// Open special tile editors
|
// Open special tile editors
|
||||||
return [layer, "Edit"];
|
return [layer, "Edit"];
|
||||||
@ -1681,22 +1752,9 @@ export class AdjustOperation extends MouseOperation {
|
|||||||
if (ADJUST_SPECIAL[tile.type.name]) {
|
if (ADJUST_SPECIAL[tile.type.name]) {
|
||||||
return [layer, "Press"];
|
return [layer, "Press"];
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
return [null, null];
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_hover(client_x, client_y, frac_cell_x, frac_cell_y, cell_x, cell_y) {
|
|
||||||
// TODO hrmm if we undo without moving the mouse then this becomes wrong (even without the
|
|
||||||
// stuff here)
|
|
||||||
// TODO uhhh that's true for all kinds of kb shortcuts actually, even for pressing/releasing
|
|
||||||
// ctrl or shift to change the target. dang
|
|
||||||
if (cell_x === this.prev_cell_x && cell_y === this.prev_cell_y)
|
|
||||||
return;
|
|
||||||
|
|
||||||
let cell = this.cell(cell_x, cell_y);
|
|
||||||
let [layer, hint] = this._find_target_tile(cell);
|
|
||||||
this.hovered_layer = layer;
|
|
||||||
if (hint === null) {
|
if (hint === null) {
|
||||||
this.click_hint.classList.remove('--visible');
|
this.click_hint.classList.remove('--visible');
|
||||||
}
|
}
|
||||||
@ -1706,47 +1764,26 @@ export class AdjustOperation extends MouseOperation {
|
|||||||
this.click_hint.setAttribute('y', cell_y - 0.125);
|
this.click_hint.setAttribute('y', cell_y - 0.125);
|
||||||
this.click_hint.textContent = hint;
|
this.click_hint.textContent = hint;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (layer === null) {
|
if (! this.adjusted_tile) {
|
||||||
this.cursor_element.classList.remove('--visible');
|
this.cursor_element.classList.remove('--visible');
|
||||||
this.gray_button_preview.classList.remove('--visible');
|
this.gray_button_preview.classList.remove('--visible');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let tile = cell[layer];
|
|
||||||
|
|
||||||
/*
|
// Draw the altered tile on top of everything else
|
||||||
this.cursor_element.classList.add('--visible');
|
|
||||||
if (layer === LAYERS.terrain) {
|
|
||||||
this.cursor_element.setAttribute('data-layer', 'terrain');
|
|
||||||
}
|
|
||||||
else if (layer === LAYERS.item) {
|
|
||||||
this.cursor_element.setAttribute('data-layer', 'item');
|
|
||||||
}
|
|
||||||
else if (layer === LAYERS.actor) {
|
|
||||||
this.cursor_element.setAttribute('data-layer', 'actor');
|
|
||||||
}
|
|
||||||
else if (layer === LAYERS.thin_wall) {
|
|
||||||
this.cursor_element.setAttribute('data-layer', 'thin-wall');
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (cell.filter(t => t).length <= 1) {
|
|
||||||
// Only one tile, so the canvas is pointless
|
|
||||||
this.cursor_element.classList.remove('--visible');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Draw the targeted tile on top of everything else
|
|
||||||
this.cursor_element.classList.add('--visible');
|
this.cursor_element.classList.add('--visible');
|
||||||
let ctx = this.canvas.getContext('2d');
|
let ctx = this.canvas.getContext('2d');
|
||||||
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
|
||||||
if (layer !== LAYERS.terrain) {
|
if (this.adjusted_tile.type.layer !== LAYERS.terrain) {
|
||||||
this.editor.renderer.draw_single_tile_type('floor', null, this.canvas);
|
this.editor.renderer.draw_single_tile_type('floor', null, this.canvas);
|
||||||
}
|
}
|
||||||
this.editor.renderer.draw_single_tile_type(tile.type.name, tile, this.canvas);
|
this.editor.renderer.draw_single_tile_type(
|
||||||
}
|
this.adjusted_tile.type.name, this.adjusted_tile, this.canvas);
|
||||||
|
|
||||||
// Special previewing behavior
|
// Special previewing behavior
|
||||||
if (tile.type.name === 'button_gray') {
|
if (this.adjusted_tile.type.name === 'button_gray') {
|
||||||
this.cursor_element.classList.remove('--visible');
|
this.cursor_element.classList.remove('--visible');
|
||||||
this.gray_button_preview.classList.add('--visible');
|
this.gray_button_preview.classList.add('--visible');
|
||||||
let gx0 = Math.max(0, cell_x - 2);
|
let gx0 = Math.max(0, cell_x - 2);
|
||||||
@ -1793,63 +1830,16 @@ export class AdjustOperation extends MouseOperation {
|
|||||||
|
|
||||||
handle_press() {
|
handle_press() {
|
||||||
let cell = this.cell(this.prev_cell_x, this.prev_cell_y);
|
let cell = this.cell(this.prev_cell_x, this.prev_cell_y);
|
||||||
let tile = cell[this.hovered_layer];
|
|
||||||
if (! tile)
|
|
||||||
return;
|
|
||||||
let behavior = SPECIAL_TILE_BEHAVIOR[tile.type.name];
|
|
||||||
|
|
||||||
// Same order as _find_target_tile
|
if (this.adjusted_tile) {
|
||||||
if (TILE_TYPES['transmogrifier']._mogrifications[tile.type.name]) {
|
this.editor.place_in_cell(cell, this.adjusted_tile);
|
||||||
// Toggle between related tile types
|
|
||||||
tile.type = TILE_TYPES[TILE_TYPES['transmogrifier']._mogrifications[tile.type.name]];
|
|
||||||
this.editor.place_in_cell(cell, tile);
|
|
||||||
this.editor.commit_undo();
|
|
||||||
}
|
|
||||||
else if (ADJUST_TILE_TYPES[tile.type.name]) {
|
|
||||||
// Toggle between related tile types
|
|
||||||
// TODO can you go backwards any more, or no?
|
|
||||||
let toggled = ADJUST_TILE_TYPES[tile.type.name].next;
|
|
||||||
tile.type = TILE_TYPES[toggled];
|
|
||||||
this.editor.place_in_cell(cell, tile);
|
|
||||||
this.editor.commit_undo();
|
|
||||||
}
|
|
||||||
else if (tile.type.name === 'logic_gate' && ADJUST_GATE_TYPES[tile.gate_type]) {
|
|
||||||
// Also toggle between related logic gate types
|
|
||||||
let toggled = ADJUST_GATE_TYPES[tile.gate_type].next;
|
|
||||||
tile.gate_type = toggled;
|
|
||||||
this.editor.place_in_cell(cell, tile);
|
|
||||||
this.editor.commit_undo();
|
|
||||||
}
|
|
||||||
else if (tile.type.name === 'logic_gate' && tile.gate_type === 'counter') {
|
|
||||||
// Adjust the starting number on a logic gate
|
|
||||||
// TODO is this in adjust_forward or...?
|
|
||||||
}
|
|
||||||
else if (this.hovered_layer === LAYERS.thin_wall) {
|
|
||||||
// Place or delete individual thin walls
|
|
||||||
// XXX don't allow deleting ALL the thin walls...??
|
|
||||||
let bit = DIRECTIONS[this.get_tile_edge()].bit;
|
|
||||||
tile.edges ^= bit;
|
|
||||||
this.editor.place_in_cell(cell, tile);
|
|
||||||
this.editor.commit_undo();
|
|
||||||
}
|
|
||||||
else if (tile.type.name === 'frame_block') {
|
|
||||||
// Place or delete individual frame block arrows
|
|
||||||
let edge = this.get_tile_edge();
|
|
||||||
tile.arrows = new Set(tile.arrows);
|
|
||||||
if (tile.arrows.has(edge)) {
|
|
||||||
tile.arrows.delete(edge);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
tile.arrows.add(edge);
|
|
||||||
}
|
|
||||||
this.editor.place_in_cell(cell, tile);
|
|
||||||
this.editor.commit_undo();
|
|
||||||
}
|
|
||||||
else if (behavior && behavior.adjust_forward) {
|
|
||||||
behavior.adjust_forward(tile);
|
|
||||||
this.editor.place_in_cell(cell, tile);
|
|
||||||
this.editor.commit_undo();
|
this.editor.commit_undo();
|
||||||
|
// The tile has changed, so invalidate our hover
|
||||||
|
// TODO should the editor do this automatically, since the cell changed?
|
||||||
|
this.handle_refresh();
|
||||||
|
this.handle_hover(null, null, null, null, this.prev_cell_x, this.prev_cell_y);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
else if (ADJUST_SPECIAL[tile.type.name]) {
|
else if (ADJUST_SPECIAL[tile.type.name]) {
|
||||||
ADJUST_SPECIAL[tile.type.name](this.editor, tile, cell);
|
ADJUST_SPECIAL[tile.type.name](this.editor, tile, cell);
|
||||||
this.editor.commit_undo();
|
this.editor.commit_undo();
|
||||||
@ -1860,7 +1850,13 @@ export class AdjustOperation extends MouseOperation {
|
|||||||
this.editor.open_tile_prop_overlay(
|
this.editor.open_tile_prop_overlay(
|
||||||
tile, cell, this.editor.renderer.get_cell_rect(cell.x, cell.y));
|
tile, cell, this.editor.renderer.get_cell_rect(cell.x, cell.y));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handle_refresh() {
|
||||||
|
this.hover_stale = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Adjust tool doesn't support dragging
|
// Adjust tool doesn't support dragging
|
||||||
// TODO should it?
|
// TODO should it?
|
||||||
// TODO if it does then it should end as soon as you spawn a popup
|
// TODO if it does then it should end as soon as you spawn a popup
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user