Mass deletion support

pull/33/head
Tobias Springer 4 years ago
parent eb46b45c9a
commit bd89c2cc9e

@ -400,6 +400,14 @@
"spriteSourceSize": {"x":0,"y":0,"w":3,"h":3},
"sourceSize": {"w":3,"h":3}
},
"sprites/misc/deletion_marker.png":
{
"frame": {"x":107,"y":95,"w":10,"h":10},
"rotated": false,
"trimmed": false,
"spriteSourceSize": {"x":0,"y":0,"w":10,"h":10},
"sourceSize": {"w":10,"h":10}
},
"sprites/misc/slot_bad_arrow.png":
{
"frame": {"x":107,"y":95,"w":10,"h":10},
@ -423,6 +431,6 @@
"format": "RGBA8888",
"size": {"w":121,"h":240},
"scale": "0.1",
"smartupdate": "$TexturePacker:SmartUpdate:80df730947c1d83df455c7645ebd4dbd:29979cacc85be7fc1c890b96110d9771:f159918d23e5952766c6d23ab52278c6$"
"smartupdate": "$TexturePacker:SmartUpdate:e1aa43844bd41a62665cbb0c503ebb65:4482f83c3403490091eed64b07ce6591:f159918d23e5952766c6d23ab52278c6$"
}
}

@ -400,6 +400,14 @@
"spriteSourceSize": {"x":4,"y":4,"w":28,"h":28},
"sourceSize": {"w":32,"h":32}
},
"sprites/misc/deletion_marker.png":
{
"frame": {"x":237,"y":1710,"w":82,"h":82},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":7,"y":7,"w":82,"h":82},
"sourceSize": {"w":96,"h":96}
},
"sprites/misc/slot_bad_arrow.png":
{
"frame": {"x":237,"y":1710,"w":82,"h":82},
@ -423,6 +431,6 @@
"format": "RGBA8888",
"size": {"w":1007,"h":1968},
"scale": "1",
"smartupdate": "$TexturePacker:SmartUpdate:80df730947c1d83df455c7645ebd4dbd:29979cacc85be7fc1c890b96110d9771:f159918d23e5952766c6d23ab52278c6$"
"smartupdate": "$TexturePacker:SmartUpdate:e1aa43844bd41a62665cbb0c503ebb65:4482f83c3403490091eed64b07ce6591:f159918d23e5952766c6d23ab52278c6$"
}
}

@ -400,6 +400,14 @@
"spriteSourceSize": {"x":0,"y":0,"w":8,"h":8},
"sourceSize": {"w":8,"h":8}
},
"sprites/misc/deletion_marker.png":
{
"frame": {"x":217,"y":159,"w":22,"h":22},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":1,"y":1,"w":22,"h":22},
"sourceSize": {"w":24,"h":24}
},
"sprites/misc/slot_bad_arrow.png":
{
"frame": {"x":217,"y":159,"w":22,"h":22},
@ -423,6 +431,6 @@
"format": "RGBA8888",
"size": {"w":591,"h":252},
"scale": "0.25",
"smartupdate": "$TexturePacker:SmartUpdate:80df730947c1d83df455c7645ebd4dbd:29979cacc85be7fc1c890b96110d9771:f159918d23e5952766c6d23ab52278c6$"
"smartupdate": "$TexturePacker:SmartUpdate:e1aa43844bd41a62665cbb0c503ebb65:4482f83c3403490091eed64b07ce6591:f159918d23e5952766c6d23ab52278c6$"
}
}

@ -400,6 +400,14 @@
"spriteSourceSize": {"x":1,"y":1,"w":15,"h":15},
"sourceSize": {"w":16,"h":16}
},
"sprites/misc/deletion_marker.png":
{
"frame": {"x":456,"y":460,"w":42,"h":42},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":3,"y":3,"w":42,"h":42},
"sourceSize": {"w":48,"h":48}
},
"sprites/misc/slot_bad_arrow.png":
{
"frame": {"x":456,"y":460,"w":42,"h":42},
@ -423,6 +431,6 @@
"format": "RGBA8888",
"size": {"w":1023,"h":509},
"scale": "0.5",
"smartupdate": "$TexturePacker:SmartUpdate:80df730947c1d83df455c7645ebd4dbd:29979cacc85be7fc1c890b96110d9771:f159918d23e5952766c6d23ab52278c6$"
"smartupdate": "$TexturePacker:SmartUpdate:e1aa43844bd41a62665cbb0c503ebb65:4482f83c3403490091eed64b07ce6591:f159918d23e5952766c6d23ab52278c6$"
}
}

@ -400,6 +400,14 @@
"spriteSourceSize": {"x":2,"y":2,"w":22,"h":22},
"sourceSize": {"w":24,"h":24}
},
"sprites/misc/deletion_marker.png":
{
"frame": {"x":1050,"y":79,"w":62,"h":62},
"rotated": false,
"trimmed": true,
"spriteSourceSize": {"x":5,"y":5,"w":62,"h":62},
"sourceSize": {"w":72,"h":72}
},
"sprites/misc/slot_bad_arrow.png":
{
"frame": {"x":1050,"y":79,"w":62,"h":62},
@ -423,6 +431,6 @@
"format": "RGBA8888",
"size": {"w":1125,"h":999},
"scale": "0.75",
"smartupdate": "$TexturePacker:SmartUpdate:80df730947c1d83df455c7645ebd4dbd:29979cacc85be7fc1c890b96110d9771:f159918d23e5952766c6d23ab52278c6$"
"smartupdate": "$TexturePacker:SmartUpdate:e1aa43844bd41a62665cbb0c503ebb65:4482f83c3403490091eed64b07ce6591:f159918d23e5952766c6d23ab52278c6$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

@ -64,7 +64,7 @@
}
}
.shift .keybinding {
.keybinding.shift {
transition: all 0.1s ease-in-out;
transition-property: background-color, color, border-color;
background: $colorRedBright;
@ -72,7 +72,7 @@
color: #fff;
}
&.shiftDown .shift .keybinding {
&.shiftDown .keybinding.shift {
border-color: darken($colorRedBright, 40);
}
}

@ -0,0 +1,20 @@
#ingame_HUD_MassSelector {
position: absolute;
@include S(top, 50px);
left: 50%;
transform: translateX(-50%);
@include S(width, 300px);
background: #f77;
@include S(border-radius, 4px);
@include S(padding, 10px);
@include PlainText;
color: #fff;
.keybinding {
position: relative;
top: unset;
left: unset;
right: unset;
bottom: unset;
}
}

@ -33,11 +33,12 @@
@import "ingame_hud/game_menu";
@import "ingame_hud/blur_overlay";
@import "ingame_hud/dialogs";
@import "ingame_hud/mass_selector";
// Z-Index
$elements: ingame_Canvas, ingame_HUD_building_placer_overlay, ingame_HUD_building_placer,
ingame_HUD_buildings_toolbar, ingame_HUD_GameMenu, ingame_HUD_KeybindingOverlay, ingame_HUD_Shop,
ingame_HUD_BetaOverlay, ingame_HUD_UnlockNotification;
ingame_HUD_BetaOverlay, ingame_HUD_MassSelector, ingame_HUD_UnlockNotification;
$zindex: 100;

@ -13,6 +13,7 @@ import { HUDUnlockNotification } from "./parts/unlock_notification";
import { HUDGameMenu } from "./parts/game_menu";
import { HUDShop } from "./parts/shop";
import { IS_MOBILE } from "../../core/config";
import { HUDMassSelector } from "./parts/mass_selector";
export class GameHUD {
/**
@ -40,6 +41,8 @@ export class GameHUD {
gameMenu: new HUDGameMenu(this.root),
massSelector: new HUDMassSelector(this.root),
shop: new HUDShop(this.root),
// betaOverlay: new HUDBetaOverlay(this.root),
@ -149,7 +152,7 @@ export class GameHUD {
* @param {DrawParameters} parameters
*/
draw(parameters) {
const partsOrder = ["buildingPlacer"];
const partsOrder = ["massSelector", "buildingPlacer"];
for (let i = 0; i < partsOrder.length; ++i) {
if (this.parts[partsOrder[i]]) {

@ -44,7 +44,9 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
</div>
<div class="binding noPlacementOnly">
<code class="keybinding rightMouse"></code>
<code class="keybinding rightMouse"></code><i></i>
<code class="keybinding shift">ALT</code>+
<code class="keybinding leftMouse"></code>
<label>Delete</label>
</div>
@ -60,13 +62,13 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
<label>Rotate Building</label>
</div>
<div class="binding placementOnly shift">
<code class="keybinding"> SHIFT</code>
<div class="binding placementOnly">
<code class="keybinding shift"> SHIFT</code>
<label>Place Multiple</label>
</div>
<div class="binding placementOnly shift">
<code class="keybinding">ALT</code>
<div class="binding placementOnly">
<code class="keybinding shift">ALT</code>
<label>Reverse orientation</label>
</div>
`

@ -1,3 +1,196 @@
import { BaseHUDPart } from "../base_hud_part";
import { Vector } from "../../../core/vector";
import { STOP_PROPAGATION } from "../../../core/signal";
import { DrawParameters } from "../../../core/draw_parameters";
import { Entity } from "../../entity";
import { Loader } from "../../../core/loader";
import { globalConfig } from "../../../core/config";
import { makeDiv } from "../../../core/utils";
import { DynamicDomAttach } from "../dynamic_dom_attach";
import { createLogger } from "../../../core/logging";
export class HUDMassSelector extends BaseHUDPart {}
const logger = createLogger("hud/mass_selector");
export class HUDMassSelector extends BaseHUDPart {
createElements(parent) {
this.element = makeDiv(
parent,
"ingame_HUD_MassSelector",
[],
`
Press <code class="keybinding">DEL</code> to remove selected buildings
and <code class="keybinding">ESCAPE</code> to cancel.
`
);
}
initialize() {
this.deletionMarker = Loader.getSprite("sprites/misc/deletion_marker.png");
this.currentSelectionStart = null;
this.currentSelectionEnd = null;
this.entityUidsMarkedForDeletion = new Set();
this.root.signals.entityQueuedForDestroy.add(this.onEntityDestroyed, this);
this.root.camera.downPreHandler.add(this.onMouseDown, this);
this.root.camera.movePreHandler.add(this.onMouseMove, this);
this.root.camera.upPostHandler.add(this.onMouseUp, this);
this.root.gameState.keyActionMapper.getBinding("back").add(this.onBack, this);
this.root.gameState.keyActionMapper.getBinding("confirm_mass_delete").add(this.confirmDelete, this);
this.domAttach = new DynamicDomAttach(this.root, this.element);
}
/**
* Handles the destroy callback and makes sure we clean our list
* @param {Entity} entity
*/
onEntityDestroyed(entity) {
this.entityUidsMarkedForDeletion.delete(entity.uid);
}
/**
*
*/
onBack() {
// Clear entities on escape
if (this.entityUidsMarkedForDeletion) {
this.entityUidsMarkedForDeletion = new Set();
return STOP_PROPAGATION;
}
}
confirmDelete() {
const entityUids = Array.from(this.entityUidsMarkedForDeletion);
for (let i = 0; i < entityUids.length; ++i) {
const uid = entityUids[i];
const entity = this.root.entityMgr.findByUid(uid);
if (!this.root.logic.tryDeleteBuilding(entity)) {
logger.error("Error in mass delete, could not remove building");
this.entityUidsMarkedForDeletion.delete(uid);
}
}
}
/**
* mouse down pre handler
* @param {Vector} pos
*/
onMouseDown(pos) {
if (!this.root.app.inputMgr.altIsDown) {
return;
}
if (!this.root.app.inputMgr.shiftIsDown) {
// Start new selection
this.entityUidsMarkedForDeletion = new Set();
}
this.currentSelectionStart = pos.copy();
this.currentSelectionEnd = pos.copy();
return STOP_PROPAGATION;
}
/**
* mouse move pre handler
* @param {Vector} pos
*/
onMouseMove(pos) {
if (this.currentSelectionStart) {
this.currentSelectionEnd = pos.copy();
}
}
onMouseUp() {
if (this.currentSelectionStart) {
const worldStart = this.root.camera.screenToWorld(this.currentSelectionStart);
const worldEnd = this.root.camera.screenToWorld(this.currentSelectionEnd);
const tileStart = worldStart.toTileSpace();
const tileEnd = worldEnd.toTileSpace();
const realTileStart = tileStart.min(tileEnd);
const realTileEnd = tileStart.max(tileEnd);
for (let x = realTileStart.x; x <= realTileEnd.x; ++x) {
for (let y = realTileStart.y; y <= realTileEnd.y; ++y) {
const contents = this.root.map.getTileContentXY(x, y);
if (contents && this.root.logic.canDeleteBuilding(contents)) {
this.entityUidsMarkedForDeletion.add(contents.uid);
}
}
}
this.currentSelectionStart = null;
this.currentSelectionEnd = null;
}
}
update() {
this.domAttach.update(this.entityUidsMarkedForDeletion.size > 0);
}
/**
*
* @param {DrawParameters} parameters
*/
draw(parameters) {
if (this.currentSelectionStart) {
const worldStart = this.root.camera.screenToWorld(this.currentSelectionStart);
const worldEnd = this.root.camera.screenToWorld(this.currentSelectionEnd);
const realWorldStart = worldStart.min(worldEnd);
const realWorldEnd = worldStart.max(worldEnd);
const tileStart = worldStart.toTileSpace();
const tileEnd = worldEnd.toTileSpace();
const realTileStart = tileStart.min(tileEnd);
const realTileEnd = tileStart.max(tileEnd);
parameters.context.lineWidth = 1;
parameters.context.fillStyle = "rgba(255, 127, 127, 0.2)";
parameters.context.strokeStyle = "rgba(255, 127, 127, 0.5)";
parameters.context.beginPath();
parameters.context.rect(
realWorldStart.x,
realWorldStart.y,
realWorldEnd.x - realWorldStart.x,
realWorldEnd.y - realWorldStart.y
);
parameters.context.fill();
parameters.context.stroke();
for (let x = realTileStart.x; x <= realTileEnd.x; ++x) {
for (let y = realTileStart.y; y <= realTileEnd.y; ++y) {
const contents = this.root.map.getTileContentXY(x, y);
if (contents && this.root.logic.canDeleteBuilding(contents)) {
const staticComp = contents.components.StaticMapEntity;
const center = staticComp.getTileSpaceBounds().getCenter().toWorldSpace();
this.deletionMarker.drawCachedCentered(
parameters,
center.x,
center.y,
globalConfig.tileSize * 0.5
);
}
}
}
}
this.entityUidsMarkedForDeletion.forEach(uid => {
const entity = this.root.entityMgr.findByUid(uid);
const staticComp = entity.components.StaticMapEntity;
const center = staticComp.getTileSpaceBounds().getCenter().toWorldSpace();
this.deletionMarker.drawCachedCentered(
parameters,
center.x,
center.y,
globalConfig.tileSize * 0.5
);
});
}
}

@ -29,6 +29,8 @@ export const defaultKeybindings = {
menu_open_shop: { keyCode: key("F") },
menu_open_stats: { keyCode: key("G") },
confirm_mass_delete: { keyCode: 46 }, // DEL
},
toolbar: {

Loading…
Cancel
Save