1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2024-10-27 20:34:29 +00:00

Fix being able to create constant signals without value

This commit is contained in:
tobspr 2020-08-28 22:56:56 +02:00
parent 7cbe5bb8e7
commit a67448fbdf
2 changed files with 573 additions and 563 deletions

View File

@ -1,434 +1,443 @@
/* typehints:start */ /* typehints:start */
import { Application } from "../application"; import { Application } from "../application";
/* typehints:end */ /* typehints:end */
import { Signal, STOP_PROPAGATION } from "./signal"; import { Signal, STOP_PROPAGATION } from "./signal";
import { arrayDeleteValue, waitNextFrame } from "./utils"; import { arrayDeleteValue, waitNextFrame } from "./utils";
import { ClickDetector } from "./click_detector"; import { ClickDetector } from "./click_detector";
import { SOUNDS } from "../platform/sound"; import { SOUNDS } from "../platform/sound";
import { InputReceiver } from "./input_receiver"; import { InputReceiver } from "./input_receiver";
import { FormElement } from "./modal_dialog_forms"; import { FormElement } from "./modal_dialog_forms";
import { globalConfig } from "./config"; import { globalConfig } from "./config";
import { getStringForKeyCode } from "../game/key_action_mapper"; import { getStringForKeyCode } from "../game/key_action_mapper";
import { createLogger } from "./logging"; import { createLogger } from "./logging";
import { T } from "../translations"; import { T } from "../translations";
const kbEnter = 13; const kbEnter = 13;
const kbCancel = 27; const kbCancel = 27;
const logger = createLogger("dialogs"); const logger = createLogger("dialogs");
/** /**
* Basic text based dialog * Basic text based dialog
*/ */
export class Dialog { export class Dialog {
/** /**
* *
* Constructs a new dialog with the given options * Constructs a new dialog with the given options
* @param {object} param0 * @param {object} param0
* @param {Application} param0.app * @param {Application} param0.app
* @param {string} param0.title Title of the dialog * @param {string} param0.title Title of the dialog
* @param {string} param0.contentHTML Inner dialog html * @param {string} param0.contentHTML Inner dialog html
* @param {Array<string>} param0.buttons * @param {Array<string>} param0.buttons
* Button list, each button contains of up to 3 parts seperated by ':'. * Button list, each button contains of up to 3 parts seperated by ':'.
* Part 0: The id, one of the one defined in dialog_buttons.yaml * Part 0: The id, one of the one defined in dialog_buttons.yaml
* Part 1: The style, either good, bad or misc * Part 1: The style, either good, bad or misc
* Part 2 (optional): Additional parameters seperated by '/', available are: * Part 2 (optional): Additional parameters seperated by '/', available are:
* timeout: This button is only available after some waiting time * timeout: This button is only available after some waiting time
* kb_enter: This button is triggered by the enter key * kb_enter: This button is triggered by the enter key
* kb_escape This button is triggered by the escape key * kb_escape This button is triggered by the escape key
* @param {string=} param0.type The dialog type, either "info" or "warn" * @param {string=} param0.type The dialog type, either "info" or "warn"
* @param {boolean=} param0.closeButton Whether this dialog has a close button * @param {boolean=} param0.closeButton Whether this dialog has a close button
*/ */
constructor({ app, title, contentHTML, buttons, type = "info", closeButton = false }) { constructor({ app, title, contentHTML, buttons, type = "info", closeButton = false }) {
this.app = app; this.app = app;
this.title = title; this.title = title;
this.contentHTML = contentHTML; this.contentHTML = contentHTML;
this.type = type; this.type = type;
this.buttonIds = buttons; this.buttonIds = buttons;
this.closeButton = closeButton; this.closeButton = closeButton;
this.closeRequested = new Signal(); this.closeRequested = new Signal();
this.buttonSignals = {}; this.buttonSignals = {};
for (let i = 0; i < buttons.length; ++i) { for (let i = 0; i < buttons.length; ++i) {
if (G_IS_DEV && globalConfig.debug.disableTimedButtons) { if (G_IS_DEV && globalConfig.debug.disableTimedButtons) {
this.buttonIds[i] = this.buttonIds[i].replace(":timeout", ""); this.buttonIds[i] = this.buttonIds[i].replace(":timeout", "");
} }
const buttonId = this.buttonIds[i].split(":")[0]; const buttonId = this.buttonIds[i].split(":")[0];
this.buttonSignals[buttonId] = new Signal(); this.buttonSignals[buttonId] = new Signal();
} }
this.timeouts = []; this.timeouts = [];
this.clickDetectors = []; this.clickDetectors = [];
this.inputReciever = new InputReceiver("dialog-" + this.title); this.inputReciever = new InputReceiver("dialog-" + this.title);
this.inputReciever.keydown.add(this.handleKeydown, this); this.inputReciever.keydown.add(this.handleKeydown, this);
this.enterHandler = null; this.enterHandler = null;
this.escapeHandler = null; this.escapeHandler = null;
} }
/** /**
* Internal keydown handler * Internal keydown handler
* @param {object} param0 * @param {object} param0
* @param {number} param0.keyCode * @param {number} param0.keyCode
* @param {boolean} param0.shift * @param {boolean} param0.shift
* @param {boolean} param0.alt * @param {boolean} param0.alt
*/ */
handleKeydown({ keyCode, shift, alt }) { handleKeydown({ keyCode, shift, alt }) {
if (keyCode === kbEnter && this.enterHandler) { if (keyCode === kbEnter && this.enterHandler) {
this.internalButtonHandler(this.enterHandler); this.internalButtonHandler(this.enterHandler);
return STOP_PROPAGATION; return STOP_PROPAGATION;
} }
if (keyCode === kbCancel && this.escapeHandler) { if (keyCode === kbCancel && this.escapeHandler) {
this.internalButtonHandler(this.escapeHandler); this.internalButtonHandler(this.escapeHandler);
return STOP_PROPAGATION; return STOP_PROPAGATION;
} }
} }
internalButtonHandler(id, ...payload) { internalButtonHandler(id, ...payload) {
this.app.inputMgr.popReciever(this.inputReciever); this.app.inputMgr.popReciever(this.inputReciever);
if (id !== "close-button") { if (id !== "close-button") {
this.buttonSignals[id].dispatch(...payload); this.buttonSignals[id].dispatch(...payload);
} }
this.closeRequested.dispatch(); this.closeRequested.dispatch();
} }
createElement() { createElement() {
const elem = document.createElement("div"); const elem = document.createElement("div");
elem.classList.add("ingameDialog"); elem.classList.add("ingameDialog");
this.dialogElem = document.createElement("div"); this.dialogElem = document.createElement("div");
this.dialogElem.classList.add("dialogInner"); this.dialogElem.classList.add("dialogInner");
if (this.type) { if (this.type) {
this.dialogElem.classList.add(this.type); this.dialogElem.classList.add(this.type);
} }
elem.appendChild(this.dialogElem); elem.appendChild(this.dialogElem);
const title = document.createElement("h1"); const title = document.createElement("h1");
title.innerText = this.title; title.innerText = this.title;
title.classList.add("title"); title.classList.add("title");
this.dialogElem.appendChild(title); this.dialogElem.appendChild(title);
if (this.closeButton) { if (this.closeButton) {
this.dialogElem.classList.add("hasCloseButton"); this.dialogElem.classList.add("hasCloseButton");
const closeBtn = document.createElement("button"); const closeBtn = document.createElement("button");
closeBtn.classList.add("closeButton"); closeBtn.classList.add("closeButton");
this.trackClicks(closeBtn, () => this.internalButtonHandler("close-button"), { this.trackClicks(closeBtn, () => this.internalButtonHandler("close-button"), {
applyCssClass: "pressedSmallElement", applyCssClass: "pressedSmallElement",
}); });
title.appendChild(closeBtn); title.appendChild(closeBtn);
this.inputReciever.backButton.add(() => this.internalButtonHandler("close-button")); this.inputReciever.backButton.add(() => this.internalButtonHandler("close-button"));
} }
const content = document.createElement("div"); const content = document.createElement("div");
content.classList.add("content"); content.classList.add("content");
content.innerHTML = this.contentHTML; content.innerHTML = this.contentHTML;
this.dialogElem.appendChild(content); this.dialogElem.appendChild(content);
if (this.buttonIds.length > 0) { if (this.buttonIds.length > 0) {
const buttons = document.createElement("div"); const buttons = document.createElement("div");
buttons.classList.add("buttons"); buttons.classList.add("buttons");
// Create buttons // Create buttons
for (let i = 0; i < this.buttonIds.length; ++i) { for (let i = 0; i < this.buttonIds.length; ++i) {
const [buttonId, buttonStyle, rawParams] = this.buttonIds[i].split(":"); const [buttonId, buttonStyle, rawParams] = this.buttonIds[i].split(":");
const button = document.createElement("button"); const button = document.createElement("button");
button.classList.add("button"); button.classList.add("button");
button.classList.add("styledButton"); button.classList.add("styledButton");
button.classList.add(buttonStyle); button.classList.add(buttonStyle);
button.innerText = T.dialogs.buttons[buttonId]; button.innerText = T.dialogs.buttons[buttonId];
const params = (rawParams || "").split("/"); const params = (rawParams || "").split("/");
const useTimeout = params.indexOf("timeout") >= 0; const useTimeout = params.indexOf("timeout") >= 0;
const isEnter = params.indexOf("enter") >= 0; const isEnter = params.indexOf("enter") >= 0;
const isEscape = params.indexOf("escape") >= 0; const isEscape = params.indexOf("escape") >= 0;
if (isEscape && this.closeButton) { if (isEscape && this.closeButton) {
logger.warn("Showing dialog with close button, and additional cancel button"); logger.warn("Showing dialog with close button, and additional cancel button");
} }
if (useTimeout) { if (useTimeout) {
button.classList.add("timedButton"); button.classList.add("timedButton");
const timeout = setTimeout(() => { const timeout = setTimeout(() => {
button.classList.remove("timedButton"); button.classList.remove("timedButton");
arrayDeleteValue(this.timeouts, timeout); arrayDeleteValue(this.timeouts, timeout);
}, 5000); }, 5000);
this.timeouts.push(timeout); this.timeouts.push(timeout);
} }
if (isEnter || isEscape) { if (isEnter || isEscape) {
// if (this.app.settings.getShowKeyboardShortcuts()) { // if (this.app.settings.getShowKeyboardShortcuts()) {
// Show keybinding // Show keybinding
const spacer = document.createElement("code"); const spacer = document.createElement("code");
spacer.classList.add("keybinding"); spacer.classList.add("keybinding");
spacer.innerHTML = getStringForKeyCode(isEnter ? kbEnter : kbCancel); spacer.innerHTML = getStringForKeyCode(isEnter ? kbEnter : kbCancel);
button.appendChild(spacer); button.appendChild(spacer);
// } // }
if (isEnter) { if (isEnter) {
this.enterHandler = buttonId; this.enterHandler = buttonId;
} }
if (isEscape) { if (isEscape) {
this.escapeHandler = buttonId; this.escapeHandler = buttonId;
} }
} }
this.trackClicks(button, () => this.internalButtonHandler(buttonId)); this.trackClicks(button, () => this.internalButtonHandler(buttonId));
buttons.appendChild(button); buttons.appendChild(button);
} }
this.dialogElem.appendChild(buttons); this.dialogElem.appendChild(buttons);
} else { } else {
this.dialogElem.classList.add("buttonless"); this.dialogElem.classList.add("buttonless");
} }
this.element = elem; this.element = elem;
this.app.inputMgr.pushReciever(this.inputReciever); this.app.inputMgr.pushReciever(this.inputReciever);
return this.element; return this.element;
} }
setIndex(index) { setIndex(index) {
this.element.style.zIndex = index; this.element.style.zIndex = index;
} }
destroy() { destroy() {
if (!this.element) { if (!this.element) {
assert(false, "Tried to destroy dialog twice"); assert(false, "Tried to destroy dialog twice");
return; return;
} }
// We need to do this here, because if the backbutton event gets // We need to do this here, because if the backbutton event gets
// dispatched to the modal dialogs, it will not call the internalButtonHandler, // dispatched to the modal dialogs, it will not call the internalButtonHandler,
// and thus our receiver stays attached the whole time // and thus our receiver stays attached the whole time
this.app.inputMgr.destroyReceiver(this.inputReciever); this.app.inputMgr.destroyReceiver(this.inputReciever);
for (let i = 0; i < this.clickDetectors.length; ++i) { for (let i = 0; i < this.clickDetectors.length; ++i) {
this.clickDetectors[i].cleanup(); this.clickDetectors[i].cleanup();
} }
this.clickDetectors = []; this.clickDetectors = [];
this.element.remove(); this.element.remove();
this.element = null; this.element = null;
for (let i = 0; i < this.timeouts.length; ++i) { for (let i = 0; i < this.timeouts.length; ++i) {
clearTimeout(this.timeouts[i]); clearTimeout(this.timeouts[i]);
} }
this.timeouts = []; this.timeouts = [];
} }
hide() { hide() {
this.element.classList.remove("visible"); this.element.classList.remove("visible");
} }
show() { show() {
this.element.classList.add("visible"); this.element.classList.add("visible");
} }
/** /**
* Helper method to track clicks on an element * Helper method to track clicks on an element
* @param {Element} elem * @param {Element} elem
* @param {function():void} handler * @param {function():void} handler
* @param {import("./click_detector").ClickDetectorConstructorArgs=} args * @param {import("./click_detector").ClickDetectorConstructorArgs=} args
* @returns {ClickDetector} * @returns {ClickDetector}
*/ */
trackClicks(elem, handler, args = {}) { trackClicks(elem, handler, args = {}) {
const detector = new ClickDetector(elem, args); const detector = new ClickDetector(elem, args);
detector.click.add(handler, this); detector.click.add(handler, this);
this.clickDetectors.push(detector); this.clickDetectors.push(detector);
return detector; return detector;
} }
} }
/** /**
* Dialog which simply shows a loading spinner * Dialog which simply shows a loading spinner
*/ */
export class DialogLoading extends Dialog { export class DialogLoading extends Dialog {
constructor(app) { constructor(app) {
super({ super({
app, app,
title: "", title: "",
contentHTML: "", contentHTML: "",
buttons: [], buttons: [],
type: "loading", type: "loading",
}); });
// Loading dialog can not get closed with back button // Loading dialog can not get closed with back button
this.inputReciever.backButton.removeAll(); this.inputReciever.backButton.removeAll();
this.inputReciever.context = "dialog-loading"; this.inputReciever.context = "dialog-loading";
} }
createElement() { createElement() {
const elem = document.createElement("div"); const elem = document.createElement("div");
elem.classList.add("ingameDialog"); elem.classList.add("ingameDialog");
elem.classList.add("loadingDialog"); elem.classList.add("loadingDialog");
this.element = elem; this.element = elem;
const loader = document.createElement("div"); const loader = document.createElement("div");
loader.classList.add("prefab_LoadingTextWithAnim"); loader.classList.add("prefab_LoadingTextWithAnim");
loader.classList.add("loadingIndicator"); loader.classList.add("loadingIndicator");
loader.innerText = T.global.loading; loader.innerText = T.global.loading;
elem.appendChild(loader); elem.appendChild(loader);
this.app.inputMgr.pushReciever(this.inputReciever); this.app.inputMgr.pushReciever(this.inputReciever);
return elem; return elem;
} }
} }
export class DialogOptionChooser extends Dialog { export class DialogOptionChooser extends Dialog {
constructor({ app, title, options }) { constructor({ app, title, options }) {
let html = "<div class='optionParent'>"; let html = "<div class='optionParent'>";
options.options.forEach(({ value, text, desc = null, iconPrefix = null }) => { options.options.forEach(({ value, text, desc = null, iconPrefix = null }) => {
const descHtml = desc ? `<span class="desc">${desc}</span>` : ""; const descHtml = desc ? `<span class="desc">${desc}</span>` : "";
let iconHtml = iconPrefix ? `<span class="icon icon-${iconPrefix}-${value}"></span>` : ""; let iconHtml = iconPrefix ? `<span class="icon icon-${iconPrefix}-${value}"></span>` : "";
html += ` html += `
<div class='option ${value === options.active ? "active" : ""} ${ <div class='option ${value === options.active ? "active" : ""} ${
iconPrefix ? "hasIcon" : "" iconPrefix ? "hasIcon" : ""
}' data-optionvalue='${value}'> }' data-optionvalue='${value}'>
${iconHtml} ${iconHtml}
<span class='title'>${text}</span> <span class='title'>${text}</span>
${descHtml} ${descHtml}
</div> </div>
`; `;
}); });
html += "</div>"; html += "</div>";
super({ super({
app, app,
title, title,
contentHTML: html, contentHTML: html,
buttons: [], buttons: [],
type: "info", type: "info",
closeButton: true, closeButton: true,
}); });
this.options = options; this.options = options;
this.initialOption = options.active; this.initialOption = options.active;
this.buttonSignals.optionSelected = new Signal(); this.buttonSignals.optionSelected = new Signal();
} }
createElement() { createElement() {
const div = super.createElement(); const div = super.createElement();
this.dialogElem.classList.add("optionChooserDialog"); this.dialogElem.classList.add("optionChooserDialog");
div.querySelectorAll("[data-optionvalue]").forEach(handle => { div.querySelectorAll("[data-optionvalue]").forEach(handle => {
const value = handle.getAttribute("data-optionvalue"); const value = handle.getAttribute("data-optionvalue");
if (!handle) { if (!handle) {
logger.error("Failed to bind option value in dialog:", value); logger.error("Failed to bind option value in dialog:", value);
return; return;
} }
// Need click detector here to forward elements, otherwise scrolling does not work // Need click detector here to forward elements, otherwise scrolling does not work
const detector = new ClickDetector(handle, { const detector = new ClickDetector(handle, {
consumeEvents: false, consumeEvents: false,
preventDefault: false, preventDefault: false,
clickSound: null, clickSound: null,
applyCssClass: "pressedOption", applyCssClass: "pressedOption",
targetOnly: true, targetOnly: true,
}); });
this.clickDetectors.push(detector); this.clickDetectors.push(detector);
if (value !== this.initialOption) { if (value !== this.initialOption) {
detector.click.add(() => { detector.click.add(() => {
const selected = div.querySelector(".option.active"); const selected = div.querySelector(".option.active");
if (selected) { if (selected) {
selected.classList.remove("active"); selected.classList.remove("active");
} else { } else {
logger.warn("No selected option"); logger.warn("No selected option");
} }
handle.classList.add("active"); handle.classList.add("active");
this.app.sound.playUiSound(SOUNDS.uiClick); this.app.sound.playUiSound(SOUNDS.uiClick);
this.internalButtonHandler("optionSelected", value); this.internalButtonHandler("optionSelected", value);
}); });
} }
}); });
return div; return div;
} }
} }
export class DialogWithForm extends Dialog { export class DialogWithForm extends Dialog {
/** /**
* *
* @param {object} param0 * @param {object} param0
* @param {Application} param0.app * @param {Application} param0.app
* @param {string} param0.title * @param {string} param0.title
* @param {string} param0.desc * @param {string} param0.desc
* @param {array=} param0.buttons * @param {array=} param0.buttons
* @param {string=} param0.confirmButtonId * @param {string=} param0.confirmButtonId
* @param {string=} param0.extraButton * @param {string=} param0.extraButton
* @param {Array<FormElement>} param0.formElements * @param {boolean=} param0.closeButton
*/ * @param {Array<FormElement>} param0.formElements
constructor({ app, title, desc, formElements, buttons = ["cancel", "ok:good"], confirmButtonId = "ok" }) { */
let html = ""; constructor({
html += desc + "<br>"; app,
for (let i = 0; i < formElements.length; ++i) { title,
html += formElements[i].getHtml(); desc,
} formElements,
buttons = ["cancel", "ok:good"],
super({ confirmButtonId = "ok",
app, closeButton = true,
title: title, }) {
contentHTML: html, let html = "";
buttons: buttons, html += desc + "<br>";
type: "info", for (let i = 0; i < formElements.length; ++i) {
closeButton: true, html += formElements[i].getHtml();
}); }
this.confirmButtonId = confirmButtonId;
this.formElements = formElements; super({
app,
this.enterHandler = confirmButtonId; title: title,
} contentHTML: html,
buttons: buttons,
internalButtonHandler(id, ...payload) { type: "info",
if (id === this.confirmButtonId) { closeButton,
if (this.hasAnyInvalid()) { });
this.dialogElem.classList.remove("errorShake"); this.confirmButtonId = confirmButtonId;
waitNextFrame().then(() => { this.formElements = formElements;
if (this.dialogElem) {
this.dialogElem.classList.add("errorShake"); this.enterHandler = confirmButtonId;
} }
});
this.app.sound.playUiSound(SOUNDS.uiError); internalButtonHandler(id, ...payload) {
return; if (id === this.confirmButtonId) {
} if (this.hasAnyInvalid()) {
} this.dialogElem.classList.remove("errorShake");
waitNextFrame().then(() => {
super.internalButtonHandler(id, payload); if (this.dialogElem) {
} this.dialogElem.classList.add("errorShake");
}
hasAnyInvalid() { });
for (let i = 0; i < this.formElements.length; ++i) { this.app.sound.playUiSound(SOUNDS.uiError);
if (!this.formElements[i].isValid()) { return;
return true; }
} }
}
return false; super.internalButtonHandler(id, payload);
} }
createElement() { hasAnyInvalid() {
const div = super.createElement(); for (let i = 0; i < this.formElements.length; ++i) {
if (!this.formElements[i].isValid()) {
for (let i = 0; i < this.formElements.length; ++i) { return true;
const elem = this.formElements[i]; }
elem.bindEvents(div, this.clickDetectors); }
} return false;
}
waitNextFrame().then(() => {
this.formElements[0].focus(); createElement() {
}); const div = super.createElement();
return div; for (let i = 0; i < this.formElements.length; ++i) {
} const elem = this.formElements[i];
} elem.bindEvents(div, this.clickDetectors);
}
waitNextFrame().then(() => {
this.formElements[0].focus();
});
return div;
}
}

View File

@ -1,129 +1,130 @@
import trim from "trim"; import trim from "trim";
import { DialogWithForm } from "../../core/modal_dialog_elements"; import { DialogWithForm } from "../../core/modal_dialog_elements";
import { FormElementInput } from "../../core/modal_dialog_forms"; import { FormElementInput } from "../../core/modal_dialog_forms";
import { BaseItem } from "../base_item"; import { BaseItem } from "../base_item";
import { enumColors } from "../colors"; import { enumColors } from "../colors";
import { ConstantSignalComponent } from "../components/constant_signal"; import { ConstantSignalComponent } from "../components/constant_signal";
import { Entity } from "../entity"; import { Entity } from "../entity";
import { GameSystemWithFilter } from "../game_system_with_filter"; import { GameSystemWithFilter } from "../game_system_with_filter";
import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON } from "../items/boolean_item"; import { BOOL_FALSE_SINGLETON, BOOL_TRUE_SINGLETON } from "../items/boolean_item";
import { COLOR_ITEM_SINGLETONS } from "../items/color_item"; import { COLOR_ITEM_SINGLETONS } from "../items/color_item";
import { ShapeDefinition } from "../shape_definition"; import { ShapeDefinition } from "../shape_definition";
export class ConstantSignalSystem extends GameSystemWithFilter { export class ConstantSignalSystem extends GameSystemWithFilter {
constructor(root) { constructor(root) {
super(root, [ConstantSignalComponent]); super(root, [ConstantSignalComponent]);
this.root.signals.entityManuallyPlaced.add(this.querySigalValue, this); this.root.signals.entityManuallyPlaced.add(this.querySigalValue, this);
} }
update() { update() {
// Set signals // Set signals
for (let i = 0; i < this.allEntities.length; ++i) { for (let i = 0; i < this.allEntities.length; ++i) {
const entity = this.allEntities[i]; const entity = this.allEntities[i];
const pinsComp = entity.components.WiredPins; const pinsComp = entity.components.WiredPins;
const signalComp = entity.components.ConstantSignal; const signalComp = entity.components.ConstantSignal;
pinsComp.slots[0].value = signalComp.signal; pinsComp.slots[0].value = signalComp.signal;
} }
} }
/** /**
* Asks the entity to enter a valid signal code * Asks the entity to enter a valid signal code
* @param {Entity} entity * @param {Entity} entity
*/ */
querySigalValue(entity) { querySigalValue(entity) {
if (!entity.components.ConstantSignal) { if (!entity.components.ConstantSignal) {
return; return;
} }
// Ok, query, but also save the uid because it could get stale // Ok, query, but also save the uid because it could get stale
const uid = entity.uid; const uid = entity.uid;
const signalValueInput = new FormElementInput({ const signalValueInput = new FormElementInput({
id: "signalValue", id: "signalValue",
label: null, label: null,
placeholder: "", placeholder: "",
defaultValue: "", defaultValue: "",
validator: val => this.parseSignalCode(val), validator: val => this.parseSignalCode(val),
}); });
const dialog = new DialogWithForm({ const dialog = new DialogWithForm({
app: this.root.app, app: this.root.app,
title: "Set Signal", title: "Set Signal",
desc: "Enter a shape code, color or '0' or '1'", desc: "Enter a shape code, color or '0' or '1'",
formElements: [signalValueInput], formElements: [signalValueInput],
buttons: ["cancel:bad:escape", "ok:good:enter"], buttons: ["cancel:bad:escape", "ok:good:enter"],
}); closeButton: false,
this.root.hud.parts.dialogs.internalShowDialog(dialog); });
this.root.hud.parts.dialogs.internalShowDialog(dialog);
// When confirmed, set the signal
dialog.buttonSignals.ok.add(() => { // When confirmed, set the signal
if (!this.root || !this.root.entityMgr) { dialog.buttonSignals.ok.add(() => {
// Game got stopped if (!this.root || !this.root.entityMgr) {
return; // Game got stopped
} return;
}
const entityRef = this.root.entityMgr.findByUid(uid, false);
if (!entityRef) { const entityRef = this.root.entityMgr.findByUid(uid, false);
// outdated if (!entityRef) {
return; // outdated
} return;
}
const constantComp = entityRef.components.ConstantSignal;
if (!constantComp) { const constantComp = entityRef.components.ConstantSignal;
// no longer interesting if (!constantComp) {
return; // no longer interesting
} return;
}
constantComp.signal = this.parseSignalCode(signalValueInput.getValue());
}); constantComp.signal = this.parseSignalCode(signalValueInput.getValue());
});
// When cancelled, destroy the entity again
dialog.buttonSignals.cancel.add(() => { // When cancelled, destroy the entity again
if (!this.root || !this.root.entityMgr) { dialog.buttonSignals.cancel.add(() => {
// Game got stopped if (!this.root || !this.root.entityMgr) {
return; // Game got stopped
} return;
}
const entityRef = this.root.entityMgr.findByUid(uid, false);
if (!entityRef) { const entityRef = this.root.entityMgr.findByUid(uid, false);
// outdated if (!entityRef) {
return; // outdated
} return;
}
const constantComp = entityRef.components.ConstantSignal;
if (!constantComp) { const constantComp = entityRef.components.ConstantSignal;
// no longer interesting if (!constantComp) {
return; // no longer interesting
} return;
}
this.root.logic.tryDeleteBuilding(entityRef);
}); this.root.logic.tryDeleteBuilding(entityRef);
} });
}
/**
* Tries to parse a signal code /**
* @param {string} code * Tries to parse a signal code
* @returns {BaseItem} * @param {string} code
*/ * @returns {BaseItem}
parseSignalCode(code) { */
code = trim(code); parseSignalCode(code) {
const codeLower = code.toLowerCase(); code = trim(code);
const codeLower = code.toLowerCase();
if (enumColors[codeLower]) {
return COLOR_ITEM_SINGLETONS[codeLower]; if (enumColors[codeLower]) {
} return COLOR_ITEM_SINGLETONS[codeLower];
if (code === "1" || codeLower === "true") { }
return BOOL_TRUE_SINGLETON; if (code === "1" || codeLower === "true") {
} return BOOL_TRUE_SINGLETON;
}
if (code === "0" || codeLower === "false") {
return BOOL_FALSE_SINGLETON; if (code === "0" || codeLower === "false") {
} return BOOL_FALSE_SINGLETON;
}
if (ShapeDefinition.isValidShortKey(code)) {
return this.root.shapeDefinitionMgr.getShapeItemFromShortKey(code); if (ShapeDefinition.isValidShortKey(code)) {
} return this.root.shapeDefinitionMgr.getShapeItemFromShortKey(code);
}
return null;
} return null;
} }
}