1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Add enum form element and update screenshot dialog

The enum form element allows for cycling through a list of options.
The screenshot dialog now uses this, and has a list of image qualities.
The map quality has not yet been implemented.
This commit is contained in:
EmeraldBlock 2021-03-16 20:45:14 -05:00
parent da6b1a437c
commit 96170f8d22
3 changed files with 151 additions and 14 deletions

View File

@ -214,6 +214,53 @@
}
}
}
.checkBoxFormElem {
@include S(margin, 10px, 0);
> label {
@include S(margin-right, 10px);
}
display: flex;
align-items: center;
}
.enum {
@include S(margin, 10px, 0);
display: grid;
grid-template-columns: auto 1fr auto;
@include S(grid-gap, 4px);
@include S(width, 200px);
> * {
background: #fff;
text-align: center;
pointer-events: all;
cursor: pointer;
@include S(border-radius, $globalBorderRadius);
@include S(padding, 4px);
transition: background-color 0.12s ease-in-out;
&:hover {
background-color: #fafafa;
}
@include DarkThemeOverride {
background-color: $darkModeControlsBackground;
color: #ddd;
&:hover {
background-color: darken($darkModeControlsBackground, 2);
}
}
&.toggle {
@include S(width, 20px);
}
&.value {
transform: none !important;
}
}
}
}
> .buttons {

View File

@ -1,6 +1,7 @@
import { BaseItem } from "../game/base_item";
import { ClickDetector } from "./click_detector";
import { Signal } from "./signal";
import { safeModulo } from "./utils";
/*
* ***************************************************
@ -235,3 +236,56 @@ export class FormElementItemChooser extends FormElement {
focus() {}
}
export class FormElementEnum extends FormElement {
constructor({ id, label = null, options, valueGetter, textGetter }) {
super(id, label);
this.options = options;
this.valueGetter = valueGetter;
this.textGetter = textGetter;
this.index = 0;
this.element = null;
}
getHtml() {
return `
<div class="formElement enumFormElem">
${this.label ? `<label>${this.label}</label>` : ""}
<div class="enum" data-formId="${this.id}">
<div class="toggle prev"></div>
<div class="value">${this.textGetter(this.options[0])}</div>
<div class="toggle next"></div>
</div>
</div>
`;
}
/**
* @param {HTMLElement} parent
* @param {Array<ClickDetector>} clickTrackers
*/
bindEvents(parent, clickTrackers) {
this.element = this.getFormElement(parent);
const children = this.element.children;
for (let i = 0; i < children.length; ++i) {
const child = children[i];
const detector = new ClickDetector(child, { preventDefault: false });
clickTrackers.push(detector);
const change = child.classList.contains("prev") ? -1 : 1;
detector.click.add(() => this.toggle(change), this);
}
}
getValue() {
return this.valueGetter(this.options[this.index]);
}
toggle(amount) {
this.index = safeModulo(this.index + amount, this.options.length);
this.element.querySelector(".value").innerText = this.textGetter(this.options[this.index]);
}
focus() {}
}

View File

@ -9,10 +9,38 @@ import { StaticMapEntityComponent } from "../../components/static_map_entity";
import { KEYMAPPINGS } from "../../key_action_mapper";
import { BaseHUDPart } from "../base_hud_part";
import { DialogWithForm } from "../../../core/modal_dialog_elements";
import { FormElementInput, FormElementCheckbox } from "../../../core/modal_dialog_forms";
import { FormElementInput, FormElementCheckbox, FormElementEnum } from "../../../core/modal_dialog_forms";
const logger = createLogger("screenshot_exporter");
/**
* @typedef {{mode: string, resolution?: number}} QualityOptions
*/
/**
* @type {{id: string, options: QualityOptions}[]}
*/
const screenshotQualities = [
{
id: "high",
options: { mode: "regular", resolution: 16384 },
},
{
id: "medium",
options: { mode: "regular", resolution: 4096 },
},
{
id: "low",
options: { mode: "regular", resolution: 1024 },
},
{
id: "map",
options: { mode: "map" },
},
];
// @TODO: translation (T.dialogs.exportScreenshotWarning.qualities)
const qualityNames = { high: "High", medium: "Medium", low: "Low", map: "Map" };
export class HUDScreenshotExporter extends BaseHUDPart {
createElements() {}
@ -26,23 +54,24 @@ export class HUDScreenshotExporter extends BaseHUDPart {
return;
}
const qualityInput = new FormElementEnum({
id: "screenshotQuality",
options: screenshotQualities,
valueGetter: quality => quality.options,
// @TODO: translation (T.dialogs.exportScreenshotWarning.qualityLabel)
textGetter: quality => "Quality:" + " " + qualityNames[quality.id],
});
const layerInput = new FormElementCheckbox({
id: "screenshotLayer",
// @TODO: translation (T.dialogs.exportScreenshotWarning.descLayer)
label: "Include wires layer",
defaultValue: this.root.currentLayer === "wires" ? true : false,
});
const qualityInput = new FormElementInput({
id: "screenshotQuality",
label: "Pixel width per tile",
placeholder: "",
defaultValue: "",
validator: val => !isNaN(val) && parseInt(val) === parseFloat(val) && !isNaN(parseInt(val, 10)),
});
const dialog = new DialogWithForm({
app: this.root.app,
title: T.dialogs.exportScreenshotWarning.title,
desc: T.dialogs.exportScreenshotWarning.desc,
formElements: [layerInput, qualityInput],
formElements: [qualityInput, layerInput],
buttons: ["cancel:good", "ok:bad"],
});
@ -53,7 +82,11 @@ export class HUDScreenshotExporter extends BaseHUDPart {
);
}
doExport(wiresLayer, quality) {
/**
* @param {boolean} wiresLayer
* @param {QualityOptions} options
*/
doExport(wiresLayer, options) {
logger.log("Starting export ...");
// Find extends
@ -76,12 +109,15 @@ export class HUDScreenshotExporter extends BaseHUDPart {
const dimensions = maxChunk.sub(minChunk);
logger.log("Dimensions:", dimensions);
let chunkSizePixels = quality * globalConfig.mapChunkSize;
const maxDimensions = Math.max(dimensions.x, dimensions.y);
if (maxDimensions > 128) {
chunkSizePixels = Math.max(1, Math.floor(chunkSizePixels * (128 / maxDimensions)));
}
// we want integer pixels per tile
// if resolution too low, we want integer pixels per chunk
const chunkSizePixels =
maxDimensions * globalConfig.mapChunkSize > options.resolution
? Math.max(1, Math.floor(options.resolution / maxDimensions))
: Math.floor(options.resolution / (maxDimensions * globalConfig.mapChunkSize)) *
globalConfig.mapChunkSize;
logger.log("ChunkSizePixels:", chunkSizePixels);
const chunkScale = chunkSizePixels / globalConfig.mapChunkWorldSize;