Rework constant signal dialog
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 283 KiB |
Before Width: | Height: | Size: 713 KiB After Width: | Height: | Size: 706 KiB |
Before Width: | Height: | Size: 7.8 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.6 KiB |
@ -178,6 +178,27 @@
|
|||||||
display: list-item;
|
display: list-item;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ingameItemChooser {
|
||||||
|
@include S(margin, 20px, 0);
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-auto-columns: 1fr;
|
||||||
|
@include S(grid-column-gap, 3px);
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
pointer-events: all;
|
||||||
|
@include S(width, 25px);
|
||||||
|
@include S(height, 25px);
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
@include IncreasedClickArea(3px);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
> .buttons {
|
> .buttons {
|
||||||
|
@ -20,6 +20,7 @@ export const THIRDPARTY_URLS = {
|
|||||||
discord: "https://discord.gg/HN7EVzV",
|
discord: "https://discord.gg/HN7EVzV",
|
||||||
github: "https://github.com/tobspr/shapez.io",
|
github: "https://github.com/tobspr/shapez.io",
|
||||||
reddit: "https://www.reddit.com/r/shapezio",
|
reddit: "https://www.reddit.com/r/shapezio",
|
||||||
|
shapeViewer: "https://viewer.shapez.io",
|
||||||
|
|
||||||
standaloneStorePage: "https://store.steampowered.com/app/1318690/shapezio/",
|
standaloneStorePage: "https://store.steampowered.com/app/1318690/shapezio/",
|
||||||
};
|
};
|
||||||
|
@ -60,6 +60,8 @@ export class Dialog {
|
|||||||
this.buttonSignals[buttonId] = new Signal();
|
this.buttonSignals[buttonId] = new Signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.valueChosen = new Signal();
|
||||||
|
|
||||||
this.timeouts = [];
|
this.timeouts = [];
|
||||||
this.clickDetectors = [];
|
this.clickDetectors = [];
|
||||||
|
|
||||||
@ -431,10 +433,12 @@ export class DialogWithForm extends Dialog {
|
|||||||
for (let i = 0; i < this.formElements.length; ++i) {
|
for (let i = 0; i < this.formElements.length; ++i) {
|
||||||
const elem = this.formElements[i];
|
const elem = this.formElements[i];
|
||||||
elem.bindEvents(div, this.clickDetectors);
|
elem.bindEvents(div, this.clickDetectors);
|
||||||
|
elem.valueChosen.add(this.closeRequested.dispatch, this.closeRequested);
|
||||||
|
elem.valueChosen.add(this.valueChosen.dispatch, this.valueChosen);
|
||||||
}
|
}
|
||||||
|
|
||||||
waitNextFrame().then(() => {
|
waitNextFrame().then(() => {
|
||||||
this.formElements[0].focus();
|
this.formElements[this.formElements.length - 1].focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
return div;
|
return div;
|
||||||
|
@ -1,150 +1,221 @@
|
|||||||
import { ClickDetector } from "./click_detector";
|
import { BaseItem } from "../game/base_item";
|
||||||
|
import { ClickDetector } from "./click_detector";
|
||||||
export class FormElement {
|
import { Signal } from "./signal";
|
||||||
constructor(id, label) {
|
|
||||||
this.id = id;
|
export class FormElement {
|
||||||
this.label = label;
|
constructor(id, label) {
|
||||||
}
|
this.id = id;
|
||||||
|
this.label = label;
|
||||||
getHtml() {
|
|
||||||
abstract;
|
this.valueChosen = new Signal();
|
||||||
return "";
|
}
|
||||||
}
|
|
||||||
|
getHtml() {
|
||||||
getFormElement(parent) {
|
abstract;
|
||||||
return parent.querySelector("[data-formId='" + this.id + "']");
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
bindEvents(parent, clickTrackers) {
|
getFormElement(parent) {
|
||||||
abstract;
|
return parent.querySelector("[data-formId='" + this.id + "']");
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {}
|
bindEvents(parent, clickTrackers) {
|
||||||
|
abstract;
|
||||||
isValid() {
|
}
|
||||||
return true;
|
|
||||||
}
|
focus() {}
|
||||||
|
|
||||||
/** @returns {any} */
|
isValid() {
|
||||||
getValue() {
|
return true;
|
||||||
abstract;
|
}
|
||||||
}
|
|
||||||
}
|
/** @returns {any} */
|
||||||
|
getValue() {
|
||||||
export class FormElementInput extends FormElement {
|
abstract;
|
||||||
constructor({ id, label = null, placeholder, defaultValue = "", inputType = "text", validator = null }) {
|
}
|
||||||
super(id, label);
|
}
|
||||||
this.placeholder = placeholder;
|
|
||||||
this.defaultValue = defaultValue;
|
export class FormElementInput extends FormElement {
|
||||||
this.inputType = inputType;
|
constructor({ id, label = null, placeholder, defaultValue = "", inputType = "text", validator = null }) {
|
||||||
this.validator = validator;
|
super(id, label);
|
||||||
|
this.placeholder = placeholder;
|
||||||
this.element = null;
|
this.defaultValue = defaultValue;
|
||||||
}
|
this.inputType = inputType;
|
||||||
|
this.validator = validator;
|
||||||
getHtml() {
|
|
||||||
let classes = [];
|
this.element = null;
|
||||||
let inputType = "text";
|
}
|
||||||
let maxlength = 256;
|
|
||||||
switch (this.inputType) {
|
getHtml() {
|
||||||
case "text": {
|
let classes = [];
|
||||||
classes.push("input-text");
|
let inputType = "text";
|
||||||
break;
|
let maxlength = 256;
|
||||||
}
|
switch (this.inputType) {
|
||||||
|
case "text": {
|
||||||
case "email": {
|
classes.push("input-text");
|
||||||
classes.push("input-email");
|
break;
|
||||||
inputType = "email";
|
}
|
||||||
break;
|
|
||||||
}
|
case "email": {
|
||||||
|
classes.push("input-email");
|
||||||
case "token": {
|
inputType = "email";
|
||||||
classes.push("input-token");
|
break;
|
||||||
inputType = "text";
|
}
|
||||||
maxlength = 4;
|
|
||||||
break;
|
case "token": {
|
||||||
}
|
classes.push("input-token");
|
||||||
}
|
inputType = "text";
|
||||||
|
maxlength = 4;
|
||||||
return `
|
break;
|
||||||
<div class="formElement input">
|
}
|
||||||
${this.label ? `<label>${this.label}</label>` : ""}
|
}
|
||||||
<input
|
|
||||||
type="${inputType}"
|
return `
|
||||||
value="${this.defaultValue.replace(/["\\]+/gi, "")}"
|
<div class="formElement input">
|
||||||
maxlength="${maxlength}"
|
${this.label ? `<label>${this.label}</label>` : ""}
|
||||||
autocomplete="off"
|
<input
|
||||||
autocorrect="off"
|
type="${inputType}"
|
||||||
autocapitalize="off"
|
value="${this.defaultValue.replace(/["\\]+/gi, "")}"
|
||||||
spellcheck="false"
|
maxlength="${maxlength}"
|
||||||
class="${classes.join(" ")}"
|
autocomplete="off"
|
||||||
placeholder="${this.placeholder.replace(/["\\]+/gi, "")}"
|
autocorrect="off"
|
||||||
data-formId="${this.id}">
|
autocapitalize="off"
|
||||||
</div>
|
spellcheck="false"
|
||||||
`;
|
class="${classes.join(" ")}"
|
||||||
}
|
placeholder="${this.placeholder.replace(/["\\]+/gi, "")}"
|
||||||
|
data-formId="${this.id}">
|
||||||
bindEvents(parent, clickTrackers) {
|
</div>
|
||||||
this.element = this.getFormElement(parent);
|
`;
|
||||||
this.element.addEventListener("input", event => this.updateErrorState());
|
}
|
||||||
this.updateErrorState();
|
|
||||||
}
|
bindEvents(parent, clickTrackers) {
|
||||||
|
this.element = this.getFormElement(parent);
|
||||||
updateErrorState() {
|
this.element.addEventListener("input", event => this.updateErrorState());
|
||||||
this.element.classList.toggle("errored", !this.isValid());
|
this.updateErrorState();
|
||||||
}
|
}
|
||||||
|
|
||||||
isValid() {
|
updateErrorState() {
|
||||||
return !this.validator || this.validator(this.element.value);
|
this.element.classList.toggle("errored", !this.isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
getValue() {
|
isValid() {
|
||||||
return this.element.value;
|
return !this.validator || this.validator(this.element.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
getValue() {
|
||||||
this.element.focus();
|
return this.element.value;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
focus() {
|
||||||
export class FormElementCheckbox extends FormElement {
|
this.element.focus();
|
||||||
constructor({ id, label, defaultValue = true }) {
|
}
|
||||||
super(id, label);
|
}
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
this.value = this.defaultValue;
|
export class FormElementCheckbox extends FormElement {
|
||||||
|
constructor({ id, label, defaultValue = true }) {
|
||||||
this.element = null;
|
super(id, label);
|
||||||
}
|
this.defaultValue = defaultValue;
|
||||||
|
this.value = this.defaultValue;
|
||||||
getHtml() {
|
|
||||||
return `
|
this.element = null;
|
||||||
<div class="formElement checkBoxFormElem">
|
}
|
||||||
${this.label ? `<label>${this.label}</label>` : ""}
|
|
||||||
<div class="checkbox ${this.defaultValue ? "checked" : ""}" data-formId='${this.id}'>
|
getHtml() {
|
||||||
<span class="knob"></span >
|
return `
|
||||||
</div >
|
<div class="formElement checkBoxFormElem">
|
||||||
</div>
|
${this.label ? `<label>${this.label}</label>` : ""}
|
||||||
`;
|
<div class="checkbox ${this.defaultValue ? "checked" : ""}" data-formId='${this.id}'>
|
||||||
}
|
<span class="knob"></span >
|
||||||
|
</div >
|
||||||
bindEvents(parent, clickTrackers) {
|
</div>
|
||||||
this.element = this.getFormElement(parent);
|
`;
|
||||||
const detector = new ClickDetector(this.element, {
|
}
|
||||||
consumeEvents: false,
|
|
||||||
preventDefault: false,
|
bindEvents(parent, clickTrackers) {
|
||||||
});
|
this.element = this.getFormElement(parent);
|
||||||
clickTrackers.push(detector);
|
const detector = new ClickDetector(this.element, {
|
||||||
detector.click.add(this.toggle, this);
|
consumeEvents: false,
|
||||||
}
|
preventDefault: false,
|
||||||
|
});
|
||||||
getValue() {
|
clickTrackers.push(detector);
|
||||||
return this.value;
|
detector.click.add(this.toggle, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
toggle() {
|
getValue() {
|
||||||
this.value = !this.value;
|
return this.value;
|
||||||
this.element.classList.toggle("checked", this.value);
|
}
|
||||||
}
|
|
||||||
|
toggle() {
|
||||||
focus(parent) {}
|
this.value = !this.value;
|
||||||
}
|
this.element.classList.toggle("checked", this.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
focus(parent) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FormElementItemChooser extends FormElement {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {object} param0
|
||||||
|
* @param {string} param0.id
|
||||||
|
* @param {string=} param0.label
|
||||||
|
* @param {Array<BaseItem>} param0.items
|
||||||
|
*/
|
||||||
|
constructor({ id, label, items = [] }) {
|
||||||
|
super(id, label);
|
||||||
|
this.items = items;
|
||||||
|
this.element = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {BaseItem}
|
||||||
|
*/
|
||||||
|
this.chosenItem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
getHtml() {
|
||||||
|
let classes = [];
|
||||||
|
|
||||||
|
return `
|
||||||
|
<div class="formElement">
|
||||||
|
${this.label ? `<label>${this.label}</label>` : ""}
|
||||||
|
<div class="ingameItemChooser input" data-formId="${this.id}"></div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} parent
|
||||||
|
* @param {Array<ClickDetector>} clickTrackers
|
||||||
|
*/
|
||||||
|
bindEvents(parent, clickTrackers) {
|
||||||
|
this.element = this.getFormElement(parent);
|
||||||
|
|
||||||
|
for (let i = 0; i < this.items.length; ++i) {
|
||||||
|
const item = this.items[i];
|
||||||
|
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
canvas.width = 128;
|
||||||
|
canvas.height = 128;
|
||||||
|
const context = canvas.getContext("2d");
|
||||||
|
item.drawRaw(context, 128);
|
||||||
|
this.element.appendChild(canvas);
|
||||||
|
|
||||||
|
const detector = new ClickDetector(canvas, {});
|
||||||
|
clickTrackers.push(detector);
|
||||||
|
detector.click.add(() => {
|
||||||
|
this.chosenItem = item;
|
||||||
|
this.valueChosen.dispatch(item);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
getValue() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
focus() {}
|
||||||
|
}
|
||||||
|
@ -670,3 +670,14 @@ export function safeModulo(n, m) {
|
|||||||
export function smoothPulse(time) {
|
export function smoothPulse(time) {
|
||||||
return Math.sin(time * 4) * 0.5 + 0.5;
|
return Math.sin(time * 4) * 0.5 + 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fills in a <link> tag
|
||||||
|
* @param {string} translation
|
||||||
|
* @param {string} link
|
||||||
|
*/
|
||||||
|
export function fillInLinkIntoTranslation(translation, link) {
|
||||||
|
return translation
|
||||||
|
.replace("<link>", "<a href='" + link + "' target='_blank'>")
|
||||||
|
.replace("</link>", "</a>");
|
||||||
|
}
|
||||||
|
@ -1,82 +1,91 @@
|
|||||||
import { globalConfig } from "../core/config";
|
import { globalConfig } from "../core/config";
|
||||||
import { DrawParameters } from "../core/draw_parameters";
|
import { DrawParameters } from "../core/draw_parameters";
|
||||||
import { BasicSerializableObject } from "../savegame/serialization";
|
import { BasicSerializableObject } from "../savegame/serialization";
|
||||||
|
|
||||||
/** @type {ItemType[]} **/
|
/** @type {ItemType[]} **/
|
||||||
export const itemTypes = ["shape", "color", "boolean"];
|
export const itemTypes = ["shape", "color", "boolean"];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for items on belts etc. Not an entity for performance reasons
|
* Class for items on belts etc. Not an entity for performance reasons
|
||||||
*/
|
*/
|
||||||
export class BaseItem extends BasicSerializableObject {
|
export class BaseItem extends BasicSerializableObject {
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
static getId() {
|
static getId() {
|
||||||
return "base_item";
|
return "base_item";
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {object} */
|
/** @returns {object} */
|
||||||
static getSchema() {
|
static getSchema() {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {ItemType} **/
|
/** @returns {ItemType} **/
|
||||||
getItemType() {
|
getItemType() {
|
||||||
abstract;
|
abstract;
|
||||||
return "shape";
|
return "shape";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the item equals the other itme
|
* Returns if the item equals the other itme
|
||||||
* @param {BaseItem} other
|
* @param {BaseItem} other
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
equals(other) {
|
equals(other) {
|
||||||
if (this.getItemType() !== other.getItemType()) {
|
if (this.getItemType() !== other.getItemType()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.equalsImpl(other);
|
return this.equalsImpl(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override for custom comparison
|
* Override for custom comparison
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {BaseItem} other
|
* @param {BaseItem} other
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
equalsImpl(other) {
|
equalsImpl(other) {
|
||||||
abstract;
|
abstract;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the item at the given position
|
* Draws the item to a canvas
|
||||||
* @param {number} x
|
* @param {CanvasRenderingContext2D} context
|
||||||
* @param {number} y
|
* @param {number} size
|
||||||
* @param {DrawParameters} parameters
|
*/
|
||||||
* @param {number=} diameter
|
drawRaw(context, size) {
|
||||||
*/
|
abstract;
|
||||||
drawItemCenteredClipped(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
|
}
|
||||||
if (parameters.visibleRect.containsCircle(x, y, diameter / 2)) {
|
|
||||||
this.drawItemCenteredImpl(x, y, parameters, diameter);
|
/**
|
||||||
}
|
* Draws the item at the given position
|
||||||
}
|
* @param {number} x
|
||||||
|
* @param {number} y
|
||||||
/**
|
* @param {DrawParameters} parameters
|
||||||
* INTERNAL
|
* @param {number=} diameter
|
||||||
* @param {number} x
|
*/
|
||||||
* @param {number} y
|
drawItemCenteredClipped(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
|
||||||
* @param {DrawParameters} parameters
|
if (parameters.visibleRect.containsCircle(x, y, diameter / 2)) {
|
||||||
* @param {number=} diameter
|
this.drawItemCenteredImpl(x, y, parameters, diameter);
|
||||||
*/
|
}
|
||||||
drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
|
}
|
||||||
abstract;
|
|
||||||
}
|
/**
|
||||||
|
* INTERNAL
|
||||||
getBackgroundColorAsResource() {
|
* @param {number} x
|
||||||
abstract;
|
* @param {number} y
|
||||||
return "";
|
* @param {DrawParameters} parameters
|
||||||
}
|
* @param {number=} diameter
|
||||||
}
|
*/
|
||||||
|
drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
|
||||||
|
abstract;
|
||||||
|
}
|
||||||
|
|
||||||
|
getBackgroundColorAsResource() {
|
||||||
|
abstract;
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,12 +1,18 @@
|
|||||||
import { makeOffscreenBuffer } from "../../../core/buffer_utils";
|
import { makeOffscreenBuffer } from "../../../core/buffer_utils";
|
||||||
import { globalConfig, IS_DEMO } from "../../../core/config";
|
import { globalConfig, IS_DEMO, THIRDPARTY_URLS } from "../../../core/config";
|
||||||
import { DrawParameters } from "../../../core/draw_parameters";
|
import { DrawParameters } from "../../../core/draw_parameters";
|
||||||
import { Loader } from "../../../core/loader";
|
import { Loader } from "../../../core/loader";
|
||||||
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 { Rectangle } from "../../../core/rectangle";
|
import { Rectangle } from "../../../core/rectangle";
|
||||||
import { STOP_PROPAGATION } from "../../../core/signal";
|
import { STOP_PROPAGATION } from "../../../core/signal";
|
||||||
import { arrayDeleteValue, lerp, makeDiv, removeAllChildren } from "../../../core/utils";
|
import {
|
||||||
|
arrayDeleteValue,
|
||||||
|
fillInLinkIntoTranslation,
|
||||||
|
lerp,
|
||||||
|
makeDiv,
|
||||||
|
removeAllChildren,
|
||||||
|
} from "../../../core/utils";
|
||||||
import { Vector } from "../../../core/vector";
|
import { Vector } from "../../../core/vector";
|
||||||
import { T } from "../../../translations";
|
import { T } from "../../../translations";
|
||||||
import { BaseItem } from "../../base_item";
|
import { BaseItem } from "../../base_item";
|
||||||
@ -272,7 +278,7 @@ export class HUDWaypoints extends BaseHUDPart {
|
|||||||
const dialog = new DialogWithForm({
|
const dialog = new DialogWithForm({
|
||||||
app: this.root.app,
|
app: this.root.app,
|
||||||
title: waypoint ? T.dialogs.createMarker.titleEdit : T.dialogs.createMarker.title,
|
title: waypoint ? T.dialogs.createMarker.titleEdit : T.dialogs.createMarker.title,
|
||||||
desc: T.dialogs.createMarker.desc,
|
desc: fillInLinkIntoTranslation(T.dialogs.createMarker.desc, THIRDPARTY_URLS.shapeViewer),
|
||||||
formElements: [markerNameInput],
|
formElements: [markerNameInput],
|
||||||
buttons: waypoint ? ["delete:bad", "cancel", "ok:good"] : ["cancel", "ok:good"],
|
buttons: waypoint ? ["delete:bad", "cancel", "ok:good"] : ["cancel", "ok:good"],
|
||||||
});
|
});
|
||||||
|
@ -56,6 +56,21 @@ export class BooleanItem extends BaseItem {
|
|||||||
}
|
}
|
||||||
sprite.drawCachedCentered(parameters, x, y, diameter);
|
sprite.drawCachedCentered(parameters, x, y, diameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the item to a canvas
|
||||||
|
* @param {CanvasRenderingContext2D} context
|
||||||
|
* @param {number} size
|
||||||
|
*/
|
||||||
|
drawRaw(context, size) {
|
||||||
|
let sprite;
|
||||||
|
if (this.value) {
|
||||||
|
sprite = Loader.getSprite("sprites/wires/boolean_true.png");
|
||||||
|
} else {
|
||||||
|
sprite = Loader.getSprite("sprites/wires/boolean_false.png");
|
||||||
|
}
|
||||||
|
sprite.drawCentered(context, size / 2, size / 2, size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BOOL_FALSE_SINGLETON = new BooleanItem(0);
|
export const BOOL_FALSE_SINGLETON = new BooleanItem(0);
|
||||||
|
@ -47,6 +47,18 @@ export class ColorItem extends BaseItem {
|
|||||||
return THEME.map.resources[this.color];
|
return THEME.map.resources[this.color];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the item to a canvas
|
||||||
|
* @param {CanvasRenderingContext2D} context
|
||||||
|
* @param {number} size
|
||||||
|
*/
|
||||||
|
drawRaw(context, size) {
|
||||||
|
if (!this.cachedSprite) {
|
||||||
|
this.cachedSprite = Loader.getSprite("sprites/colors/" + this.color + ".png");
|
||||||
|
}
|
||||||
|
this.cachedSprite.drawCentered(context, size / 2, size / 2, size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} x
|
* @param {number} x
|
||||||
* @param {number} y
|
* @param {number} y
|
||||||
|
@ -1,62 +1,71 @@
|
|||||||
import { DrawParameters } from "../../core/draw_parameters";
|
import { DrawParameters } from "../../core/draw_parameters";
|
||||||
import { types } from "../../savegame/serialization";
|
import { types } from "../../savegame/serialization";
|
||||||
import { BaseItem } from "../base_item";
|
import { BaseItem } from "../base_item";
|
||||||
import { ShapeDefinition } from "../shape_definition";
|
import { ShapeDefinition } from "../shape_definition";
|
||||||
import { THEME } from "../theme";
|
import { THEME } from "../theme";
|
||||||
import { globalConfig } from "../../core/config";
|
import { globalConfig } from "../../core/config";
|
||||||
|
|
||||||
export class ShapeItem extends BaseItem {
|
export class ShapeItem extends BaseItem {
|
||||||
static getId() {
|
static getId() {
|
||||||
return "shape";
|
return "shape";
|
||||||
}
|
}
|
||||||
|
|
||||||
static getSchema() {
|
static getSchema() {
|
||||||
return types.string;
|
return types.string;
|
||||||
}
|
}
|
||||||
|
|
||||||
serialize() {
|
serialize() {
|
||||||
return this.definition.getHash();
|
return this.definition.getHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialize(data) {
|
deserialize(data) {
|
||||||
this.definition = ShapeDefinition.fromShortKey(data);
|
this.definition = ShapeDefinition.fromShortKey(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @returns {"shape"} **/
|
/** @returns {"shape"} **/
|
||||||
getItemType() {
|
getItemType() {
|
||||||
return "shape";
|
return "shape";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {BaseItem} other
|
* @param {BaseItem} other
|
||||||
*/
|
*/
|
||||||
equalsImpl(other) {
|
equalsImpl(other) {
|
||||||
return this.definition.getHash() === /** @type {ShapeItem} */ (other).definition.getHash();
|
return this.definition.getHash() === /** @type {ShapeItem} */ (other).definition.getHash();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {ShapeDefinition} definition
|
* @param {ShapeDefinition} definition
|
||||||
*/
|
*/
|
||||||
constructor(definition) {
|
constructor(definition) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This property must not be modified on runtime, you have to clone the class in order to change the definition
|
* This property must not be modified on runtime, you have to clone the class in order to change the definition
|
||||||
*/
|
*/
|
||||||
this.definition = definition;
|
this.definition = definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
getBackgroundColorAsResource() {
|
getBackgroundColorAsResource() {
|
||||||
return THEME.map.resources.shape;
|
return THEME.map.resources.shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} x
|
* Draws the item to a canvas
|
||||||
* @param {number} y
|
* @param {CanvasRenderingContext2D} context
|
||||||
* @param {DrawParameters} parameters
|
* @param {number} size
|
||||||
* @param {number=} diameter
|
*/
|
||||||
*/
|
drawRaw(context, size) {
|
||||||
drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
|
this.definition.drawRaw(context, size);
|
||||||
this.definition.drawCentered(x, y, parameters, diameter);
|
}
|
||||||
}
|
|
||||||
}
|
/**
|
||||||
|
* @param {number} x
|
||||||
|
* @param {number} y
|
||||||
|
* @param {DrawParameters} parameters
|
||||||
|
* @param {number=} diameter
|
||||||
|
*/
|
||||||
|
drawItemCenteredImpl(x, y, parameters, diameter = globalConfig.defaultItemDiameter) {
|
||||||
|
this.definition.drawCentered(x, y, parameters, diameter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -297,6 +297,15 @@ export class ShapeDefinition extends BasicSerializableObject {
|
|||||||
parameters.context.drawImage(canvas, x - diameter / 2, y - diameter / 2, diameter, diameter);
|
parameters.context.drawImage(canvas, x - diameter / 2, y - diameter / 2, diameter, diameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the item to a canvas
|
||||||
|
* @param {CanvasRenderingContext2D} context
|
||||||
|
* @param {number} size
|
||||||
|
*/
|
||||||
|
drawRaw(context, size) {
|
||||||
|
this.internalGenerateShapeBuffer(null, context, size, size, 1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates this shape as a canvas
|
* Generates this shape as a canvas
|
||||||
* @param {number} size
|
* @param {number} size
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import trim from "trim";
|
import trim from "trim";
|
||||||
|
import { THIRDPARTY_URLS } from "../../core/config";
|
||||||
import { DialogWithForm } from "../../core/modal_dialog_elements";
|
import { DialogWithForm } from "../../core/modal_dialog_elements";
|
||||||
import { FormElementInput } from "../../core/modal_dialog_forms";
|
import { FormElementInput, FormElementItemChooser } from "../../core/modal_dialog_forms";
|
||||||
|
import { fillInLinkIntoTranslation } from "../../core/utils";
|
||||||
|
import { T } from "../../translations";
|
||||||
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";
|
||||||
@ -9,6 +12,7 @@ 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";
|
||||||
|
import { blueprintShape } from "../upgrades";
|
||||||
|
|
||||||
export class ConstantSignalSystem extends GameSystemWithFilter {
|
export class ConstantSignalSystem extends GameSystemWithFilter {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
@ -41,23 +45,35 @@ export class ConstantSignalSystem extends GameSystemWithFilter {
|
|||||||
|
|
||||||
const signalValueInput = new FormElementInput({
|
const signalValueInput = new FormElementInput({
|
||||||
id: "signalValue",
|
id: "signalValue",
|
||||||
label: null,
|
label: fillInLinkIntoTranslation(T.dialogs.editSignal.descShortKey, THIRDPARTY_URLS.shapeViewer),
|
||||||
placeholder: "",
|
placeholder: "",
|
||||||
defaultValue: "",
|
defaultValue: "",
|
||||||
validator: val => this.parseSignalCode(val),
|
validator: val => this.parseSignalCode(val),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const itemInput = new FormElementItemChooser({
|
||||||
|
id: "signalItem",
|
||||||
|
label: null,
|
||||||
|
items: [
|
||||||
|
BOOL_FALSE_SINGLETON,
|
||||||
|
BOOL_TRUE_SINGLETON,
|
||||||
|
...Object.values(COLOR_ITEM_SINGLETONS),
|
||||||
|
this.root.shapeDefinitionMgr.getShapeItemFromShortKey(blueprintShape),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
const dialog = new DialogWithForm({
|
const dialog = new DialogWithForm({
|
||||||
app: this.root.app,
|
app: this.root.app,
|
||||||
title: "Set Signal",
|
title: T.dialogs.editSignal.title,
|
||||||
desc: "Enter a shape code, color or '0' or '1'",
|
desc: T.dialogs.editSignal.descItems,
|
||||||
formElements: [signalValueInput],
|
formElements: [itemInput, signalValueInput],
|
||||||
buttons: ["cancel:bad:escape", "ok:good:enter"],
|
buttons: ["cancel:bad:escape", "ok:good:enter"],
|
||||||
closeButton: false,
|
closeButton: false,
|
||||||
});
|
});
|
||||||
this.root.hud.parts.dialogs.internalShowDialog(dialog);
|
this.root.hud.parts.dialogs.internalShowDialog(dialog);
|
||||||
|
|
||||||
// When confirmed, set the signal
|
// When confirmed, set the signal
|
||||||
dialog.buttonSignals.ok.add(() => {
|
const closeHandler = () => {
|
||||||
if (!this.root || !this.root.entityMgr) {
|
if (!this.root || !this.root.entityMgr) {
|
||||||
// Game got stopped
|
// Game got stopped
|
||||||
return;
|
return;
|
||||||
@ -75,8 +91,16 @@ export class ConstantSignalSystem extends GameSystemWithFilter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
constantComp.signal = this.parseSignalCode(signalValueInput.getValue());
|
if (itemInput.chosenItem) {
|
||||||
});
|
console.log(itemInput.chosenItem);
|
||||||
|
constantComp.signal = itemInput.chosenItem;
|
||||||
|
} else {
|
||||||
|
constantComp.signal = this.parseSignalCode(signalValueInput.getValue());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dialog.buttonSignals.ok.add(closeHandler);
|
||||||
|
dialog.valueChosen.add(closeHandler);
|
||||||
|
|
||||||
// When cancelled, destroy the entity again
|
// When cancelled, destroy the entity again
|
||||||
dialog.buttonSignals.cancel.add(() => {
|
dialog.buttonSignals.cancel.add(() => {
|
||||||
|
@ -268,7 +268,13 @@ dialogs:
|
|||||||
createMarker:
|
createMarker:
|
||||||
title: New Marker
|
title: New Marker
|
||||||
titleEdit: Edit Marker
|
titleEdit: Edit Marker
|
||||||
desc: Give it a meaningful name, you can also include a <strong>short key</strong> of a shape (Which you can generate <a href="https://viewer.shapez.io" target="_blank">here</a>)
|
desc: Give it a meaningful name, you can also include a <strong>short key</strong> of a shape (Which you can generate <link>here</link>)
|
||||||
|
|
||||||
|
editSignal:
|
||||||
|
title: Set Signal
|
||||||
|
descItems: >-
|
||||||
|
Choose a pre-defined item:
|
||||||
|
descShortKey: ... or enter the <strong>short key</strong> of a shape (Which you can generate <link>here</link>)
|
||||||
|
|
||||||
markerDemoLimit:
|
markerDemoLimit:
|
||||||
desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers!
|
desc: You can only create two custom markers in the demo. Get the standalone for unlimited markers!
|
||||||
|