mirror of
https://github.com/tobspr/shapez.io.git
synced 2024-10-27 20:34:29 +00:00
Improve pipette
This commit is contained in:
parent
5b2df00cc7
commit
d907dbb191
@ -76,7 +76,6 @@ export class GameHUD {
|
|||||||
shapeUnpinRequested: /** @type {TypedSignal<[string]>} */ (new Signal()),
|
shapeUnpinRequested: /** @type {TypedSignal<[string]>} */ (new Signal()),
|
||||||
notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()),
|
notification: /** @type {TypedSignal<[string, enumNotificationType]>} */ (new Signal()),
|
||||||
buildingsSelectedForCopy: /** @type {TypedSignal<[Array<number>]>} */ (new Signal()),
|
buildingsSelectedForCopy: /** @type {TypedSignal<[Array<number>]>} */ (new Signal()),
|
||||||
pipetteExecuted: /** @type {TypedSignal<[Entity]>} */ (new Signal()),
|
|
||||||
pasteBlueprintRequested: new Signal(),
|
pasteBlueprintRequested: new Signal(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,16 +1,15 @@
|
|||||||
import { DrawParameters } from "../../../core/draw_parameters";
|
import { DrawParameters } from "../../../core/draw_parameters";
|
||||||
import { STOP_PROPAGATION } from "../../../core/signal";
|
import { STOP_PROPAGATION } from "../../../core/signal";
|
||||||
import { TrackedState } from "../../../core/tracked_state";
|
import { TrackedState } from "../../../core/tracked_state";
|
||||||
|
import { makeDiv } from "../../../core/utils";
|
||||||
import { Vector } from "../../../core/vector";
|
import { Vector } from "../../../core/vector";
|
||||||
|
import { T } from "../../../translations";
|
||||||
import { enumMouseButton } from "../../camera";
|
import { enumMouseButton } from "../../camera";
|
||||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
|
||||||
import { Blueprint } from "./blueprint";
|
|
||||||
import { makeDiv } from "../../../core/utils";
|
|
||||||
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
|
||||||
import { blueprintShape } from "../../upgrades";
|
import { blueprintShape } from "../../upgrades";
|
||||||
import { T } from "../../../translations";
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { PipetteBlueprint } from "./pipette_blueprint";
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
|
import { Blueprint } from "./blueprint";
|
||||||
|
|
||||||
export class HUDBlueprintPlacer extends BaseHUDPart {
|
export class HUDBlueprintPlacer extends BaseHUDPart {
|
||||||
createElements(parent) {
|
createElements(parent) {
|
||||||
@ -37,7 +36,6 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
|
|||||||
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.placement.rotateWhilePlacing).add(this.rotateBlueprint, this);
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.massSelect.pasteLastBlueprint).add(this.pasteBlueprint, this);
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.startPipette, this);
|
|
||||||
|
|
||||||
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
this.root.camera.downPreHandler.add(this.onMouseDown, this);
|
||||||
this.root.camera.movePreHandler.add(this.onMouseMove, this);
|
this.root.camera.movePreHandler.add(this.onMouseMove, this);
|
||||||
@ -56,37 +54,6 @@ export class HUDBlueprintPlacer extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts the pipette function
|
|
||||||
*/
|
|
||||||
startPipette() {
|
|
||||||
// Disable in overview
|
|
||||||
if (this.root.camera.getIsMapOverlayActive()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const mousePosition = this.root.app.mousePosition;
|
|
||||||
if (!mousePosition) {
|
|
||||||
// Not on screen
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
|
||||||
const tile = worldPos.toTileSpace();
|
|
||||||
const contents = this.root.map.getTileContent(tile);
|
|
||||||
|
|
||||||
// Make sure we selected something, and also make sure it's not a special entity
|
|
||||||
if (contents && !contents.components.Unremovable && !contents.components.Belt) {
|
|
||||||
const blueprint = PipetteBlueprint.fromEntity(contents);
|
|
||||||
|
|
||||||
// Notice: Order here matters, since pipetteExecuted clears the blueprint
|
|
||||||
this.root.hud.signals.pipetteExecuted.dispatch(contents);
|
|
||||||
this.currentBlueprint.set(blueprint);
|
|
||||||
} else {
|
|
||||||
this.root.hud.signals.pipetteExecuted.dispatch(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onCanAffordChanged(canAfford) {
|
onCanAffordChanged(canAfford) {
|
||||||
this.costDisplayParent.classList.toggle("canAfford", canAfford);
|
this.costDisplayParent.classList.toggle("canAfford", canAfford);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Math_abs, Math_degrees, Math_round } from "../../../core/builtins";
|
import { Math_abs, Math_degrees, Math_round } from "../../../core/builtins";
|
||||||
import { globalConfig } from "../../../core/config";
|
import { globalConfig } from "../../../core/config";
|
||||||
|
import { gMetaBuildingRegistry } from "../../../core/global_registries";
|
||||||
import { Signal, STOP_PROPAGATION } from "../../../core/signal";
|
import { Signal, STOP_PROPAGATION } from "../../../core/signal";
|
||||||
import { TrackedState } from "../../../core/tracked_state";
|
import { TrackedState } from "../../../core/tracked_state";
|
||||||
import { Vector } from "../../../core/vector";
|
import { Vector } from "../../../core/vector";
|
||||||
@ -9,7 +10,6 @@ import { Entity } from "../../entity";
|
|||||||
import { KEYMAPPINGS } from "../../key_action_mapper";
|
import { KEYMAPPINGS } from "../../key_action_mapper";
|
||||||
import { defaultBuildingVariant, MetaBuilding } from "../../meta_building";
|
import { defaultBuildingVariant, MetaBuilding } from "../../meta_building";
|
||||||
import { BaseHUDPart } from "../base_hud_part";
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
import { lerp } from "../../../core/utils";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains all logic for the building placer - this doesn't include the rendering
|
* Contains all logic for the building placer - this doesn't include the rendering
|
||||||
@ -98,12 +98,12 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
|||||||
.getBinding(KEYMAPPINGS.placement.switchDirectionLockSide)
|
.getBinding(KEYMAPPINGS.placement.switchDirectionLockSide)
|
||||||
.add(this.switchDirectionLockSide, this);
|
.add(this.switchDirectionLockSide, this);
|
||||||
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.abortPlacement, this);
|
||||||
|
keyActionMapper.getBinding(KEYMAPPINGS.placement.pipette).add(this.startPipette, this);
|
||||||
this.root.gameState.inputReciever.keyup.add(this.checkForDirectionLockSwitch, this);
|
this.root.gameState.inputReciever.keyup.add(this.checkForDirectionLockSwitch, this);
|
||||||
|
|
||||||
// BINDINGS TO GAME EVENTS
|
// BINDINGS TO GAME EVENTS
|
||||||
this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this);
|
this.root.hud.signals.buildingsSelectedForCopy.add(this.abortPlacement, this);
|
||||||
this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this);
|
this.root.hud.signals.pasteBlueprintRequested.add(this.abortPlacement, this);
|
||||||
this.root.hud.signals.pipetteExecuted.add(this.abortPlacement, this);
|
|
||||||
this.root.signals.storyGoalCompleted.add(() => this.signals.variantChanged.dispatch());
|
this.root.signals.storyGoalCompleted.add(() => this.signals.variantChanged.dispatch());
|
||||||
this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch());
|
this.root.signals.upgradePurchased.add(() => this.signals.variantChanged.dispatch());
|
||||||
|
|
||||||
@ -218,6 +218,125 @@ export class HUDBuildingPlacerLogic extends BaseHUDPart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the pipette function
|
||||||
|
*/
|
||||||
|
startPipette() {
|
||||||
|
// Disable in overview
|
||||||
|
if (this.root.camera.getIsMapOverlayActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const mousePosition = this.root.app.mousePosition;
|
||||||
|
if (!mousePosition) {
|
||||||
|
// Not on screen
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||||
|
const tile = worldPos.toTileSpace();
|
||||||
|
const contents = this.root.map.getTileContent(tile);
|
||||||
|
|
||||||
|
if (!contents) {
|
||||||
|
this.currentMetaBuilding.set(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to extract the building
|
||||||
|
const extracted = this.hack_reconstructMetaBuildingAndVariantFromBuilding(contents);
|
||||||
|
if (!extracted) {
|
||||||
|
this.currentMetaBuilding.set(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.currentMetaBuilding.set(extracted.metaBuilding);
|
||||||
|
this.currentVariant.set(extracted.variant);
|
||||||
|
this.currentBaseRotation = contents.components.StaticMapEntity.rotation;
|
||||||
|
|
||||||
|
// Make sure we selected something, and also make sure it's not a special entity
|
||||||
|
// if (contents && !contents.components.Unremovable) {
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HACK!
|
||||||
|
*
|
||||||
|
* This attempts to reconstruct the meta building and its variant from a given entity
|
||||||
|
* @param {Entity} entity
|
||||||
|
* @returns {{ metaBuilding: MetaBuilding, variant: string }}
|
||||||
|
*/
|
||||||
|
hack_reconstructMetaBuildingAndVariantFromBuilding(entity) {
|
||||||
|
if (entity.components.Hub) {
|
||||||
|
// Hub is not copyable
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const matches = [];
|
||||||
|
const metaBuildings = gMetaBuildingRegistry.entries;
|
||||||
|
for (let i = 0; i < metaBuildings.length; ++i) {
|
||||||
|
const metaBuilding = metaBuildings[i];
|
||||||
|
const availableVariants = metaBuilding.getAvailableVariants(this.root);
|
||||||
|
checkVariant: for (let k = 0; k < availableVariants.length; ++k) {
|
||||||
|
const variant = availableVariants[k];
|
||||||
|
let unplaced = metaBuilding.createEntity({
|
||||||
|
root: this.root,
|
||||||
|
variant,
|
||||||
|
origin: new Vector(0, 0),
|
||||||
|
rotation: 0,
|
||||||
|
originalRotation: 0,
|
||||||
|
rotationVariant: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Compare if both entities share the same components
|
||||||
|
for (let component in entity.components) {
|
||||||
|
if ((entity.components[component] == null) !== (unplaced.components[component] == null)) {
|
||||||
|
continue checkVariant;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for same item processor
|
||||||
|
if (
|
||||||
|
entity.components.ItemProcessor &&
|
||||||
|
entity.components.ItemProcessor.type != unplaced.components.ItemProcessor.type
|
||||||
|
) {
|
||||||
|
continue checkVariant;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for underground belt
|
||||||
|
if (
|
||||||
|
entity.components.UndergroundBelt &&
|
||||||
|
entity.components.UndergroundBelt.tier != unplaced.components.UndergroundBelt.tier
|
||||||
|
) {
|
||||||
|
continue checkVariant;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for same sprite key - except for underground belts
|
||||||
|
// since the sprite may vary here
|
||||||
|
if (
|
||||||
|
!entity.components.UndergroundBelt &&
|
||||||
|
entity.components.StaticMapEntity.spriteKey !=
|
||||||
|
unplaced.components.StaticMapEntity.spriteKey
|
||||||
|
) {
|
||||||
|
continue checkVariant;
|
||||||
|
}
|
||||||
|
matches.push({ metaBuilding, variant });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matches.length == 1) {
|
||||||
|
const staticEntity = entity.components.StaticMapEntity;
|
||||||
|
const key = staticEntity.spriteKey || staticEntity.blueprintSpriteKey;
|
||||||
|
assert(
|
||||||
|
key &&
|
||||||
|
key.includes(matches[0].metaBuilding.id) &&
|
||||||
|
(matches[0].variant === defaultBuildingVariant || key.includes(matches[0].variant))
|
||||||
|
);
|
||||||
|
return matches[0];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
switchDirectionLockSide() {
|
switchDirectionLockSide() {
|
||||||
this.currentDirectionLockSide = 1 - this.currentDirectionLockSide;
|
this.currentDirectionLockSide = 1 - this.currentDirectionLockSide;
|
||||||
}
|
}
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
import { Vector } from "../../../core/vector";
|
|
||||||
import { Entity } from "../../entity";
|
|
||||||
import { Blueprint } from "./blueprint";
|
|
||||||
|
|
||||||
export class PipetteBlueprint extends Blueprint {
|
|
||||||
/**
|
|
||||||
* @see Blueprint.getCost
|
|
||||||
*/
|
|
||||||
getCost() {
|
|
||||||
// Its free
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new pipetted blueprint from a given entity
|
|
||||||
* @param {Entity} entity
|
|
||||||
*/
|
|
||||||
static fromEntity(entity) {
|
|
||||||
const clone = entity.duplicateWithoutContents();
|
|
||||||
clone.components.StaticMapEntity.origin = new Vector(0, 0);
|
|
||||||
return new PipetteBlueprint([clone]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -147,10 +147,32 @@ export class MetaBuilding {
|
|||||||
* @param {string} param0.variant
|
* @param {string} param0.variant
|
||||||
*/
|
*/
|
||||||
createAndPlaceEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
|
createAndPlaceEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
|
||||||
|
const entity = this.createEntity({
|
||||||
|
root,
|
||||||
|
origin,
|
||||||
|
rotation,
|
||||||
|
originalRotation,
|
||||||
|
rotationVariant,
|
||||||
|
variant,
|
||||||
|
});
|
||||||
|
root.map.placeStaticEntity(entity);
|
||||||
|
root.entityMgr.registerEntity(entity);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the entity without placing it
|
||||||
|
* @param {object} param0
|
||||||
|
* @param {GameRoot} param0.root
|
||||||
|
* @param {Vector} param0.origin Origin tile
|
||||||
|
* @param {number=} param0.rotation Rotation
|
||||||
|
* @param {number} param0.originalRotation Original Rotation
|
||||||
|
* @param {number} param0.rotationVariant Rotation variant
|
||||||
|
* @param {string} param0.variant
|
||||||
|
*/
|
||||||
|
createEntity({ root, origin, rotation, originalRotation, rotationVariant, variant }) {
|
||||||
const entity = new Entity(root);
|
const entity = new Entity(root);
|
||||||
|
|
||||||
const blueprintSprite = this.getBlueprintSprite(rotationVariant, variant);
|
const blueprintSprite = this.getBlueprintSprite(rotationVariant, variant);
|
||||||
|
|
||||||
entity.addComponent(
|
entity.addComponent(
|
||||||
new StaticMapEntityComponent({
|
new StaticMapEntityComponent({
|
||||||
spriteKey:
|
spriteKey:
|
||||||
@ -166,12 +188,8 @@ export class MetaBuilding {
|
|||||||
blueprintSpriteKey: blueprintSprite ? blueprintSprite.spriteName : "",
|
blueprintSpriteKey: blueprintSprite ? blueprintSprite.spriteName : "",
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
this.setupEntityComponents(entity, root);
|
this.setupEntityComponents(entity, root);
|
||||||
this.updateVariants(entity, rotationVariant, variant);
|
this.updateVariants(entity, rotationVariant, variant);
|
||||||
|
|
||||||
root.map.placeStaticEntity(entity);
|
|
||||||
root.entityMgr.registerEntity(entity);
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user