1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2024-10-27 20:34:29 +00:00
tobspr_shapez.io/src/js/game/hud/parts/base_toolbar.js

178 lines
6.0 KiB
JavaScript
Raw Normal View History

2020-06-24 20:23:10 +00:00
import { gMetaBuildingRegistry } from "../../../core/global_registries";
import { Signal, STOP_PROPAGATION } from "../../../core/signal";
2020-06-24 20:23:10 +00:00
import { makeDiv } from "../../../core/utils";
import { KEYMAPPINGS } from "../../key_action_mapper";
import { MetaBuilding } from "../../meta_building";
import { GameRoot } from "../../root";
2020-06-28 17:34:10 +00:00
import { BaseHUDPart } from "../base_hud_part";
import { DynamicDomAttach } from "../dynamic_dom_attach";
2020-06-24 20:23:10 +00:00
export class HUDBaseToolbar extends BaseHUDPart {
/**
* @param {GameRoot} root
2020-06-28 17:34:10 +00:00
* @param {object} param0
* @param {Array<typeof MetaBuilding>} param0.supportedBuildings
* @param {function} param0.visibilityCondition
* @param {string} param0.htmlElementId
2020-06-24 20:23:10 +00:00
*/
2020-06-28 17:34:10 +00:00
constructor(root, { supportedBuildings, visibilityCondition, htmlElementId }) {
2020-06-24 20:23:10 +00:00
super(root);
this.supportedBuildings = supportedBuildings;
this.visibilityCondition = visibilityCondition;
2020-06-28 17:34:10 +00:00
this.htmlElementId = htmlElementId;
2020-06-24 20:23:10 +00:00
/** @type {Object.<string, {
* metaBuilding: MetaBuilding,
* unlocked: boolean,
* selected: boolean,
* element: HTMLElement,
* index: number
* }>} */
this.buildingHandles = {};
}
/**
* Should create all require elements
* @param {HTMLElement} parent
*/
createElements(parent) {
2020-06-28 17:34:10 +00:00
this.element = makeDiv(parent, this.htmlElementId, ["ingame_buildingsToolbar"], "");
2020-06-24 20:23:10 +00:00
}
initialize() {
const actionMapper = this.root.keyMapper;
const items = makeDiv(this.element, null, ["buildings"]);
for (let i = 0; i < this.supportedBuildings.length; ++i) {
const metaBuilding = gMetaBuildingRegistry.findByClass(this.supportedBuildings[i]);
const binding = actionMapper.getBinding(KEYMAPPINGS.buildings[metaBuilding.getId()]);
const itemContainer = makeDiv(items, null, ["building"]);
itemContainer.setAttribute("data-icon", "building_icons/" + metaBuilding.getId() + ".png");
binding.add(() => this.selectBuildingForPlacement(metaBuilding));
this.trackClicks(itemContainer, () => this.selectBuildingForPlacement(metaBuilding), {
clickSound: null,
});
this.buildingHandles[metaBuilding.id] = {
metaBuilding,
element: itemContainer,
unlocked: false,
selected: false,
index: i,
};
}
this.root.hud.signals.selectedPlacementBuildingChanged.add(
this.onSelectedPlacementBuildingChanged,
this
);
2020-06-28 17:34:10 +00:00
this.domAttach = new DynamicDomAttach(this.root, this.element, {
timeToKeepSeconds: 0.12,
attachClass: "visible",
});
2020-06-24 20:23:10 +00:00
this.lastSelectedIndex = 0;
actionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildings).add(this.cycleBuildings, this);
}
/**
* Updates the toolbar
*/
update() {
2020-06-28 17:34:10 +00:00
const visible = this.visibilityCondition();
this.domAttach.update(visible);
2020-06-24 20:23:10 +00:00
2020-06-28 17:34:10 +00:00
if (visible) {
2020-06-24 20:23:10 +00:00
for (const buildingId in this.buildingHandles) {
const handle = this.buildingHandles[buildingId];
const newStatus = handle.metaBuilding.getIsUnlocked(this.root);
if (handle.unlocked !== newStatus) {
handle.unlocked = newStatus;
handle.element.classList.toggle("unlocked", newStatus);
}
}
}
}
/**
* Cycles through all buildings
*/
cycleBuildings() {
2020-06-30 13:26:30 +00:00
const visible = this.visibilityCondition();
if (!visible) {
return;
}
2020-07-03 07:29:29 +00:00
let newBuildingFound = false;
2020-06-24 20:23:10 +00:00
let newIndex = this.lastSelectedIndex;
for (let i = 0; i < this.supportedBuildings.length; ++i, ++newIndex) {
newIndex %= this.supportedBuildings.length;
const metaBuilding = gMetaBuildingRegistry.findByClass(this.supportedBuildings[newIndex]);
const handle = this.buildingHandles[metaBuilding.id];
if (!handle.selected && handle.unlocked) {
2020-07-03 07:29:29 +00:00
newBuildingFound = true;
2020-06-24 20:23:10 +00:00
break;
}
}
2020-07-03 07:29:29 +00:00
if (!newBuildingFound) {
2020-06-30 13:26:30 +00:00
return;
}
2020-06-24 20:23:10 +00:00
const metaBuildingClass = this.supportedBuildings[newIndex];
const metaBuilding = gMetaBuildingRegistry.findByClass(metaBuildingClass);
this.selectBuildingForPlacement(metaBuilding);
}
/**
* Called when the selected building got changed
* @param {MetaBuilding} metaBuilding
*/
onSelectedPlacementBuildingChanged(metaBuilding) {
for (const buildingId in this.buildingHandles) {
const handle = this.buildingHandles[buildingId];
const newStatus = handle.metaBuilding === metaBuilding;
if (handle.selected !== newStatus) {
handle.selected = newStatus;
handle.element.classList.toggle("selected", newStatus);
}
if (handle.selected) {
this.lastSelectedIndex = handle.index;
}
}
this.element.classList.toggle("buildingSelected", !!metaBuilding);
}
/**
* @param {MetaBuilding} metaBuilding
*/
selectBuildingForPlacement(metaBuilding) {
if (!this.visibilityCondition()) {
// Not active
return;
}
if (!metaBuilding.getIsUnlocked(this.root)) {
this.root.soundProxy.playUiError();
return STOP_PROPAGATION;
}
// Allow clicking an item again to deselect it
for (const buildingId in this.buildingHandles) {
const handle = this.buildingHandles[buildingId];
if (handle.selected && handle.metaBuilding === metaBuilding) {
metaBuilding = null;
break;
}
}
this.root.soundProxy.playUiClick();
2020-06-28 17:34:10 +00:00
this.root.hud.signals.buildingSelectedForPlacement.dispatch(metaBuilding);
2020-06-24 20:23:10 +00:00
this.onSelectedPlacementBuildingChanged(metaBuilding);
}
}