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
|
||||
const ADJUST_SPECIAL = {
|
||||
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?
|
||||
// - rotate terrain (cw, ccw)
|
||||
@ -1229,6 +1282,59 @@ const ADJUST_SPECIAL = {
|
||||
// - rotate actor (cw, ccw)
|
||||
// - press button
|
||||
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() {
|
||||
let cell = this.cell(this.prev_cell_x, this.prev_cell_y);
|
||||
if (this.ctrl) {
|
||||
@ -1274,7 +1380,7 @@ export class AdjustOperation extends MouseOperation {
|
||||
// Other special tile behavior
|
||||
let special = ADJUST_SPECIAL[tile.type.name];
|
||||
if (special) {
|
||||
special(this.editor);
|
||||
special(this.editor, tile, cell);
|
||||
this.editor.commit_undo();
|
||||
break;
|
||||
}
|
||||
@ -1283,6 +1389,10 @@ export class AdjustOperation extends MouseOperation {
|
||||
// Adjust tool doesn't support dragging
|
||||
// TODO should it?
|
||||
// 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
|
||||
|
||||
@ -66,6 +66,7 @@ function _define_force_floor(direction, opposite_type) {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, opposite_type);
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
};
|
||||
@ -505,6 +506,7 @@ const TILE_TYPES = {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'swivel_se');
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
},
|
||||
@ -522,6 +524,7 @@ const TILE_TYPES = {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'swivel_sw');
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
},
|
||||
@ -539,6 +542,7 @@ const TILE_TYPES = {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'swivel_nw');
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
},
|
||||
@ -556,6 +560,7 @@ const TILE_TYPES = {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'swivel_ne');
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
},
|
||||
@ -653,6 +658,7 @@ const TILE_TYPES = {
|
||||
on_power(me, level) {
|
||||
me.type._switch_track(me, level);
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button(me, level) {
|
||||
me.type._switch_track(me, level);
|
||||
},
|
||||
@ -791,6 +797,7 @@ const TILE_TYPES = {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'turntable_ccw');
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
},
|
||||
@ -812,6 +819,7 @@ const TILE_TYPES = {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'turntable_cw');
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
},
|
||||
@ -1328,12 +1336,12 @@ const TILE_TYPES = {
|
||||
level.pending_green_toggle &&
|
||||
(other.type.collision_mask & COLLISION.all_but_ghost));
|
||||
},
|
||||
on_gray_button(me, level) {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'green_wall');
|
||||
},
|
||||
on_power(me, level) {
|
||||
me.type.on_gray_button(me, level);
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
},
|
||||
green_wall: {
|
||||
layer: LAYERS.terrain,
|
||||
@ -1344,12 +1352,12 @@ const TILE_TYPES = {
|
||||
! level.pending_green_toggle &&
|
||||
(other.type.collision_mask & COLLISION.all_but_ghost));
|
||||
},
|
||||
on_gray_button(me, level) {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'green_floor');
|
||||
},
|
||||
on_power(me, level) {
|
||||
me.type.on_gray_button(me, level);
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
},
|
||||
green_chip: {
|
||||
layer: LAYERS.item,
|
||||
@ -1377,28 +1385,24 @@ const TILE_TYPES = {
|
||||
},
|
||||
purple_floor: {
|
||||
layer: LAYERS.terrain,
|
||||
on_gray_button(me, level) {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'purple_wall');
|
||||
},
|
||||
on_power(me, level) {
|
||||
me.type.on_gray_button(me, level);
|
||||
},
|
||||
on_depower(me, level) {
|
||||
me.type.on_gray_button(me, level);
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
on_depower: activate_me,
|
||||
},
|
||||
purple_wall: {
|
||||
layer: LAYERS.terrain,
|
||||
blocks_collision: COLLISION.all_but_ghost,
|
||||
on_gray_button(me, level) {
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'purple_floor');
|
||||
},
|
||||
on_power(me, level) {
|
||||
me.type.on_gray_button(me, level);
|
||||
},
|
||||
on_depower(me, level) {
|
||||
me.type.on_gray_button(me, level);
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
on_depower: activate_me,
|
||||
},
|
||||
|
||||
// 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) {
|
||||
me.type.activate(me, level, true);
|
||||
},
|
||||
on_gray_button(me, level) {
|
||||
me.type.activate(me, level);
|
||||
},
|
||||
is_gray_button_editor_safe: false,
|
||||
on_gray_button: activate_me,
|
||||
},
|
||||
trap: {
|
||||
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
|
||||
// adjacent orange button; this is probably why flame jets kill on tics
|
||||
},
|
||||
on_gray_button(me, level) {
|
||||
me.type.activate(me, level);
|
||||
},
|
||||
on_power(me, level) {
|
||||
me.type.activate(me, level);
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
},
|
||||
flame_jet_on: {
|
||||
layer: LAYERS.terrain,
|
||||
activate(me, level) {
|
||||
level.transmute_tile(me, 'flame_jet_off');
|
||||
},
|
||||
on_gray_button(me, level) {
|
||||
me.type.activate(me, level);
|
||||
},
|
||||
on_power(me, level) {
|
||||
me.type.activate(me, level);
|
||||
},
|
||||
is_gray_button_editor_safe: true,
|
||||
on_gray_button: activate_me,
|
||||
on_power: activate_me,
|
||||
on_stand(me, level, other) {
|
||||
// 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
|
||||
|
||||
@ -2290,6 +2290,14 @@ svg.level-editor-overlay g.overlay-connection.--implicit line.-arrow {
|
||||
svg.level-editor-overlay g.overlay-connection line.-arrow {
|
||||
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 {
|
||||
stroke: #808080;
|
||||
fill: #80808040;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user