mirror of
https://github.com/tobspr/shapez.io.git
synced 2026-03-02 03:39:21 +00:00
Add support for different building variants
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import { MetaBuilding } from "../../meta_building";
|
||||
import { MetaBuilding, defaultBuildingVariant } from "../../meta_building";
|
||||
import { DrawParameters } from "../../../core/draw_parameters";
|
||||
import { globalConfig } from "../../../core/config";
|
||||
import { StaticMapEntityComponent } from "../../components/static_map_entity";
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
enumInvertedDirections,
|
||||
enumDirectionToVector,
|
||||
} from "../../../core/vector";
|
||||
import { pulseAnimation, makeDiv } from "../../../core/utils";
|
||||
import { pulseAnimation, makeDiv, removeAllChildren } from "../../../core/utils";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { TrackedState } from "../../../core/tracked_state";
|
||||
import { Math_abs, Math_radians, Math_degrees } from "../../../core/builtins";
|
||||
@@ -32,6 +32,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
keyActionMapper.getBinding("back").add(this.abortPlacement, this);
|
||||
|
||||
keyActionMapper.getBinding("rotate_while_placing").add(this.tryRotate, this);
|
||||
keyActionMapper.getBinding("cycle_variants").add(this.cycleVariants, this);
|
||||
|
||||
this.domAttach = new DynamicDomAttach(this.root, this.element, {});
|
||||
|
||||
@@ -40,6 +41,15 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
this.root.camera.upPostHandler.add(this.abortDragging, this);
|
||||
|
||||
this.currentlyDragging = false;
|
||||
this.currentVariant = new TrackedState(this.rerenderVariants, this);
|
||||
|
||||
this.variantsAttach = new DynamicDomAttach(this.root, this.variantsElement, {});
|
||||
|
||||
/**
|
||||
* Stores which variants for each building we prefer, this is based on what
|
||||
* the user last selected
|
||||
*/
|
||||
this.preferredVariants = {};
|
||||
|
||||
/**
|
||||
* The tile we last dragged onto
|
||||
@@ -55,7 +65,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
}
|
||||
|
||||
createElements(parent) {
|
||||
this.element = makeDiv(parent, "ingame_HUD_building_placer", [], ``);
|
||||
this.element = makeDiv(parent, "ingame_HUD_PlacementHints", [], ``);
|
||||
|
||||
this.buildingInfoElements = {};
|
||||
this.buildingInfoElements.label = makeDiv(this.element, null, ["buildingLabel"], "Extract");
|
||||
@@ -63,6 +73,8 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
this.buildingInfoElements.descText = makeDiv(this.buildingInfoElements.desc, null, ["text"], "");
|
||||
this.buildingInfoElements.hotkey = makeDiv(this.buildingInfoElements.desc, null, ["hotkey"], "");
|
||||
this.buildingInfoElements.tutorialImage = makeDiv(this.element, null, ["buildingImage"]);
|
||||
|
||||
this.variantsElement = makeDiv(parent, "ingame_HUD_PlacerVariants");
|
||||
}
|
||||
|
||||
abortPlacement() {
|
||||
@@ -106,8 +118,17 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
const oldPos = this.lastDragTile;
|
||||
const newPos = this.root.camera.screenToWorld(pos).toTileSpace();
|
||||
|
||||
if (this.root.camera.desiredCenter) {
|
||||
// Camera is moving
|
||||
this.lastDragTile = newPos;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!oldPos.equals(newPos)) {
|
||||
if (metaBuilding.getRotateAutomaticallyWhilePlacing()) {
|
||||
if (
|
||||
metaBuilding.getRotateAutomaticallyWhilePlacing(this.currentVariant.get()) &&
|
||||
!this.root.app.inputMgr.ctrlIsDown
|
||||
) {
|
||||
const delta = newPos.sub(oldPos);
|
||||
const angleDeg = Math_degrees(delta.angle());
|
||||
this.currentBaseRotation = (Math.round(angleDeg / 90) * 90 + 360) % 360;
|
||||
@@ -177,7 +198,6 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {MetaBuilding} metaBuilding
|
||||
*/
|
||||
onSelectedMetaBuildingChanged(metaBuilding) {
|
||||
@@ -189,16 +209,18 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
const binding = this.root.gameState.keyActionMapper.getBinding(
|
||||
"building_" + metaBuilding.getId()
|
||||
);
|
||||
|
||||
this.buildingInfoElements.hotkey.innerHTML = "Hotkey: " + binding.getKeyCodeString();
|
||||
|
||||
const variant = this.preferredVariants[metaBuilding.getId()] || defaultBuildingVariant;
|
||||
this.currentVariant.set(variant);
|
||||
|
||||
this.fakeEntity = new Entity(null);
|
||||
metaBuilding.setupEntityComponents(this.fakeEntity, null);
|
||||
metaBuilding.setupEntityComponents(this.fakeEntity, null, variant);
|
||||
this.fakeEntity.addComponent(
|
||||
new StaticMapEntityComponent({
|
||||
origin: new Vector(0, 0),
|
||||
rotation: 0,
|
||||
tileSize: metaBuilding.getDimensions().copy(),
|
||||
tileSize: metaBuilding.getDimensions(this.currentVariant.get()).copy(),
|
||||
})
|
||||
);
|
||||
|
||||
@@ -210,6 +232,74 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
this.currentlyDragging = false;
|
||||
this.fakeEntity = null;
|
||||
}
|
||||
|
||||
// Since it depends on both, rerender twice
|
||||
this.rerenderVariants();
|
||||
}
|
||||
|
||||
rerenderVariants() {
|
||||
removeAllChildren(this.variantsElement);
|
||||
|
||||
const metaBuilding = this.currentMetaBuilding.get();
|
||||
|
||||
if (!metaBuilding) {
|
||||
return;
|
||||
}
|
||||
const availableVariants = metaBuilding.getAvailableVariants(this.root);
|
||||
if (availableVariants.length === 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
makeDiv(
|
||||
this.variantsElement,
|
||||
null,
|
||||
["explanation"],
|
||||
`
|
||||
Press <code class='keybinding'>${this.root.gameState.keyActionMapper
|
||||
.getBinding("cycle_variants")
|
||||
.getKeyCodeString()}</code> to cycle variants.
|
||||
`
|
||||
);
|
||||
|
||||
for (let i = 0; i < availableVariants.length; ++i) {
|
||||
const variant = availableVariants[i];
|
||||
|
||||
const element = makeDiv(this.variantsElement, null, ["variant"]);
|
||||
element.classList.toggle("active", variant === this.currentVariant.get());
|
||||
makeDiv(element, null, ["label"], variant);
|
||||
|
||||
const iconSize = 64;
|
||||
|
||||
const dimensions = metaBuilding.getDimensions(variant);
|
||||
const sprite = metaBuilding.getPreviewSprite(0, variant);
|
||||
const spriteWrapper = makeDiv(element, null, ["iconWrap"]);
|
||||
spriteWrapper.setAttribute("data-tile-w", dimensions.x);
|
||||
spriteWrapper.setAttribute("data-tile-h", dimensions.y);
|
||||
|
||||
spriteWrapper.innerHTML = sprite.getAsHTML(iconSize * dimensions.x, iconSize * dimensions.y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cycles through the variants
|
||||
*/
|
||||
cycleVariants() {
|
||||
const metaBuilding = this.currentMetaBuilding.get();
|
||||
if (!metaBuilding) {
|
||||
this.currentVariant.set(defaultBuildingVariant);
|
||||
} else {
|
||||
const availableVariants = metaBuilding.getAvailableVariants(this.root);
|
||||
const index = availableVariants.indexOf(this.currentVariant.get());
|
||||
assert(
|
||||
index >= 0,
|
||||
"Current variant was invalid: " + this.currentVariant.get() + " out of " + availableVariants
|
||||
);
|
||||
const newIndex = (index + 1) % availableVariants.length;
|
||||
const newVariant = availableVariants[newIndex];
|
||||
this.currentVariant.set(newVariant);
|
||||
|
||||
this.preferredVariants[metaBuilding.getId()] = newVariant;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,6 +380,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
rotationVariant,
|
||||
originalRotation: this.currentBaseRotation,
|
||||
building: this.currentMetaBuilding.get(),
|
||||
variant: this.currentVariant.get(),
|
||||
})
|
||||
) {
|
||||
// Succesfully placed
|
||||
@@ -317,10 +408,12 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
if (this.root.camera.zoomLevel < globalConfig.mapChunkOverviewMinZoom) {
|
||||
// Dont allow placing in overview mode
|
||||
this.domAttach.update(false);
|
||||
this.variantsAttach.update(false);
|
||||
return;
|
||||
}
|
||||
|
||||
this.domAttach.update(this.currentMetaBuilding.get());
|
||||
this.variantsAttach.update(this.currentMetaBuilding.get());
|
||||
const metaBuilding = this.currentMetaBuilding.get();
|
||||
|
||||
if (!metaBuilding) {
|
||||
@@ -382,7 +475,9 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
const staticComp = this.fakeEntity.components.StaticMapEntity;
|
||||
staticComp.origin = tile;
|
||||
staticComp.rotation = rotation;
|
||||
staticComp.tileSize = metaBuilding.getDimensions(this.currentVariant.get());
|
||||
metaBuilding.updateRotationVariant(this.fakeEntity, rotationVariant);
|
||||
metaBuilding.updateVariant(this.fakeEntity, this.currentVariant.get());
|
||||
|
||||
// Check if we could place the buildnig
|
||||
const canBuild = this.root.logic.checkCanPlaceBuilding({
|
||||
@@ -390,6 +485,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
rotation,
|
||||
rotationVariant,
|
||||
building: metaBuilding,
|
||||
variant: this.currentVariant.get(),
|
||||
});
|
||||
|
||||
// Fade in / out
|
||||
@@ -419,7 +515,7 @@ export class HUDBuildingPlacer extends BaseHUDPart {
|
||||
parameters.context.globalAlpha = 1;
|
||||
|
||||
// HACK to draw the entity sprite
|
||||
const previewSprite = metaBuilding.getBlueprintSprite(rotationVariant);
|
||||
const previewSprite = metaBuilding.getBlueprintSprite(rotationVariant, this.currentVariant.get());
|
||||
staticComp.origin = worldPos.divideScalar(globalConfig.tileSize).subScalars(0.5, 0.5);
|
||||
staticComp.drawSpriteOnFullEntityBounds(parameters, previewSprite);
|
||||
staticComp.origin = tile;
|
||||
|
||||
@@ -57,24 +57,14 @@ export class HUDBuildingsToolbar extends BaseHUDPart {
|
||||
const actionMapper = this.root.gameState.keyActionMapper;
|
||||
|
||||
const items = makeDiv(this.element, null, ["buildings"]);
|
||||
const iconSize = 32;
|
||||
|
||||
for (let i = 0; i < toolbarBuildings.length; ++i) {
|
||||
const metaBuilding = gMetaBuildingRegistry.findByClass(toolbarBuildings[i]);
|
||||
const binding = actionMapper.getBinding("building_" + metaBuilding.getId());
|
||||
|
||||
const dimensions = metaBuilding.getDimensions();
|
||||
const itemContainer = makeDiv(items, null, ["building"]);
|
||||
itemContainer.setAttribute("data-tilewidth", dimensions.x);
|
||||
itemContainer.setAttribute("data-tileheight", dimensions.y);
|
||||
itemContainer.setAttribute("data-icon", "building_icons/" + metaBuilding.getId() + ".png");
|
||||
|
||||
const label = makeDiv(itemContainer, null, ["label"]);
|
||||
label.innerText = metaBuilding.getName();
|
||||
|
||||
const sprite = metaBuilding.getPreviewSprite(0);
|
||||
|
||||
const spriteWrapper = makeDiv(itemContainer, null, ["iconWrap"]);
|
||||
spriteWrapper.innerHTML = sprite.getAsHTML(iconSize * dimensions.x, iconSize * dimensions.y);
|
||||
binding.add(() => this.selectBuildingForPlacement(metaBuilding));
|
||||
|
||||
this.trackClicks(itemContainer, () => this.selectBuildingForPlacement(metaBuilding), {
|
||||
|
||||
@@ -72,6 +72,11 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
|
||||
<code class="keybinding shift">ALT</code>
|
||||
<label>Reverse orientation</label>
|
||||
</div>
|
||||
|
||||
<div class="binding placementOnly">
|
||||
<code class="keybinding shift">CTRL</code>
|
||||
<label>Disable auto orientation</label>
|
||||
</div>
|
||||
` +
|
||||
(queryParamOptions.betaMode
|
||||
? `
|
||||
|
||||
@@ -5,12 +5,7 @@ import { Application } from "../../../application";
|
||||
import { SOUNDS } from "../../../platform/sound";
|
||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||
import { BaseHUDPart } from "../base_hud_part";
|
||||
import {
|
||||
Dialog,
|
||||
DialogLoading,
|
||||
DialogVideoTutorial,
|
||||
DialogOptionChooser,
|
||||
} from "../../../core/modal_dialog_elements";
|
||||
import { Dialog, DialogLoading, DialogOptionChooser } from "../../../core/modal_dialog_elements";
|
||||
import { makeDiv } from "../../../core/utils";
|
||||
|
||||
export class HUDModalDialogs extends BaseHUDPart {
|
||||
|
||||
@@ -94,7 +94,7 @@ export class HUDShapeStatisticsHandle {
|
||||
if (displayMode === enumDisplayMode.detailed) {
|
||||
const graphDpi = globalConfig.statisticsGraphDpi;
|
||||
|
||||
const w = 300;
|
||||
const w = 270;
|
||||
const h = 40;
|
||||
|
||||
if (!this.graphCanvas) {
|
||||
|
||||
Reference in New Issue
Block a user