mirror of
https://github.com/tobspr/shapez.io.git
synced 2026-02-12 19:09:21 +00:00
Mirror buildings and blueprints
This commit is contained in:
parent
66eac93460
commit
12539f8045
@ -519,6 +519,49 @@ export class Vector {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors this vector
|
||||
* @param {boolean} mirror
|
||||
* @returns {Vector} new vector
|
||||
*/
|
||||
mirror(mirror = true) {
|
||||
if (mirror) {
|
||||
return new Vector(-this.x, this.y);
|
||||
}
|
||||
else {
|
||||
return new Vector(this.x, this.y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to mirror a direction
|
||||
* @param {enumDirection} direction
|
||||
* @param {boolean} mirror
|
||||
* @returns {enumDirection}
|
||||
*/
|
||||
static mirrorDirection(direction, mirror = true) {
|
||||
if (mirror) {
|
||||
switch (direction) {
|
||||
case enumDirection.left: return enumDirection.right;
|
||||
case enumDirection.right: return enumDirection.left;
|
||||
}
|
||||
}
|
||||
return direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to mirror an angle
|
||||
* @param {number} angle
|
||||
* @param {boolean} mirror
|
||||
* @returns {number}
|
||||
*/
|
||||
static mirrorAngle(angle, mirror = true) {
|
||||
if (mirror && (angle == 90 || angle == 270) ) {
|
||||
return 360 - angle;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to rotate a direction
|
||||
* @param {enumDirection} direction
|
||||
|
||||
@ -141,7 +141,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
|
||||
* @param {string} variant
|
||||
* @return {{ rotation: number, rotationVariant: number }}
|
||||
*/
|
||||
computeOptimalDirectionAndRotationVariantAtTile(root, tile, rotation, variant) {
|
||||
computeOptimalDirectionAndRotationVariantAtTile(root, tile, rotation, mirrored, variant) {
|
||||
const topDirection = enumAngleToDirection[rotation];
|
||||
const rightDirection = enumAngleToDirection[(rotation + 90) % 360];
|
||||
const bottomDirection = enumAngleToDirection[(rotation + 180) % 360];
|
||||
@ -191,6 +191,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
|
||||
if (hasRightEjector && !hasLeftEjector) {
|
||||
return {
|
||||
rotation: (rotation + 270) % 360,
|
||||
mirrored: false,
|
||||
rotationVariant: 2,
|
||||
};
|
||||
}
|
||||
@ -200,6 +201,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
|
||||
if (hasLeftEjector && !hasRightEjector) {
|
||||
return {
|
||||
rotation: (rotation + 90) % 360,
|
||||
mirrored: false,
|
||||
rotationVariant: 1,
|
||||
};
|
||||
}
|
||||
@ -213,6 +215,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
|
||||
if (hasRightAcceptor && !hasLeftAcceptor) {
|
||||
return {
|
||||
rotation,
|
||||
mirrored: false,
|
||||
rotationVariant: 2,
|
||||
};
|
||||
}
|
||||
@ -222,6 +225,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
|
||||
if (hasLeftAcceptor && !hasRightAcceptor) {
|
||||
return {
|
||||
rotation,
|
||||
mirrored: false,
|
||||
rotationVariant: 1,
|
||||
};
|
||||
}
|
||||
@ -229,6 +233,7 @@ export class MetaBeltBaseBuilding extends MetaBuilding {
|
||||
|
||||
return {
|
||||
rotation,
|
||||
mirrored: false,
|
||||
rotationVariant: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -24,6 +24,10 @@ export class MetaHubBuilding extends MetaBuilding {
|
||||
return false;
|
||||
}
|
||||
|
||||
isMirrorable(variant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
getBlueprintSprite() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -18,6 +18,10 @@ export class MetaRotaterBuilding extends MetaBuilding {
|
||||
super("rotater");
|
||||
}
|
||||
|
||||
isMirrorable(variant) {
|
||||
return false;
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#7dc6cd";
|
||||
}
|
||||
|
||||
@ -24,6 +24,10 @@ export class MetaTrashBuilding extends MetaBuilding {
|
||||
return variant !== defaultBuildingVariant;
|
||||
}
|
||||
|
||||
isMirrorable(variant) {
|
||||
return variant !== defaultBuildingVariant;
|
||||
}
|
||||
|
||||
getSilhouetteColor() {
|
||||
return "#cd7d86";
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
* @param {string} variant
|
||||
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
|
||||
*/
|
||||
computeOptimalDirectionAndRotationVariantAtTile(root, tile, rotation, variant) {
|
||||
computeOptimalDirectionAndRotationVariantAtTile(root, tile, rotation, mirrored, variant) {
|
||||
const searchDirection = enumAngleToDirection[rotation];
|
||||
const searchVector = enumDirectionToVector[searchDirection];
|
||||
const tier = enumUndergroundBeltVariantToTier[variant];
|
||||
@ -164,6 +164,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
}
|
||||
return {
|
||||
rotation: targetRotation,
|
||||
mirrored: false,
|
||||
rotationVariant: 1,
|
||||
connectedEntities: [contents],
|
||||
};
|
||||
@ -172,6 +173,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
if (undergroundComp.mode === enumUndergroundBeltMode.receiver) {
|
||||
return {
|
||||
rotation: rotation,
|
||||
mirrored: false,
|
||||
rotationVariant: 0,
|
||||
connectedEntities: [contents],
|
||||
};
|
||||
@ -185,6 +187,7 @@ export class MetaUndergroundBeltBuilding extends MetaBuilding {
|
||||
|
||||
return {
|
||||
rotation,
|
||||
mirrored: false,
|
||||
rotationVariant: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -18,6 +18,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
tileSize: types.tileVector,
|
||||
rotation: types.float,
|
||||
originalRotation: types.float,
|
||||
mirrored: types.bool,
|
||||
spriteKey: types.nullable(types.string),
|
||||
blueprintSpriteKey: types.string,
|
||||
silhouetteColor: types.nullable(types.string),
|
||||
@ -30,6 +31,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
tileSize: this.tileSize.copy(),
|
||||
rotation: this.rotation,
|
||||
originalRotation: this.originalRotation,
|
||||
mirrored: this.mirrored,
|
||||
spriteKey: this.spriteKey,
|
||||
silhouetteColor: this.silhouetteColor,
|
||||
blueprintSpriteKey: this.blueprintSpriteKey,
|
||||
@ -52,6 +54,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
tileSize = new Vector(1, 1),
|
||||
rotation = 0,
|
||||
originalRotation = 0,
|
||||
mirrored = false,
|
||||
spriteKey = null,
|
||||
silhouetteColor = null,
|
||||
blueprintSpriteKey = null,
|
||||
@ -67,6 +70,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
this.spriteKey = spriteKey;
|
||||
this.rotation = rotation;
|
||||
this.originalRotation = originalRotation;
|
||||
this.mirrored = mirrored;
|
||||
this.silhouetteColor = silhouetteColor;
|
||||
this.blueprintSpriteKey = blueprintSpriteKey;
|
||||
}
|
||||
@ -76,32 +80,62 @@ export class StaticMapEntityComponent extends Component {
|
||||
* @returns {Rectangle}
|
||||
*/
|
||||
getTileSpaceBounds() {
|
||||
switch (this.rotation) {
|
||||
case 0:
|
||||
return new Rectangle(this.origin.x, this.origin.y, this.tileSize.x, this.tileSize.y);
|
||||
case 90:
|
||||
return new Rectangle(
|
||||
this.origin.x - this.tileSize.y + 1,
|
||||
this.origin.y,
|
||||
this.tileSize.y,
|
||||
this.tileSize.x
|
||||
);
|
||||
case 180:
|
||||
return new Rectangle(
|
||||
this.origin.x - this.tileSize.x + 1,
|
||||
this.origin.y - this.tileSize.y + 1,
|
||||
this.tileSize.x,
|
||||
this.tileSize.y
|
||||
);
|
||||
case 270:
|
||||
return new Rectangle(
|
||||
this.origin.x,
|
||||
this.origin.y - this.tileSize.x + 1,
|
||||
this.tileSize.y,
|
||||
this.tileSize.x
|
||||
);
|
||||
default:
|
||||
assert(false, "Invalid rotation");
|
||||
if (!this.mirrored) {
|
||||
switch (this.rotation) {
|
||||
case 0:
|
||||
return new Rectangle(this.origin.x, this.origin.y, this.tileSize.x, this.tileSize.y);
|
||||
case 90:
|
||||
return new Rectangle(
|
||||
this.origin.x - this.tileSize.y + 1,
|
||||
this.origin.y,
|
||||
this.tileSize.y,
|
||||
this.tileSize.x
|
||||
);
|
||||
case 180:
|
||||
return new Rectangle(
|
||||
this.origin.x - this.tileSize.x + 1,
|
||||
this.origin.y - this.tileSize.y + 1,
|
||||
this.tileSize.x,
|
||||
this.tileSize.y
|
||||
);
|
||||
case 270:
|
||||
return new Rectangle(
|
||||
this.origin.x,
|
||||
this.origin.y - this.tileSize.x + 1,
|
||||
this.tileSize.y,
|
||||
this.tileSize.x
|
||||
);
|
||||
default:
|
||||
assert(false, "Invalid rotation");
|
||||
}
|
||||
} else {
|
||||
switch (this.rotation) {
|
||||
case 0:
|
||||
return new Rectangle(this.origin.x - this.tileSize.x + 1, this.origin.y, this.tileSize.x, this.tileSize.y);
|
||||
case 90:
|
||||
return new Rectangle(
|
||||
this.origin.x - this.tileSize.y + 1,
|
||||
this.origin.y - this.tileSize.x + 1,
|
||||
this.tileSize.y,
|
||||
this.tileSize.x
|
||||
);
|
||||
case 180:
|
||||
return new Rectangle(
|
||||
this.origin.x,
|
||||
this.origin.y - this.tileSize.y + 1,
|
||||
this.tileSize.x,
|
||||
this.tileSize.y
|
||||
);
|
||||
case 270:
|
||||
return new Rectangle(
|
||||
this.origin.x,
|
||||
this.origin.y,
|
||||
this.tileSize.y,
|
||||
this.tileSize.x
|
||||
);
|
||||
default:
|
||||
assert(false, "Invalid rotation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -111,7 +145,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
* @returns {Vector}
|
||||
*/
|
||||
applyRotationToVector(vector) {
|
||||
return vector.rotateFastMultipleOf90(this.rotation);
|
||||
return vector.mirror(this.mirrored).rotateFastMultipleOf90(this.rotation);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,7 +154,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
* @returns {Vector}
|
||||
*/
|
||||
unapplyRotationToVector(vector) {
|
||||
return vector.rotateFastMultipleOf90(360 - this.rotation);
|
||||
return vector.rotateFastMultipleOf90(360 - this.rotation).mirror(this.mirrored);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -129,7 +163,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
* @returns {enumDirection}
|
||||
*/
|
||||
localDirectionToWorld(direction) {
|
||||
return Vector.transformDirectionFromMultipleOf90(direction, this.rotation);
|
||||
return Vector.transformDirectionFromMultipleOf90(Vector.mirrorDirection(direction, this.mirrored), this.rotation);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -138,7 +172,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
* @returns {enumDirection}
|
||||
*/
|
||||
worldDirectionToLocal(direction) {
|
||||
return Vector.transformDirectionFromMultipleOf90(direction, 360 - this.rotation);
|
||||
return Vector.mirrorDirection(Vector.transformDirectionFromMultipleOf90(direction, 360 - this.rotation), this.mirrored);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,49 +200,13 @@ export class StaticMapEntityComponent extends Component {
|
||||
* @param {DrawParameters} parameters
|
||||
*/
|
||||
shouldBeDrawn(parameters) {
|
||||
let x = 0;
|
||||
let y = 0;
|
||||
let w = 0;
|
||||
let h = 0;
|
||||
|
||||
switch (this.rotation) {
|
||||
case 0: {
|
||||
x = this.origin.x;
|
||||
y = this.origin.y;
|
||||
w = this.tileSize.x;
|
||||
h = this.tileSize.y;
|
||||
break;
|
||||
}
|
||||
case 90: {
|
||||
x = this.origin.x - this.tileSize.y + 1;
|
||||
y = this.origin.y;
|
||||
w = this.tileSize.y;
|
||||
h = this.tileSize.x;
|
||||
break;
|
||||
}
|
||||
case 180: {
|
||||
x = this.origin.x - this.tileSize.x + 1;
|
||||
y = this.origin.y - this.tileSize.y + 1;
|
||||
w = this.tileSize.x;
|
||||
h = this.tileSize.y;
|
||||
break;
|
||||
}
|
||||
case 270: {
|
||||
x = this.origin.x;
|
||||
y = this.origin.y - this.tileSize.x + 1;
|
||||
w = this.tileSize.y;
|
||||
h = this.tileSize.x;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false, "Invalid rotation");
|
||||
}
|
||||
const rect = this.getTileSpaceBounds();
|
||||
|
||||
return parameters.visibleRect.containsRect4Params(
|
||||
x * globalConfig.tileSize,
|
||||
y * globalConfig.tileSize,
|
||||
w * globalConfig.tileSize,
|
||||
h * globalConfig.tileSize
|
||||
rect.x * globalConfig.tileSize,
|
||||
rect.y * globalConfig.tileSize,
|
||||
rect.w * globalConfig.tileSize,
|
||||
rect.h * globalConfig.tileSize
|
||||
);
|
||||
}
|
||||
|
||||
@ -238,7 +236,7 @@ export class StaticMapEntityComponent extends Component {
|
||||
worldY = overridePosition.y * globalConfig.tileSize;
|
||||
}
|
||||
|
||||
if (this.rotation === 0) {
|
||||
if (this.rotation === 0 && this.mirrored == false) {
|
||||
// Early out, is faster
|
||||
sprite.drawCached(
|
||||
parameters,
|
||||
@ -254,6 +252,9 @@ export class StaticMapEntityComponent extends Component {
|
||||
|
||||
parameters.context.translate(rotationCenterX, rotationCenterY);
|
||||
parameters.context.rotate(Math_radians(this.rotation));
|
||||
if (this.mirrored == true) {
|
||||
parameters.context.scale(-1.0, 1.0);
|
||||
}
|
||||
|
||||
sprite.drawCached(
|
||||
parameters,
|
||||
@ -264,6 +265,9 @@ export class StaticMapEntityComponent extends Component {
|
||||
false
|
||||
);
|
||||
|
||||
if (this.mirrored == true) {
|
||||
parameters.context.scale(-1.0, 1.0);
|
||||
}
|
||||
parameters.context.rotate(-Math_radians(this.rotation));
|
||||
parameters.context.translate(-rotationCenterX, -rotationCenterY);
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import { findNiceIntegerValue } from "../../../core/utils";
|
||||
import { Math_pow } from "../../../core/builtins";
|
||||
import { blueprintShape } from "../../upgrades";
|
||||
import { globalConfig } from "../../../core/config";
|
||||
import { enumItemProcessorTypes } from "../../components/item_processor";
|
||||
|
||||
const logger = createLogger("blueprint");
|
||||
|
||||
@ -130,6 +131,36 @@ export class Blueprint {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mirrors the blueprint horizontally
|
||||
*/
|
||||
mirror() {
|
||||
for (let i = 0; i < this.entities.length; ++i) {
|
||||
const entity = this.entities[i];
|
||||
const staticComp = entity.components.StaticMapEntity;
|
||||
const beltComp = entity.components.Belt;
|
||||
const itemProcComp = entity.components.ItemProcessor;
|
||||
|
||||
staticComp.rotation = Vector.mirrorAngle(staticComp.rotation)
|
||||
staticComp.originalRotation = Vector.mirrorAngle(staticComp.originalRotation)
|
||||
staticComp.origin = staticComp.origin.mirror();
|
||||
|
||||
if (beltComp) {
|
||||
// It is a belt! Flipping the direction is enough.
|
||||
beltComp.direction = Vector.mirrorDirection( beltComp.direction );
|
||||
staticComp.blueprintSpriteKey = "sprites/blueprints/belt_" + beltComp.direction + ".png";
|
||||
} else if ( itemProcComp && (
|
||||
itemProcComp.type == enumItemProcessorTypes.rotater ||
|
||||
itemProcComp.type == enumItemProcessorTypes.rotaterCCW
|
||||
) ) {
|
||||
// Don't flip the rotater
|
||||
} else {
|
||||
staticComp.mirrored = !staticComp.mirrored;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the blueprint can be placed at the given tile
|
||||
* @param {GameRoot} root
|
||||
|
||||
@ -37,6 +37,7 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.abortPlacement, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.mirrorWhilePlacing).add(this.mirrorBlueprint, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this);
|
||||
|
||||
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
||||
@ -139,6 +140,20 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||
}
|
||||
}
|
||||
|
||||
mirrorBlueprint() {
|
||||
if (this.currentBlueprint.get()) {
|
||||
if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) {
|
||||
// Mirror vertically
|
||||
this.currentBlueprint.get().rotateCw();
|
||||
this.currentBlueprint.get().mirror();
|
||||
this.currentBlueprint.get().rotateCcw();
|
||||
} else {
|
||||
// Mirror horizontally
|
||||
this.currentBlueprint.get().mirror();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pasteBlueprint() {
|
||||
if (this.lastBlueprintUsed !== null) {
|
||||
this.root.hud.signals.pasteBlueprintRequested.dispatch();
|
||||
|
||||
@ -229,11 +229,13 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
const {
|
||||
rotation,
|
||||
rotationVariant,
|
||||
mirrored,
|
||||
connectedEntities,
|
||||
} = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile(
|
||||
this.root,
|
||||
mouseTile,
|
||||
this.currentBaseRotation,
|
||||
this.currentMirrored,
|
||||
this.currentVariant.get()
|
||||
);
|
||||
|
||||
@ -272,6 +274,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
const staticComp = this.fakeEntity.components.StaticMapEntity;
|
||||
staticComp.origin = mouseTile;
|
||||
staticComp.rotation = rotation;
|
||||
staticComp.mirrored = mirrored;
|
||||
staticComp.tileSize = metaBuilding.getDimensions(this.currentVariant.get());
|
||||
metaBuilding.updateVariants(this.fakeEntity, rotationVariant, this.currentVariant.get());
|
||||
|
||||
@ -280,6 +283,7 @@ export class HUDBuildingPlacer extends HUDBuildingPlacerLogic {
|
||||
origin: mouseTile,
|
||||
rotation,
|
||||
rotationVariant,
|
||||
mirrored,
|
||||
building: metaBuilding,
|
||||
variant: this.currentVariant.get(),
|
||||
});
|
||||
|
||||
@ -56,6 +56,12 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
||||
*/
|
||||
this.preferredBaseRotations = {};
|
||||
|
||||
/**
|
||||
* The current mirror state
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.currentMirrored = false;
|
||||
|
||||
/**
|
||||
* Whether we are currently dragging
|
||||
* @type {boolean}
|
||||
@ -103,6 +109,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
||||
// KEYBINDINGS
|
||||
const keyActionMapper = this.root.keyMapper;
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.tryRotate, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.mirrorWhilePlacing).add(this.tryMirror, this);
|
||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.cycleBuildingVariants).add(this.cycleVariants, this);
|
||||
keyActionMapper
|
||||
.getBinding(KEYMAPPINGS.placement.switchDirectionLockSide)
|
||||
@ -265,6 +272,25 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
||||
staticComp.rotation = this.currentBaseRotation;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Tries to mirror the current building
|
||||
*/
|
||||
tryMirror() {
|
||||
const selectedBuilding = this.currentMetaBuilding.get();
|
||||
if (selectedBuilding) {
|
||||
this.currentMirrored = !this.currentMirrored;
|
||||
this.currentBaseRotation = Vector.mirrorAngle(this.currentBaseRotation);
|
||||
const staticComp = this.fakeEntity.components.StaticMapEntity;
|
||||
staticComp.mirrored = this.currentMirrored;
|
||||
staticComp.rotation = this.currentBaseRotation;
|
||||
|
||||
if (this.root.keyMapper.getBinding(KEYMAPPINGS.placement.rotateInverseModifier).pressed) {
|
||||
// Rotate twice to get a vertical mirroring
|
||||
this.tryRotate();
|
||||
this.tryRotate();
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Tries to delete the building under the mouse
|
||||
*/
|
||||
@ -331,6 +357,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
||||
this.currentMetaBuilding.set(extracted.metaBuilding);
|
||||
this.currentVariant.set(extracted.variant);
|
||||
this.currentBaseRotation = contents.components.StaticMapEntity.rotation;
|
||||
this.currentMirrored = contents.components.StaticMapEntity.mirrored;
|
||||
|
||||
// Make sure we selected something, and also make sure it's not a special entity
|
||||
// if (contents && !contents.components.Unremovable) {
|
||||
@ -444,10 +471,11 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
||||
}
|
||||
|
||||
const metaBuilding = this.currentMetaBuilding.get();
|
||||
const { rotation, rotationVariant } = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile(
|
||||
const { rotation, rotationVariant, mirrored } = metaBuilding.computeOptimalDirectionAndRotationVariantAtTile(
|
||||
this.root,
|
||||
tile,
|
||||
this.currentBaseRotation,
|
||||
this.currentMirrored,
|
||||
this.currentVariant.get()
|
||||
);
|
||||
|
||||
@ -456,6 +484,7 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
||||
rotation,
|
||||
rotationVariant,
|
||||
originalRotation: this.currentBaseRotation,
|
||||
mirrored,
|
||||
building: this.currentMetaBuilding.get(),
|
||||
variant: this.currentVariant.get(),
|
||||
});
|
||||
|
||||
@ -207,6 +207,13 @@ export class HUDKeybindingOverlay extends BaseHUDPart {
|
||||
condition: () => this.anyPlacementActive && !this.beltPlannerActive,
|
||||
},
|
||||
|
||||
{
|
||||
// Mirror
|
||||
label: T.ingame.keybindingsOverlay.mirrorBuilding,
|
||||
keys: [k.placement.mirrorWhilePlacing],
|
||||
condition: () => this.anyPlacementActive && !this.beltPlannerActive,
|
||||
},
|
||||
|
||||
{
|
||||
// [BELT PLANNER] Flip Side
|
||||
label: T.ingame.keybindingsOverlay.plannerSwitchSide,
|
||||
|
||||
@ -61,6 +61,7 @@ export const KEYMAPPINGS = {
|
||||
placement: {
|
||||
pipette: { keyCode: key("Q") },
|
||||
rotateWhilePlacing: { keyCode: key("R") },
|
||||
mirrorWhilePlacing: { keyCode: key("N") },
|
||||
rotateInverseModifier: { keyCode: 16 }, // SHIFT
|
||||
cycleBuildingVariants: { keyCode: key("T") },
|
||||
cycleBuildings: { keyCode: 9 }, // TAB
|
||||
|
||||
@ -56,11 +56,12 @@ export class GameLogic {
|
||||
* @param {MetaBuilding} param0.building
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isAreaFreeToBuild({ origin, rotation, rotationVariant, variant, building }) {
|
||||
isAreaFreeToBuild({ origin, rotation, mirrored, rotationVariant, variant, building }) {
|
||||
const checker = new StaticMapEntityComponent({
|
||||
origin,
|
||||
tileSize: building.getDimensions(variant),
|
||||
rotation,
|
||||
mirrored,
|
||||
blueprintSpriteKey: "",
|
||||
});
|
||||
|
||||
@ -76,6 +77,7 @@ export class GameLogic {
|
||||
origin,
|
||||
building,
|
||||
rotation,
|
||||
mirrored,
|
||||
rotationVariant,
|
||||
})
|
||||
) {
|
||||
@ -95,10 +97,11 @@ export class GameLogic {
|
||||
* @param {Vector} param0.origin
|
||||
* @param {number} param0.rotation
|
||||
* @param {number} param0.rotationVariant
|
||||
* @param {boolean} param0.mirrored
|
||||
* @param {MetaBuilding} param0.building
|
||||
* @returns {boolean}
|
||||
*/
|
||||
checkCanReplaceBuilding({ original, origin, building, rotation, rotationVariant }) {
|
||||
checkCanReplaceBuilding({ original, origin, building, rotation, mirrored, rotationVariant }) {
|
||||
if (!original.components.ReplaceableMapEntity) {
|
||||
// Can not get replaced at all
|
||||
return false;
|
||||
@ -128,7 +131,7 @@ export class GameLogic {
|
||||
* @param {string} param0.variant
|
||||
* @param {MetaBuilding} param0.building
|
||||
*/
|
||||
checkCanPlaceBuilding({ origin, rotation, rotationVariant, variant, building }) {
|
||||
checkCanPlaceBuilding({ origin, rotation, mirrored, rotationVariant, variant, building }) {
|
||||
if (!building.getIsUnlocked(this.root)) {
|
||||
return false;
|
||||
}
|
||||
@ -136,6 +139,7 @@ export class GameLogic {
|
||||
return this.isAreaFreeToBuild({
|
||||
origin,
|
||||
rotation,
|
||||
mirrored,
|
||||
rotationVariant,
|
||||
variant,
|
||||
building,
|
||||
@ -153,13 +157,14 @@ export class GameLogic {
|
||||
* @param {MetaBuilding} param0.building
|
||||
* @returns {Entity}
|
||||
*/
|
||||
tryPlaceBuilding({ origin, rotation, rotationVariant, originalRotation, variant, building }) {
|
||||
if (this.checkCanPlaceBuilding({ origin, rotation, rotationVariant, variant, building })) {
|
||||
tryPlaceBuilding({ origin, rotation, rotationVariant, originalRotation, mirrored, variant, building }) {
|
||||
if (this.checkCanPlaceBuilding({ origin, rotation, mirrored, rotationVariant, variant, building })) {
|
||||
// Remove any removeable entities below
|
||||
const checker = new StaticMapEntityComponent({
|
||||
origin,
|
||||
tileSize: building.getDimensions(variant),
|
||||
rotation,
|
||||
mirrored,
|
||||
blueprintSpriteKey: "",
|
||||
});
|
||||
|
||||
@ -182,6 +187,7 @@ export class GameLogic {
|
||||
origin,
|
||||
rotation,
|
||||
rotationVariant,
|
||||
mirrored,
|
||||
originalRotation,
|
||||
variant,
|
||||
});
|
||||
|
||||
@ -129,6 +129,15 @@ export class MetaBuilding {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this building can be mirrored
|
||||
* @param {string} variant
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isMirrorable(variant) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether this building is unlocked for the given game
|
||||
* @param {GameRoot} root
|
||||
@ -151,15 +160,17 @@ export class MetaBuilding {
|
||||
* @param {Vector} param0.origin Origin tile
|
||||
* @param {number=} param0.rotation Rotation
|
||||
* @param {number} param0.originalRotation Original Rotation
|
||||
* @param {boolean} param0.mirrored
|
||||
* @param {number} param0.rotationVariant Rotation variant
|
||||
* @param {string} param0.variant
|
||||
*/
|
||||
createAndPlaceEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
|
||||
createAndPlaceEntity({ root, origin, rotation, originalRotation, mirrored, rotationVariant, variant }) {
|
||||
const entity = this.createEntity({
|
||||
root,
|
||||
origin,
|
||||
rotation,
|
||||
originalRotation,
|
||||
mirrored,
|
||||
rotationVariant,
|
||||
variant,
|
||||
});
|
||||
@ -175,10 +186,11 @@ export class MetaBuilding {
|
||||
* @param {Vector} param0.origin Origin tile
|
||||
* @param {number=} param0.rotation Rotation
|
||||
* @param {number} param0.originalRotation Original Rotation
|
||||
* @param {boolean} param0.mirrored
|
||||
* @param {number} param0.rotationVariant Rotation variant
|
||||
* @param {string} param0.variant
|
||||
*/
|
||||
createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
|
||||
createEntity({ root, origin, rotation, originalRotation, mirrored, rotationVariant, variant }) {
|
||||
const entity = new Entity(root);
|
||||
const blueprintSprite = this.getBlueprintSprite(rotationVariant, variant);
|
||||
entity.addComponent(
|
||||
@ -191,6 +203,7 @@ export class MetaBuilding {
|
||||
origin: new Vector(origin.x, origin.y),
|
||||
rotation,
|
||||
originalRotation,
|
||||
mirrored,
|
||||
tileSize: this.getDimensions(variant).copy(),
|
||||
silhouetteColor: this.getSilhouetteColor(),
|
||||
blueprintSpriteKey: blueprintSprite ? blueprintSprite.spriteName : "",
|
||||
@ -207,17 +220,18 @@ export class MetaBuilding {
|
||||
* @param {Vector} tile
|
||||
* @param {number} rotation
|
||||
* @param {string} variant
|
||||
* @return {{ rotation: number, rotationVariant: number, connectedEntities?: Array<Entity> }}
|
||||
* @return {{ rotation: number, rotationVariant: number, mirrored: boolean, connectedEntities?: Array<Entity> }}
|
||||
*/
|
||||
computeOptimalDirectionAndRotationVariantAtTile(root, tile, rotation, variant) {
|
||||
computeOptimalDirectionAndRotationVariantAtTile(root, tile, rotation, mirrored, variant) {
|
||||
if (!this.isRotateable(variant)) {
|
||||
return {
|
||||
rotation: 0,
|
||||
rotationVariant: 0,
|
||||
};
|
||||
rotation = 0;
|
||||
}
|
||||
if (!this.isMirrorable(variant)) {
|
||||
mirrored = false;
|
||||
}
|
||||
return {
|
||||
rotation,
|
||||
mirrored,
|
||||
rotationVariant: 0,
|
||||
};
|
||||
}
|
||||
|
||||
@ -100,6 +100,7 @@ export class BeltSystem extends GameSystemWithFilter {
|
||||
this.root,
|
||||
new Vector(x, y),
|
||||
targetStaticComp.originalRotation,
|
||||
false,
|
||||
defaultBuildingVariant
|
||||
);
|
||||
targetStaticComp.rotation = rotation;
|
||||
|
||||
@ -311,11 +311,9 @@ export class ItemEjectorSystem extends GameSystemWithFilter {
|
||||
continue;
|
||||
}
|
||||
|
||||
const realPosition = slot.pos.rotateFastMultipleOf90(staticComp.rotation);
|
||||
const realDirection = Vector.transformDirectionFromMultipleOf90(
|
||||
slot.direction,
|
||||
staticComp.rotation
|
||||
);
|
||||
const realPosition = staticComp.applyRotationToVector(slot.pos);
|
||||
const realDirection = staticComp.localDirectionToWorld(slot.direction);
|
||||
|
||||
const realDirectionVector = enumDirectionToVector[realDirection];
|
||||
|
||||
const tileX =
|
||||
|
||||
@ -276,6 +276,7 @@ ingame:
|
||||
selectBuildings: Select area
|
||||
stopPlacement: Stop placement
|
||||
rotateBuilding: Rotate building
|
||||
mirrorBuilding: Mirror building
|
||||
placeMultiple: Place multiple
|
||||
reverseOrientation: Reverse orientation
|
||||
disableAutoOrientation: Disable auto orientation
|
||||
@ -802,6 +803,7 @@ keybindings:
|
||||
|
||||
pipette: Pipette
|
||||
rotateWhilePlacing: Rotate
|
||||
mirrorWhilePlacing: Mirror
|
||||
rotateInverseModifier: >-
|
||||
Modifier: Rotate CCW instead
|
||||
cycleBuildingVariants: Cycle Variants
|
||||
|
||||
Loading…
Reference in New Issue
Block a user