parent
f204189fdb
commit
9a67115ba7
After Width: | Height: | Size: 577 B |
@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:1dc8775fdf5155097d6e1d60a436f48916af56eec14fb9034e71b32ad3b6f1b0
|
||||||
|
size 358896
|
@ -0,0 +1,18 @@
|
|||||||
|
#ingame_HUD_ColorBlindBelowTileHelper {
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
@include SuperSmallText;
|
||||||
|
color: #fff;
|
||||||
|
background: $ingameHudBg;
|
||||||
|
@include S(padding, 5px);
|
||||||
|
@include S(top, 20px);
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&:not(.visible) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@include DarkThemeInvert;
|
||||||
|
}
|
@ -0,0 +1,131 @@
|
|||||||
|
#ingame_HUD_ShapeViewer {
|
||||||
|
.dialogInner {
|
||||||
|
@include S(width, 160px);
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
justify-items: center;
|
||||||
|
|
||||||
|
.seperator {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.layer {
|
||||||
|
position: relative;
|
||||||
|
background: #eee;
|
||||||
|
|
||||||
|
@include DarkThemeOverride {
|
||||||
|
background: rgba(0, 10, 20, 0.2);
|
||||||
|
}
|
||||||
|
@include S(width, 150px);
|
||||||
|
@include S(height, 100px);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
> canvas {
|
||||||
|
@include S(width, 50px);
|
||||||
|
@include S(height, 50px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.quad {
|
||||||
|
position: absolute;
|
||||||
|
width: 50%;
|
||||||
|
height: 50%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
$arrowDims: 23px;
|
||||||
|
$spacing: 9px;
|
||||||
|
@include S(padding, 6px);
|
||||||
|
|
||||||
|
.colorLabel {
|
||||||
|
text-transform: uppercase;
|
||||||
|
@include SuperSmallText;
|
||||||
|
@include S(font-size, 9px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.emptyLabel {
|
||||||
|
text-transform: uppercase;
|
||||||
|
@include SuperSmallText;
|
||||||
|
@include S(font-size, 9px);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: " ";
|
||||||
|
background: rgba(0, 10, 20, 0.5);
|
||||||
|
@include S(width, $arrowDims);
|
||||||
|
@include S(height, 1px);
|
||||||
|
position: absolute;
|
||||||
|
transform: rotate(45deg);
|
||||||
|
transform-origin: 50% 50%;
|
||||||
|
}
|
||||||
|
@include DarkThemeOverride {
|
||||||
|
&::after {
|
||||||
|
background: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.quad-0 {
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
@include S(left, $spacing);
|
||||||
|
@include S(bottom, $arrowDims / 2 + $spacing);
|
||||||
|
transform: rotate(-45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.quad-1 {
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: flex-end;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
@include S(left, $spacing);
|
||||||
|
@include S(top, $arrowDims / 2 + $spacing);
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.quad-2 {
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
align-items: flex-end;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
@include S(right, $spacing);
|
||||||
|
@include S(top, $arrowDims / 2 + $spacing);
|
||||||
|
transform: rotate(135deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&.quad-3 {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
|
||||||
|
align-items: flex-start;
|
||||||
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
@include S(right, $spacing);
|
||||||
|
@include S(bottom, $arrowDims / 2 + $spacing);
|
||||||
|
transform: rotate(225deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
|
import { makeDiv } from "../../../core/utils";
|
||||||
|
import { TrackedState } from "../../../core/tracked_state";
|
||||||
|
import { enumColors } from "../../colors";
|
||||||
|
import { ColorItem } from "../../items/color_item";
|
||||||
|
import { DrawParameters } from "../../../core/draw_parameters";
|
||||||
|
import { THEME } from "../../theme";
|
||||||
|
import { globalConfig } from "../../../core/config";
|
||||||
|
import { T } from "../../../translations";
|
||||||
|
|
||||||
|
export class HUDColorBlindHelper extends BaseHUDPart {
|
||||||
|
createElements(parent) {
|
||||||
|
this.belowTileIndicator = makeDiv(parent, "ingame_HUD_ColorBlindBelowTileHelper", []);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
this.trackedColorBelowTile = new TrackedState(this.onColorBelowTileChanged, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the color below the current tile changed
|
||||||
|
* @param {enumColors|null} color
|
||||||
|
*/
|
||||||
|
onColorBelowTileChanged(color) {
|
||||||
|
this.belowTileIndicator.classList.toggle("visible", !!color);
|
||||||
|
if (color) {
|
||||||
|
this.belowTileIndicator.innerText = T.ingame.colors[color];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes the color below the current tile
|
||||||
|
* @returns {enumColors}
|
||||||
|
*/
|
||||||
|
computeColorBelowTile() {
|
||||||
|
const mousePosition = this.root.app.mousePosition;
|
||||||
|
if (!mousePosition) {
|
||||||
|
// Not on screen
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||||
|
const tile = worldPos.toTileSpace();
|
||||||
|
const contents = this.root.map.getTileContent(tile);
|
||||||
|
|
||||||
|
if (contents && !contents.components.Miner) {
|
||||||
|
const beltComp = contents.components.Belt;
|
||||||
|
|
||||||
|
// Check if the belt has a color item
|
||||||
|
if (beltComp) {
|
||||||
|
const firstItem = beltComp.sortedItems[0];
|
||||||
|
if (firstItem && firstItem[1] instanceof ColorItem) {
|
||||||
|
return firstItem[1].color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we are ejecting an item, if so use that color
|
||||||
|
const ejectorComp = contents.components.ItemEjector;
|
||||||
|
if (ejectorComp) {
|
||||||
|
for (let i = 0; i < ejectorComp.slots.length; ++i) {
|
||||||
|
const slot = ejectorComp.slots[i];
|
||||||
|
if (slot.item && slot.item instanceof ColorItem) {
|
||||||
|
return slot.item.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We hovered a lower layer, show the color there
|
||||||
|
const lowerLayer = this.root.map.getLowerLayerContentXY(tile.x, tile.y);
|
||||||
|
if (lowerLayer && lowerLayer instanceof ColorItem) {
|
||||||
|
return lowerLayer.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.trackedColorBelowTile.set(this.computeColorBelowTile());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws the currently selected tile
|
||||||
|
* @param {DrawParameters} parameters
|
||||||
|
*/
|
||||||
|
draw(parameters) {
|
||||||
|
const mousePosition = this.root.app.mousePosition;
|
||||||
|
if (!mousePosition) {
|
||||||
|
// Not on screen
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const below = this.computeColorBelowTile();
|
||||||
|
if (below) {
|
||||||
|
// We have something below our tile
|
||||||
|
const worldPos = this.root.camera.screenToWorld(mousePosition);
|
||||||
|
const tile = worldPos.toTileSpace().toWorldSpace();
|
||||||
|
|
||||||
|
parameters.context.strokeStyle = THEME.map.colorBlindPickerTile;
|
||||||
|
parameters.context.lineWidth = 1;
|
||||||
|
parameters.context.beginPath();
|
||||||
|
parameters.context.rect(tile.x, tile.y, globalConfig.tileSize, globalConfig.tileSize);
|
||||||
|
parameters.context.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,109 @@
|
|||||||
|
import { BaseHUDPart } from "../base_hud_part";
|
||||||
|
import { makeDiv, removeAllChildren } from "../../../core/utils";
|
||||||
|
import { T } from "../../../translations";
|
||||||
|
import { defaultBuildingVariant } from "../../meta_building";
|
||||||
|
import { ShapeDefinition } from "../../shape_definition";
|
||||||
|
import { KEYMAPPINGS, KeyActionMapper } from "../../key_action_mapper";
|
||||||
|
import { InputReceiver } from "../../../core/input_receiver";
|
||||||
|
import { DynamicDomAttach } from "../dynamic_dom_attach";
|
||||||
|
|
||||||
|
export class HUDShapeViewer extends BaseHUDPart {
|
||||||
|
createElements(parent) {
|
||||||
|
this.background = makeDiv(parent, "ingame_HUD_ShapeViewer", ["ingameDialog"]);
|
||||||
|
|
||||||
|
// DIALOG Inner / Wrapper
|
||||||
|
this.dialogInner = makeDiv(this.background, null, ["dialogInner"]);
|
||||||
|
this.title = makeDiv(this.dialogInner, null, ["title"], T.ingame.shapeViewer.title);
|
||||||
|
this.closeButton = makeDiv(this.title, null, ["closeButton"]);
|
||||||
|
this.trackClicks(this.closeButton, this.close);
|
||||||
|
this.contentDiv = makeDiv(this.dialogInner, null, ["content"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
this.root.hud.signals.viewShapeDetailsRequested.add(this.renderForShape, this);
|
||||||
|
|
||||||
|
this.domAttach = new DynamicDomAttach(this.root, this.background, {
|
||||||
|
attachClass: "visible",
|
||||||
|
});
|
||||||
|
|
||||||
|
this.inputReciever = new InputReceiver("shape_viewer");
|
||||||
|
this.keyActionMapper = new KeyActionMapper(this.root, this.inputReciever);
|
||||||
|
|
||||||
|
this.keyActionMapper.getBinding(KEYMAPPINGS.general.back).add(this.close, this);
|
||||||
|
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the dialog
|
||||||
|
*/
|
||||||
|
close() {
|
||||||
|
this.visible = false;
|
||||||
|
document.body.classList.remove("ingameDialogOpen");
|
||||||
|
this.root.app.inputMgr.makeSureDetached(this.inputReciever);
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the viewer for a given definition
|
||||||
|
* @param {ShapeDefinition} definition
|
||||||
|
*/
|
||||||
|
renderForShape(definition) {
|
||||||
|
this.visible = true;
|
||||||
|
document.body.classList.add("ingameDialogOpen");
|
||||||
|
this.root.app.inputMgr.makeSureAttachedAndOnTop(this.inputReciever);
|
||||||
|
|
||||||
|
removeAllChildren(this.contentDiv);
|
||||||
|
|
||||||
|
const layers = definition.layers;
|
||||||
|
for (let i = 0; i < layers.length; ++i) {
|
||||||
|
const layerElem = makeDiv(this.contentDiv, null, ["layer", "layer-" + i]);
|
||||||
|
|
||||||
|
let fakeLayers = [];
|
||||||
|
for (let k = 0; k < i; ++k) {
|
||||||
|
fakeLayers.push([null, null, null, null]);
|
||||||
|
}
|
||||||
|
fakeLayers.push(layers[i]);
|
||||||
|
|
||||||
|
const thisLayerOnly = new ShapeDefinition({ layers: fakeLayers });
|
||||||
|
const thisLayerCanvas = thisLayerOnly.generateAsCanvas(160);
|
||||||
|
layerElem.appendChild(thisLayerCanvas);
|
||||||
|
|
||||||
|
for (let quad = 0; quad < 4; ++quad) {
|
||||||
|
const quadElem = makeDiv(layerElem, null, ["quad", "quad-" + quad]);
|
||||||
|
|
||||||
|
const contents = layers[i][quad];
|
||||||
|
if (contents) {
|
||||||
|
const colorLabelElem = makeDiv(
|
||||||
|
quadElem,
|
||||||
|
null,
|
||||||
|
["colorLabel"],
|
||||||
|
T.ingame.colors[contents.color]
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
const emptyLabelElem = makeDiv(
|
||||||
|
quadElem,
|
||||||
|
null,
|
||||||
|
["emptyLabel"],
|
||||||
|
T.ingame.shapeViewer.empty
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < layers.length - 1) {
|
||||||
|
makeDiv(this.contentDiv, null, ["seperator"], "+");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans up everything
|
||||||
|
*/
|
||||||
|
cleanup() {
|
||||||
|
document.body.classList.remove("ingameDialogOpen");
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.domAttach.update(this.visible);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in new issue