Add support for gray buttons to the adjust tool
This commit is contained in:
parent
1170c5970e
commit
abbda898c7
@ -1201,6 +1201,42 @@ const ADJUST_TOGGLES_CCW = {};
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Little wrapper that allows calling (simple) callbacks on tile types from the editor.
|
||||||
|
// Note that editor tiles don't even have .cell, so we have to fake that too
|
||||||
|
class DummyRunningLevel {
|
||||||
|
constructor(editor, tile, cell) {
|
||||||
|
this.editor = editor;
|
||||||
|
this.tile = tile;
|
||||||
|
this.cell = cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
_set_tile_prop(tile, key, value) {
|
||||||
|
if (tile !== this.tile) {
|
||||||
|
console.error("DummyRunningLevel._set_tile_prop called on an unknown tile:", tile, "expected:", this.tile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editor.place_in_cell(this.cell, {...tile, key: value});
|
||||||
|
}
|
||||||
|
|
||||||
|
transmute_tile(tile, type_name) {
|
||||||
|
if (tile !== this.tile) {
|
||||||
|
console.error("DummyRunningLevel.transmute_tile called on an unknown tile:", tile, "expected:", this.tile);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let type = TILE_TYPES[type_name];
|
||||||
|
if (! type) {
|
||||||
|
console.error("DummyRunningLevel.transmute_tile called with bad type:", type_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (tile.type.layer !== type.layer) {
|
||||||
|
console.error("DummyRunningLevel.transmute_tile refusing to change tile layers:", tile, type_name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.editor.place_in_cell(this.cell, {...tile, type});
|
||||||
|
}
|
||||||
|
}
|
||||||
// Tiles with special behavior when clicked
|
// Tiles with special behavior when clicked
|
||||||
const ADJUST_SPECIAL = {
|
const ADJUST_SPECIAL = {
|
||||||
button_green(editor) {
|
button_green(editor) {
|
||||||
@ -1221,7 +1257,24 @@ const ADJUST_SPECIAL = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
button_gray(editor, tile, cell) {
|
||||||
|
// Toggle gray objects... er... objects affected by gray buttons
|
||||||
|
for (let dy = -2; dy <= 2; dy++) {
|
||||||
|
for (let dx = -2; dx <= 2; dx++) {
|
||||||
|
if (dx === 0 && dy === 0)
|
||||||
|
continue;
|
||||||
|
let other_cell = editor.cell(cell.x + dx, cell.y + dy);
|
||||||
|
if (! other_cell)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (let other of other_cell) {
|
||||||
|
if (other && other.type.on_gray_button && other.type.is_gray_button_editor_safe) {
|
||||||
|
other.type.on_gray_button(other, new DummyRunningLevel(editor, other, other_cell));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
// TODO maybe better visual feedback of what will happen when you click?
|
// TODO maybe better visual feedback of what will happen when you click?
|
||||||
// - rotate terrain (cw, ccw)
|
// - rotate terrain (cw, ccw)
|
||||||
@ -1229,6 +1282,59 @@ const ADJUST_SPECIAL = {
|
|||||||
// - rotate actor (cw, ccw)
|
// - rotate actor (cw, ccw)
|
||||||
// - press button
|
// - press button
|
||||||
export class AdjustOperation extends MouseOperation {
|
export class AdjustOperation extends MouseOperation {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
|
||||||
|
this.gray_button_preview = mk_svg('g.overlay-transient', {'data-source': 'AdjustOperation'});
|
||||||
|
this.gray_button_preview.append(mk_svg('rect.overlay-adjust-gray-button-radius', {
|
||||||
|
x: -2,
|
||||||
|
y: -2,
|
||||||
|
width: 5,
|
||||||
|
height: 5,
|
||||||
|
}));
|
||||||
|
this.editor.svg_overlay.append(this.gray_button_preview);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_hover(client_x, client_y, frac_cell_x, frac_cell_y, cell_x, cell_y) {
|
||||||
|
let cell = this.cell(cell_x, cell_y);
|
||||||
|
let terrain = cell[LAYERS.terrain];
|
||||||
|
if (terrain.type.name === 'button_gray') {
|
||||||
|
this.gray_button_preview.classList.add('--visible');
|
||||||
|
this.gray_button_preview.setAttribute('transform', `translate(${cell_x} ${cell_y})`);
|
||||||
|
for (let el of this.gray_button_preview.querySelectorAll('rect.overlay-adjust-gray-button-shroud')) {
|
||||||
|
el.remove();
|
||||||
|
}
|
||||||
|
// The easiest way I can find to preview this is to slap an overlay on everything NOT
|
||||||
|
// affected by the button. Try to consolidate some of the resulting rectangles though
|
||||||
|
for (let dy = -2; dy <= 2; dy++) {
|
||||||
|
let last_rect, last_dx;
|
||||||
|
for (let dx = -2; dx <= 2; dx++) {
|
||||||
|
let target = this.cell(cell_x + dx, cell_y + dy);
|
||||||
|
if (target && target !== cell && target[LAYERS.terrain].type.on_gray_button)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (last_rect && last_dx === dx - 1) {
|
||||||
|
last_rect.setAttribute('width', 1 + parseInt(last_rect.getAttribute('width'), 10));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
last_rect = mk_svg('rect.overlay-adjust-gray-button-shroud', {
|
||||||
|
x: dx,
|
||||||
|
y: dy,
|
||||||
|
width: 1,
|
||||||
|
height: 1,
|
||||||
|
});
|
||||||
|
this.gray_button_preview.append(last_rect);
|
||||||
|
}
|
||||||
|
last_dx = dx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.gray_button_preview.classList.remove('--visible');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
if (this.ctrl) {
|
if (this.ctrl) {
|
||||||
@ -1274,7 +1380,7 @@ export class AdjustOperation extends MouseOperation {
|
|||||||
// Other special tile behavior
|
// Other special tile behavior
|
||||||
let special = ADJUST_SPECIAL[tile.type.name];
|
let special = ADJUST_SPECIAL[tile.type.name];
|
||||||
if (special) {
|
if (special) {
|
||||||
special(this.editor);
|
special(this.editor, tile, cell);
|
||||||
this.editor.commit_undo();
|
this.editor.commit_undo();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1283,6 +1389,10 @@ export class AdjustOperation extends MouseOperation {
|
|||||||
// 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
|
||||||
|
do_destroy() {
|
||||||
|
this.gray_button_preview.remove();
|
||||||
|
super.do_destroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME currently allows creating outside the map bounds and moving beyond the right/bottom, sigh
|
// FIXME currently allows creating outside the map bounds and moving beyond the right/bottom, sigh
|
||||||
|
|||||||
@ -66,6 +66,7 @@ function _define_force_floor(direction, opposite_type) {
|
|||||||
activate(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, opposite_type);
|
level.transmute_tile(me, opposite_type);
|
||||||
},
|
},
|
||||||
|
is_gray_button_editor_safe: true,
|
||||||
on_gray_button: activate_me,
|
on_gray_button: activate_me,
|
||||||
on_power: activate_me,
|
on_power: activate_me,
|
||||||
};
|
};
|
||||||
@ -505,6 +506,7 @@ const TILE_TYPES = {
|
|||||||
activate(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'swivel_se');
|
level.transmute_tile(me, 'swivel_se');
|
||||||
},
|
},
|
||||||
|
is_gray_button_editor_safe: true,
|
||||||
on_gray_button: activate_me,
|
on_gray_button: activate_me,
|
||||||
on_power: activate_me,
|
on_power: activate_me,
|
||||||
},
|
},
|
||||||
@ -522,6 +524,7 @@ const TILE_TYPES = {
|
|||||||
activate(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'swivel_sw');
|
level.transmute_tile(me, 'swivel_sw');
|
||||||
},
|
},
|
||||||
|
is_gray_button_editor_safe: true,
|
||||||
on_gray_button: activate_me,
|
on_gray_button: activate_me,
|
||||||
on_power: activate_me,
|
on_power: activate_me,
|
||||||
},
|
},
|
||||||
@ -539,6 +542,7 @@ const TILE_TYPES = {
|
|||||||
activate(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'swivel_nw');
|
level.transmute_tile(me, 'swivel_nw');
|
||||||
},
|
},
|
||||||
|
is_gray_button_editor_safe: true,
|
||||||
on_gray_button: activate_me,
|
on_gray_button: activate_me,
|
||||||
on_power: activate_me,
|
on_power: activate_me,
|
||||||
},
|
},
|
||||||
@ -556,6 +560,7 @@ const TILE_TYPES = {
|
|||||||
activate(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'swivel_ne');
|
level.transmute_tile(me, 'swivel_ne');
|
||||||
},
|
},
|
||||||
|
is_gray_button_editor_safe: true,
|
||||||
on_gray_button: activate_me,
|
on_gray_button: activate_me,
|
||||||
on_power: activate_me,
|
on_power: activate_me,
|
||||||
},
|
},
|
||||||
@ -653,6 +658,7 @@ const TILE_TYPES = {
|
|||||||
on_power(me, level) {
|
on_power(me, level) {
|
||||||
me.type._switch_track(me, level);
|
me.type._switch_track(me, level);
|
||||||
},
|
},
|
||||||
|
is_gray_button_editor_safe: true,
|
||||||
on_gray_button(me, level) {
|
on_gray_button(me, level) {
|
||||||
me.type._switch_track(me, level);
|
me.type._switch_track(me, level);
|
||||||
},
|
},
|
||||||
@ -791,6 +797,7 @@ const TILE_TYPES = {
|
|||||||
activate(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'turntable_ccw');
|
level.transmute_tile(me, 'turntable_ccw');
|
||||||
},
|
},
|
||||||
|
is_gray_button_editor_safe: true,
|
||||||
on_gray_button: activate_me,
|
on_gray_button: activate_me,
|
||||||
on_power: activate_me,
|
on_power: activate_me,
|
||||||
},
|
},
|
||||||
@ -812,6 +819,7 @@ const TILE_TYPES = {
|
|||||||
activate(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'turntable_cw');
|
level.transmute_tile(me, 'turntable_cw');
|
||||||
},
|
},
|
||||||
|
is_gray_button_editor_safe: true,
|
||||||
on_gray_button: activate_me,
|
on_gray_button: activate_me,
|
||||||
on_power: activate_me,
|
on_power: activate_me,
|
||||||
},
|
},
|
||||||
@ -1328,12 +1336,12 @@ const TILE_TYPES = {
|
|||||||
level.pending_green_toggle &&
|
level.pending_green_toggle &&
|
||||||
(other.type.collision_mask & COLLISION.all_but_ghost));
|
(other.type.collision_mask & COLLISION.all_but_ghost));
|
||||||
},
|
},
|
||||||
on_gray_button(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'green_wall');
|
level.transmute_tile(me, 'green_wall');
|
||||||
},
|
},
|
||||||
on_power(me, level) {
|
is_gray_button_editor_safe: true,
|
||||||
me.type.on_gray_button(me, level);
|
on_gray_button: activate_me,
|
||||||
},
|
on_power: activate_me,
|
||||||
},
|
},
|
||||||
green_wall: {
|
green_wall: {
|
||||||
layer: LAYERS.terrain,
|
layer: LAYERS.terrain,
|
||||||
@ -1344,12 +1352,12 @@ const TILE_TYPES = {
|
|||||||
! level.pending_green_toggle &&
|
! level.pending_green_toggle &&
|
||||||
(other.type.collision_mask & COLLISION.all_but_ghost));
|
(other.type.collision_mask & COLLISION.all_but_ghost));
|
||||||
},
|
},
|
||||||
on_gray_button(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'green_floor');
|
level.transmute_tile(me, 'green_floor');
|
||||||
},
|
},
|
||||||
on_power(me, level) {
|
is_gray_button_editor_safe: true,
|
||||||
me.type.on_gray_button(me, level);
|
on_gray_button: activate_me,
|
||||||
},
|
on_power: activate_me,
|
||||||
},
|
},
|
||||||
green_chip: {
|
green_chip: {
|
||||||
layer: LAYERS.item,
|
layer: LAYERS.item,
|
||||||
@ -1377,28 +1385,24 @@ const TILE_TYPES = {
|
|||||||
},
|
},
|
||||||
purple_floor: {
|
purple_floor: {
|
||||||
layer: LAYERS.terrain,
|
layer: LAYERS.terrain,
|
||||||
on_gray_button(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'purple_wall');
|
level.transmute_tile(me, 'purple_wall');
|
||||||
},
|
},
|
||||||
on_power(me, level) {
|
is_gray_button_editor_safe: true,
|
||||||
me.type.on_gray_button(me, level);
|
on_gray_button: activate_me,
|
||||||
},
|
on_power: activate_me,
|
||||||
on_depower(me, level) {
|
on_depower: activate_me,
|
||||||
me.type.on_gray_button(me, level);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
purple_wall: {
|
purple_wall: {
|
||||||
layer: LAYERS.terrain,
|
layer: LAYERS.terrain,
|
||||||
blocks_collision: COLLISION.all_but_ghost,
|
blocks_collision: COLLISION.all_but_ghost,
|
||||||
on_gray_button(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'purple_floor');
|
level.transmute_tile(me, 'purple_floor');
|
||||||
},
|
},
|
||||||
on_power(me, level) {
|
is_gray_button_editor_safe: true,
|
||||||
me.type.on_gray_button(me, level);
|
on_gray_button: activate_me,
|
||||||
},
|
on_power: activate_me,
|
||||||
on_depower(me, level) {
|
on_depower: activate_me,
|
||||||
me.type.on_gray_button(me, level);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Sokoban blocks, buttons, and walls -- they each come in four colors, the buttons can be
|
// Sokoban blocks, buttons, and walls -- they each come in four colors, the buttons can be
|
||||||
@ -1578,9 +1582,8 @@ const TILE_TYPES = {
|
|||||||
on_power(me, level) {
|
on_power(me, level) {
|
||||||
me.type.activate(me, level, true);
|
me.type.activate(me, level, true);
|
||||||
},
|
},
|
||||||
on_gray_button(me, level) {
|
is_gray_button_editor_safe: false,
|
||||||
me.type.activate(me, level);
|
on_gray_button: activate_me,
|
||||||
},
|
|
||||||
},
|
},
|
||||||
trap: {
|
trap: {
|
||||||
layer: LAYERS.terrain,
|
layer: LAYERS.terrain,
|
||||||
@ -2004,24 +2007,18 @@ const TILE_TYPES = {
|
|||||||
// Do NOT immediately nuke anything on us, or it'd be impossible to push a block off an
|
// Do NOT immediately nuke anything on us, or it'd be impossible to push a block off an
|
||||||
// adjacent orange button; this is probably why flame jets kill on tics
|
// adjacent orange button; this is probably why flame jets kill on tics
|
||||||
},
|
},
|
||||||
on_gray_button(me, level) {
|
is_gray_button_editor_safe: true,
|
||||||
me.type.activate(me, level);
|
on_gray_button: activate_me,
|
||||||
},
|
on_power: activate_me,
|
||||||
on_power(me, level) {
|
|
||||||
me.type.activate(me, level);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
flame_jet_on: {
|
flame_jet_on: {
|
||||||
layer: LAYERS.terrain,
|
layer: LAYERS.terrain,
|
||||||
activate(me, level) {
|
activate(me, level) {
|
||||||
level.transmute_tile(me, 'flame_jet_off');
|
level.transmute_tile(me, 'flame_jet_off');
|
||||||
},
|
},
|
||||||
on_gray_button(me, level) {
|
is_gray_button_editor_safe: true,
|
||||||
me.type.activate(me, level);
|
on_gray_button: activate_me,
|
||||||
},
|
on_power: activate_me,
|
||||||
on_power(me, level) {
|
|
||||||
me.type.activate(me, level);
|
|
||||||
},
|
|
||||||
on_stand(me, level, other) {
|
on_stand(me, level, other) {
|
||||||
// Note that (dirt?) blocks, fireballs, and anything with fire boots are immune
|
// Note that (dirt?) blocks, fireballs, and anything with fire boots are immune
|
||||||
// TODO would be neat if this understood "ignores anything with fire immunity" but that
|
// TODO would be neat if this understood "ignores anything with fire immunity" but that
|
||||||
|
|||||||
@ -2290,6 +2290,14 @@ svg.level-editor-overlay g.overlay-connection.--implicit line.-arrow {
|
|||||||
svg.level-editor-overlay g.overlay-connection line.-arrow {
|
svg.level-editor-overlay g.overlay-connection line.-arrow {
|
||||||
marker-end: url(#overlay-arrowhead);
|
marker-end: url(#overlay-arrowhead);
|
||||||
}
|
}
|
||||||
|
svg.level-editor-overlay .overlay-adjust-gray-button-radius {
|
||||||
|
stroke: #f4f4f4;
|
||||||
|
fill: hsla(10, 10%, 80%, 0.125);
|
||||||
|
}
|
||||||
|
svg.level-editor-overlay .overlay-adjust-gray-button-shroud {
|
||||||
|
stroke: none;
|
||||||
|
fill: hsla(10, 10%, 60%, 0.75);
|
||||||
|
}
|
||||||
svg.level-editor-overlay rect.overlay-camera {
|
svg.level-editor-overlay rect.overlay-camera {
|
||||||
stroke: #808080;
|
stroke: #808080;
|
||||||
fill: #80808040;
|
fill: #80808040;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user