Teach the editor to do partial redraws
This commit is contained in:
parent
90fa352a50
commit
1ce704864c
@ -10,8 +10,20 @@ class TileEditorOverlay extends TransientOverlay {
|
|||||||
this.tile = null;
|
this.tile = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
edit_tile(tile) {
|
edit_tile(tile, cell) {
|
||||||
this.tile = tile;
|
this.tile = tile;
|
||||||
|
this.cell = cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
mark_dirty() {
|
||||||
|
if (this.cell) {
|
||||||
|
this.editor.mark_cell_dirty(this.cell);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO i guess i'm just kind of assuming it's the palette selection, but it doesn't
|
||||||
|
// necessarily have to be, if i... do something later
|
||||||
|
this.editor.redraw_palette_selection();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static configure_tile_defaults(tile) {
|
static configure_tile_defaults(tile) {
|
||||||
@ -46,13 +58,13 @@ class LetterTileEditor extends TileEditorOverlay {
|
|||||||
list.addEventListener('change', ev => {
|
list.addEventListener('change', ev => {
|
||||||
if (this.tile) {
|
if (this.tile) {
|
||||||
this.tile.overlaid_glyph = this.root.elements['glyph'].value;
|
this.tile.overlaid_glyph = this.root.elements['glyph'].value;
|
||||||
this.editor.mark_tile_dirty(this.tile);
|
this.mark_dirty();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
edit_tile(tile) {
|
edit_tile(tile, cell) {
|
||||||
super.edit_tile(tile);
|
super.edit_tile(tile, cell);
|
||||||
this.root.elements['glyph'].value = tile.overlaid_glyph;
|
this.root.elements['glyph'].value = tile.overlaid_glyph;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,8 +87,8 @@ class HintTileEditor extends TileEditorOverlay {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
edit_tile(tile) {
|
edit_tile(tile, cell) {
|
||||||
super.edit_tile(tile);
|
super.edit_tile(tile, cell);
|
||||||
this.text.value = tile.hint_text ?? "";
|
this.text.value = tile.hint_text ?? "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,13 +156,13 @@ class FrameBlockTileEditor extends TileEditorOverlay {
|
|||||||
else {
|
else {
|
||||||
this.tile.arrows.delete(ev.target.value);
|
this.tile.arrows.delete(ev.target.value);
|
||||||
}
|
}
|
||||||
this.editor.mark_tile_dirty(this.tile);
|
this.mark_dirty();
|
||||||
});
|
});
|
||||||
this.root.append(arrow_list);
|
this.root.append(arrow_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
edit_tile(tile) {
|
edit_tile(tile, cell) {
|
||||||
super.edit_tile(tile);
|
super.edit_tile(tile, cell);
|
||||||
|
|
||||||
for (let input of this.root.elements['direction']) {
|
for (let input of this.root.elements['direction']) {
|
||||||
input.checked = tile.arrows.has(input.value);
|
input.checked = tile.arrows.has(input.value);
|
||||||
@ -197,7 +209,7 @@ class RailroadTileEditor extends TileEditorOverlay {
|
|||||||
else {
|
else {
|
||||||
this.tile.tracks &= ~bit;
|
this.tile.tracks &= ~bit;
|
||||||
}
|
}
|
||||||
this.editor.mark_tile_dirty(this.tile);
|
this.mark_dirty();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.root.append(track_list);
|
this.root.append(track_list);
|
||||||
@ -213,7 +225,7 @@ class RailroadTileEditor extends TileEditorOverlay {
|
|||||||
switch_list.addEventListener('change', ev => {
|
switch_list.addEventListener('change', ev => {
|
||||||
if (this.tile) {
|
if (this.tile) {
|
||||||
this.tile.track_switch = parseInt(ev.target.value, 10);
|
this.tile.track_switch = parseInt(ev.target.value, 10);
|
||||||
this.editor.mark_tile_dirty(this.tile);
|
this.mark_dirty();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.root.append(switch_list);
|
this.root.append(switch_list);
|
||||||
@ -222,8 +234,8 @@ class RailroadTileEditor extends TileEditorOverlay {
|
|||||||
// TODO initial actor facing (maybe only if there's an actor in the cell)
|
// TODO initial actor facing (maybe only if there's an actor in the cell)
|
||||||
}
|
}
|
||||||
|
|
||||||
edit_tile(tile) {
|
edit_tile(tile, cell) {
|
||||||
super.edit_tile(tile);
|
super.edit_tile(tile, cell);
|
||||||
|
|
||||||
for (let input of this.root.elements['track']) {
|
for (let input of this.root.elements['track']) {
|
||||||
input.checked = !! (tile.tracks & (1 << input.value));
|
input.checked = !! (tile.tracks & (1 << input.value));
|
||||||
|
|||||||
@ -869,7 +869,7 @@ class WireOperation extends DrawOperation {
|
|||||||
// Draw
|
// Draw
|
||||||
tile.wire_directions |= DIRECTIONS[wire_direction].bit;
|
tile.wire_directions |= DIRECTIONS[wire_direction].bit;
|
||||||
}
|
}
|
||||||
// TODO this.editor.mark_tile_dirty(tile);
|
this.editor.mark_cell_dirty(cell);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -921,7 +921,7 @@ class AdjustOperation extends MouseOperation {
|
|||||||
for (let tile of cell) {
|
for (let tile of cell) {
|
||||||
if (tile && TILES_WITH_PROPS[tile.type.name] !== undefined) {
|
if (tile && TILES_WITH_PROPS[tile.type.name] !== undefined) {
|
||||||
// TODO use the tile's bbox, not the mouse position
|
// TODO use the tile's bbox, not the mouse position
|
||||||
this.editor.open_tile_prop_overlay(tile, this.mx0, this.my0);
|
this.editor.open_tile_prop_overlay(tile, cell, this.mx0, this.my0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -942,7 +942,7 @@ class AdjustOperation extends MouseOperation {
|
|||||||
rotated = this.editor.rotate_tile_right(tile);
|
rotated = this.editor.rotate_tile_right(tile);
|
||||||
}
|
}
|
||||||
if (rotated) {
|
if (rotated) {
|
||||||
this.editor.mark_tile_dirty(tile);
|
this.editor.mark_cell_dirty(cell);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -950,7 +950,7 @@ class AdjustOperation extends MouseOperation {
|
|||||||
let other = (this.alt_mode ? ADJUST_TOGGLES_CCW : ADJUST_TOGGLES_CW)[tile.type.name];
|
let other = (this.alt_mode ? ADJUST_TOGGLES_CCW : ADJUST_TOGGLES_CW)[tile.type.name];
|
||||||
if (other) {
|
if (other) {
|
||||||
tile.type = TILE_TYPES[other];
|
tile.type = TILE_TYPES[other];
|
||||||
this.editor.mark_tile_dirty(tile);
|
this.editor.mark_cell_dirty(cell);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2397,6 +2397,7 @@ export class Editor extends PrimaryView {
|
|||||||
}
|
}
|
||||||
else if (this.palette_selection) {
|
else if (this.palette_selection) {
|
||||||
this.rotate_tile_left(this.palette_selection);
|
this.rotate_tile_left(this.palette_selection);
|
||||||
|
this.redraw_palette_selection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ev.key === '.') {
|
else if (ev.key === '.') {
|
||||||
@ -2405,6 +2406,7 @@ export class Editor extends PrimaryView {
|
|||||||
}
|
}
|
||||||
else if (this.palette_selection) {
|
else if (this.palette_selection) {
|
||||||
this.rotate_tile_right(this.palette_selection);
|
this.rotate_tile_right(this.palette_selection);
|
||||||
|
this.redraw_palette_selection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -2497,7 +2499,7 @@ export class Editor extends PrimaryView {
|
|||||||
this.selected_tile_el.addEventListener('click', ev => {
|
this.selected_tile_el.addEventListener('click', ev => {
|
||||||
if (this.palette_selection && TILES_WITH_PROPS[this.palette_selection.type.name]) {
|
if (this.palette_selection && TILES_WITH_PROPS[this.palette_selection.type.name]) {
|
||||||
// FIXME use tile bounds
|
// FIXME use tile bounds
|
||||||
this.open_tile_prop_overlay(this.palette_selection, ev.clientX, ev.clientY);
|
this.open_tile_prop_overlay(this.palette_selection, null, ev.clientX, ev.clientY);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// TODO ones for the palette too??
|
// TODO ones for the palette too??
|
||||||
@ -2506,10 +2508,12 @@ export class Editor extends PrimaryView {
|
|||||||
let rotate_right_button = mk('button.--image', {type: 'button'}, mk('img', {src: 'icons/rotate-right.png'}));
|
let rotate_right_button = mk('button.--image', {type: 'button'}, mk('img', {src: 'icons/rotate-right.png'}));
|
||||||
rotate_right_button.addEventListener('click', ev => {
|
rotate_right_button.addEventListener('click', ev => {
|
||||||
this.rotate_tile_right(this.palette_selection);
|
this.rotate_tile_right(this.palette_selection);
|
||||||
|
this.redraw_palette_selection();
|
||||||
});
|
});
|
||||||
let rotate_left_button = mk('button.--image', {type: 'button'}, mk('img', {src: 'icons/rotate-left.png'}));
|
let rotate_left_button = mk('button.--image', {type: 'button'}, mk('img', {src: 'icons/rotate-left.png'}));
|
||||||
rotate_left_button.addEventListener('click', ev => {
|
rotate_left_button.addEventListener('click', ev => {
|
||||||
this.rotate_tile_left(this.palette_selection);
|
this.rotate_tile_left(this.palette_selection);
|
||||||
|
this.redraw_palette_selection();
|
||||||
});
|
});
|
||||||
this.root.querySelector('.controls').append(
|
this.root.querySelector('.controls').append(
|
||||||
mk('div.editor-tile-controls', rotate_right_button, this.selected_tile_el, rotate_left_button));
|
mk('div.editor-tile-controls', rotate_right_button, this.selected_tile_el, rotate_left_button));
|
||||||
@ -2721,6 +2725,15 @@ export class Editor extends PrimaryView {
|
|||||||
activate() {
|
activate() {
|
||||||
super.activate();
|
super.activate();
|
||||||
this.redraw_entire_level();
|
this.redraw_entire_level();
|
||||||
|
this._schedule_redraw_loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
deactivate() {
|
||||||
|
if (this._redraw_handle) {
|
||||||
|
window.cancelAnimationFrame(this._redraw_handle);
|
||||||
|
this._redraw_handle = null;
|
||||||
|
}
|
||||||
|
super.deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Level creation, management, and saving
|
// Level creation, management, and saving
|
||||||
@ -3028,7 +3041,7 @@ export class Editor extends PrimaryView {
|
|||||||
this.palette_selection_el.classList.add('--selected');
|
this.palette_selection_el.classList.add('--selected');
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mark_tile_dirty(tile);
|
this.redraw_palette_selection();
|
||||||
|
|
||||||
// Some tools obviously don't work with a palette selection, in which case changing tiles
|
// Some tools obviously don't work with a palette selection, in which case changing tiles
|
||||||
// should default you back to the pencil
|
// should default you back to the pencil
|
||||||
@ -3048,7 +3061,6 @@ export class Editor extends PrimaryView {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mark_tile_dirty(tile);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3063,7 +3075,6 @@ export class Editor extends PrimaryView {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.mark_tile_dirty(tile);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3075,26 +3086,55 @@ export class Editor extends PrimaryView {
|
|||||||
|
|
||||||
// -- Drawing --
|
// -- Drawing --
|
||||||
|
|
||||||
mark_tile_dirty(tile) {
|
redraw_palette_selection() {
|
||||||
// TODO partial redraws! until then, redraw everything
|
// FIXME should redraw in an existing canvas
|
||||||
if (tile === this.palette_selection) {
|
this.selected_tile_el.textContent = '';
|
||||||
// FIXME should redraw in an existing canvas
|
this.selected_tile_el.append(this.renderer.create_tile_type_canvas(
|
||||||
this.selected_tile_el.textContent = '';
|
this.palette_selection.type.name, this.palette_selection));
|
||||||
this.selected_tile_el.append(this.renderer.create_tile_type_canvas(tile.type.name, tile));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.redraw_entire_level();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mark_cell_dirty(cell) {
|
mark_cell_dirty(cell) {
|
||||||
this.redraw_entire_level();
|
if (! this._dirty_rect) {
|
||||||
|
this._dirty_rect = new DOMRect(cell.x, cell.y, 1, 1);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let rect = this._dirty_rect;
|
||||||
|
if (cell.x < rect.left) {
|
||||||
|
rect.width = rect.right - cell.x;
|
||||||
|
rect.x = cell.x;
|
||||||
|
}
|
||||||
|
else if (cell.x >= rect.right) {
|
||||||
|
rect.width = cell.x - rect.left + 1;
|
||||||
|
}
|
||||||
|
if (cell.y < rect.top) {
|
||||||
|
rect.height = rect.bottom - cell.y;
|
||||||
|
rect.y = cell.y;
|
||||||
|
}
|
||||||
|
else if (cell.y >= rect.bottom) {
|
||||||
|
rect.height = cell.y - rect.top + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
redraw_entire_level() {
|
redraw_entire_level() {
|
||||||
this.renderer.draw_static_region(0, 0, this.stored_level.size_x, this.stored_level.size_y);
|
this.renderer.draw_static_region(0, 0, this.stored_level.size_x, this.stored_level.size_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_schedule_redraw_loop() {
|
||||||
|
this._redraw_handle = window.requestAnimationFrame(this._redraw_dirty.bind(this));
|
||||||
|
this._dirty_rect = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatically redraw only what's changed
|
||||||
|
_redraw_dirty() {
|
||||||
|
if (this._dirty_rect) {
|
||||||
|
this.renderer.draw_static_region(
|
||||||
|
this._dirty_rect.left, this._dirty_rect.top,
|
||||||
|
this._dirty_rect.right, this._dirty_rect.bottom);
|
||||||
|
this._schedule_redraw_loop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// -- Utility/inspection --
|
// -- Utility/inspection --
|
||||||
|
|
||||||
is_in_bounds(x, y) {
|
is_in_bounds(x, y) {
|
||||||
@ -3179,12 +3219,12 @@ export class Editor extends PrimaryView {
|
|||||||
|
|
||||||
// -- Misc?? --
|
// -- Misc?? --
|
||||||
|
|
||||||
open_tile_prop_overlay(tile, x0, y0) {
|
open_tile_prop_overlay(tile, cell, x0, y0) {
|
||||||
this.cancel_mouse_operation();
|
this.cancel_mouse_operation();
|
||||||
// FIXME keep these around, don't recreate them constantly
|
// FIXME keep these around, don't recreate them constantly
|
||||||
let overlay_class = TILES_WITH_PROPS[tile.type.name];
|
let overlay_class = TILES_WITH_PROPS[tile.type.name];
|
||||||
let overlay = new overlay_class(this.conductor);
|
let overlay = new overlay_class(this.conductor);
|
||||||
overlay.edit_tile(tile);
|
overlay.edit_tile(tile, cell);
|
||||||
overlay.open();
|
overlay.open();
|
||||||
|
|
||||||
// FIXME move this into TransientOverlay or some other base class
|
// FIXME move this into TransientOverlay or some other base class
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user