mirror of
https://github.com/tobspr/shapez.io.git
synced 2025-12-17 12:11:51 +00:00
Minor fixes and adjustments for easier use
This commit is contained in:
parent
900fcc8479
commit
a0421ff14b
BIN
res/ui/icons/upload.png
Normal file
BIN
res/ui/icons/upload.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.6 KiB |
@ -1,4 +1,4 @@
|
||||
#ingame_HUD_PuzzleEditorDownload {
|
||||
#ingame_HUD_PuzzleImportExport {
|
||||
position: absolute;
|
||||
@include S(top, 35px);
|
||||
left: 50%;
|
||||
@ -17,12 +17,14 @@
|
||||
transition-property: opacity, transform;
|
||||
text-transform: uppercase;
|
||||
@include PlainText;
|
||||
@include S(width, 30px);
|
||||
@include S(height, 30px);
|
||||
@include S(width, 20px);
|
||||
@include S(height, 20px);
|
||||
margin: 8px 5px;
|
||||
|
||||
@include DarkThemeInvert;
|
||||
|
||||
opacity: 1;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.9 !important;
|
||||
}
|
||||
@ -31,7 +33,13 @@
|
||||
transform: scale(0.95) !important;
|
||||
}
|
||||
|
||||
& {
|
||||
&.import {
|
||||
/* @load-async */
|
||||
background: uiResource("icons/upload.png") center center / D(15px) no-repeat;
|
||||
//transform: rotate(180deg);
|
||||
}
|
||||
|
||||
&.export {
|
||||
/* @load-async */
|
||||
background: uiResource("icons/download.png") center center / D(15px) no-repeat;
|
||||
}
|
||||
@ -65,7 +65,7 @@
|
||||
@import "ingame_hud/puzzle_play_settings";
|
||||
@import "ingame_hud/puzzle_play_metadata";
|
||||
@import "ingame_hud/puzzle_complete_notification";
|
||||
@import "ingame_hud/puzzle_editor_download";
|
||||
@import "ingame_hud/puzzle_import_export";
|
||||
|
||||
// prettier-ignore
|
||||
$elements:
|
||||
@ -85,7 +85,7 @@ ingame_HUD_GameMenu,
|
||||
ingame_HUD_KeybindingOverlay,
|
||||
ingame_HUD_PuzzleBackToMenu,
|
||||
ingame_HUD_PuzzleEditorReview,
|
||||
ingame_HUD_PuzzleEditorDownload,
|
||||
ingame_HUD_PuzzleImportExport,
|
||||
ingame_HUD_PuzzleEditorControls,
|
||||
ingame_HUD_PuzzleEditorTitle,
|
||||
ingame_HUD_PuzzleEditorSettings,
|
||||
@ -138,7 +138,7 @@ body.uiHidden {
|
||||
#ingame_HUD_PuzzleEditorSettings,
|
||||
#ingame_HUD_PuzzlePlaySettings,
|
||||
#ingame_HUD_PuzzleEditorControls,
|
||||
#ingame_HUD_PuzzleEditorDownload,
|
||||
#ingame_HUD_PuzzleImportExport,
|
||||
#ingame_HUD_PuzzlePlayMetadata,
|
||||
#ingame_HUD_Notifications,
|
||||
#ingame_HUD_TutorialHints,
|
||||
|
||||
@ -302,8 +302,9 @@ export class HUDBaseToolbar extends BaseHUDPart {
|
||||
|
||||
/**
|
||||
* @param {MetaBuilding} metaBuilding
|
||||
* @param {boolean | null} force
|
||||
*/
|
||||
toggleBuildingLock(metaBuilding) {
|
||||
toggleBuildingLock(metaBuilding, force = null) {
|
||||
if (!this.visibilityCondition()) {
|
||||
// Not active
|
||||
return;
|
||||
@ -315,7 +316,11 @@ export class HUDBaseToolbar extends BaseHUDPart {
|
||||
}
|
||||
|
||||
const handle = this.buildingHandles[metaBuilding.getId()];
|
||||
handle.puzzleLocked = !handle.puzzleLocked;
|
||||
if (force != null) {
|
||||
handle.puzzleLocked = force;
|
||||
} else {
|
||||
handle.puzzleLocked = !handle.puzzleLocked;
|
||||
}
|
||||
handle.element.classList.toggle("unlocked", !handle.puzzleLocked);
|
||||
|
||||
const entityManager = this.root.entityMgr;
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
import { ReadWriteProxy } from "../../../core/read_write_proxy";
|
||||
import { generateFileDownload, makeDiv } from "../../../core/utils";
|
||||
import { PuzzleSerializer } from "../../../savegame/puzzle_serializer";
|
||||
import { T } from "../../../translations";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
|
||||
export class HUDPuzzleEditorDownload extends BaseHUDPart {
|
||||
constructor(root) {
|
||||
super(root);
|
||||
}
|
||||
|
||||
createElements(parent) {
|
||||
this.element = makeDiv(parent, "ingame_HUD_PuzzleEditorDownload");
|
||||
this.button = document.createElement("button");
|
||||
this.button.classList.add("button");
|
||||
this.element.appendChild(this.button);
|
||||
|
||||
this.trackClicks(this.button, () => {
|
||||
const { ok } = this.root.hud.parts.dialogs.showWarning(
|
||||
T.dialogs.puzzleDownload.title,
|
||||
T.dialogs.puzzleDownload.desc,
|
||||
["cancel", "ok:good:enter"]
|
||||
);
|
||||
ok.add(() => this.downloadPuzzle());
|
||||
});
|
||||
}
|
||||
|
||||
initialize() {}
|
||||
|
||||
downloadPuzzle() {
|
||||
const serialized = new PuzzleSerializer().generateDumpFromGameRoot(this.root);
|
||||
|
||||
const data = ReadWriteProxy.serializeObject(serialized);
|
||||
const filename = "puzzle.bin";
|
||||
generateFileDownload(filename, data);
|
||||
}
|
||||
}
|
||||
@ -92,45 +92,50 @@ export class HUDPuzzleEditorSettings extends BaseHUDPart {
|
||||
testButton.classList.toggle("disabled", false);
|
||||
}, 140);
|
||||
|
||||
this.root.logic.performBulkOperation(() => {
|
||||
if (this.testMode) {
|
||||
for (const entity of this.root.entityMgr.getAllWithComponent(StaticMapEntityComponent)) {
|
||||
if (this.testMode) {
|
||||
this.storedSolution.push(entity.clone());
|
||||
this.storedSolution.push(entity.clone());
|
||||
|
||||
const metaBuilding = entity.components.StaticMapEntity.getMetaBuilding();
|
||||
const goalComp = entity.components.GoalAcceptor;
|
||||
if (goalComp) {
|
||||
goalComp.clear();
|
||||
continue;
|
||||
}
|
||||
const metaBuilding = entity.components.StaticMapEntity.getMetaBuilding();
|
||||
const goalComp = entity.components.GoalAcceptor;
|
||||
if (goalComp) {
|
||||
goalComp.clear();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
[MetaConstantProducerBuilding, MetaBlockBuilding]
|
||||
.map(metaClass => gMetaBuildingRegistry.findByClass(metaClass).id)
|
||||
.includes(metaBuilding.id)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
[MetaConstantProducerBuilding, MetaBlockBuilding]
|
||||
.map(metaClass => gMetaBuildingRegistry.findByClass(metaClass).id)
|
||||
.includes(metaBuilding.id)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
this.root.map.removeStaticEntity(entity);
|
||||
this.root.entityMgr.destroyEntity(entity);
|
||||
}
|
||||
this.root.entityMgr.processDestroyList();
|
||||
|
||||
if (!this.testMode) {
|
||||
for (const entity of this.storedSolution) {
|
||||
const placedEntity = this.root.logic.tryPlaceEntity(entity);
|
||||
|
||||
for (const key in entity.components) {
|
||||
/** @type {import("../../../core/global_registries").Component} */ (entity.components[
|
||||
key
|
||||
]).copyAdditionalStateTo(placedEntity.components[key]);
|
||||
} else if (this.storedSolution.length) {
|
||||
this.root.logic.performBulkOperation(() => {
|
||||
this.root.logic.performImmutableOperation(() => {
|
||||
for (const entity of this.root.entityMgr.getAllWithComponent(StaticMapEntityComponent)) {
|
||||
this.root.map.removeStaticEntity(entity);
|
||||
this.root.entityMgr.destroyEntity(entity);
|
||||
}
|
||||
}
|
||||
this.storedSolution = [];
|
||||
}
|
||||
});
|
||||
this.root.entityMgr.processDestroyList();
|
||||
|
||||
for (const entity of this.storedSolution) {
|
||||
const placedEntity = this.root.logic.tryPlaceEntity(entity);
|
||||
|
||||
for (const key in entity.components) {
|
||||
/** @type {import("../../../core/global_registries").Component} */ (entity
|
||||
.components[key]).copyAdditionalStateTo(placedEntity.components[key]);
|
||||
}
|
||||
}
|
||||
this.storedSolution = [];
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
trim() {
|
||||
|
||||
118
src/js/game/hud/parts/puzzle_import_export.js
Normal file
118
src/js/game/hud/parts/puzzle_import_export.js
Normal file
@ -0,0 +1,118 @@
|
||||
import { gMetaBuildingRegistry } from "../../../core/global_registries";
|
||||
import { ReadWriteProxy } from "../../../core/read_write_proxy";
|
||||
import { generateFileDownload, makeDiv, startFileChoose, waitNextFrame } from "../../../core/utils";
|
||||
import { PuzzleSerializer } from "../../../savegame/puzzle_serializer";
|
||||
import { T } from "../../../translations";
|
||||
import { StaticMapEntityComponent } from "../../components/static_map_entity";
|
||||
import { PuzzleGameMode } from "../../modes/puzzle";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
|
||||
export class HUDPuzzleImportExport extends BaseHUDPart {
|
||||
constructor(root) {
|
||||
super(root);
|
||||
}
|
||||
|
||||
createElements(parent) {
|
||||
this.element = makeDiv(parent, "ingame_HUD_PuzzleImportExport");
|
||||
this.importButton = document.createElement("button");
|
||||
this.importButton.classList.add("button", "import");
|
||||
this.element.appendChild(this.importButton);
|
||||
|
||||
this.exportButton = document.createElement("button");
|
||||
this.exportButton.classList.add("button", "export");
|
||||
this.element.appendChild(this.exportButton);
|
||||
|
||||
this.trackClicks(this.importButton, this.importPuzzle);
|
||||
|
||||
this.trackClicks(this.exportButton, () => {
|
||||
const { yes } = this.root.hud.parts.dialogs.showWarning(
|
||||
T.dialogs.puzzleExport.title,
|
||||
T.dialogs.puzzleExport.desc,
|
||||
["no", "yes:good:enter"]
|
||||
);
|
||||
yes.add(() => this.exportPuzzle());
|
||||
});
|
||||
}
|
||||
|
||||
initialize() {}
|
||||
|
||||
importPuzzle() {
|
||||
startFileChoose(".bin").then(file => {
|
||||
if (file) {
|
||||
const closeLoader = this.root.hud.parts.dialogs.showLoadingDialog("Importing Puzzle");
|
||||
waitNextFrame().then(() => {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener("load", event => {
|
||||
const fileContents = String(event.target.result);
|
||||
|
||||
/** @type {import("../../../savegame/savegame_typedefs").PuzzleGameData} */
|
||||
let gameData;
|
||||
|
||||
try {
|
||||
gameData = ReadWriteProxy.deserializeObject(fileContents);
|
||||
} catch (err) {
|
||||
closeLoader();
|
||||
this.root.hud.parts.dialogs.showWarning(T.global.error, String(err));
|
||||
return;
|
||||
}
|
||||
|
||||
const mode = /** @type {PuzzleGameMode} */ (this.root.gameMode);
|
||||
let errorText;
|
||||
try {
|
||||
// set excluded buildings first so if we get an error we haven't removed buildings yet
|
||||
const toolbar = this.root.hud.parts.buildingsToolbar;
|
||||
const handles = toolbar.buildingHandles;
|
||||
const ids = gMetaBuildingRegistry.getAllIds();
|
||||
|
||||
for (let i = 0; i < ids.length; ++i) {
|
||||
const handle = handles[ids[i]];
|
||||
if (handle && !toolbar.inRequiredBuildings(handle.metaBuilding)) {
|
||||
const locked = gameData.excludedBuildings.includes(ids[i]);
|
||||
|
||||
toolbar.toggleBuildingLock(handle.metaBuilding, locked);
|
||||
}
|
||||
}
|
||||
|
||||
for (const entity of this.root.entityMgr.getAllWithComponent(
|
||||
StaticMapEntityComponent
|
||||
)) {
|
||||
this.root.map.removeStaticEntity(entity);
|
||||
this.root.entityMgr.destroyEntity(entity);
|
||||
}
|
||||
this.root.entityMgr.processDestroyList();
|
||||
|
||||
mode.zoneWidth = gameData.bounds.w;
|
||||
mode.zoneHeight = gameData.bounds.h;
|
||||
|
||||
errorText = new PuzzleSerializer().deserializePuzzle(this.root, gameData);
|
||||
} catch (ex) {
|
||||
errorText = ex.message || ex;
|
||||
}
|
||||
|
||||
if (errorText) {
|
||||
this.root.hud.parts.dialogs.showWarning(
|
||||
T.dialogs.puzzleLoadError.title,
|
||||
T.dialogs.puzzleLoadError.desc + " " + errorText
|
||||
);
|
||||
} else {
|
||||
this.root.hud.parts.dialogs.showInfo(
|
||||
T.dialogs.puzzleImport.title,
|
||||
T.dialogs.puzzleImport.desc
|
||||
);
|
||||
}
|
||||
closeLoader();
|
||||
});
|
||||
reader.readAsText(file);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exportPuzzle() {
|
||||
const serialized = new PuzzleSerializer().generateDumpFromGameRoot(this.root);
|
||||
|
||||
const data = ReadWriteProxy.serializeObject(serialized);
|
||||
const filename = "puzzle.bin";
|
||||
generateFileDownload(filename, data);
|
||||
}
|
||||
}
|
||||
@ -23,10 +23,7 @@ import { HUDPuzzleEditorControls } from "../hud/parts/puzzle_editor_controls";
|
||||
import { HUDPuzzleEditorReview } from "../hud/parts/puzzle_editor_review";
|
||||
import { HUDPuzzleEditorSettings } from "../hud/parts/puzzle_editor_settings";
|
||||
import { createLogger } from "../../core/logging";
|
||||
import { PuzzleSerializer } from "../../savegame/puzzle_serializer";
|
||||
import { T } from "../../translations";
|
||||
import { gMetaBuildingRegistry } from "../../core/global_registries";
|
||||
import { HUDPuzzleEditorDownload } from "../hud/parts/puzzle_editor_download";
|
||||
import { HUDPuzzleImportExport } from "../hud/parts/puzzle_import_export";
|
||||
|
||||
const logger = createLogger("puzzle-edit");
|
||||
|
||||
@ -41,11 +38,8 @@ export class PuzzleEditGameMode extends PuzzleGameMode {
|
||||
|
||||
/**
|
||||
* @param {GameRoot} root
|
||||
* @param {object} payload
|
||||
* @param {import("../../savegame/savegame_typedefs").PuzzleGameData} payload.gameData
|
||||
* @param {boolean} payload.startInTestMode
|
||||
*/
|
||||
constructor(root, { gameData = null, startInTestMode = false }) {
|
||||
constructor(root) {
|
||||
super(root);
|
||||
|
||||
this.hiddenBuildings = [
|
||||
@ -70,57 +64,7 @@ export class PuzzleEditGameMode extends PuzzleGameMode {
|
||||
this.additionalHudParts.puzzleEditorControls = HUDPuzzleEditorControls;
|
||||
this.additionalHudParts.puzzleEditorReview = HUDPuzzleEditorReview;
|
||||
this.additionalHudParts.puzzleEditorSettings = HUDPuzzleEditorSettings;
|
||||
this.additionalHudParts.puzzleEditorDownload = HUDPuzzleEditorDownload;
|
||||
|
||||
this.gameData = gameData;
|
||||
|
||||
if (gameData) {
|
||||
root.signals.postLoadHook.add(() => this.loadPuzzle(gameData), this);
|
||||
}
|
||||
|
||||
this.startInTestMode = startInTestMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../../savegame/savegame_typedefs").PuzzleGameData} puzzle
|
||||
*/
|
||||
loadPuzzle(puzzle) {
|
||||
let errorText;
|
||||
logger.log("Loading puzzle", puzzle);
|
||||
|
||||
// set zone and add buildings
|
||||
try {
|
||||
this.zoneWidth = puzzle.bounds.w;
|
||||
this.zoneHeight = puzzle.bounds.h;
|
||||
errorText = new PuzzleSerializer().deserializePuzzle(this.root, puzzle);
|
||||
} catch (ex) {
|
||||
errorText = ex.message || ex;
|
||||
}
|
||||
|
||||
if (errorText) {
|
||||
this.root.gameState.moveToState("PuzzleMenuState", {
|
||||
error: {
|
||||
title: T.dialogs.puzzleLoadError.title,
|
||||
desc: T.dialogs.puzzleLoadError.desc + " " + errorText,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const toolbar = this.root.hud.parts.buildingsToolbar;
|
||||
|
||||
// lock excluded buildings
|
||||
for (let i = 0; i < this.gameData.excludedBuildings.length; ++i) {
|
||||
const id = this.gameData.excludedBuildings[i];
|
||||
|
||||
if (!gMetaBuildingRegistry.hasId(id)) {
|
||||
continue;
|
||||
}
|
||||
toolbar.toggleBuildingLock(gMetaBuildingRegistry.findById(id));
|
||||
}
|
||||
|
||||
if (this.startInTestMode) {
|
||||
this.root.hud.parts.puzzleEditorSettings.toggleTestMode();
|
||||
}
|
||||
this.additionalHudParts.puzzleEditorDownload = HUDPuzzleImportExport;
|
||||
}
|
||||
|
||||
getIsEditor() {
|
||||
|
||||
@ -43,7 +43,6 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
<h1><button class="backButton"></button> ${this.getStateHeaderTitle()}</h1>
|
||||
|
||||
<div class="actions">
|
||||
<button class="styledButton importPuzzle">Import</button>
|
||||
<button class="styledButton loadPuzzle">${T.puzzleMenu.loadPuzzle}</button>
|
||||
<button class="styledButton createPuzzle">+ ${T.puzzleMenu.createPuzzle}</button>
|
||||
</div>
|
||||
@ -390,7 +389,6 @@ export class PuzzleMenuState extends TextualGameState {
|
||||
|
||||
this.trackClicks(this.htmlElement.querySelector("button.createPuzzle"), () => this.createNewPuzzle());
|
||||
this.trackClicks(this.htmlElement.querySelector("button.loadPuzzle"), () => this.loadPuzzle());
|
||||
this.trackClicks(this.htmlElement.querySelector("button.importPuzzle"), () => this.importPuzzle());
|
||||
}
|
||||
|
||||
createEmptySavegame() {
|
||||
|
||||
@ -189,6 +189,8 @@ dialogs:
|
||||
retry: Retry
|
||||
continue: Continue
|
||||
playOffline: Play Offline
|
||||
yes: Yes
|
||||
no: No
|
||||
|
||||
importSavegameError:
|
||||
title: Import Error
|
||||
@ -400,8 +402,13 @@ dialogs:
|
||||
desc: >-
|
||||
Are you sure you want to delete '<title>'? This can not be undone!
|
||||
|
||||
puzzleDownload:
|
||||
title: Download Puzzle
|
||||
puzzleImport:
|
||||
title: Puzzle Imported
|
||||
desc: >-
|
||||
Your puzzle has been successfully imported.
|
||||
|
||||
puzzleExport:
|
||||
title: Export Puzzle
|
||||
desc: >-
|
||||
Do you want to download this puzzle?
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user