1
0
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:
Gerd Wachsmuth 2020-06-25 20:33:01 +02:00
parent 66eac93460
commit 12539f8045
18 changed files with 268 additions and 93 deletions

View File

@ -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

View File

@ -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,
};
}

View File

@ -24,6 +24,10 @@ export class MetaHubBuilding extends MetaBuilding {
return false;
}
isMirrorable(variant) {
return false;
}
getBlueprintSprite() {
return null;
}

View File

@ -18,6 +18,10 @@ export class MetaRotaterBuilding extends MetaBuilding {
super("rotater");
}
isMirrorable(variant) {
return false;
}
getSilhouetteColor() {
return "#7dc6cd";
}

View File

@ -24,6 +24,10 @@ export class MetaTrashBuilding extends MetaBuilding {
return variant !== defaultBuildingVariant;
}
isMirrorable(variant) {
return variant !== defaultBuildingVariant;
}
getSilhouetteColor() {
return "#cd7d86";
}

View File

@ -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,
};
}

View File

@ -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);
}

View File

@ -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

View File

@ -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();

View File

@ -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(),
});

View File

@ -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(),
});

View File

@ -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,

View File

@ -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

View File

@ -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,
});

View File

@ -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,
};
}

View File

@ -100,6 +100,7 @@ export class BeltSystem extends GameSystemWithFilter {
this.root,
new Vector(x, y),
targetStaticComp.originalRotation,
false,
defaultBuildingVariant
);
targetStaticComp.rotation = rotation;

View File

@ -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 =

View File

@ -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