1
0
mirror of https://github.com/tobspr/shapez.io.git synced 2025-06-13 13:04:03 +00:00

Merge pull request #2 from tobspr/master

Update to base project
This commit is contained in:
BaleineSanguine 2020-09-22 17:52:44 +02:00 committed by GitHub
commit cfd8cc9736
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
216 changed files with 14855 additions and 13056 deletions

View File

@ -64,7 +64,7 @@ This project is based on ES5. Some ES2015 features are used but most of them are
5. Add a constructor. **The constructor must be called with optional parameters only!** `new MyFancyComponent({})` should always work. 5. Add a constructor. **The constructor must be called with optional parameters only!** `new MyFancyComponent({})` should always work.
6. Add any props you need in the constructor. 6. Add any props you need in the constructor.
7. Add the component in `src/js/game/component_registry.js` 7. Add the component in `src/js/game/component_registry.js`
8. Add the componetn in `src/js/game/entity_components.js` 8. Add the component in `src/js/game/entity_components.js`
9. Done! You can use your component now 9. Done! You can use your component now
#### Adding a new building #### Adding a new building
@ -96,6 +96,6 @@ This project is based on ES5. Some ES2015 features are used but most of them are
For most assets I use Adobe Photoshop, you can find them in `assets/`. For most assets I use Adobe Photoshop, you can find them in `assets/`.
You will need a <a href="https://www.codeandweb.com/texturepacker" target="_blank">Texture Packer</a> license in order to regenerate the atlas. If you don't have one but want to contribute assets, let me know and I might compile it for you. I'm currently switching to an open source solution but I can't give an estimate when thats done. You will need a <a href="https://www.codeandweb.com/texturepacker" target="_blank">Texture Packer</a> license in order to regenerate the atlas. If you don't have one but want to contribute assets, let me know and I might compile it for you. I'm currently switching to an open source solution but I can't give an estimate when that's done.
<img src="https://i.imgur.com/W25Fkl0.png" alt="shapez.io Screenshot"> <img src="https://i.imgur.com/W25Fkl0.png" alt="shapez.io Screenshot">

View File

@ -16,6 +16,12 @@ function gulptasksSounds($, gulp, buildFolder) {
cacheDirName: "shapezio-precompiled-sounds", cacheDirName: "shapezio-precompiled-sounds",
}); });
function getFileCacheValue(file) {
const { _isVinyl, base, cwd, contents, history, stat, path } = file;
const encodedContents = Buffer.from(contents).toString('base64');
return { _isVinyl, base, cwd, contents: encodedContents, history, stat, path };
}
// Encodes the game music // Encodes the game music
gulp.task("sounds.music", () => { gulp.task("sounds.music", () => {
return gulp return gulp
@ -34,6 +40,7 @@ function gulptasksSounds($, gulp, buildFolder) {
{ {
name: "music", name: "music",
fileCache, fileCache,
value: getFileCacheValue,
} }
) )
) )
@ -58,6 +65,7 @@ function gulptasksSounds($, gulp, buildFolder) {
{ {
name: "music-high-quality", name: "music-high-quality",
fileCache, fileCache,
value: getFileCacheValue,
} }
) )
) )

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 825 B

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 756 B

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 731 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 728 B

After

Width:  |  Height:  |  Size: 385 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 927 B

After

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.3 MiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 280 KiB

After

Width:  |  Height:  |  Size: 281 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 677 KiB

After

Width:  |  Height:  |  Size: 700 KiB

View File

@ -197,7 +197,7 @@
<key>scaleMode</key> <key>scaleMode</key>
<enum type="ScaleMode">Smooth</enum> <enum type="ScaleMode">Smooth</enum>
<key>extrude</key> <key>extrude</key>
<uint>2</uint> <uint>3</uint>
<key>trimThreshold</key> <key>trimThreshold</key>
<uint>2</uint> <uint>2</uint>
<key>trimMargin</key> <key>trimMargin</key>
@ -269,7 +269,7 @@
<key type="filename">sprites/blueprints/miner.png</key> <key type="filename">sprites/blueprints/miner.png</key>
<key type="filename">sprites/blueprints/reader.png</key> <key type="filename">sprites/blueprints/reader.png</key>
<key type="filename">sprites/blueprints/rotater-ccw.png</key> <key type="filename">sprites/blueprints/rotater-ccw.png</key>
<key type="filename">sprites/blueprints/rotater-fl.png</key> <key type="filename">sprites/blueprints/rotater-rotate180.png</key>
<key type="filename">sprites/blueprints/rotater.png</key> <key type="filename">sprites/blueprints/rotater.png</key>
<key type="filename">sprites/blueprints/splitter-compact-inverse.png</key> <key type="filename">sprites/blueprints/splitter-compact-inverse.png</key>
<key type="filename">sprites/blueprints/splitter-compact-merge-inverse.png</key> <key type="filename">sprites/blueprints/splitter-compact-merge-inverse.png</key>
@ -281,8 +281,10 @@
<key type="filename">sprites/blueprints/underground_belt_exit-tier2.png</key> <key type="filename">sprites/blueprints/underground_belt_exit-tier2.png</key>
<key type="filename">sprites/blueprints/underground_belt_exit.png</key> <key type="filename">sprites/blueprints/underground_belt_exit.png</key>
<key type="filename">sprites/blueprints/virtual_processor-analyzer.png</key> <key type="filename">sprites/blueprints/virtual_processor-analyzer.png</key>
<key type="filename">sprites/blueprints/virtual_processor-painter.png</key>
<key type="filename">sprites/blueprints/virtual_processor-rotater.png</key> <key type="filename">sprites/blueprints/virtual_processor-rotater.png</key>
<key type="filename">sprites/blueprints/virtual_processor-shapecompare.png</key> <key type="filename">sprites/blueprints/virtual_processor-shapecompare.png</key>
<key type="filename">sprites/blueprints/virtual_processor-stacker.png</key>
<key type="filename">sprites/blueprints/virtual_processor-unstacker.png</key> <key type="filename">sprites/blueprints/virtual_processor-unstacker.png</key>
<key type="filename">sprites/blueprints/virtual_processor.png</key> <key type="filename">sprites/blueprints/virtual_processor.png</key>
<key type="filename">sprites/blueprints/wire_tunnel-coating.png</key> <key type="filename">sprites/blueprints/wire_tunnel-coating.png</key>
@ -298,7 +300,7 @@
<key type="filename">sprites/buildings/miner-chainable.png</key> <key type="filename">sprites/buildings/miner-chainable.png</key>
<key type="filename">sprites/buildings/reader.png</key> <key type="filename">sprites/buildings/reader.png</key>
<key type="filename">sprites/buildings/rotater-ccw.png</key> <key type="filename">sprites/buildings/rotater-ccw.png</key>
<key type="filename">sprites/buildings/rotater-fl.png</key> <key type="filename">sprites/buildings/rotater-rotate180.png</key>
<key type="filename">sprites/buildings/splitter-compact-inverse.png</key> <key type="filename">sprites/buildings/splitter-compact-inverse.png</key>
<key type="filename">sprites/buildings/splitter-compact-merge-inverse.png</key> <key type="filename">sprites/buildings/splitter-compact-merge-inverse.png</key>
<key type="filename">sprites/buildings/splitter-compact-merge.png</key> <key type="filename">sprites/buildings/splitter-compact-merge.png</key>
@ -308,8 +310,10 @@
<key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key> <key type="filename">sprites/buildings/underground_belt_exit-tier2.png</key>
<key type="filename">sprites/buildings/underground_belt_exit.png</key> <key type="filename">sprites/buildings/underground_belt_exit.png</key>
<key type="filename">sprites/buildings/virtual_processor-analyzer.png</key> <key type="filename">sprites/buildings/virtual_processor-analyzer.png</key>
<key type="filename">sprites/buildings/virtual_processor-painter.png</key>
<key type="filename">sprites/buildings/virtual_processor-rotater.png</key> <key type="filename">sprites/buildings/virtual_processor-rotater.png</key>
<key type="filename">sprites/buildings/virtual_processor-shapecompare.png</key> <key type="filename">sprites/buildings/virtual_processor-shapecompare.png</key>
<key type="filename">sprites/buildings/virtual_processor-stacker.png</key>
<key type="filename">sprites/buildings/virtual_processor-unstacker.png</key> <key type="filename">sprites/buildings/virtual_processor-unstacker.png</key>
<key type="filename">sprites/buildings/virtual_processor.png</key> <key type="filename">sprites/buildings/virtual_processor.png</key>
<key type="filename">sprites/buildings/wire_tunnel-coating.png</key> <key type="filename">sprites/buildings/wire_tunnel-coating.png</key>
@ -503,6 +507,28 @@
<key>scale9FromFile</key> <key>scale9FromFile</key>
<false/> <false/>
</struct> </struct>
<key type="filename">sprites/colors/blue.png</key>
<key type="filename">sprites/colors/cyan.png</key>
<key type="filename">sprites/colors/green.png</key>
<key type="filename">sprites/colors/purple.png</key>
<key type="filename">sprites/colors/red.png</key>
<key type="filename">sprites/colors/uncolored.png</key>
<key type="filename">sprites/colors/white.png</key>
<key type="filename">sprites/colors/yellow.png</key>
<struct type="IndividualSpriteSettings">
<key>pivotPoint</key>
<point_f>0.5,0.5</point_f>
<key>spriteScale</key>
<double>1</double>
<key>scale9Enabled</key>
<false/>
<key>scale9Borders</key>
<rect>18,18,36,36</rect>
<key>scale9Paddings</key>
<rect>18,18,36,36</rect>
<key>scale9FromFile</key>
<false/>
</struct>
<key type="filename">sprites/debug/acceptor_slot.png</key> <key type="filename">sprites/debug/acceptor_slot.png</key>
<key type="filename">sprites/debug/ejector_slot.png</key> <key type="filename">sprites/debug/ejector_slot.png</key>
<key type="filename">sprites/misc/hub_direction_indicator.png</key> <key type="filename">sprites/misc/hub_direction_indicator.png</key>

View File

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -392,13 +392,18 @@ canvas {
&::after { &::after {
content: " "; content: " ";
background: uiResource("loading.svg") center center / contain no-repeat; background: uiResource("loading.svg") center center / contain no-repeat;
@include S(width, 15px); @include S(width, 35px);
@include S(height, 15px); @include S(height, 35px);
@include S(margin-top, 1px);
@include S(margin-left, 5px);
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
} }
@include InlineAnimation(1.5s ease-in-out infinite) {
50% {
transform: scale(1.2) rotate(160deg);
}
}
@include DarkThemeOverride { @include DarkThemeOverride {
color: #fff; color: #fff;
} }
@ -463,18 +468,44 @@ canvas {
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
.loadingImage { .loadingImage {
background: uiResource("loading.svg") center center / #{D(60px)} no-repeat; background: uiResource("loading.svg") center center / #{D(40px)} no-repeat;
width: 100%; width: 100%;
display: flex; display: flex;
flex-grow: 1; flex-grow: 1;
@include InlineAnimation(1.5s ease-in-out infinite) {
50% {
transform: scale(1.2) rotate(160deg);
}
}
} }
.prefab_GameHint {
position: absolute;
@include S(left, 20px);
@include S(right, 20px);
@include S(bottom, 60px);
@include Text;
color: #666;
@include DarkThemeOverride() {
color: lighten($darkModeGameBackground, 50);
}
}
.loadingStatus { .loadingStatus {
position: absolute; position: absolute;
@include S(left, 20px); @include S(left, 20px);
@include S(right, 20px); @include S(right, 20px);
@include S(bottom, 30px); @include S(bottom, 30px);
@include Text; @include Text;
@include TextShadow3D(#aaa); @include PlainText;
color: #aaa;
@include DarkThemeOverride {
color: lighten($darkModeGameBackground, 20);
}
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
@ -568,6 +599,13 @@ canvas {
background-color: lighten($themeColor, 15); background-color: lighten($themeColor, 15);
} }
} }
@include DarkThemeOverride {
background-color: $darkModeGameBackground !important;
&.checked {
background-color: $colorBlueBright !important;
}
}
} }
.rangeInputContainer { .rangeInputContainer {
@ -597,6 +635,16 @@ input.rangeInput {
@include S(border-radius, 8px); @include S(border-radius, 8px);
} }
@include DarkThemeOverride {
&::-webkit-slider-runnable-track {
background-color: $darkModeControlsBackground;
}
&::-webkit-slider-thumb {
box-shadow: inset 0 0 0 D(10px) #eee;
}
}
&::-webkit-slider-thumb { &::-webkit-slider-thumb {
appearance: none; appearance: none;
-webkit-appearance: none; -webkit-appearance: none;

View File

@ -1,4 +1,4 @@
$buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, trash, underground_belt, wire, $buildings: belt, cutter, miner, mixer, painter, rotater, balancer, stacker, trash, underground_belt, wire,
constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader; constant_signal, logic_gate, lever, filter, wire_tunnel, display, virtual_processor, reader;
@each $building in $buildings { @each $building in $buildings {
@ -7,7 +7,7 @@ $buildings: belt, cutter, miner, mixer, painter, rotater, splitter, stacker, tra
} }
} }
$buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-inverse, underground_belt, $buildingsAndVariants: belt, balancer, balancer-merger, balancer-splitter, underground_belt,
underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, rotater-fl, underground_belt-tier2, miner, miner-chainable, cutter, cutter-quad, rotater, rotater-ccw, rotater-fl,
stacker, mixer, painter, painter-double, painter-quad, trash, trash-storage; stacker, mixer, painter, painter-double, painter-quad, trash, trash-storage;
@each $building in $buildingsAndVariants { @each $building in $buildingsAndVariants {
@ -16,10 +16,18 @@ $buildingsAndVariants: belt, splitter, splitter-compact, splitter-compact-invers
} }
} }
// Special case // @TODO: New buildings (balancer, wires, etc)
// Special cases for mirrored vairants
[data-icon="building_tutorials/painter-mirrored.png"] { [data-icon="building_tutorials/painter-mirrored.png"] {
background-image: uiResource("res/ui/building_tutorials/painter.png") !important; background-image: uiResource("res/ui/building_tutorials/painter.png") !important;
} }
[data-icon="building_tutorials/balancer-merger-inverse.png"] {
background-image: uiResource("res/ui/building_tutorials/balancer-merger.png") !important;
}
[data-icon="building_tutorials/balancer-splitter-inverse.png"] {
background-image: uiResource("res/ui/building_tutorials/balancer-splitter.png") !important;
}
$icons: notification_saved, notification_success, notification_upgrade; $icons: notification_saved, notification_success, notification_upgrade;
@each $icon in $icons { @each $icon in $icons {

View File

@ -1,107 +1,93 @@
.ingame_buildingsToolbar { .ingame_buildingsToolbar {
position: fixed; position: absolute;
@include S(bottom, 0px); @include S(bottom, 5px);
left: 50%; left: 50%;
transform: translateX(-50%); transform: translateX(-50%);
// NOTE: This flex rule may not be necessary. Need to find out intent. // NOTE: This flex rule may not be necessary. Need to find out intent.
display: flex; display: flex;
flex-direction: column; flex-direction: column;
background: transparent; background: transparent;
border-bottom-width: 0; transition: transform 120ms ease-in-out;
transition: transform 120ms ease-in-out; will-change: transform;
will-change: transform;
backdrop-filter: blur(D(3px));
background-color: rgba(mix(#ddd, $colorBlueBright, 90%), 0.5); background-color: rgba(0, 40, 80, 0.05);
backdrop-filter: blur(D(3px)); @include S(border-radius, $globalBorderRadius);
@include DarkThemeOverride { @include DarkThemeOverride {
background-color: #222428; background-color: rgba(darken($darkModeGameBackground, 15), 0.4);
}
&#ingame_HUD_wires_toolbar {
&:not(.visible) { background-color: rgba(darken($darkModeGameBackground, 5), 0.1);
transform: translateX(-50%) translateY(#{D(100px)}); }
} }
@include S(border-top-left-radius, $globalBorderRadius); &:not(.visible) {
@include S(border-top-right-radius, $globalBorderRadius); transform: translateX(-50%) translateY(#{D(100px)});
}
.buildings {
display: grid; .buildings {
grid-auto-flow: column; display: grid;
grid-auto-flow: column;
.building {
color: $accentColorDark; .building {
display: flex; color: $accentColorDark;
flex-direction: column; display: flex;
position: relative; flex-direction: column;
align-items: center; position: relative;
justify-content: center; align-items: center;
@include S(padding, 5px); justify-content: center;
@include S(padding-bottom, 1px); @include S(padding, 5px);
@include S(width, 35px); @include S(padding-bottom, 1px);
@include S(height, 40px); @include S(width, 35px);
@include S(height, 40px);
background: center center / 65% no-repeat;
background: center center / 70% no-repeat;
&:not(.unlocked) {
@include S(width, 20px); &:not(.unlocked) {
opacity: 0.15; @include S(width, 20px);
background-image: none !important; opacity: 0.15;
background-image: none !important;
&::before {
content: " "; &::before {
background: uiResource("locked_building.png") center center / #{D(20px)} #{D(20px)} content: " ";
no-repeat; background: uiResource("locked_building.png") center center / #{D(20px)} #{D(20px)}
position: absolute; no-repeat;
top: 0; position: absolute;
right: 0; top: 0;
bottom: 0; right: 0;
left: 0; bottom: 0;
z-index: 4; left: 0;
} z-index: 4;
} }
}
@include S(border-radius, $globalBorderRadius);
@include S(border-radius, $globalBorderRadius);
&.unlocked {
pointer-events: all; &.unlocked {
transition: all 50ms ease-in-out; pointer-events: all;
transition-property: background-color, transform; transition: all 50ms ease-in-out;
cursor: pointer; transition-property: background-color, transform;
will-change: transform;
cursor: pointer;
&::before { &:hover {
content: ""; background-color: rgba(30, 40, 90, 0.1);
position: absolute; }
top: 0;
right: 0; &.pressed {
bottom: 0; transform: scale(0.9) !important;
left: 0; }
background-color: $accentColorDark;
opacity: 0; &.selected {
will-change: opacity; // transform: scale(1.05);
} background-color: rgba(lighten($colorBlueBright, 9), 0.4);
&:hover { .keybinding {
&::before { color: #111;
opacity: 0.1; }
} }
} }
}
&.selected { }
transform: scale(1.05); }
&::before {
background-color: $colorBlueBright;
opacity: 0.6;
}
.keybinding {
color: #111;
}
}
}
}
}
}

View File

@ -1,231 +1,233 @@
.ingameDialog { .ingameDialog {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
pointer-events: all; pointer-events: all;
background: $modalDialogBg; background: $modalDialogBg;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@include InlineAnimation(0.12s ease-in-out) { @include InlineAnimation(0.12s ease-in-out) {
0% { 0% {
background-color: transparent; background-color: transparent;
opacity: 0.5; opacity: 0.5;
} }
100% { 100% {
background-color: $modalDialogBg; background-color: $modalDialogBg;
} }
} }
$darkModeDialogBg: darken($darkModeGameBackground, 10); $darkModeDialogBg: darken($darkModeGameBackground, 5);
@include DarkThemeOverride { @include DarkThemeOverride {
background: rgba($darkModeDialogBg, 0.9); background: rgba($darkModeDialogBg, 0.9);
@include InlineAnimation(0.12s ease-in-out) { @include InlineAnimation(0.12s ease-in-out) {
0% { 0% {
background-color: transparent; background-color: transparent;
opacity: 0.5; opacity: 0.5;
} }
100% { 100% {
background-color: rgba($darkModeDialogBg, 0.9); background-color: rgba($darkModeDialogBg, 0.9);
} }
} }
> .dialogInner.optionChooserDialog .optionParent { > .dialogInner.optionChooserDialog .optionParent {
.option { .option {
background: #3d3f42; background: $darkModeControlsBackground;
&:hover { &:hover {
background-color: #424348; background-color: lighten($darkModeControlsBackground, 5);
} }
&.active { &.active {
background: $colorBlueBright; background: $colorBlueBright;
color: #fff; color: #fff;
} }
} }
} }
} }
&.visible { &.visible {
.dialogInner { .dialogInner {
opacity: 1; opacity: 1;
} }
backdrop-filter: blur(D(3px)); backdrop-filter: blur(D(3px));
} }
.dialogInner { .dialogInner {
transition: opacity 0.2s ease-in-out; transition: opacity 0.2s ease-in-out;
opacity: 0; opacity: 0;
} }
&.loadingDialog { &.loadingDialog {
* { * {
color: #fff; color: #fff;
} }
} }
> .dialogInner { > .dialogInner {
background: #fff; background: #fff;
max-height: calc(100vh - #{D(40px)}); max-height: calc(100vh - #{D(40px)});
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@include S(padding, 12px); @include S(padding, 12px);
pointer-events: all; pointer-events: all;
@include DarkThemeOverride { @include DarkThemeOverride {
background: #333438; background: darken($darkModeControlsBackground, 5);
} }
&.optionChooserDialog { &.optionChooserDialog {
.optionParent { .optionParent {
display: grid; display: grid;
@include S(grid-gap, 5px); @include S(grid-gap, 5px);
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
.option { .option {
pointer-events: all; pointer-events: all;
cursor: pointer; cursor: pointer;
@include S(padding, 10px); @include S(padding, 10px);
background: #eee;
transition: background-color 0.12s ease-in-out; background: #eee;
&:hover { transition: background-color 0.12s ease-in-out;
background-color: #e7e7e7;
} &:hover {
background-color: #e7e7e7;
&.active { }
background-color: $colorBlueBright;
color: #fff; &.active {
} background-color: $colorBlueBright;
} color: #fff;
} }
} }
}
> .title { }
@include Heading;
margin: 0; > .title {
text-transform: uppercase; @include Heading;
display: grid; margin: 0;
align-items: center; text-transform: uppercase;
grid-template-columns: 1fr auto; display: grid;
@include S(margin-bottom, 10px); align-items: center;
grid-template-columns: 1fr auto;
@include DarkThemeInvert(); @include S(margin-bottom, 10px);
> .closeButton {
opacity: 0.7; @include DarkThemeInvert();
@include S(width, 20px); > .closeButton {
@include S(height, 20px); opacity: 0.7;
background: uiResource("icons/close.png") center center / 80% no-repeat; @include S(width, 20px);
cursor: pointer; @include S(height, 20px);
pointer-events: all; background: uiResource("icons/close.png") center center / 80% no-repeat;
transition: opacity 0.2s ease-in-out; cursor: pointer;
&:hover { pointer-events: all;
opacity: 0.4; transition: opacity 0.2s ease-in-out;
} &:hover {
} opacity: 0.4;
} }
}
> .content { }
@include PlainText;
overflow-y: auto; > .content {
pointer-events: all; @include PlainText;
@include S(width, 350px); overflow-y: auto;
pointer-events: all;
@include DarkThemeOverride { @include S(width, 350px);
color: #aaa;
} @include DarkThemeOverride {
color: #aaa;
a { }
color: $colorBlueBright;
} a {
color: $colorBlueBright;
strong { }
font-weight: bold;
} strong {
font-weight: bold;
.keybinding { }
position: relative;
background: #eee; .keybinding {
@include PlainText; position: relative;
height: unset; background: #eee;
margin: 1px 0; @include PlainText;
} height: unset;
margin: 1px 0;
input { }
background: #eee;
color: #333438; input {
width: 100%; background: #eee;
color: #333438;
&.errored { width: 100%;
background-color: rgb(250, 206, 206);
} &.errored {
} background-color: rgb(250, 206, 206);
}
ul.bucketList { }
padding-left: 30px;
ul.bucketList {
li { padding-left: 30px;
display: list-item;
} li {
} display: list-item;
} }
}
> .buttons { }
@include S(margin-top, 15px);
display: flex; > .buttons {
justify-content: flex-end; @include S(margin-top, 15px);
> button { display: flex;
@include S(margin-left, 8px); justify-content: flex-end;
@include Text; > button {
@include S(min-width, 60px); @include S(margin-left, 8px);
@include S(padding, 5px, 15px); @include Text;
@include S(min-width, 60px);
transition: opacity 0.12s ease-in-out; @include S(padding, 5px, 15px);
&:hover {
opacity: 0.9; transition: opacity 0.12s ease-in-out;
} &:hover {
opacity: 0.9;
&.good { }
background-color: $colorGreenBright;
color: #fff; &.good {
} background-color: $colorGreenBright;
color: #fff;
&.bad { }
background-color: $colorRedBright;
color: #fff; &.bad {
} background-color: $colorRedBright;
color: #fff;
&.timedButton { }
pointer-events: none;
cursor: default; &.timedButton {
position: relative; pointer-events: none;
overflow: hidden; cursor: default;
&::after { position: relative;
position: absolute; overflow: hidden;
top: 0; &::after {
right: 0; position: absolute;
bottom: 0; top: 0;
left: unset; right: 0;
z-index: 5; bottom: 0;
content: " "; left: unset;
display: inline-block; z-index: 5;
background: rgba(#fff, 0.6); content: " ";
@include InlineAnimation(5s linear) { display: inline-block;
0% { background: rgba(#fff, 0.6);
width: 100%; @include InlineAnimation(5s linear) {
} 0% {
100% { width: 100%;
width: 0%; }
} 100% {
} width: 0%;
} }
} }
} }
} }
} }
} }
}
}

View File

@ -1,43 +1,79 @@
#ingame_HUD_EntityDebugger { #ingame_HUD_EntityDebugger {
position: absolute; position: absolute;
background: $ingameHudBg;
@include S(padding, 5px);
@include S(right, 30px); @include S(right, 30px);
@include S(top, 200px);
font-size: 14px; top: 50%;
line-height: 16px; transform: translateY(-50%);
color: #fff;
background: rgba(0, 10, 20, 0.7); @include SuperSmallText;
padding: 10px; color: #eee;
display: flex;
flex-direction: column;
> label {
text-transform: uppercase;
}
.hint {
color: #aaa;
}
&, &,
* { * {
pointer-events: all; pointer-events: all;
} }
.flag { .propertyTable {
display: inline-block; @include S(margin-top, 8px);
background: #333438;
@include S(padding, 2px);
@include S(margin-right, 2px);
u {
opacity: 0.5;
}
} }
.components { .propertyTable,
@include S(margin-top, 4px); .entityComponents,
.entityComponents .object > div {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr auto;
@include S(grid-gap, 3px); @include S(column-gap, 10px);
.component { }
@include S(padding, 2px);
background: #333;
display: flex;
flex-direction: column;
.data { .entityComponents {
@include S(width, 150px); grid-column: 1 / 3;
@include S(height, 130px); @include S(margin-top, 5px);
font-family: "Roboto Mono", "Fira Code", monospace;
font-size: 90%;
@include S(letter-spacing, -0.5px);
label,
span {
line-height: 1.5em;
&:not(span) {
opacity: 0.5;
}
}
&,
* {
@include SuperSmallText;
@include S(font-size, 7px, $important: true);
@include S(line-height, 12px, $important: true);
}
.object {
grid-column: 1 / 3;
line-height: 1.5em;
> summary {
transition: opacity 0.1s ease-in-out;
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
> div {
@include S(margin-left, 4px);
cursor: pointer;
} }
} }
} }

View File

@ -1,111 +1,95 @@
#ingame_HUD_GameMenu { #ingame_HUD_GameMenu {
position: absolute; position: absolute;
top: 0; @include S(top, 10px);
right: 0; @include S(right, 10px);
display: flex; display: grid;
grid-auto-flow: column; grid-template-columns: 1fr 1fr 1fr 1fr;
@include S(grid-gap, 6px);
> .menuButtons { backdrop-filter: blur(D(1px));
> button,
> .button {
@include PlainText;
@include IncreasedClickArea(0px);
background: green;
@include S(width, 30px);
@include S(height, 30px);
pointer-events: all;
cursor: pointer;
position: relative; position: relative;
display: flex; transition: all 0.12s ease-in-out;
flex-grow: 1; transition-property: opacity, transform;
@include S(padding, 5px, 4px);
justify-content: flex-end;
@include S(margin-left, 20px);
> .button { display: inline-flex;
@include S(width, 30px); background: center center / 70% no-repeat;
@include S(height, 30px); grid-row: 1;
display: inline-block;
background: center center / 60% no-repeat;
pointer-events: all;
cursor: pointer;
transition: all 0.12s ease-in-out;
transition-property: opacity, transform;
will-change: opacity;
opacity: 0.9;
@include S(margin-left, 5px);
position: relative;
@include IncreasedClickArea(0px); &.pressed {
transform: scale(0.9) !important;
}
@include DarkThemeInvert; opacity: 0.7;
&:hover {
opacity: 0.9 !important;
}
&:hover { @include DarkThemeInvert;
opacity: 0.8;
}
&.save { &.shop {
background-image: uiResource("icons/save.png"); background-image: uiResource("icons/shop.png");
@include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) { grid-column: 1;
0% { }
transform: scale(1, 1);
}
70% { &.stats {
transform: scale(1.5, 1.5) rotate(20deg); background-image: uiResource("icons/statistics.png");
opacity: 0.2; grid-column: 2;
} }
85% { &.save {
transform: scale(0.9, 0.9); background-image: uiResource("icons/save.png");
opacity: 1; grid-column: 3;
} @include MakeAnimationWrappedEvenOdd(0.5s ease-in-out) {
0% {
transform: scale(1, 1);
}
90% { 70% {
transform: scale(1.1, 1.1); transform: scale(1.5, 1.5) rotate(20deg);
} opacity: 0.2;
}
85% {
transform: scale(0.9, 0.9);
opacity: 1;
}
90% {
transform: scale(1.1, 1.1);
} }
} }
&.settings { &.saving {
background-image: uiResource("icons/settings.png"); @include InlineAnimation(0.4s ease-in-out infinite) {
50% {
opacity: 0.5;
transform: scale(0.8);
}
}
pointer-events: none;
cursor: default;
} }
} }
}
.buttonContainer button { &.settings {
@include PlainText; background-image: uiResource("icons/settings_menu_settings.png");
color: #fff; grid-column: 4;
border-color: rgba(0, 0, 0, 0.1);
@include S(padding, 5px, 5px, 5px);
@include S(padding-left, 30px);
@include S(margin-right, 3px);
@include IncreasedClickArea(0px);
@include ButtonText;
@include S(min-height, 40px);
transition: all 0.12s ease-in-out;
transition-property: opacity, transform;
display: inline-flex;
background: center #{D(13px)} / #{D(20px)} no-repeat;
background-color: $colorGreenBright;
&[data-button-id="shop"] {
background-color: rgb(93, 103, 250);
background-image: uiResource("icons/shop.png");
background-size: #{D(18px)};
}
&[data-button-id="stats"] {
background-color: rgb(85, 199, 138);
background-image: uiResource("icons/statistics.png");
} }
&:hover { &:hover {
opacity: 0.9; opacity: 0.9;
} transform: translateY(0);
.keybinding {
border: 0;
color: #fff;
border-top-left-radius: 0;
border-top-right-radius: 0;
bottom: unset;
background: transparent;
@include S(top, 0px);
right: unset;
left: 50%;
transform: translateX(-50%);
} }
&:not(.hasBadge) .badge { &:not(.hasBadge) .badge {
@ -113,34 +97,27 @@
} }
&.hasBadge { &.hasBadge {
transform-origin: 50% 0%; &.shop {
@include InlineAnimation(1s ease-in-out infinite) { filter: none;
background-image: uiResource("icons/shop_active.png");
opacity: 0.9;
}
transform-origin: 50% 50%;
@include InlineAnimation(0.8s ease-in-out infinite) {
50% { 50% {
transform: scale(1.02); transform: scale(1.3) rotate(6deg);
} }
} }
.badge { .badge {
position: absolute; position: absolute;
@include S(bottom, -8px); top: 50%;
left: 50%; left: 50%;
transform: translateX(-50%); transform: translate(-50%, -50%);
background: #333;
@include PlainText; @include PlainText;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@include S(min-width, 5px);
@include S(height, 10px);
@include S(padding, 1px, 3px, 2px);
@include S(border-radius, $globalBorderRadius);
border: #{D(1px)} solid #fff;
@include InlineAnimation(1s ease-in-out infinite) {
50% {
transform: translateX(-50%) scale(1.05);
}
}
} }
} }
} }

View File

@ -7,7 +7,7 @@
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
color: #333438; color: #333438;
backdrop-filter: blur(D(2px)); backdrop-filter: blur(D(1px));
padding: D(3px); padding: D(3px);
@include DarkThemeOverride { @include DarkThemeOverride {

View File

@ -1,138 +1,137 @@
#ingame_HUD_PinnedShapes { #ingame_HUD_PinnedShapes {
position: absolute; position: absolute;
@include S(left, 9px); @include S(left, 9px);
@include S(top, 150px); @include S(top, 150px);
@include PlainText; @include PlainText;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
justify-content: flex-start; justify-content: flex-start;
> .shape { > .shape {
position: relative; position: relative;
display: grid; display: grid;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
grid-template-columns: auto 1fr; grid-template-columns: auto 1fr;
grid-template-rows: 1fr 1fr; grid-template-rows: 1fr 1fr;
@include S(margin-bottom, 4px); @include S(margin-bottom, 4px);
color: #333438; color: #333438;
// text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.2); // text-shadow: #{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.2);
filter: drop-shadow(#{D(1px)} #{D(1px)} 0 rgba(0, 10, 20, 0.2));
&.unpinable {
&.unpinable { > canvas {
> canvas { cursor: pointer;
cursor: pointer; pointer-events: all;
pointer-events: all; }
} }
}
> canvas {
> canvas { @include S(width, 25px);
@include S(width, 25px); @include S(height, 25px);
@include S(height, 25px); grid-column: 1 / 2;
grid-column: 1 / 2; grid-row: 1 / 3;
grid-row: 1 / 3; pointer-events: all;
pointer-events: all; transition: transform 0.1s ease-in-out;
transition: transform 0.1s ease-in-out; transform-origin: D(2px) center;
transform-origin: D(2px) center; will-change: transform;
will-change: transform; position: relative;
position: relative; z-index: 20;
z-index: 20; &:hover {
&:hover { transform: scale(2);
transform: scale(2); z-index: 21;
z-index: 21; }
} }
}
> .amountLabel,
> .amountLabel, > .goalLabel {
> .goalLabel { @include S(margin-left, 5px);
@include S(margin-left, 5px); @include SuperSmallText;
@include SuperSmallText; font-weight: bold;
font-weight: bold; display: inline-flex;
display: inline-flex; align-items: center;
align-items: center; flex-direction: row;
flex-direction: row; grid-column: 2 / 3;
grid-column: 2 / 3; @include S(height, 9px);
@include S(height, 9px);
@include DarkThemeOverride {
@include DarkThemeOverride { color: #eee;
color: #eee; }
} }
}
> .goalLabel {
> .goalLabel { @include S(font-size, 7px);
@include S(font-size, 7px); opacity: 0.9;
opacity: 0.9; align-self: start;
align-self: start; justify-self: start;
justify-self: start; font-weight: normal;
font-weight: normal; grid-row: 2 / 3;
grid-row: 2 / 3; }
}
> .amountLabel {
> .amountLabel { align-self: end;
align-self: end; justify-self: start;
justify-self: start; grid-row: 1 / 2;
grid-row: 1 / 2; }
}
> .infoButton {
> .infoButton { @include S(width, 8px);
@include S(width, 8px); @include S(height, 8px);
@include S(height, 8px); background: uiResource("icons/info_button.png") center center / 95% no-repeat;
background: uiResource("icons/info_button.png") center center / 95% no-repeat; position: absolute;
position: absolute; opacity: 0.7;
opacity: 0.7; @include S(top, 13px);
@include S(top, 13px); @include S(left, -7px);
@include S(left, -7px); @include DarkThemeInvert;
@include DarkThemeInvert; @include IncreasedClickArea(2px);
@include IncreasedClickArea(2px); transition: opacity 0.12s ease-in-out;
transition: opacity 0.12s ease-in-out; z-index: 100;
z-index: 100;
&:hover {
&:hover { opacity: 0.8;
opacity: 0.8; }
} }
}
&.goal,
&.goal, &.blueprint {
&.blueprint { .amountLabel::after {
.amountLabel::after { content: " ";
content: " "; position: absolute;
position: absolute; display: inline-block;
display: inline-block; @include S(width, 8px);
@include S(width, 8px); @include S(height, 8px);
@include S(height, 8px); @include S(top, 4px);
@include S(top, 4px); @include S(left, -7px);
@include S(left, -7px); background: center center / contain no-repeat;
background: center center / contain no-repeat; }
}
&.goal .amountLabel {
&.goal .amountLabel { &::after {
&::after { background-image: uiResource("icons/current_goal_marker.png");
background-image: uiResource("icons/current_goal_marker.png"); background-size: 90%;
background-size: 90%; }
} @include DarkThemeOverride {
@include DarkThemeOverride { &::after {
&::after { background-image: uiResource("icons/current_goal_marker_inverted.png") !important;
background-image: uiResource("icons/current_goal_marker_inverted.png") !important; }
} }
} }
}
&.blueprint .amountLabel {
&.blueprint .amountLabel { &::after {
&::after { background-image: uiResource("icons/blueprint_marker.png");
background-image: uiResource("icons/blueprint_marker.png"); background-size: 90%;
background-size: 90%; }
} @include DarkThemeOverride {
@include DarkThemeOverride { &::after {
&::after { background-image: uiResource("icons/blueprint_marker_inverted.png") !important;
background-image: uiResource("icons/blueprint_marker_inverted.png") !important; }
} }
} }
} }
}
&.completed {
&.completed { opacity: 0.5;
opacity: 0.5; }
} }
} }
}

View File

@ -1,50 +1,50 @@
#ingame_HUD_SandboxController { #ingame_HUD_SandboxController {
position: absolute; position: absolute;
background: $ingameHudBg; background: $ingameHudBg;
@include S(padding, 5px); @include S(padding, 5px);
@include S(bottom, 10px); @include S(bottom, 10px);
@include S(left, 10px); @include S(left, 10px);
@include SuperSmallText; @include SuperSmallText;
color: #eee; color: #eee;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
> label { > label {
text-transform: uppercase; text-transform: uppercase;
} }
.hint { .sandboxHint {
color: #aaa; color: #aaa;
} }
.plusMinus { .plusMinus {
@include S(margin-top, 4px); @include S(margin-top, 4px);
display: grid; display: grid;
grid-template-columns: 1fr auto auto; grid-template-columns: 1fr auto auto;
align-items: center; align-items: center;
@include S(grid-gap, 4px); @include S(grid-gap, 4px);
button { button {
@include PlainText; @include PlainText;
@include S(padding, 0); @include S(padding, 0);
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@include S(width, 15px); @include S(width, 15px);
@include S(height, 15px); @include S(height, 15px);
@include IncreasedClickArea(0px); @include IncreasedClickArea(0px);
} }
} }
.additionalOptions { .additionalOptions {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@include S(margin-top, 10px); @include S(margin-top, 10px);
button { button {
@include S(margin-bottom, 2px); @include S(margin-bottom, 2px);
@include IncreasedClickArea(0px); @include IncreasedClickArea(0px);
@include SuperSmallText; @include SuperSmallText;
} }
} }
} }

View File

@ -1,41 +1,61 @@
#ingame_HUD_SettingsMenu { #ingame_HUD_SettingsMenu {
.statsElement { .statsElement {
position: absolute; position: absolute;
@include S(left, 30px); @include S(left, 30px);
@include S(top, 30px); @include S(right, 30px);
color: #fff; @include S(bottom, 30px);
display: flex; color: #fff;
grid-template-rows: 1fr auto; display: grid;
flex-direction: column; grid-template-rows: auto auto;
grid-auto-columns: 1fr;
strong { align-items: center;
text-transform: uppercase; justify-items: center;
@include PlainText;
opacity: 0.5; strong {
} text-transform: uppercase;
@include PlainText;
span { opacity: 0.5;
@include S(margin-bottom, 25px); grid-row: 1;
@include Heading; }
}
} span {
@include Heading;
display: flex; grid-row: 2;
flex-direction: column; }
align-items: center; }
justify-content: center;
display: flex;
.buttons { flex-direction: column;
display: grid; align-items: center;
grid-auto-flow: row; justify-content: center;
@include S(grid-gap, 10px);
background: rgba(0, 10, 20, 0.1); .buttons {
@include S(padding, 10px); display: grid;
@include S(border-radius, $globalBorderRadius); grid-auto-flow: column;
@include S(grid-gap, 50px);
button { @include S(margin-top, -10px);
background-color: #eee;
color: #55585a; button {
} background: transparent;
} filter: invert(1);
}
background: uiResource("icons/settings_menu_play.png") center top / contain no-repeat;
content: "";
opacity: 0.8;
@include S(width, 35px);
@include S(height, 35px);
&.settings {
background-image: uiResource("icons/settings_menu_settings.png");
}
&.menu {
background-image: uiResource("icons/settings_menu_exit.png");
}
&:hover {
opacity: 0.6;
}
}
}
}

View File

@ -1,161 +1,154 @@
#ingame_HUD_ShapeViewer { #ingame_HUD_ShapeViewer {
$dims: 170px; $dims: 170px;
.content { .content {
display: flex; display: flex;
@include S(width, $dims); @include S(width, $dims);
width: 100%; width: 100%;
flex-direction: column; flex-direction: column;
overflow-x: hidden; overflow-x: hidden;
&[data-layers="3"], &[data-layers="3"],
&[data-layers="4"] { &[data-layers="4"] {
@include S(width, 2 * $dims); @include S(width, 2 * $dims);
.renderArea { .renderArea {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: 1fr 1fr;
@include S(grid-row-gap, 15px); @include S(grid-row-gap, 15px);
} }
} }
.renderArea { .renderArea {
display: grid; display: grid;
width: 100%; width: 100%;
@include S(grid-row-gap, 10px); @include S(grid-row-gap, 10px);
align-items: center; align-items: center;
justify-items: center; justify-items: center;
} }
.infoArea { .infoArea {
align-self: flex-end; align-self: flex-end;
@include S(margin-top, 10px); @include S(margin-top, 10px);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
overflow: hidden; overflow: hidden;
button { button {
@include S(margin, 0); @include S(margin, 0);
@include PlainText; @include PlainText;
} }
} }
.seperator { .layer {
display: flex; position: relative;
align-items: center; background: #eee;
justify-content: center;
width: 100%; @include DarkThemeOverride {
} background: rgba(0, 10, 20, 0.2);
}
.layer { @include S(width, 150px);
position: relative; @include S(height, 100px);
background: #eee; display: flex;
align-items: center;
@include DarkThemeOverride { justify-content: center;
background: rgba(0, 10, 20, 0.2);
} > canvas {
@include S(width, 150px); @include S(width, 50px);
@include S(height, 100px); @include S(height, 50px);
display: flex; }
align-items: center;
justify-content: center; .quad {
position: absolute;
> canvas { width: 50%;
@include S(width, 50px); height: 50%;
@include S(height, 50px); display: flex;
} justify-content: center;
align-items: center;
.quad { box-sizing: border-box;
position: absolute;
width: 50%; $arrowDims: 23px;
height: 50%; $spacing: 9px;
display: flex; @include S(padding, 6px);
justify-content: center;
align-items: center; .colorLabel {
box-sizing: border-box; text-transform: uppercase;
@include SuperSmallText;
$arrowDims: 23px; @include S(font-size, 9px);
$spacing: 9px; }
@include S(padding, 6px);
.emptyLabel {
.colorLabel { text-transform: uppercase;
text-transform: uppercase; @include SuperSmallText;
@include SuperSmallText; @include S(font-size, 9px);
@include S(font-size, 9px); }
}
&::after {
.emptyLabel { content: " ";
text-transform: uppercase; background: rgba(0, 10, 20, 0.5);
@include SuperSmallText; @include S(width, $arrowDims);
@include S(font-size, 9px); @include S(height, 1px);
} position: absolute;
transform: rotate(45deg);
&::after { transform-origin: 50% 50%;
content: " "; }
background: rgba(0, 10, 20, 0.5); @include DarkThemeOverride {
@include S(width, $arrowDims); &::after {
@include S(height, 1px); background: rgba(255, 255, 255, 0.5);
position: absolute; }
transform: rotate(45deg); }
transform-origin: 50% 50%;
} &.quad-0 {
@include DarkThemeOverride { right: 0;
&::after { top: 0;
background: rgba(255, 255, 255, 0.5); align-items: flex-start;
} justify-content: flex-end;
}
&::after {
&.quad-0 { @include S(left, $spacing);
right: 0; @include S(bottom, $arrowDims / 2 + $spacing);
top: 0; transform: rotate(-45deg);
align-items: flex-start; }
justify-content: flex-end; }
&.quad-1 {
&::after { bottom: 0;
@include S(left, $spacing); right: 0;
@include S(bottom, $arrowDims / 2 + $spacing);
transform: rotate(-45deg); align-items: flex-end;
} justify-content: flex-end;
}
&.quad-1 { &::after {
bottom: 0; @include S(left, $spacing);
right: 0; @include S(top, $arrowDims / 2 + $spacing);
transform: rotate(45deg);
align-items: flex-end; }
justify-content: flex-end; }
&.quad-2 {
&::after { bottom: 0;
@include S(left, $spacing); left: 0;
@include S(top, $arrowDims / 2 + $spacing);
transform: rotate(45deg); align-items: flex-end;
} justify-content: flex-start;
}
&.quad-2 { &::after {
bottom: 0; @include S(right, $spacing);
left: 0; @include S(top, $arrowDims / 2 + $spacing);
transform: rotate(135deg);
align-items: flex-end; }
justify-content: flex-start; }
&.quad-3 {
&::after { top: 0;
@include S(right, $spacing); left: 0;
@include S(top, $arrowDims / 2 + $spacing);
transform: rotate(135deg); align-items: flex-start;
} justify-content: flex-start;
}
&.quad-3 { &::after {
top: 0; @include S(right, $spacing);
left: 0; @include S(bottom, $arrowDims / 2 + $spacing);
transform: rotate(225deg);
align-items: flex-start; }
justify-content: flex-start; }
}
&::after { }
@include S(right, $spacing); }
@include S(bottom, $arrowDims / 2 + $spacing); }
transform: rotate(225deg);
}
}
}
}
}
}

View File

@ -1,320 +1,320 @@
#ingame_HUD_Shop { #ingame_HUD_Shop {
.content { .content {
@include S(padding-right, 10px); @include S(padding-right, 10px);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@include S(width, 500px); @include S(width, 500px);
.upgrade { .upgrade {
display: grid; display: grid;
grid-template-columns: auto 1fr auto; grid-template-columns: auto 1fr auto;
background: #eee; background: #eee;
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
@include S(margin-bottom, 4px); @include S(margin-bottom, 4px);
@include S(padding, 5px, 10px); @include S(padding, 5px, 10px);
@include S(grid-row-gap, 1px); @include S(grid-row-gap, 1px);
@include S(height, 85px); @include S(height, 85px);
grid-template-rows: #{D(20px)} auto; grid-template-rows: #{D(20px)} auto;
&:last-child { &:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
@include DarkThemeOverride { @include DarkThemeOverride {
background: #55585a; background: $darkModeControlsBackground;
} }
.title { .title {
grid-column: 1 / 3; grid-column: 1 / 3;
grid-row: 1 / 2; grid-row: 1 / 2;
@include PlainText; @include PlainText;
display: flex; display: flex;
align-items: center; align-items: center;
flex-direction: row-reverse; flex-direction: row-reverse;
justify-content: flex-end; justify-content: flex-end;
@include DarkThemeOverride { @include DarkThemeOverride {
color: #fff; color: #fff;
} }
.tier { .tier {
@include S(margin-right, 9px); @include S(margin-right, 9px);
background: $colorGreenBright; background: $colorGreenBright;
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
text-transform: uppercase; text-transform: uppercase;
@include PlainText; @include PlainText;
color: #fff; color: #fff;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
@include S(min-width, 50px); @include S(min-width, 50px);
@include S(padding, 0px, 5px); @include S(padding, 0px, 5px);
&[data-tier="0"] { &[data-tier="0"] {
background-color: rgb(73, 186, 190); background-color: rgb(73, 186, 190);
} }
&[data-tier="1"] { &[data-tier="1"] {
background-color: rgb(88, 110, 207); background-color: rgb(88, 110, 207);
} }
&[data-tier="2"] { &[data-tier="2"] {
background-color: rgb(189, 100, 192); background-color: rgb(189, 100, 192);
} }
&[data-tier="3"] { &[data-tier="3"] {
background-color: rgb(117, 192, 98); background-color: rgb(117, 192, 98);
} }
&[data-tier="4"] { &[data-tier="4"] {
background-color: rgb(243, 77, 48); background-color: rgb(243, 77, 48);
} }
&[data-tier="5"] { &[data-tier="5"] {
background-color: rgb(255, 209, 6); background-color: rgb(255, 209, 6);
} }
&[data-tier="6"] { &[data-tier="6"] {
background-color: rgb(44, 41, 46); background-color: rgb(44, 41, 46);
} }
} }
} }
.icon { .icon {
@include S(width, 40px); @include S(width, 40px);
@include S(height, 40px); @include S(height, 40px);
background: center center / 80% no-repeat; background: center center / 80% no-repeat;
align-self: center; align-self: center;
justify-self: center; justify-self: center;
grid-column: 1 / 2; grid-column: 1 / 2;
grid-row: 2 / 4; grid-row: 2 / 4;
@include S(margin-right, 30px); @include S(margin-right, 30px);
@include S(margin-left, 10px); @include S(margin-left, 10px);
opacity: 0.32; opacity: 0.32;
display: none; display: none;
} }
.description { .description {
grid-column: 2 / 4; grid-column: 2 / 4;
grid-row: 1 / 2; grid-row: 1 / 2;
@include PlainText; @include PlainText;
color: #aaa; color: #aaa;
align-self: start; align-self: start;
justify-self: end; justify-self: end;
} }
.requirements { .requirements {
grid-column: 2 / 3; grid-column: 2 / 3;
grid-row: 3 / 4; grid-row: 3 / 4;
display: grid; display: grid;
grid-auto-flow: column; grid-auto-flow: column;
@include S(grid-gap, 9px); @include S(grid-gap, 9px);
justify-content: start; justify-content: start;
.requirement { .requirement {
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
@include S(width, 70px); @include S(width, 70px);
overflow: hidden; overflow: hidden;
button.pin { button.pin {
@include S(width, 12px); @include S(width, 12px);
@include S(height, 12px); @include S(height, 12px);
background: uiResource("icons/pin.png") center center / 95% no-repeat; background: uiResource("icons/pin.png") center center / 95% no-repeat;
position: absolute; position: absolute;
@include S(top, 2px); @include S(top, 2px);
@include S(right, 2px); @include S(right, 2px);
opacity: 0.6; opacity: 0.6;
cursor: pointer; cursor: pointer;
pointer-events: all; pointer-events: all;
@include IncreasedClickArea(5px); @include IncreasedClickArea(5px);
transition: opacity 0.12s ease-in-out; transition: opacity 0.12s ease-in-out;
@include DarkThemeInvert; @include DarkThemeInvert;
$disabledOpacity: 0.2; $disabledOpacity: 0.2;
$enabledOpacity: 0.6; $enabledOpacity: 0.6;
&:hover { &:hover {
opacity: $enabledOpacity + 0.1; opacity: $enabledOpacity + 0.1;
} }
&.alreadyPinned { &.alreadyPinned {
opacity: $disabledOpacity !important; opacity: $disabledOpacity !important;
&:hover { &:hover {
opacity: $disabledOpacity + 0.1 !important; opacity: $disabledOpacity + 0.1 !important;
} }
} }
&.isGoal { &.isGoal {
background: uiResource("icons/current_goal_marker.png") center center / 95% background: uiResource("icons/current_goal_marker.png") center center / 95%
no-repeat; no-repeat;
opacity: $disabledOpacity !important; opacity: $disabledOpacity !important;
cursor: default; cursor: default;
pointer-events: none; pointer-events: none;
} }
&.pinned { &.pinned {
opacity: $disabledOpacity; opacity: $disabledOpacity;
@include InlineAnimation(0.3s ease-in-out) { @include InlineAnimation(0.3s ease-in-out) {
0% { 0% {
opacity: 1; opacity: 1;
transform: scale(0.8); transform: scale(0.8);
} }
30% { 30% {
opacity: 1; opacity: 1;
transform: scale(1.2); transform: scale(1.2);
} }
100% { 100% {
transform: scale(1); transform: scale(1);
} }
} }
&:hover { &:hover {
opacity: $disabledOpacity + 0.1; opacity: $disabledOpacity + 0.1;
} }
} }
&.unpinned { &.unpinned {
opacity: $enabledOpacity; opacity: $enabledOpacity;
@include InlineAnimation(0.3s ease-in-out) { @include InlineAnimation(0.3s ease-in-out) {
0% { 0% {
opacity: 1; opacity: 1;
transform: scale(0.8); transform: scale(0.8);
} }
30% { 30% {
opacity: 1; opacity: 1;
transform: scale(1.2); transform: scale(1.2);
} }
100% { 100% {
transform: scale(1); transform: scale(1);
} }
} }
&:hover { &:hover {
opacity: $enabledOpacity + 0.1; opacity: $enabledOpacity + 0.1;
} }
} }
} }
button.showInfo { button.showInfo {
@include S(width, 11px); @include S(width, 11px);
@include S(height, 11px); @include S(height, 11px);
background: uiResource("icons/info_button.png") center center / 95% no-repeat; background: uiResource("icons/info_button.png") center center / 95% no-repeat;
position: absolute; position: absolute;
@include S(top, 17px); @include S(top, 17px);
@include S(right, 2.5px); @include S(right, 2.5px);
opacity: 0.5; opacity: 0.5;
cursor: pointer; cursor: pointer;
pointer-events: all; pointer-events: all;
@include IncreasedClickArea(5px); @include IncreasedClickArea(5px);
transition: opacity 0.12s ease-in-out; transition: opacity 0.12s ease-in-out;
@include DarkThemeInvert; @include DarkThemeInvert;
&:hover { &:hover {
opacity: 0.6; opacity: 0.6;
} }
} }
canvas { canvas {
@include S(width, 40px); @include S(width, 40px);
@include S(height, 40px); @include S(height, 40px);
} }
.amount { .amount {
@include S(margin-top, 4px); @include S(margin-top, 4px);
z-index: 10; z-index: 10;
@include SuperSmallText; @include SuperSmallText;
letter-spacing: 0; letter-spacing: 0;
background: #e2e4e6; background: #e2e4e6;
@include S(line-height, 13px); @include S(line-height, 13px);
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
@include S(padding, 1px, 0px, 2px); @include S(padding, 1px, 0px, 2px);
position: relative; position: relative;
text-align: center; text-align: center;
@include S(min-width, 50px); @include S(min-width, 50px);
// @include S(max-width, 100px); // @include S(max-width, 100px);
overflow: hidden; overflow: hidden;
width: 100%; width: 100%;
@include DarkThemeOverride { @include DarkThemeOverride {
background: #333438; background: #333438;
color: #fff; color: #fff;
} }
.progressBar { .progressBar {
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
top: 0; top: 0;
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
position: absolute; position: absolute;
display: inline-block; display: inline-block;
z-index: -1; z-index: -1;
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
transition-property: width, background-color; transition-property: width, background-color;
background: #bdbfca; background: #bdbfca;
@include DarkThemeOverride { @include DarkThemeOverride {
background: #8c8d96; background: #8c8d96;
} }
&.complete { &.complete {
background-color: $colorGreenBright; background-color: $colorGreenBright;
@include DarkThemeOverride { @include DarkThemeOverride {
background-color: $colorGreenBright; background-color: $colorGreenBright;
} }
} }
} }
} }
} }
} }
button.buy { button.buy {
grid-column: 3 / 4; grid-column: 3 / 4;
grid-row: 3 / 4; grid-row: 3 / 4;
align-self: center; align-self: center;
justify-self: end; justify-self: end;
// @include S(padding, 4px, 5px); // @include S(padding, 4px, 5px);
// @include PlainText; // @include PlainText;
background-color: $colorGreenBright; background-color: $colorGreenBright;
color: #fff; color: #fff;
transition: all 0.2s ease-in-out; transition: all 0.2s ease-in-out;
transition-property: background-color, opacity; transition-property: background-color, opacity;
&:not(.buyable) { &:not(.buyable) {
background-color: #aaa; background-color: #aaa;
cursor: default; cursor: default;
pointer-events: none; pointer-events: none;
opacity: 0.3; opacity: 0.3;
} }
&.buyable { &.buyable {
@include InlineAnimation(1s ease-in-out infinite) { @include InlineAnimation(1s ease-in-out infinite) {
0% { 0% {
} }
50% { 50% {
background-color: lighten($colorGreenBright, 10); background-color: lighten($colorGreenBright, 10);
} }
100% { 100% {
} }
} }
} }
} }
&.maxLevel { &.maxLevel {
button.buy { button.buy {
opacity: 0 !important; opacity: 0 !important;
} }
.requirements { .requirements {
display: none; display: none;
} }
.description { .description {
color: $colorGreenBright; color: $colorGreenBright;
} }
} }
} }
} }
} }

View File

@ -33,22 +33,47 @@
&.displayIcons, &.displayIcons,
&.displayDetailed, &.displayDetailed,
&.displaySorted,
&.displayIterateUnit {
background: transparent center center / #{D(15px)} no-repeat;
}
&.displayDetailed {
background-image: uiResource("icons/display_list.png");
}
&.displayIcons {
background-image: uiResource("icons/display_icons.png");
background-size: #{D(11.5px)};
}
&.displayDetailed {
@include S(border-top-left-radius, $globalBorderRadius);
@include S(border-bottom-left-radius, $globalBorderRadius);
}
&.displaySorted { &.displaySorted {
background: uiResource("icons/display_list.png") center center / #{D(15px)} no-repeat; background-image: uiResource("icons/display_sorted.png");
&.displayIcons { background-size: #{D(11.5px)};
background-image: uiResource("icons/display_icons.png"); margin-right: 5px;
background-size: #{D(11.5px)}; @include S(border-top-right-radius, $globalBorderRadius);
} @include S(border-bottom-right-radius, $globalBorderRadius);
&.displaySorted {
background-image: uiResource("icons/display_sorted.png"); @include S(padding, 1px, 0);
background-size: #{D(11.5px)}; }
margin-right: 4px;
@include S(padding, 1px, 0); &.displayIterateUnit {
} background-image: uiResource("icons/toggle_unit.png");
opacity: 0.8;
@include S(padding, 1px, 0);
} }
background-color: #44484a !important; background-color: #44484a !important;
transition: opacity 0.2s ease-in-out; transition: opacity 0.2s ease-in-out;
@include DarkThemeOverride {
background-color: lighten($darkModeControlsBackground, 10) !important;
}
} }
.filtersDataSource, .filtersDataSource,
@ -110,10 +135,10 @@
} }
@include DarkThemeOverride { @include DarkThemeOverride {
background: #222428; background: $darkModeControlsBackground;
&.pinned { &.pinned {
background: darken(#222428, 10); background: mix($darkModeControlsBackground, $colorBlueBright, 90%);
} }
} }
@ -159,6 +184,11 @@
grid-column: 1 / 2; grid-column: 1 / 2;
grid-row: 2 / 3; grid-row: 2 / 3;
justify-self: end; justify-self: end;
color: #55595a;
@include DarkThemeOverride {
color: #aaa;
}
} }
} }
} }
@ -176,6 +206,10 @@
align-self: center; align-self: center;
text-align: right; text-align: right;
color: #55595a; color: #55595a;
@include DarkThemeOverride {
color: #aaa;
}
} }
canvas.graph { canvas.graph {

View File

@ -1,37 +1,52 @@
#state_InGameState { #state_InGameState {
.gameLoadingOverlay { .gameLoadingOverlay {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
z-index: 9999; z-index: 9999;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
pointer-events: all; pointer-events: all;
display: flex; display: flex;
background: $mainBgColor; background: $mainBgColor;
flex-direction: column; flex-direction: column;
} }
#ingame_Canvas { .prefab_GameHint {
position: absolute; position: absolute;
top: 0; @include S(bottom, 40px);
left: 0; @include S(left, 20px);
right: 0; @include S(right, 20px);
bottom: 0; @include PlainText;
} text-align: center;
#ingame_HUD_ModalDialogs {
position: absolute; color: #666;
top: 0;
left: 0; @include DarkThemeOverride() {
right: 0; color: lighten($darkModeGameBackground, 50);
bottom: 0; }
} }
@include DarkThemeOverride { #ingame_Canvas {
.gameLoadingOverlay { position: absolute;
background: $darkModeGameBackground; top: 0;
} left: 0;
} right: 0;
} bottom: 0;
}
#ingame_HUD_ModalDialogs {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
@include DarkThemeOverride {
.gameLoadingOverlay {
background: $darkModeGameBackground;
}
}
}

View File

@ -1,71 +1,71 @@
#state_KeybindingsState { #state_KeybindingsState {
.content { .content {
.topEntries { .topEntries {
display: grid; display: grid;
grid-template-columns: 1fr auto; grid-template-columns: 1fr auto;
@include S(grid-gap, 5px); @include S(grid-gap, 5px);
@include S(margin-bottom, 10px); @include S(margin-bottom, 10px);
} }
.hint { .hint {
display: block; display: block;
background: #eee; background: #eee;
@include S(padding, 4px); @include S(padding, 4px);
@include PlainText; @include PlainText;
} }
.category { .category {
.entry { .entry {
display: grid; display: grid;
@include S(margin-top, 2px); @include S(margin-top, 2px);
@include S(padding-top, 2px); @include S(padding-top, 2px);
@include S(grid-gap, 4px); @include S(grid-gap, 4px);
grid-template-columns: 1fr #{D(100px)} auto auto; grid-template-columns: 1fr #{D(100px)} auto auto;
border-bottom: #{D(1px)} dotted #eee; border-bottom: #{D(1px)} dotted #eee;
color: #888c8f; color: #888c8f;
.mapping { .mapping {
color: $colorBlueBright; color: $colorBlueBright;
text-align: center; text-align: center;
} }
button { button {
@include S(height, 15px); @include S(height, 15px);
@include S(width, 15px); @include S(width, 15px);
@include IncreasedClickArea(0px); @include IncreasedClickArea(0px);
background: transparent center center / 40% no-repeat; background: transparent center center / 40% no-repeat;
opacity: 0.9; opacity: 0.9;
&.editKeybinding { &.editKeybinding {
background-image: uiResource("icons/edit_key.png"); background-image: uiResource("icons/edit_key.png");
} }
&.resetKeybinding { &.resetKeybinding {
background-image: uiResource("icons/reset_key.png"); background-image: uiResource("icons/reset_key.png");
} }
&.disabled { &.disabled {
pointer-events: none; pointer-events: none;
cursor: default; cursor: default;
opacity: 0.1 !important; opacity: 0.1 !important;
} }
} }
} }
} }
} }
@include DarkThemeOverride { @include DarkThemeOverride {
.content { .content {
.hint { .hint {
background: #3b3d40; background: darken($darkModeControlsBackground, 4);
} }
.category .entry { .category .entry {
color: #c0c4c8; color: #c0c4c8;
border-bottom-color: #888; border-bottom-color: #888;
button { button {
filter: invert(1); filter: invert(1);
} }
} }
} }
} }
} }

View File

@ -25,13 +25,15 @@
background: uiResource("icons/main_menu_settings.png") center center / contain no-repeat; background: uiResource("icons/main_menu_settings.png") center center / contain no-repeat;
transition: opacity 0.12s ease-in-out; transition: opacity 0.12s ease-in-out;
@include IncreasedClickArea(2px); @include IncreasedClickArea(2px);
opacity: 0.7;
&:hover { &:hover {
opacity: 0.9; opacity: 1;
} }
} }
.exitAppButton { .exitAppButton {
background-image: uiResource("icons/main_menu_exit.png"); background-image: uiResource("icons/main_menu_exit.png");
background-size: 90%;
} }
.languageChoose { .languageChoose {
@ -40,6 +42,7 @@
background-color: #fff; background-color: #fff;
@include S(border-width, 2px); @include S(border-width, 2px);
background-size: cover; background-size: cover;
opacity: 0.8;
} }
} }
@ -57,7 +60,7 @@
transform: translate(50%, 50%); transform: translate(50%, 50%);
filter: blur(D(3px)); filter: blur(D(3px));
$opacity: 0.2; $opacity: 0.07;
&.loaded { &.loaded {
display: block; display: block;
opacity: $opacity; opacity: $opacity;
@ -121,10 +124,13 @@
} }
.steamLink { .steamLink {
align-self: center;
justify-self: center;
width: 100%; width: 100%;
@include S(height, 40px); @include S(height, 40px);
@include S(width, 180px);
background: uiResource("get_on_steam.png") center center / contain no-repeat; background: #171a23 uiResource("get_on_steam.png") center center / contain no-repeat;
overflow: hidden; overflow: hidden;
display: block; display: block;
text-indent: -999em; text-indent: -999em;
@ -134,8 +140,11 @@
transition: all 0.12s ease-in; transition: all 0.12s ease-in;
transition-property: opacity, transform; transition-property: opacity, transform;
transform: skewX(-0.5deg); transform: skewX(-0.5deg);
@include S(border-radius, $globalBorderRadius);
&:hover { &:hover {
transform: skewX(-1deg) scale(1.02); transform: scale(1.02);
opacity: 0.9; opacity: 0.9;
} }
} }
@ -332,25 +341,39 @@
button.downloadGame { button.downloadGame {
grid-column: 3 / 4; grid-column: 3 / 4;
grid-row: 1 / 2; grid-row: 1 / 2;
background-color: $colorBlueBright; background-color: transparent;
background-image: uiResource("icons/download.png"); background-image: uiResource("icons/download.png");
@include S(width, 15px); @include S(width, 15px);
@include IncreasedClickArea(0px); @include IncreasedClickArea(0px);
@include S(height, 15px); @include S(height, 15px);
background-size: 60%; background-size: 80%;
align-self: start; align-self: start;
opacity: 0.4;
&:hover {
opacity: 0.5;
}
@include DarkThemeInvert;
} }
button.deleteGame { button.deleteGame {
grid-column: 3 / 4; grid-column: 3 / 4;
grid-row: 2 / 3; grid-row: 2 / 3;
background-color: $colorRedBright; background-color: transparent;
@include IncreasedClickArea(0px); @include IncreasedClickArea(0px);
background-image: uiResource("icons/delete.png"); background-image: uiResource("icons/delete.png");
@include S(width, 15px); @include S(width, 15px);
@include S(height, 15px); @include S(height, 15px);
align-self: end; align-self: end;
background-size: 60%; background-size: 80%;
opacity: 0.4;
&:hover {
opacity: 0.5;
}
@include DarkThemeInvert;
} }
button.renameGame { button.renameGame {
@ -363,11 +386,11 @@
justify-self: center; justify-self: center;
background-size: 90%; background-size: 90%;
opacity: 0.25; opacity: 0.4;
@include S(margin-left, 4px); @include S(margin-left, 4px);
&:hover { &:hover {
opacity: 0.35; opacity: 0.5;
} }
@include DarkThemeInvert; @include DarkThemeInvert;
@ -379,6 +402,11 @@
margin: 0; margin: 0;
@include S(width, 32px); @include S(width, 32px);
height: 100%; height: 100%;
@include S(margin-left, 4px);
@include DarkThemeOverride {
background-color: lighten($darkModeControlsBackground, 10);
}
} }
} }
} }
@ -407,13 +435,17 @@
@include S(padding, 15px); @include S(padding, 15px);
$linkBg: #fdfdff;
$linkBgHover: darken($linkBg, 2);
$linkColor: #55586a;
> .boxLink { > .boxLink {
display: grid; display: grid;
align-items: center; align-items: center;
grid-template-columns: 1fr auto; grid-template-columns: 1fr auto;
justify-content: center; justify-content: center;
background: #fdfdfd uiResource("icons/link.png") top D(3px) right D(3px) / D(9px) no-repeat; background: $linkBg uiResource("icons/link.png") top D(3px) right D(3px) / D(9px) no-repeat;
@include S(padding, 5px); @include S(padding, 5px);
@include S(padding-left, 10px); @include S(padding-left, 10px);
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
@ -422,7 +454,7 @@
font-weight: bold; font-weight: bold;
box-sizing: border-box; box-sizing: border-box;
text-transform: uppercase; text-transform: uppercase;
color: #616266; color: $linkColor;
transition: background-color 0.12s ease-in-out; transition: background-color 0.12s ease-in-out;
pointer-events: all; pointer-events: all;
@ -431,7 +463,7 @@
cursor: pointer; cursor: pointer;
&:hover { &:hover {
background-color: #f0f6ff; background-color: $linkBgHover;
} }
.thirdpartyLogo { .thirdpartyLogo {
@ -458,12 +490,12 @@
@include S(height, 60px); @include S(height, 60px);
> a { > a {
color: #616266; color: $linkColor;
background: #fdfdfd; background: $linkBg;
height: 100%; height: 100%;
&:hover { &:hover {
background-color: #f0f6ff; background-color: $linkBgHover;
} }
@include SuperSmallText; @include SuperSmallText;
text-transform: uppercase; text-transform: uppercase;
@ -499,19 +531,11 @@
@include DarkThemeOverride { @include DarkThemeOverride {
background: $darkModeGameBackground center center / cover !important; background: $darkModeGameBackground center center / cover !important;
.topButtons {
filter: invert(1);
.languageChoose {
filter: invert(1);
}
}
.mainContainer { .mainContainer {
background: darken($darkModeGameBackground, 10); background: $darkModeControlsBackground;
.savegames .savegame { .savegames .savegame {
background: darken($darkModeGameBackground, 15); background: darken($darkModeControlsBackground, 5);
color: white; color: white;
} }
} }
@ -519,11 +543,11 @@
.footer { .footer {
> a, > a,
.sidelinks > a { .sidelinks > a {
background-color: darken($darkModeGameBackground, 10); background-color: $darkModeControlsBackground;
color: #eee; color: #eee;
&:hover { &:hover {
background-color: darken($darkModeGameBackground, 8); background-color: darken($darkModeControlsBackground, 5);
} }
} }

View File

@ -1,145 +1,145 @@
#state_PreloadState { #state_PreloadState {
&.failure { &.failure {
.loadingImage, .loadingImage,
.loadingStatus { .loadingStatus {
display: none; display: none;
} }
} }
.changelogDialogEntry { .changelogDialogEntry {
margin-top: 10px; margin-top: 10px;
width: 100%; width: 100%;
flex-direction: column; flex-direction: column;
text-align: left; text-align: left;
padding: 10px; padding: 10px;
box-sizing: border-box; box-sizing: border-box;
background: #eef1f4; background: #eef1f4;
@include DarkThemeOverride { @include DarkThemeOverride {
background: #424242; background: #424242;
} }
.version { .version {
@include Heading; @include Heading;
} }
.date { .date {
@include PlainText; @include PlainText;
&::before { &::before {
content: " | "; content: " | ";
} }
color: #aaabaf; color: #aaabaf;
} }
.changes { .changes {
@include PlainText; @include PlainText;
@include S(padding-left, 15px); @include S(padding-left, 15px);
strong { strong {
background: $colorBlueBright; background: $colorBlueBright;
color: #fff; color: #fff;
text-transform: uppercase; text-transform: uppercase;
@include S(padding, 1px, 2px); @include S(padding, 1px, 2px);
@include S(margin-right, 3px); @include S(margin-right, 3px);
} }
a { a {
color: $colorBlueBright; color: $colorBlueBright;
} }
li { li {
@include SuperSmallText; @include SuperSmallText;
@include S(margin-bottom, 10px); @include S(margin-bottom, 10px);
} }
} }
} }
.failureBox { .failureBox {
.logo { .logo {
img { img {
@include S(width, 240px); @include S(width, 240px);
} }
@include S(margin-bottom, 30px); @include S(margin-bottom, 30px);
} }
@include InlineAnimation(0.3s ease-in-out) { @include InlineAnimation(0.3s ease-in-out) {
0% { 0% {
opacity: 0; opacity: 0;
} }
100% { 100% {
opacity: 1; opacity: 1;
} }
} }
.failureInner { .failureInner {
// background: darken($mainBgColor, 6); // background: darken($mainBgColor, 6);
@include S(max-width, 350px); @include S(max-width, 350px);
margin: 0 20px; margin: 0 20px;
text-align: left; text-align: left;
@include BoxShadow3D(#fff); @include BoxShadow3D(#fff);
@include S(padding, 15px); @include S(padding, 15px);
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
@include DropShadow; @include DropShadow;
.errorHeader { .errorHeader {
color: #ef5072; color: #ef5072;
} }
.errorMessage { .errorMessage {
@include PlainText; @include PlainText;
display: block; display: block;
color: #666; color: #666;
text-align: left; text-align: left;
@include BreakText; @include BreakText;
hyphens: auto; hyphens: auto;
// border: dotted #666; // border: dotted #666;
// @include S(border-width, 1px, 0); // @include S(border-width, 1px, 0);
@include S(padding, 10px, 0); @include S(padding, 10px, 0);
@include S(margin-top, 10px); @include S(margin-top, 10px);
} }
.supportHelp { .supportHelp {
@include S(margin-top, 10px); @include S(margin-top, 10px);
@include PlainText; @include PlainText;
.email { .email {
color: $themeColor; color: $themeColor;
cursor: pointer; cursor: pointer;
pointer-events: all; pointer-events: all;
} }
} }
.lower { .lower {
display: flex; display: flex;
align-items: center; align-items: center;
@include S(margin-top, 16px); @include S(margin-top, 16px);
i { i {
flex-grow: 1; flex-grow: 1;
text-align: right; text-align: right;
color: #777; color: #777;
@include PlainText; @include PlainText;
} }
button.resetApp { button.resetApp {
@include Button3D($colorRedBright); @include Button3D($colorRedBright);
@include PlainText; @include PlainText;
@include S(padding, 5px, 8px, 4px); @include S(padding, 5px, 8px, 4px);
color: #fff; color: #fff;
} }
} }
} }
} }
/* Animations */ /* Animations */
.status { .status {
transform: scale(0.7) $hardwareAcc; transform: scale(0.7) $hardwareAcc;
opacity: 0; opacity: 0;
@include StateAnim(transform, opacity); @include StateAnim(transform, opacity);
} }
&.arrived { &.arrived {
.status { .status {
opacity: 1; opacity: 1;
transform: none; transform: none;
} }
} }
} }

View File

@ -1,13 +1,95 @@
#state_SettingsState { #state_SettingsState {
$colorCategoryButton: #eee; $colorCategoryButton: #eeeff5;
$colorCategoryButtonSelected: #5f748b; $colorCategoryButtonSelected: $colorBlueBright;
$layoutBreak: 1000px;
.container .content { .container .content {
display: flex; display: grid;
overflow-y: scroll; grid-template-columns: auto 1fr;
@include S(grid-gap, 10px);
@include StyleBelowWidth($layoutBreak) {
grid-template-columns: 1fr;
}
.sidebar {
display: grid;
@include S(min-width, 210px);
@include S(max-width, 320px);
@include S(grid-gap, 3px);
grid-template-rows: auto auto auto auto auto 1fr;
@include StyleBelowWidth($layoutBreak) {
grid-template-rows: 1fr 1fr;
grid-template-columns: auto auto;
max-width: unset !important;
}
button {
text-align: left;
&::after {
content: unset;
}
width: 100%;
box-sizing: border-box;
@include StyleBelowWidth($layoutBreak) {
text-align: center;
}
}
.other {
@include S(margin-top, 10px);
align-self: end;
@include StyleBelowWidth($layoutBreak) {
margin-top: 0;
}
}
button.categoryButton,
button.about {
background-color: $colorCategoryButton;
color: #777a7f;
&.active {
background-color: $colorCategoryButtonSelected;
color: #fff;
&:hover {
opacity: 1;
}
}
&.pressed {
transform: none !important;
}
}
.versionbar {
@include S(margin-top, 10px);
@include StyleBelowWidth($layoutBreak) {
display: none;
}
@include SuperSmallText;
display: grid;
align-items: center;
grid-template-columns: 1fr auto;
.buildVersion {
display: flex;
flex-direction: column;
color: #aaadaf;
}
}
}
.categoryContainer { .categoryContainer {
width: 100%; overflow-y: scroll;
pointer-events: all;
@include S(padding-right, 10px);
.category { .category {
display: none; display: none;
@ -88,65 +170,6 @@
} }
} }
} }
.sidebar {
display: flex;
flex-direction: column;
@include S(min-width, 210px);
@include S(max-width, 320px);
width: 30%;
height: 100%;
position: sticky;
top: 0;
@include S(margin-left, 20px);
@include S(margin-right, 32px);
.other {
margin-top: auto;
}
button {
@include S(margin-top, 4px);
width: calc(100% - #{D(20px)});
text-align: start;
&::after {
content: unset;
}
}
button.categoryButton,
button.about {
background-color: $colorCategoryButton;
color: #777a7f;
&.active {
background-color: $colorCategoryButtonSelected;
color: #fff;
&:hover {
opacity: 1;
}
}
&.pressed {
transform: none !important;
}
}
.versionbar {
@include S(margin-top, 20px);
@include SuperSmallText;
display: grid;
align-items: center;
grid-template-columns: 1fr auto;
.buildVersion {
display: flex;
flex-direction: column;
color: #aaadaf;
}
}
}
} }
@include DarkThemeOverride { @include DarkThemeOverride {
@ -154,10 +177,12 @@
.sidebar { .sidebar {
button.categoryButton, button.categoryButton,
button.about { button.about {
background-color: #3f3f47; color: #ccc;
background-color: darken($darkModeControlsBackground, 5);
&.active { &.active {
background-color: $colorBlueBright; color: #fff;
background-color: $colorCategoryButtonSelected;
} }
} }
} }
@ -169,8 +194,13 @@
.value.enum { .value.enum {
// dirty but works // dirty but works
filter: invert(0.78) sepia(40%) hue-rotate(190deg); // color: #222;
color: #222; background-color: $darkModeControlsBackground;
background-image: uiResource("icons/enum_selector_white.png");
color: #ddd;
&:hover {
background-color: darken($darkModeControlsBackground, 2);
}
} }
.value.checkbox { .value.checkbox {

View File

@ -1,81 +1,81 @@
.gameState.textualState { .gameState.textualState {
display: grid; display: grid;
grid-template-rows: auto 1fr; grid-template-rows: auto 1fr;
box-sizing: border-box; box-sizing: border-box;
@include S(padding, 32px); @include S(padding, 32px);
height: 100vh; height: 100vh;
.headerBar { .headerBar {
display: flex; display: flex;
h1 { h1 {
display: grid; display: grid;
grid-template-columns: auto 1fr; grid-template-columns: auto 1fr;
align-items: center; align-items: center;
pointer-events: all; pointer-events: all;
cursor: pointer; cursor: pointer;
@include SuperHeading; @include SuperHeading;
text-transform: uppercase; text-transform: uppercase;
color: #333438; color: #333438;
position: relative; position: relative;
@include IncreasedClickArea(10px); @include IncreasedClickArea(10px);
} }
.backButton { .backButton {
@include S(width, 30px); @include S(width, 30px);
@include S(height, 30px); @include S(height, 30px);
@include S(margin-right, 10px); @include S(margin-right, 10px);
@include S(margin-left, -5px); @include S(margin-left, -5px);
background: uiResource("icons/state_back_button.png") center center / 70% no-repeat; background: uiResource("icons/state_back_button.png") center center / 70% no-repeat;
} }
@include S(margin-bottom, 20px); @include S(margin-bottom, 20px);
} }
> .container { > .container {
display: flex; display: flex;
justify-content: center; justify-content: center;
width: 100%; width: 100%;
overflow-y: auto; overflow-y: auto;
> .content { > .content {
width: 100%; width: 100%;
background: #fff; background: #fff;
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
@include S(padding, 10px); @include S(padding, 10px);
height: 100%; height: 100%;
overflow-y: auto; overflow-y: auto;
box-sizing: border-box; box-sizing: border-box;
pointer-events: all; pointer-events: all;
a { a {
color: $colorBlueBright; color: $colorBlueBright;
} }
.categoryLabel { .categoryLabel {
display: block; display: block;
text-transform: uppercase; text-transform: uppercase;
@include S(margin-top, 15px); @include S(margin-top, 15px);
@include S(margin-bottom, 15px); @include S(margin-bottom, 15px);
@include Heading; @include Heading;
} }
} }
} }
@include DarkThemeOverride { @include DarkThemeOverride {
.headerBar { .headerBar {
h1 { h1 {
color: #e2e0db; color: #e2e0db;
} }
.backButton { .backButton {
filter: invert(1); filter: invert(1);
} }
} }
> .container > .content { > .container > .content {
background: darken($darkModeGameBackground, 3); background: $darkModeControlsBackground;
color: #eee; color: #eee;
} }
} }
} }

View File

@ -1,198 +1,199 @@
$globalBorderRadius: 2px; $globalBorderRadius: 2px;
// When to reduce control elements size for small devices // When to reduce control elements size for small devices
$layoutExpandMinWidth: 340px; $layoutExpandMinWidth: 340px;
// Font sizes and line heights // Font sizes and line heights
$superHeadingFontSize: 25px; $superHeadingFontSize: 25px;
$superHeadingLineHeight: 24px; $superHeadingLineHeight: 24px;
$breakTooltipShowStatsPx: 1023px; $breakTooltipShowStatsPx: 1023px;
$headingFontSize: 19px; $headingFontSize: 19px;
$headingLineHeight: 21px; $headingLineHeight: 21px;
$textFontSize: 16px; $textFontSize: 16px;
$textLineHeight: 21px; $textLineHeight: 21px;
$plainTextFontSize: 13px; $plainTextFontSize: 13px;
$plainTextLineHeight: 17px; $plainTextLineHeight: 17px;
$supersmallTextFontSize: 10px; $supersmallTextFontSize: 10px;
$supersmallTextLineHeight: 13px; $supersmallTextLineHeight: 13px;
$buttonFontSize: 14px; $buttonFontSize: 14px;
$buttonLineHeight: 18px; $buttonLineHeight: 18px;
// Main background color // Main background color
$mainBgColor: #dee1ea; $mainBgColor: #dee1ea;
// Accent colors // Accent colors
$accentColorBright: #e1e4ed; $accentColorBright: #e1e4ed;
$accentColorDark: #7d808a; $accentColorDark: #7d808a;
$colorGreenBright: #66bb6a; $colorGreenBright: #66bb6a;
$colorBlueBright: rgb(74, 163, 223); $colorBlueBright: rgb(74, 151, 223);
$colorRedBright: #ef5072; $colorRedBright: #ef5072;
$themeColor: #393747; $themeColor: #393747;
$ingameHudBg: rgba(#333438, 0.9); $ingameHudBg: rgba(#333438, 0.9);
$text3dColor: #f4ffff; $text3dColor: #f4ffff;
$darkModeGameBackground: #5c606c; $darkModeGameBackground: #535866;
$darkModeControlsBackground: darken($darkModeGameBackground, 5);
// Dialog properties
$modalDialogBg: rgba(160, 165, 180, 0.8); // Dialog properties
$dialogBgColor: lighten($mainBgColor, 10); $modalDialogBg: rgba(160, 165, 180, 0.8);
$dialogBgColor: lighten($mainBgColor, 10);
$lightFontWeight: normal;
$boldFontWeight: 600; $lightFontWeight: normal;
$boldFontWeight: 600;
$iconSizeSmall: 30px;
$iconSizeMedium: 40px; $iconSizeSmall: 30px;
$iconSizeLarge: 60px; $iconSizeMedium: 40px;
$iconSizeLarge: 60px;
// Poppins 500
// Rubik 400 // Poppins 500
// Cairo 400 // Rubik 400
// Viga 400 // Cairo 400
// Sniglet 400 // Viga 400
// Sniglet 400
$mainFont: "GameFont", sans-serif;
// $mainFont: "DK Canoodle"; $mainFont: "GameFont", sans-serif;
// $mainFont: "MADE Florence Sans"; // $mainFont: "DK Canoodle";
$numberFont: $mainFont; // $mainFont: "MADE Florence Sans";
$textFont: $mainFont; $numberFont: $mainFont;
$textFont: $mainFont;
$mainFontWeight: 400;
$mainFontSpacing: 0.04em; $mainFontWeight: 400;
$mainFontScale: 1; $mainFontSpacing: 0.04em;
$mainFontScale: 1;
@mixin DebugText($color) {
// font-size: 3px; @mixin DebugText($color) {
// &, // font-size: 3px;
// * { // &,
// color: $color !important; // * {
// } // color: $color !important;
} // }
}
@mixin SuperSmallText {
@include ScaleFont($supersmallTextFontSize, $supersmallTextLineHeight); @mixin SuperSmallText {
font-weight: $mainFontWeight; @include ScaleFont($supersmallTextFontSize, $supersmallTextLineHeight);
font-family: $mainFont; font-weight: $mainFontWeight;
letter-spacing: $mainFontSpacing; font-family: $mainFont;
@include DebugText(green); letter-spacing: $mainFontSpacing;
} @include DebugText(green);
}
@mixin PlainText {
@include ScaleFont($plainTextFontSize, $plainTextLineHeight); @mixin PlainText {
font-weight: $mainFontWeight; @include ScaleFont($plainTextFontSize, $plainTextLineHeight);
font-family: $mainFont; font-weight: $mainFontWeight;
letter-spacing: $mainFontSpacing; font-family: $mainFont;
letter-spacing: $mainFontSpacing;
@include DebugText(red);
} @include DebugText(red);
}
@mixin Text {
@include ScaleFont($textFontSize, $textLineHeight); @mixin Text {
font-weight: $mainFontWeight; @include ScaleFont($textFontSize, $textLineHeight);
font-family: $mainFont; font-weight: $mainFontWeight;
font-family: $mainFont;
letter-spacing: $mainFontSpacing;
letter-spacing: $mainFontSpacing;
@include DebugText(blue);
} @include DebugText(blue);
}
@mixin Heading {
@include ScaleFont($headingFontSize, $headingLineHeight); @mixin Heading {
font-weight: $mainFontWeight; @include ScaleFont($headingFontSize, $headingLineHeight);
font-family: $mainFont; font-weight: $mainFontWeight;
letter-spacing: $mainFontSpacing; font-family: $mainFont;
letter-spacing: $mainFontSpacing;
@include DebugText(yellow);
} @include DebugText(yellow);
}
@mixin SuperHeading {
@include ScaleFont($superHeadingFontSize, $superHeadingLineHeight); @mixin SuperHeading {
font-weight: $mainFontWeight; @include ScaleFont($superHeadingFontSize, $superHeadingLineHeight);
font-family: $mainFont; font-weight: $mainFontWeight;
letter-spacing: $mainFontSpacing; font-family: $mainFont;
letter-spacing: $mainFontSpacing;
@include DebugText(orange);
} @include DebugText(orange);
}
@mixin ButtonText {
@include ScaleFont($buttonFontSize, $buttonLineHeight); @mixin ButtonText {
font-weight: $mainFontWeight; @include ScaleFont($buttonFontSize, $buttonLineHeight);
font-family: $mainFont; font-weight: $mainFontWeight;
letter-spacing: $mainFontSpacing; font-family: $mainFont;
@include DebugText(purple); letter-spacing: $mainFontSpacing;
} @include DebugText(purple);
}
@function str-split($string, $separator) {
// empty array/list @function str-split($string, $separator) {
$split-arr: (); // empty array/list
// first index of separator in string $split-arr: ();
$index: str-index($string, $separator); // first index of separator in string
// loop through string $index: str-index($string, $separator);
@while $index != null { // loop through string
// get the substring from the first character to the separator @while $index != null {
$item: str-slice($string, 1, $index - 1); // get the substring from the first character to the separator
// push item to array $item: str-slice($string, 1, $index - 1);
$split-arr: append($split-arr, $item); // push item to array
// remove item and separator from string $split-arr: append($split-arr, $item);
$string: str-slice($string, $index + 1); // remove item and separator from string
// find new index of separator $string: str-slice($string, $index + 1);
$index: str-index($string, $separator); // find new index of separator
} $index: str-index($string, $separator);
// add the remaining string to list (the last item) }
$split-arr: append($split-arr, $string); // add the remaining string to list (the last item)
$split-arr: append($split-arr, $string);
@return $split-arr;
} @return $split-arr;
}
@function _first-index($string, $direction: "left") {
@for $i from 1 through str-length($string) { @function _first-index($string, $direction: "left") {
$index: if($direction == "left", $i, -$i); @for $i from 1 through str-length($string) {
$index: if($direction == "left", $i, -$i);
@if str-slice($string, $index, $index) != " " {
@return $index; @if str-slice($string, $index, $index) != " " {
} @return $index;
} }
}
@return 0;
} @return 0;
}
@function trim($string) {
@return str-slice($string, _first-index($string, "left"), _first-index($string, "right")); @function trim($string) {
} @return str-slice($string, _first-index($string, "left"), _first-index($string, "right"));
}
@mixin AppendGlobal($prefix) {
$strSelector: quote(&); @mixin AppendGlobal($prefix) {
$selectors: str-split($strSelector, ","); $strSelector: quote(&);
$selectors: str-split($strSelector, ",");
$builtSelector: null;
$builtSelector: null;
@if (& == null) {
$builtSelector: "html" + $prefix; @if (& == null) {
} @else { $builtSelector: "html" + $prefix;
$builtSelector: (); } @else {
// @debug ($strSelector, "->>>", $selectors); $builtSelector: ();
@each $srcSelector in $selectors { // @debug ($strSelector, "->>>", $selectors);
$srcSelector: trim($srcSelector); @each $srcSelector in $selectors {
// @debug ("___", $srcSelector); $srcSelector: trim($srcSelector);
$selector: "html" + $prefix + " " + $srcSelector; // @debug ("___", $srcSelector);
@if str-index($srcSelector, "html.") { $selector: "html" + $prefix + " " + $srcSelector;
$selector: "html" + @if str-index($srcSelector, "html.") {
$prefix + $selector: "html" +
"." + $prefix +
str-slice($srcSelector, str-index($srcSelector, "html.") + 5); "." +
} str-slice($srcSelector, str-index($srcSelector, "html.") + 5);
// @debug ("_______", $selector); }
$builtSelector: append($builtSelector, $selector, comma); // @debug ("_______", $selector);
} $builtSelector: append($builtSelector, $selector, comma);
} }
}
@at-root #{$builtSelector} {
@content; @at-root #{$builtSelector} {
} @content;
} }
}

View File

@ -1,408 +1,411 @@
import { AnimationFrame } from "./core/animation_frame"; import { AnimationFrame } from "./core/animation_frame";
import { BackgroundResourcesLoader } from "./core/background_resources_loader"; import { BackgroundResourcesLoader } from "./core/background_resources_loader";
import { IS_MOBILE } from "./core/config"; import { IS_MOBILE } from "./core/config";
import { GameState } from "./core/game_state"; import { GameState } from "./core/game_state";
import { GLOBAL_APP, setGlobalApp } from "./core/globals"; import { GLOBAL_APP, setGlobalApp } from "./core/globals";
import { InputDistributor } from "./core/input_distributor"; import { InputDistributor } from "./core/input_distributor";
import { Loader } from "./core/loader"; import { Loader } from "./core/loader";
import { createLogger, logSection } from "./core/logging"; import { createLogger, logSection } from "./core/logging";
import { StateManager } from "./core/state_manager"; import { StateManager } from "./core/state_manager";
import { TrackedState } from "./core/tracked_state"; import { TrackedState } from "./core/tracked_state";
import { getPlatformName, waitNextFrame } from "./core/utils"; import { getPlatformName, waitNextFrame } from "./core/utils";
import { Vector } from "./core/vector"; import { Vector } from "./core/vector";
import { AdProviderInterface } from "./platform/ad_provider"; import { AdProviderInterface } from "./platform/ad_provider";
import { NoAdProvider } from "./platform/ad_providers/no_ad_provider"; import { NoAdProvider } from "./platform/ad_providers/no_ad_provider";
import { AnalyticsInterface } from "./platform/analytics"; import { AnalyticsInterface } from "./platform/analytics";
import { GoogleAnalyticsImpl } from "./platform/browser/google_analytics"; import { GoogleAnalyticsImpl } from "./platform/browser/google_analytics";
import { SoundImplBrowser } from "./platform/browser/sound"; import { SoundImplBrowser } from "./platform/browser/sound";
import { PlatformWrapperImplBrowser } from "./platform/browser/wrapper"; import { PlatformWrapperImplBrowser } from "./platform/browser/wrapper";
import { PlatformWrapperImplElectron } from "./platform/electron/wrapper"; import { PlatformWrapperImplElectron } from "./platform/electron/wrapper";
import { PlatformWrapperInterface } from "./platform/wrapper"; import { PlatformWrapperInterface } from "./platform/wrapper";
import { ApplicationSettings } from "./profile/application_settings"; import { ApplicationSettings } from "./profile/application_settings";
import { SavegameManager } from "./savegame/savegame_manager"; import { SavegameManager } from "./savegame/savegame_manager";
import { AboutState } from "./states/about"; import { AboutState } from "./states/about";
import { ChangelogState } from "./states/changelog"; import { ChangelogState } from "./states/changelog";
import { InGameState } from "./states/ingame"; import { InGameState } from "./states/ingame";
import { KeybindingsState } from "./states/keybindings"; import { KeybindingsState } from "./states/keybindings";
import { MainMenuState } from "./states/main_menu"; import { MainMenuState } from "./states/main_menu";
import { MobileWarningState } from "./states/mobile_warning"; import { MobileWarningState } from "./states/mobile_warning";
import { PreloadState } from "./states/preload"; import { PreloadState } from "./states/preload";
import { SettingsState } from "./states/settings"; import { SettingsState } from "./states/settings";
import { ShapezGameAnalytics } from "./platform/browser/game_analytics"; import { ShapezGameAnalytics } from "./platform/browser/game_analytics";
/** /**
* @typedef {import("./platform/game_analytics").GameAnalyticsInterface} GameAnalyticsInterface * @typedef {import("./platform/game_analytics").GameAnalyticsInterface} GameAnalyticsInterface
* @typedef {import("./platform/sound").SoundInterface} SoundInterface * @typedef {import("./platform/sound").SoundInterface} SoundInterface
* @typedef {import("./platform/storage").StorageInterface} StorageInterface * @typedef {import("./platform/storage").StorageInterface} StorageInterface
*/ */
const logger = createLogger("application"); const logger = createLogger("application");
// Set the name of the hidden property and the change event for visibility // Set the name of the hidden property and the change event for visibility
let pageHiddenPropName, pageVisibilityEventName; let pageHiddenPropName, pageVisibilityEventName;
if (typeof document.hidden !== "undefined") { if (typeof document.hidden !== "undefined") {
// Opera 12.10 and Firefox 18 and later support // Opera 12.10 and Firefox 18 and later support
pageHiddenPropName = "hidden"; pageHiddenPropName = "hidden";
pageVisibilityEventName = "visibilitychange"; pageVisibilityEventName = "visibilitychange";
// @ts-ignore // @ts-ignore
} else if (typeof document.msHidden !== "undefined") { } else if (typeof document.msHidden !== "undefined") {
pageHiddenPropName = "msHidden"; pageHiddenPropName = "msHidden";
pageVisibilityEventName = "msvisibilitychange"; pageVisibilityEventName = "msvisibilitychange";
// @ts-ignore // @ts-ignore
} else if (typeof document.webkitHidden !== "undefined") { } else if (typeof document.webkitHidden !== "undefined") {
pageHiddenPropName = "webkitHidden"; pageHiddenPropName = "webkitHidden";
pageVisibilityEventName = "webkitvisibilitychange"; pageVisibilityEventName = "webkitvisibilitychange";
} }
export class Application { export class Application {
constructor() { constructor() {
assert(!GLOBAL_APP, "Tried to construct application twice"); assert(!GLOBAL_APP, "Tried to construct application twice");
logger.log("Creating application, platform =", getPlatformName()); logger.log("Creating application, platform =", getPlatformName());
setGlobalApp(this); setGlobalApp(this);
this.unloaded = false; this.unloaded = false;
// Global stuff // Global stuff
this.settings = new ApplicationSettings(this); this.settings = new ApplicationSettings(this);
this.ticker = new AnimationFrame(); this.ticker = new AnimationFrame();
this.stateMgr = new StateManager(this); this.stateMgr = new StateManager(this);
this.savegameMgr = new SavegameManager(this); this.savegameMgr = new SavegameManager(this);
this.inputMgr = new InputDistributor(this); this.inputMgr = new InputDistributor(this);
this.backgroundResourceLoader = new BackgroundResourcesLoader(this); this.backgroundResourceLoader = new BackgroundResourcesLoader(this);
// Platform dependent stuff // Platform dependent stuff
/** @type {StorageInterface} */ /** @type {StorageInterface} */
this.storage = null; this.storage = null;
/** @type {SoundInterface} */ /** @type {SoundInterface} */
this.sound = null; this.sound = null;
/** @type {PlatformWrapperInterface} */ /** @type {PlatformWrapperInterface} */
this.platformWrapper = null; this.platformWrapper = null;
/** @type {AdProviderInterface} */ /** @type {AdProviderInterface} */
this.adProvider = null; this.adProvider = null;
/** @type {AnalyticsInterface} */ /** @type {AnalyticsInterface} */
this.analytics = null; this.analytics = null;
/** @type {GameAnalyticsInterface} */ /** @type {GameAnalyticsInterface} */
this.gameAnalytics = null; this.gameAnalytics = null;
this.initPlatformDependentInstances(); this.initPlatformDependentInstances();
// Track if the window is focused (only relevant for browser) // Track if the window is focused (only relevant for browser)
this.focused = true; this.focused = true;
// Track if the window is visible // Track if the window is visible
this.pageVisible = true; this.pageVisible = true;
// Track if the app is paused (cordova) // Track if the app is paused (cordova)
this.applicationPaused = false; this.applicationPaused = false;
/** @type {TypedTrackedState<boolean>} */ /** @type {TypedTrackedState<boolean>} */
this.trackedIsRenderable = new TrackedState(this.onAppRenderableStateChanged, this); this.trackedIsRenderable = new TrackedState(this.onAppRenderableStateChanged, this);
// Dimensions // Dimensions
this.screenWidth = 0; this.screenWidth = 0;
this.screenHeight = 0; this.screenHeight = 0;
// Store the timestamp where we last checked for a screen resize, since orientationchange is unreliable with cordova // Store the timestamp where we last checked for a screen resize, since orientationchange is unreliable with cordova
this.lastResizeCheck = null; this.lastResizeCheck = null;
// Store the mouse position, or null if not available // Store the mouse position, or null if not available
/** @type {Vector|null} */ /** @type {Vector|null} */
this.mousePosition = null; this.mousePosition = null;
} }
/** /**
* Initializes all platform instances * Initializes all platform instances
*/ */
initPlatformDependentInstances() { initPlatformDependentInstances() {
logger.log("Creating platform dependent instances (standalone=", G_IS_STANDALONE, ")"); logger.log("Creating platform dependent instances (standalone=", G_IS_STANDALONE, ")");
if (G_IS_STANDALONE) { if (G_IS_STANDALONE) {
this.platformWrapper = new PlatformWrapperImplElectron(this); this.platformWrapper = new PlatformWrapperImplElectron(this);
} else { } else {
this.platformWrapper = new PlatformWrapperImplBrowser(this); this.platformWrapper = new PlatformWrapperImplBrowser(this);
} }
// Start with empty ad provider // Start with empty ad provider
this.adProvider = new NoAdProvider(this); this.adProvider = new NoAdProvider(this);
this.sound = new SoundImplBrowser(this); this.sound = new SoundImplBrowser(this);
this.analytics = new GoogleAnalyticsImpl(this); this.analytics = new GoogleAnalyticsImpl(this);
this.gameAnalytics = new ShapezGameAnalytics(this); this.gameAnalytics = new ShapezGameAnalytics(this);
} }
/** /**
* Registers all game states * Registers all game states
*/ */
registerStates() { registerStates() {
/** @type {Array<typeof GameState>} */ /** @type {Array<typeof GameState>} */
const states = [ const states = [
PreloadState, PreloadState,
MobileWarningState, MobileWarningState,
MainMenuState, MainMenuState,
InGameState, InGameState,
SettingsState, SettingsState,
KeybindingsState, KeybindingsState,
AboutState, AboutState,
ChangelogState, ChangelogState,
]; ];
for (let i = 0; i < states.length; ++i) { for (let i = 0; i < states.length; ++i) {
this.stateMgr.register(states[i]); this.stateMgr.register(states[i]);
} }
} }
/** /**
* Registers all event listeners * Registers all event listeners
*/ */
registerEventListeners() { registerEventListeners() {
window.addEventListener("focus", this.onFocus.bind(this)); window.addEventListener("focus", this.onFocus.bind(this));
window.addEventListener("blur", this.onBlur.bind(this)); window.addEventListener("blur", this.onBlur.bind(this));
window.addEventListener("resize", () => this.checkResize(), true); window.addEventListener("resize", () => this.checkResize(), true);
window.addEventListener("orientationchange", () => this.checkResize(), true); window.addEventListener("orientationchange", () => this.checkResize(), true);
if (!G_IS_MOBILE_APP && !IS_MOBILE) { if (!G_IS_MOBILE_APP && !IS_MOBILE) {
window.addEventListener("mousemove", this.handleMousemove.bind(this)); window.addEventListener("mousemove", this.handleMousemove.bind(this));
} window.addEventListener("mouseout", this.handleMousemove.bind(this));
window.addEventListener("mouseover", this.handleMousemove.bind(this));
// Unload events window.addEventListener("mouseleave", this.handleMousemove.bind(this));
window.addEventListener("beforeunload", this.onBeforeUnload.bind(this), true); }
window.addEventListener("unload", this.onUnload.bind(this), true);
// Unload events
document.addEventListener(pageVisibilityEventName, this.handleVisibilityChange.bind(this), false); window.addEventListener("beforeunload", this.onBeforeUnload.bind(this), true);
window.addEventListener("unload", this.onUnload.bind(this), true);
// Track touches so we can update the focus appropriately
document.addEventListener("touchstart", this.updateFocusAfterUserInteraction.bind(this), true); document.addEventListener(pageVisibilityEventName, this.handleVisibilityChange.bind(this), false);
document.addEventListener("touchend", this.updateFocusAfterUserInteraction.bind(this), true);
} // Track touches so we can update the focus appropriately
document.addEventListener("touchstart", this.updateFocusAfterUserInteraction.bind(this), true);
/** document.addEventListener("touchend", this.updateFocusAfterUserInteraction.bind(this), true);
* Checks the focus after a touch }
* @param {TouchEvent} event
*/ /**
updateFocusAfterUserInteraction(event) { * Checks the focus after a touch
const target = /** @type {HTMLElement} */ (event.target); * @param {TouchEvent} event
if (!target || !target.tagName) { */
// Safety check updateFocusAfterUserInteraction(event) {
logger.warn("Invalid touchstart/touchend event:", event); const target = /** @type {HTMLElement} */ (event.target);
return; if (!target || !target.tagName) {
} // Safety check
logger.warn("Invalid touchstart/touchend event:", event);
// When clicking an element which is not the currently focused one, defocus it return;
if (target !== document.activeElement) { }
// @ts-ignore
if (document.activeElement.blur) { // When clicking an element which is not the currently focused one, defocus it
// @ts-ignore if (target !== document.activeElement) {
document.activeElement.blur(); // @ts-ignore
} if (document.activeElement.blur) {
} // @ts-ignore
document.activeElement.blur();
// If we click an input field, focus it now }
if (target.tagName.toLowerCase() === "input") { }
// We *really* need the focus
waitNextFrame().then(() => target.focus()); // If we click an input field, focus it now
} if (target.tagName.toLowerCase() === "input") {
} // We *really* need the focus
waitNextFrame().then(() => target.focus());
/** }
* Handles a page visibility change event }
* @param {Event} event
*/ /**
handleVisibilityChange(event) { * Handles a page visibility change event
window.focus(); * @param {Event} event
const pageVisible = !document[pageHiddenPropName]; */
if (pageVisible !== this.pageVisible) { handleVisibilityChange(event) {
this.pageVisible = pageVisible; window.focus();
logger.log("Visibility changed:", this.pageVisible); const pageVisible = !document[pageHiddenPropName];
this.trackedIsRenderable.set(this.isRenderable()); if (pageVisible !== this.pageVisible) {
} this.pageVisible = pageVisible;
} logger.log("Visibility changed:", this.pageVisible);
this.trackedIsRenderable.set(this.isRenderable());
/** }
* Handles a mouse move event }
* @param {MouseEvent} event
*/ /**
handleMousemove(event) { * Handles a mouse move event
this.mousePosition = new Vector(event.clientX, event.clientY); * @param {MouseEvent} event
} */
handleMousemove(event) {
/** this.mousePosition = new Vector(event.clientX, event.clientY);
* Internal on focus handler }
*/
onFocus() { /**
this.focused = true; * Internal on focus handler
} */
onFocus() {
/** this.focused = true;
* Internal blur handler }
*/
onBlur() { /**
this.focused = false; * Internal blur handler
} */
onBlur() {
/** this.focused = false;
* Returns if the app is currently visible }
*/
isRenderable() { /**
return !this.applicationPaused && this.pageVisible; * Returns if the app is currently visible
} */
isRenderable() {
onAppRenderableStateChanged(renderable) { return !this.applicationPaused && this.pageVisible;
logger.log("Application renderable:", renderable); }
window.focus();
const currentState = this.stateMgr.getCurrentState(); onAppRenderableStateChanged(renderable) {
if (!renderable) { logger.log("Application renderable:", renderable);
if (currentState) { window.focus();
currentState.onAppPause(); const currentState = this.stateMgr.getCurrentState();
} if (!renderable) {
} else { if (currentState) {
if (currentState) { currentState.onAppPause();
currentState.onAppResume(); }
} } else {
this.checkResize(); if (currentState) {
} currentState.onAppResume();
}
this.sound.onPageRenderableStateChanged(renderable); this.checkResize();
} }
/** this.sound.onPageRenderableStateChanged(renderable);
* Internal unload handler }
*/
onUnload(event) { /**
if (!this.unloaded) { * Internal unload handler
logSection("UNLOAD HANDLER", "#f77"); */
this.unloaded = true; onUnload(event) {
const currentState = this.stateMgr.getCurrentState(); if (!this.unloaded) {
if (currentState) { logSection("UNLOAD HANDLER", "#f77");
currentState.onBeforeExit(); this.unloaded = true;
} const currentState = this.stateMgr.getCurrentState();
this.deinitialize(); if (currentState) {
} currentState.onBeforeExit();
} }
this.deinitialize();
/** }
* Internal before-unload handler }
*/
onBeforeUnload(event) { /**
logSection("BEFORE UNLOAD HANDLER", "#f77"); * Internal before-unload handler
const currentState = this.stateMgr.getCurrentState(); */
onBeforeUnload(event) {
if (!G_IS_DEV && currentState && currentState.getHasUnloadConfirmation()) { logSection("BEFORE UNLOAD HANDLER", "#f77");
if (!G_IS_STANDALONE) { const currentState = this.stateMgr.getCurrentState();
// Need to show a "Are you sure you want to exit"
event.preventDefault(); if (!G_IS_DEV && currentState && currentState.getHasUnloadConfirmation()) {
event.returnValue = "Are you sure you want to exit?"; if (!G_IS_STANDALONE) {
} // Need to show a "Are you sure you want to exit"
} event.preventDefault();
} event.returnValue = "Are you sure you want to exit?";
}
/** }
* Boots the application }
*/
boot() { /**
console.log("Booting ..."); * Boots the application
this.registerStates(); */
this.registerEventListeners(); boot() {
console.log("Booting ...");
Loader.linkAppAfterBoot(this); this.registerStates();
this.registerEventListeners();
// Check for mobile
if (IS_MOBILE) { Loader.linkAppAfterBoot(this);
this.stateMgr.moveToState("MobileWarningState");
} else { // Check for mobile
this.stateMgr.moveToState("PreloadState"); if (IS_MOBILE) {
} this.stateMgr.moveToState("MobileWarningState");
} else {
// Starting rendering this.stateMgr.moveToState("PreloadState");
this.ticker.frameEmitted.add(this.onFrameEmitted, this); }
this.ticker.bgFrameEmitted.add(this.onBackgroundFrame, this);
this.ticker.start(); // Starting rendering
this.ticker.frameEmitted.add(this.onFrameEmitted, this);
window.focus(); this.ticker.bgFrameEmitted.add(this.onBackgroundFrame, this);
} this.ticker.start();
/** window.focus();
* Deinitializes the application }
*/
deinitialize() { /**
return this.sound.deinitialize(); * Deinitializes the application
} */
deinitialize() {
/** return this.sound.deinitialize();
* Background frame update callback }
* @param {number} dt
*/ /**
onBackgroundFrame(dt) { * Background frame update callback
if (this.isRenderable()) { * @param {number} dt
return; */
} onBackgroundFrame(dt) {
if (this.isRenderable()) {
const currentState = this.stateMgr.getCurrentState(); return;
if (currentState) { }
currentState.onBackgroundTick(dt);
} const currentState = this.stateMgr.getCurrentState();
} if (currentState) {
currentState.onBackgroundTick(dt);
/** }
* Frame update callback }
* @param {number} dt
*/ /**
onFrameEmitted(dt) { * Frame update callback
if (!this.isRenderable()) { * @param {number} dt
return; */
} onFrameEmitted(dt) {
if (!this.isRenderable()) {
const time = performance.now(); return;
}
// Periodically check for resizes, this is expensive (takes 2-3ms so only do it once in a while!)
if (!this.lastResizeCheck || time - this.lastResizeCheck > 1000) { const time = performance.now();
this.checkResize();
this.lastResizeCheck = time; // Periodically check for resizes, this is expensive (takes 2-3ms so only do it once in a while!)
} if (!this.lastResizeCheck || time - this.lastResizeCheck > 1000) {
this.checkResize();
const currentState = this.stateMgr.getCurrentState(); this.lastResizeCheck = time;
if (currentState) { }
currentState.onRender(dt);
} const currentState = this.stateMgr.getCurrentState();
} if (currentState) {
currentState.onRender(dt);
/** }
* Checks if the app resized. Only does this once in a while }
* @param {boolean} forceUpdate Forced update of the dimensions
*/ /**
checkResize(forceUpdate = false) { * Checks if the app resized. Only does this once in a while
const w = window.innerWidth; * @param {boolean} forceUpdate Forced update of the dimensions
const h = window.innerHeight; */
if (this.screenWidth !== w || this.screenHeight !== h || forceUpdate) { checkResize(forceUpdate = false) {
this.screenWidth = w; const w = window.innerWidth;
this.screenHeight = h; const h = window.innerHeight;
const currentState = this.stateMgr.getCurrentState(); if (this.screenWidth !== w || this.screenHeight !== h || forceUpdate) {
if (currentState) { this.screenWidth = w;
currentState.onResized(this.screenWidth, this.screenHeight); this.screenHeight = h;
} const currentState = this.stateMgr.getCurrentState();
if (currentState) {
const scale = this.getEffectiveUiScale(); currentState.onResized(this.screenWidth, this.screenHeight);
waitNextFrame().then(() => document.documentElement.style.setProperty("--ui-scale", `${scale}`)); }
window.focus();
} const scale = this.getEffectiveUiScale();
} waitNextFrame().then(() => document.documentElement.style.setProperty("--ui-scale", `${scale}`));
window.focus();
/** }
* Returns the effective ui sclae }
*/
getEffectiveUiScale() { /**
return this.platformWrapper.getUiScale() * this.settings.getInterfaceScaleValue(); * Returns the effective ui sclae
} */
getEffectiveUiScale() {
/** return this.platformWrapper.getUiScale() * this.settings.getInterfaceScaleValue();
* Callback after ui scale has changed }
*/
updateAfterUiScaleChanged() { /**
this.checkResize(true); * Callback after ui scale has changed
} */
} updateAfterUiScaleChanged() {
this.checkResize(true);
}
}

View File

@ -24,13 +24,17 @@ export const CHANGELOG = [
"Mark pinned shapes in statistics dialog and show them first (inspired by davidburhans)", "Mark pinned shapes in statistics dialog and show them first (inspired by davidburhans)",
"Added setting to show chunk borders", "Added setting to show chunk borders",
"Quad painters have been reworked! They now are integrated with the wires, and only paint the shape when the value is 1 (inspired by dengr1605)", "Quad painters have been reworked! They now are integrated with the wires, and only paint the shape when the value is 1 (inspired by dengr1605)",
"There are now compact 1x1 splitters available to be unlocked!", "There are now compact 1x1 balancers available to be unlocked!",
"Replaced level completion sound to be less distracting", "Replaced level completion sound to be less distracting",
"Allow editing waypoints (by isaisstillalive)", "Allow editing waypoints (by isaisstillalive)",
"Show confirmation when cutting area which is too expensive to get pasted again (by isaisstillalive)", "Show confirmation when cutting area which is too expensive to get pasted again (by isaisstillalive)",
"Show mouse and camera tile on debug overlay (F4) (by dengr)", "Show mouse and camera tile on debug overlay (F4) (by dengr)",
"Fix belt planner placing the belt when a dialog opens in the meantime",
"Added confirmation when deleting a savegame",
"Fixed tunnels entrances connecting to exits sometimes when they shouldn't", "Fixed tunnels entrances connecting to exits sometimes when they shouldn't",
"You can now pan the map with your mouse by moving the cursor to the edges of the screen!",
"Added setting to auto select the extractor when pipetting a resource patch (by Exund)", "Added setting to auto select the extractor when pipetting a resource patch (by Exund)",
"You can now change the unit (seconds / minutes / hours) in the statistics dialog",
"The initial belt planner direction is now based on the cursor movement (by MizardX)", "The initial belt planner direction is now based on the cursor movement (by MizardX)",
"Fix preferred variant not getting saved when clicking on the hud (by Danacus)", "Fix preferred variant not getting saved when clicking on the hud (by Danacus)",
], ],
@ -109,7 +113,7 @@ export const CHANGELOG = [
date: "17.06.2020", date: "17.06.2020",
entries: [ entries: [
"You can now place straight belts (and tunnels) by holding SHIFT! (For you, @giantwaffle ❤️)", "You can now place straight belts (and tunnels) by holding SHIFT! (For you, @giantwaffle ❤️)",
"Added continue button to main menu and add seperate 'New game' button (by jaysc)", "Added continue button to main menu and add separate 'New game' button (by jaysc)",
"Added setting to disable smart tunnel placement introduced with the last update", "Added setting to disable smart tunnel placement introduced with the last update",
"Added setting to disable vignette", "Added setting to disable vignette",
"Update translations", "Update translations",

View File

@ -13,7 +13,7 @@ import { round1Digit } from "./utils";
const logger = createLogger("buffers"); const logger = createLogger("buffers");
const bufferGcDurationSeconds = 5; const bufferGcDurationSeconds = 0.5;
export class BufferMaintainer { export class BufferMaintainer {
/** /**
@ -86,27 +86,29 @@ export class BufferMaintainer {
// Make sure our backlog never gets too big // Make sure our backlog never gets too big
clearBufferBacklog(); clearBufferBacklog();
const bufferStats = getBufferStats(); // if (G_IS_DEV) {
const mbUsed = round1Digit(bufferStats.vramUsage / (1024 * 1024)); // const bufferStats = getBufferStats();
logger.log( // const mbUsed = round1Digit(bufferStats.vramUsage / (1024 * 1024));
"GC: Remove", // logger.log(
(deletedKeys + "").padStart(4), // "GC: Remove",
", Remain", // (deletedKeys + "").padStart(4),
(totalKeys + "").padStart(4), // ", Remain",
"(", // (totalKeys + "").padStart(4),
(bufferStats.bufferCount + "").padStart(4), // "(",
"total", // (bufferStats.bufferCount + "").padStart(4),
")", // "total",
// ")",
"(", // "(",
(bufferStats.backlog + "").padStart(4), // (bufferStats.backlogSize + "").padStart(4),
"backlog", // "backlog",
")", // ")",
"VRAM:", // "VRAM:",
mbUsed, // mbUsed,
"MB" // "MB"
); // );
// }
++this.iterationIndex; ++this.iterationIndex;
} }

View File

@ -25,17 +25,43 @@ export function disableImageSmoothing(context) {
context.webkitImageSmoothingEnabled = false; context.webkitImageSmoothingEnabled = false;
} }
const registeredCanvas = []; /**
const freeCanvasList = []; * @typedef {{
* canvas: HTMLCanvasElement,
* context: CanvasRenderingContext2D
* }} CanvasCacheEntry
*/
let vramUsage = 0; /**
let bufferCount = 0; * @type {Array<CanvasCacheEntry>}
*/
const registeredCanvas = [];
/**
* Buckets for each width * height combination
* @type {Map<number, Array<CanvasCacheEntry>>}
*/
const freeCanvasBuckets = new Map();
/**
* Track statistics
*/
const stats = {
vramUsage: 0,
backlogVramUsage: 0,
bufferCount: 0,
numReused: 0,
numCreated: 0,
};
/** /**
* *
* @param {HTMLCanvasElement} canvas * @param {HTMLCanvasElement} canvas
*/ */
export function getBufferVramUsageBytes(canvas) { export function getBufferVramUsageBytes(canvas) {
assert(canvas, "no canvas given");
assert(Number.isFinite(canvas.width), "bad canvas width: " + canvas.width);
assert(Number.isFinite(canvas.height), "bad canvas height" + canvas.height);
return canvas.width * canvas.height * 4; return canvas.width * canvas.height * 4;
} }
@ -43,17 +69,31 @@ export function getBufferVramUsageBytes(canvas) {
* Returns stats on the allocated buffers * Returns stats on the allocated buffers
*/ */
export function getBufferStats() { export function getBufferStats() {
let numBuffersFree = 0;
freeCanvasBuckets.forEach(bucket => {
numBuffersFree += bucket.length;
});
return { return {
vramUsage, ...stats,
bufferCount, backlogKeys: freeCanvasBuckets.size,
backlog: freeCanvasList.length, backlogSize: numBuffersFree,
}; };
} }
/**
* Clears the backlog buffers if they grew too much
*/
export function clearBufferBacklog() { export function clearBufferBacklog() {
while (freeCanvasList.length > 50) { freeCanvasBuckets.forEach(bucket => {
freeCanvasList.pop(); while (bucket.length > 500) {
} const entry = bucket[bucket.length - 1];
stats.backlogVramUsage -= getBufferVramUsageBytes(entry.canvas);
delete entry.canvas;
delete entry.context;
bucket.pop();
}
});
} }
/** /**
@ -84,53 +124,29 @@ export function makeOffscreenBuffer(w, h, { smooth = true, reusable = true, labe
let canvas = null; let canvas = null;
let context = null; let context = null;
let bestMatchingOne = null;
let bestMatchingPixelsDiff = 1e50;
const currentPixels = w * h;
// Ok, search in cache first // Ok, search in cache first
for (let i = 0; i < freeCanvasList.length; ++i) { const bucket = freeCanvasBuckets.get(w * h) || [];
const { canvas: useableCanvas, context: useableContext } = freeCanvasList[i];
for (let i = 0; i < bucket.length; ++i) {
const { canvas: useableCanvas, context: useableContext } = bucket[i];
if (useableCanvas.width === w && useableCanvas.height === h) { if (useableCanvas.width === w && useableCanvas.height === h) {
// Ok we found one // Ok we found one
canvas = useableCanvas; canvas = useableCanvas;
context = useableContext; context = useableContext;
fastArrayDelete(freeCanvasList, i); // Restore past state
context.restore();
context.save();
context.clearRect(0, 0, canvas.width, canvas.height);
delete canvas.style.width;
delete canvas.style.height;
stats.numReused++;
stats.backlogVramUsage -= getBufferVramUsageBytes(canvas);
fastArrayDelete(bucket, i);
break; break;
} }
const otherPixels = useableCanvas.width * useableCanvas.height;
const diff = Math.abs(otherPixels - currentPixels);
if (diff < bestMatchingPixelsDiff) {
bestMatchingPixelsDiff = diff;
bestMatchingOne = {
canvas: useableCanvas,
context: useableContext,
index: i,
};
}
}
// Ok none matching, reuse one though
if (!canvas && bestMatchingOne) {
canvas = bestMatchingOne.canvas;
context = bestMatchingOne.context;
canvas.width = w;
canvas.height = h;
fastArrayDelete(freeCanvasList, bestMatchingOne.index);
}
// Reset context
if (context) {
// Restore past state
context.restore();
context.save();
context.clearRect(0, 0, canvas.width, canvas.height);
delete canvas.style.width;
delete canvas.style.height;
} }
// None found , create new one // None found , create new one
@ -138,6 +154,8 @@ export function makeOffscreenBuffer(w, h, { smooth = true, reusable = true, labe
canvas = document.createElement("canvas"); canvas = document.createElement("canvas");
context = canvas.getContext("2d" /*, { alpha } */); context = canvas.getContext("2d" /*, { alpha } */);
stats.numCreated++;
canvas.width = w; canvas.width = w;
canvas.height = h; canvas.height = h;
@ -145,6 +163,7 @@ export function makeOffscreenBuffer(w, h, { smooth = true, reusable = true, labe
context.save(); context.save();
} }
// @ts-ignore
canvas.label = label; canvas.label = label;
if (smooth) { if (smooth) {
@ -167,8 +186,9 @@ export function makeOffscreenBuffer(w, h, { smooth = true, reusable = true, labe
export function registerCanvas(canvas, context) { export function registerCanvas(canvas, context) {
registeredCanvas.push({ canvas, context }); registeredCanvas.push({ canvas, context });
bufferCount += 1; stats.bufferCount += 1;
vramUsage += getBufferVramUsageBytes(canvas); const bytesUsed = getBufferVramUsageBytes(canvas);
stats.vramUsage += bytesUsed;
} }
/** /**
@ -180,6 +200,7 @@ export function freeCanvas(canvas) {
let index = -1; let index = -1;
let data = null; let data = null;
for (let i = 0; i < registeredCanvas.length; ++i) { for (let i = 0; i < registeredCanvas.length; ++i) {
if (registeredCanvas[i].canvas === canvas) { if (registeredCanvas[i].canvas === canvas) {
index = i; index = i;
@ -193,8 +214,18 @@ export function freeCanvas(canvas) {
return; return;
} }
fastArrayDelete(registeredCanvas, index); fastArrayDelete(registeredCanvas, index);
freeCanvasList.push(data);
bufferCount -= 1; const key = canvas.width * canvas.height;
vramUsage -= getBufferVramUsageBytes(canvas); const bucket = freeCanvasBuckets.get(key);
if (bucket) {
bucket.push(data);
} else {
freeCanvasBuckets.set(key, [data]);
}
stats.bufferCount -= 1;
const bytesUsed = getBufferVramUsageBytes(canvas);
stats.vramUsage -= bytesUsed;
stats.backlogVramUsage += bytesUsed;
} }

Some files were not shown because too many files have changed in this diff Show More