S12 theme PR (#3285)

* Base of S12 theme

* Add taskbar (no subtab switching yet) for S12

* Add s12 support for old UI

* Add subtab switching support to s12

* Make S12 subtabs properly blur the background

* Add minimisation functionality

* Add images for all tabs in s12

* Move Fixed UI components into another file S12

* Style Modals for S12

* Fix bugs with S12 in the glyph cosmetic modal

* Add a245 message for S12

* Add desktop icons to s12

* Address PR feedback (S12 theme)

- Remove a bunch of debug statements
- Make image size smaller where needed
- Fix a bug with news disabled
- Fix end credits modal colours

* Add a games modal to S12

* Fix stray bugs with modal handling in S12

* Fix colouring and positioning of credits display on S12

* Fix S12 bugs (thanks hira)

* Fix S12 glyph tooltip bug
This commit is contained in:
Dys 2023-02-04 19:52:59 +08:00 committed by GitHub
parent 7d5214d3d6
commit 7e717b8de2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
64 changed files with 1725 additions and 72 deletions

View File

@ -72,6 +72,8 @@ import SwitchAutomatorEditorModal from "@/components/modals/SwitchAutomatorEdito
import UiChoiceModal from "@/components/modals/UiChoiceModal";
import UndoGlyphModal from "@/components/modals/UndoGlyphModal";
import S12GamesModal from "@/components/modals/secret-themes/S12GamesModal";
let nextModalID = 0;
export class Modal {
constructor(component, priority = 0, closeEvent) {
@ -255,6 +257,8 @@ Modal.sacrifice = new Modal(SacrificeModal, 1, GAME_EVENT.DIMBOOST_AFTER);
Modal.breakInfinity = new Modal(BreakInfinityModal, 1, GAME_EVENT.ETERNITY_RESET_AFTER);
Modal.respecIAP = new Modal(RespecIAPModal);
Modal.s12Games = new Modal(S12GamesModal);
function getSaveInfo(save) {
const resources = {
realTimePlayed: 0,

View File

@ -4,7 +4,7 @@ export const Theme = function Theme(name, config) {
this.name = name;
this.isDark = function() {
return this.isDefault()
return (this.isDefault() || name === "S12")
? player.options.newUI
: config.isDark;
};
@ -88,6 +88,7 @@ Theme.secretThemeIndex = function(name) {
"dba8336cd3224649d07952b00045a6ec3c8df277aa8a0a0e3e7c2aaa77f1fbb9",
"73de8a7f9efa1cbffc80a8effc9891a799127cd204b3a8b023bea8f513ed4753",
"f3a71114261b4af6517a53f89bf0c6b56bb81b6f0e931d0e0d71249eb196628c",
"1248689171faaa0abb68279199a8d2eb232dba10d2dacb79a705f680b6862c0e",
];
const sha = sha512_256(name.toUpperCase());
return secretThemes.indexOf(sha);
@ -153,6 +154,7 @@ export const Themes = {
Theme.create("S9", { secret: true, }),
Theme.create("S10", { dark: true, metro: true, animated: true, secret: true, }),
Theme.create("S11", { dark: true, animated: true, secret: true, }),
Theme.create("S12", { secret: true, }),
/* eslint-enable no-multi-spaces */
],

View File

@ -1436,6 +1436,9 @@ GameDatabase.news = [
${BLOB} are just blobbling and bouncing around, occasionally merging and dividing. Only ${BLOB} know where
they are from or where they are going to go. Still, ${BLOB} are there, always with me.
You love ${BLOB}, so ${BLOB} loves you too.`,
S12:
`it makes you feel warm and comfortable, as if you were right at home. However, it is highly recommended
to update your theme to the newest theme for the best user experience.`,
};
const reason = reasons[Theme.current().name.replace(/\s/gu, "")];
return `Ah, a fellow ${theme} theme user. I see that you have impeccable taste.

Binary file not shown.

BIN
public/images/s12-bg.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 465.39 513.15"><defs><style>.cls-1{fill:#bd1818;}.cls-2{fill:#e52320;}.cls-3{fill:#dc9f12;}.cls-4{fill:#f4df61;}</style></defs><g id="Layer_2" data-name="Layer 2"><g id="Layer_1-2" data-name="Layer 1"><polygon class="cls-1" points="20.21 115.95 32.02 124.19 32.02 135.2 20.21 139.25 20.21 115.95"/><polygon class="cls-2" points="349.47 473.5 319.37 451.96 319.37 120.21 349.47 106.41 349.47 473.5"/><polygon class="cls-1" points="64.88 101.04 76.69 109.47 76.69 119.87 64.88 123.92 64.88 101.04"/><polygon class="cls-2" points="349.47 84.33 319.37 105.56 319.37 120.21 349.47 120.05 349.47 84.33"/><polygon class="cls-2" points="445.18 115.95 433.38 123.92 433.38 135.2 445.18 139.25 445.18 115.95"/><polygon class="cls-2" points="400.51 101.04 388.7 109.19 388.7 119.87 400.51 123.92 400.51 101.04"/><polygon class="cls-2" points="349.47 148.97 319.44 148.97 232.73 209.23 232.73 233.27 349.47 148.97"/><polygon class="cls-1" points="146.02 148.97 145.87 148.98 145.87 120.21 145.87 106.17 115.91 84.33 115.91 106.41 115.91 120.05 115.91 473.5 145.87 452.03 145.87 171.27 232.73 233.27 232.73 209.23 146.02 148.97"/><polygon class="cls-2" points="232.73 233.27 115.92 149.89 115.92 120.05 115.92 120.05 115.92 84.33 85.82 93.64 85.82 116.74 64.88 123.92 64.88 101.04 41.37 108.9 41.37 131.99 20.21 139.25 20.21 115.95 0 122.66 0 146.19 0 146.19 0 205.18 26.54 224.19 26.54 458.69 115.92 473.5 115.92 310.95 232.73 399.41 232.73 233.27"/><polygon class="cls-1" points="445.18 115.95 445.18 139.25 424.02 131.99 424.02 108.89 400.51 101.04 400.51 123.92 379.57 116.74 379.57 93.64 349.47 84.33 349.47 106.41 349.47 120.05 349.47 148.97 232.73 233.27 232.73 399.41 349.47 309.54 349.47 473.5 438.17 462.82 438.17 224.19 465.39 205.16 465.39 148.97 465.39 146.19 465.39 122.66 445.18 115.95"/><path class="cls-3" d="M232.7,416.27h0v96.89l.8-1.1,31.12-44.37c-4.5-8.09-6.84-40.89-8.06-70.72Z"/><path class="cls-3" d="M241.18,23.83l5.26,60,40.82,0,14.06,14.64-16.44,15.93-10.69-11.06h-8.71c-4.14,4.34-7.3,9.8-7.53,16.46v54.11L232.7,193.84h0V0a12.73,12.73,0,0,1,11.65,12.66Z"/><path class="cls-4" d="M232.68,416.27h0v96.89l-.81-1.1-31.11-44.37c4.49-8.09,6.84-40.89,8-70.72Z"/><path class="cls-4" d="M224,23.83l-5.07,60-40.82,0L164.07,98.48l16.44,15.93,10.69-11.06h8.71c4.14,4.34,7.3,9.8,7.53,16.46v54.11l25.25,19.92h0V0a12.73,12.73,0,0,0-11.64,12.66Z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
public/images/s12/shop.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
public/images/s12/xmark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 B

View File

@ -14,8 +14,13 @@
--color-eternity--bg: #b341e04d;
}
:root .t-s12 {
--sidebar-width: 0;
}
:root .t-normal,
:root .t-s9 {
:root .t-s9,
:root .t-s12 {
--color-text: #ffffff;
--color-text-inverted: black;
--color-base: #1d1b22;
@ -41,7 +46,8 @@
}
body.t-normal,
body.t-s9 {
body.t-s9,
body.t-s12 {
color: white;
background-color: #111014;
}
@ -549,7 +555,8 @@ body.t-s9 {
background-color: var(--color-infinity);
}
.t-normal .c-game-header__tesseract-available {
.t-normal .c-game-header__tesseract-available,
.t-s12 .c-game-header__tesseract-available {
background: #eeeeee;
animation: a-tesseract-shift-dark 5s infinite;
}
@ -570,12 +577,14 @@ body.t-s9 {
margin: 0.6rem 0.4rem;
}
.t-normal .o-achievement__tooltip {
.t-normal .o-achievement__tooltip,
.t-s12 .o-achievement__tooltip {
background: var(--color-base);
border: 0.1rem solid var(--color-accent);
}
.t-normal .o-achievement__tooltip::after {
.t-normal .o-achievement__tooltip::after,
.t-s12 .o-achievement__tooltip::after {
border-top-color: var(--color-accent);
}
@ -891,11 +900,13 @@ body.t-s9 {
color: var(--color-eternity);
}
.t-normal .c-game-header__antimatter {
.t-normal .c-game-header__antimatter,
.t-s12 .c-game-header__antimatter {
color: var(--color-accent);
}
.t-normal .c-credits-header {
.t-normal .c-credits-header,
.t-s12 .c-credits-header {
color: var(--color-accent);
}
@ -924,17 +935,20 @@ body.t-s9 {
justify-content: flex-end;
}
.t-normal .c-sacrificed-glyphs--dragover {
.t-normal .c-sacrificed-glyphs--dragover,
.t-s12 .c-sacrificed-glyphs--dragover {
border-color: rgb(255, 255, 255);
box-shadow: 0 0 0.1rem 0.1rem rgb(255, 255, 255);
}
.t-normal .c-glyph-choice-icon {
.t-normal .c-glyph-choice-icon,
.t-s12 .c-glyph-choice-icon {
background-color: rgba(0, 0, 0, 30%);
border: var(--var-border-width, 0.2rem) solid rgba(0, 0, 0, 40%);
}
.t-normal .c-glyph-choice-effect-list {
.t-normal .c-glyph-choice-effect-list,
.t-s12 .c-glyph-choice-effect-list {
background-color: rgba(0, 0, 0, 30%);
border: var(--var-border-width, 0.2rem) solid rgba(0, 0, 0, 40%);
}

View File

@ -5358,7 +5358,7 @@ properly on certain themes. */
border: var(--var-border-width, 0.3rem) solid black;
border-radius: var(--var-border-radius, 0.6rem);
padding: 1rem;
transition-duration: 0.2s;
transition: all 0.2s, left 0s, top 0s, transform 0s;
}
.c-modal--short {
@ -9254,6 +9254,11 @@ input.o-automator-block-input {
padding: 0.5rem;
}
.t-s12 .l-h2p-body {
font-size: 1.3rem;
margin-left: 0;
}
.l-h2p-body::-webkit-scrollbar {
width: 1rem;
}
@ -9315,6 +9320,10 @@ input.o-automator-block-input {
border-bottom: 0.1rem solid white;
}
.t-s12 .o-h2p-tab-button {
border-bottom: 0.1rem solid black;
}
.l-help-me {
width: 2rem;
height: 2rem;

View File

@ -0,0 +1,326 @@
body.t-s12 {
--s12-taskbar-height: 4.5rem;
--s12-border-color: #27221e;
--s12-background-gradient:
repeating-linear-gradient(
50deg,
rgba(170, 170, 170, 10%),
rgba(170, 170, 170, 10%) 2rem,
rgba(255, 255, 255, 10%) 4rem,
rgba(255, 255, 255, 10%) 5rem,
rgba(170, 170, 170, 10%) 6rem,
rgba(170, 170, 170, 10%) 8rem
),
linear-gradient(
-50deg,
rgba(60, 60, 60, 30%),
transparent 20%,
transparent 80%,
rgba(60, 60, 60, 30%)
);
height: 100%;
background: url("../images/s12-bg.jpg") no-repeat;
background-attachment: fixed;
background-color: #1bb9ee;
/* Center and scale the image nicely */
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.t-s12 .container {
color: black;
}
.t-s12 #ui {
justify-content: flex-start;
/* stylelint-disable-next-line unit-allowed-list */
perspective: 200vh;
scrollbar-gutter: auto;
}
.t-s12 .ui-wrapper {
flex-direction: column;
height: 100%;
}
.c-s12-close-button,
.t-s12 .c-modal .c-modal__close-btn {
display: flex;
width: 5rem;
height: 1.8rem;
position: absolute;
top: 0;
right: 1rem;
justify-content: center;
align-items: center;
font-size: 0;
background-image:
url("../images/s12/xmark.png"),
linear-gradient(to bottom, rgba(255, 255, 255, 40%) 40%, transparent 60%),
radial-gradient(#b43721, #844740);
background-position: center;
background-repeat: no-repeat;
border: 0.15rem solid var(--s12-border-color);
border-top: none;
border-radius: 0 0 0.5rem 0.5rem;
box-shadow: inset 0 0 0.2rem 0.1rem rgba(255, 255, 255, 80%);
cursor: pointer;
}
.c-modal__close-btn--disabled {
filter: grayscale(1);
cursor: default;
}
.c-s12-close-button::before,
.t-s12 .c-modal .c-modal__close-btn:not(.c-modal__close-btn--disabled)::before {
content: "";
width: 100%;
height: 100%;
opacity: 0;
background-image:
url("../images/s12/xmark.png"),
linear-gradient(to bottom, transparent 50%, rgba(224, 178, 64, 60%));
background-position: center;
background-repeat: no-repeat;
border-radius: inherit;
box-shadow: 0 0 1rem 0.3rem #d35532;
transition: opacity 0.4s;
}
.c-s12-close-button:hover::before,
.c-modal__close-btn:hover::before {
opacity: 1;
}
.t-s12 .c-modal {
--color-text: black;
--color-text-inverted: white;
max-width: calc(100% - 10rem);
font-family: "Segoe UI", Typewriter;
font-weight: normal;
background-color: rgba(187, 216, 242, 75%);
background-image: var(--s12-background-gradient);
border: 0.1rem solid var(--s12-border-color);
padding: 2.4rem 1rem 1rem;
-webkit-backdrop-filter: blur(1rem);
backdrop-filter: blur(1rem);
}
.t-s12 .c-modal__inner:not(.c-credits-modal),
.t-s12 .c-modal-message,
.t-s12 .l-h2p-modal,
.t-s12 .c-information-modal,
.t-s12 .l-changelog-modal,
.t-s12 .c-modal-away-progress {
align-items: flex-start;
text-align: left;
font-size: 1.3rem;
color: black;
background-color: #f0f0f0;
border: 0.1rem solid var(--s12-border-color);
margin: 0;
padding: 1rem;
}
.t-s12 .modal-progress-bar,
.t-s12 .c-credits-modal {
color: black;
background-color: #f0f0f0;
border: 0.1rem solid var(--s12-border-color);
box-sizing: border-box;
padding: 1rem;
}
.t-s12 .c-modal-options__large {
width: 53rem;
}
.t-s12 .l-singularity-milestone-modal-container-inner .c-laitela-milestone {
text-align: center;
font-family: Typewriter;
font-size: 1.4rem;
}
.t-s12 .c-modal__title,
.t-s12 .l-h2p-header,
.t-s12 .l-changelog-header {
display: flex;
width: auto;
height: 2.2rem;
position: absolute;
top: 0.2rem;
left: 0;
align-items: center;
font-size: 1.3rem;
font-weight: normal;
text-shadow: 0 0 0.7rem white;
padding-left: 1rem;
}
.c-credits-modal .c-modal__title {
display: inline;
position: static;
}
.c-credits-modal .c-game-header__antimatter {
color: black;
}
.t-s12 .c-h2p-title,
.t-s12 .c-changelog-title {
font-size: 1.3rem;
font-weight: normal;
}
.t-s12 .c-modal__confirmation-toggle {
margin-top: 1.5rem;
}
.t-s12 .c-modal__confirmation-toggle__checkbox {
width: 1.6rem;
height: 1.6rem;
color: #4b6192;
background: linear-gradient(-45deg, #ffffffff, #aeb2b5);
border: 0.2rem solid white;
border-radius: 0;
box-shadow: 0 0 0.1rem 0.1rem var(--s12-border-color), inset 0 0 0.1rem 0.1rem #a0a0a0;
}
.t-s12 .c-modal__confirmation-toggle:hover .c-modal__confirmation-toggle__checkbox {
transform: none;
}
.t-s12 .c-modal .o-primary-btn:not(.c-modal__close-btn, .c-autobuyer-box__mode-select),
.t-s12 .c-new-game-button {
position: relative;
z-index: 0;
align-self: flex-end;
text-align: center;
font-family: "Segoe UI", Typewriter;
font-weight: normal;
color: black;
background-image: linear-gradient(to bottom, white 45%, #d7d7d7 55%);
border: 0.16rem solid #747474;
box-shadow: inset 0 0 0.2rem 0.1rem white;
padding-top: 0;
padding-bottom: 0;
transition: box-shadow 0.3s;
}
.t-s12 .c-new-game-button {
padding: 1rem;
}
.t-s12 .c-modal .o-primary-btn.c-select-notation__item,
.t-s12 .c-modal .o-primary-btn.c-select-theme__item {
background-color: white;
background-image: none;
border: none;
box-shadow: none;
}
.t-s12 .c-modal .o-primary-btn.c-select-notation__item::before,
.t-s12 .c-modal .o-primary-btn.c-select-theme__item::before {
display: none;
}
.t-s12 .c-modal .o-primary-btn.c-dropdown-btn {
z-index: 1;
align-self: center;
}
.t-s12 .c-modal .l-select-notation,
.t-s12 .c-modal .l-select-theme {
scrollbar-color: #747474 white;
border-color: #747474;
}
.l-select-notation__inner::-webkit-scrollbar,
.l-select-theme__inner::-webkit-scrollbar {
background-color: white;
}
.t-s12 .c-modal .l-select-notation__inner::-webkit-scrollbar-thumb,
.t-s12 .c-modal .l-select-theme__inner::-webkit-scrollbar-thumb {
background-color: #747474;
}
.t-s12 .c-modal .o-primary-btn--disabled {
opacity: 0.5;
}
.t-s12 .c-modal .o-primary-btn:not(.c-modal__close-btn, .c-autobuyer-box__mode-select)::after,
.t-s12 .c-new-game-button::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
z-index: -1;
background-color: transparent;
transition: background-color 0.3s;
}
.t-s12 .c-modal .o-primary-btn:not(.c-modal__close-btn):hover,
.t-s12 .c-new-game-button:hover {
box-shadow: inset 0 0 0.2rem 0.1rem #52d9fb;
}
.t-s12 .c-modal .o-primary-btn:not(.c-modal__close-btn):hover::after,
.t-s12 .c-new-game-button:hover::after {
background-color: rgba(46, 210, 255, 30%);
}
.t-s12 .c-modal .o-primary-btn.o-primary-btn.c-select-notation__item:hover,
.t-s12 .c-modal .o-primary-btn.o-primary-btn.c-select-theme__item:hover {
color: white;
background-color: #2a90ff;
box-shadow: none;
}
.t-s12 .l-modal-buttons {
align-self: flex-end;
font-size: 1.2rem;
}
.t-s12 .c-modal__confirmation-toggle__tooltip {
display: none;
}
.t-s12 .l-modal-options__save-record {
align-self: center;
}
.t-s12 .modal-progress-bar__bg {
overflow: hidden;
position: relative;
background-image: linear-gradient(to right, #cbcbcb 90%, #c0c0c0);
border: 0.1rem solid var(--s12-border-color);
border-radius: 0.2rem;
box-shadow: inset 0 0 0.2rem 0.1rem white;
}
.t-s12 .modal-progress-bar__bg::before {
content: "";
width: 100%;
height: 100%;
position: absolute;
inset: 0;
background-image: linear-gradient(rgba(255, 255, 255, 70%) 30%, transparent 40%);
}
.t-s12 .modal-progress-bar__fg {
background: linear-gradient(to right, #0cb826, #20da3e 20%, #20da3e 80%, #0cb826);
}
.t-s12 .c-modal .c-autobuyer-box-row {
text-align: center;
background-color: transparent;
}

View File

@ -11,6 +11,7 @@ export default {
computed: {
people() { return GameDatabase.credits.people; },
roles() { return GameDatabase.credits.roles; },
isS12EndDisplay() { return this.$viewModel.theme === "S12" && !this.isModal; },
},
methods: {
relevantPeople(role) {
@ -23,7 +24,7 @@ export default {
</script>
<template>
<div>
<div :class="{ 'c-credits-s12-end': isS12EndDisplay }">
<h1
v-if="!isModal"
class="c-credits-header"
@ -60,6 +61,11 @@ export default {
</template>
<style scoped>
.c-credits-s12-end {
--color-text: white;
color: white;
}
.c-credits-header {
color: black;
}
@ -70,6 +76,10 @@ export default {
animation: a-credits-header--glow 25s infinite;
}
.t-s12 .c-credits-header {
color: var(--color-antimatter);
}
@keyframes a-credits-header--glow {
0% { color: #2196f3; }
33% { color: #673ab7; }

View File

@ -5,6 +5,10 @@ import GameUiComponentFixed from "@/components/GameUiComponentFixed";
import ModernUi from "@/components/ui-modes/modern/ModernUi";
import TabComponents from "@/components/tabs";
import S12DesktopIcons from "@/components/ui-modes/s12/DesktopIcons";
import S12Ui from "@/components/ui-modes/s12/S12Ui";
import S12UiFixed from "@/components/ui-modes/s12/S12UiFixed";
export default {
name: "GameUIComponent",
components: {
@ -13,12 +17,19 @@ export default {
ModernUi,
GameUiComponentFixed,
BackgroundAnimations,
S12Ui,
S12UiFixed,
S12DesktopIcons,
},
computed: {
view() {
return this.$viewModel;
},
isThemeS12() {
return this.view.theme === "S12";
},
uiLayout() {
if (this.isThemeS12) return "S12Ui";
return this.view.newUI ? "ModernUi" : "ClassicUi";
},
containerClass() {
@ -52,6 +63,7 @@ export default {
class="c-game-tab"
/>
</component>
<S12DesktopIcons v-if="isThemeS12" />
<link
v-if="view.theme !== 'Normal'"
type="text/css"
@ -59,8 +71,9 @@ export default {
:href="themeCss"
>
</div>
<GameUiComponentFixed />
<BackgroundAnimations />
<GameUiComponentFixed v-if="!isThemeS12" />
<BackgroundAnimations v-if="!isThemeS12" />
<S12UiFixed v-if="isThemeS12" />
</div>
</template>

View File

@ -73,29 +73,31 @@ export default {
class="l-time-studies-tab__tt-shop"
/>
<ModernSidebar
v-if="view.newUI"
v-if="view.newUI && view.theme !== 'S12'"
:style="hideIfMatoFullscreen"
/>
<SaveTimer :style="hideIfMatoFullscreen" />
<SpeedrunStatus :style="hideIfMatoFullscreen" />
<ModalProgressBar v-if="view.modal.progressBar" />
<CelestialQuoteModal
v-else-if="view.quotes.current"
:quote="view.quotes.current"
/>
<CelestialQuoteHistoryDisplay
v-else-if="view.quotes.history"
:quotes="view.quotes.history"
/>
<PopupModal
v-else-if="view.modal.current"
:modal="view.modal.current"
/>
<ModalProgressBar v-if="view.modal.progressBar" />
<FadeAway v-if="ending" />
<CreditsContainer v-if="ending" />
<NewGame v-if="ending" />
<SpectateGame />
<template v-if="view.theme !== 'S12'">
<ModalProgressBar v-if="view.modal.progressBar" />
<CelestialQuoteModal
v-else-if="view.quotes.current"
:quote="view.quotes.current"
/>
<CelestialQuoteHistoryDisplay
v-else-if="view.quotes.history"
:quotes="view.quotes.history"
/>
<PopupModal
v-else-if="view.modal.current"
:modal="view.modal.current"
/>
<ModalProgressBar v-if="view.modal.progressBar" />
<FadeAway v-if="ending" />
<CreditsContainer v-if="ending" />
<NewGame v-if="ending" />
<SpectateGame />
</template>
</div>
</template>
@ -111,4 +113,8 @@ export default {
justify-content: center;
pointer-events: none;
}
.t-s12 .c-game-ui--fixed {
position: absolute;
}
</style>

View File

@ -53,8 +53,8 @@ export default {
position: absolute;
bottom: 0;
left: 0;
text-align: left;
z-index: 5;
text-align: left;
color: var(--color-text);
background-color: var(--color-base);
border-top: 0.1rem solid var(--color-accent);

View File

@ -127,6 +127,11 @@ export default {
padding: 0.5rem;
}
.t-s12 .l-changelog-body {
font-size: 1.3rem;
margin-left: 0;
}
.l-changelog-body::-webkit-scrollbar {
width: 1rem;
}
@ -187,6 +192,10 @@ export default {
.s-base--dark .o-changelog-tab-button {
border-bottom: 0.1rem solid white;
}
.t-s12 .o-changelog-tab-button {
border-bottom: 0.1rem solid black;
}
</style>
<style>

View File

@ -117,4 +117,8 @@ export default {
.s-base--dark .o-h2p-tab-button--first-irrelevant {
border-top-color: white;
}
.t-s12 .o-h2p-tab-button--first-irrelevant {
border-top-color: black;
}
</style>

View File

@ -87,6 +87,11 @@ export default {
padding: 0.5rem;
}
.t-s12 .c-info-body {
font-size: 1.3rem;
margin: 0;
}
.c-socials {
font-size: 7.5rem;
}
@ -96,4 +101,9 @@ export default {
justify-content: space-evenly;
align-items: center;
}
.t-s12 .l-socials {
width: 100%;
align-self: center;
}
</style>

View File

@ -17,6 +17,9 @@ export default {
modal() {
return this.$viewModel.modal.current;
},
isThemeS12() {
return this.$viewModel.theme === "S12";
}
},
created() {
this.on$(GAME_EVENT.ENTER_PRESSED, this.handleClick);
@ -41,9 +44,13 @@ export default {
<div class="c-modal-message l-modal-content--centered">
<ModalCloseButton
v-if="modal.closeButton"
class="c-modal__close-btn--tiny"
:class="isThemeS12 ? 'c-modal__close-btn' : 'c-modal__close-btn--tiny'"
@click="emitClose"
/>
<ModalCloseButton
v-else-if="isThemeS12"
class="c-modal__close-btn c-modal__close-btn--disabled"
/>
<div
class="c-modal-message__text"
v-html="message"
@ -54,5 +61,11 @@ export default {
>
Okay
</PrimaryButton>
<div
v-if="isThemeS12"
class="c-modal__title"
>
Message
</div>
</div>
</template>

View File

@ -31,36 +31,38 @@ export default {
<div
class="l-modal-overlay c-modal-overlay progress-bar-modal"
>
<div class="modal-progress-bar c-modal">
<div class="modal-progress-bar__label">
{{ progress.label }}
</div>
<div>
{{ progress.info() }}
</div>
<div class="modal-progress-bar__margin">
<div>
{{ progress.progressName }}: {{ formatInt(progress.current) }}/{{ formatInt(progress.max) }}
<div class="c-modal">
<div class="modal-progress-bar">
<div class="modal-progress-bar__label">
{{ progress.label }}
</div>
<div>
Remaining: {{ remainingTime }}
{{ progress.info() }}
</div>
<div class="modal-progress-bar__hbox">
<div class="modal-progress-bar__bg">
<div
class="modal-progress-bar__fg"
:style="foregroundStyle"
/>
<div class="modal-progress-bar__margin">
<div>
{{ progress.progressName }}: {{ formatInt(progress.current) }}/{{ formatInt(progress.max) }}
</div>
<div>
Remaining: {{ remainingTime }}
</div>
<div class="modal-progress-bar__hbox">
<div class="modal-progress-bar__bg">
<div
class="modal-progress-bar__fg"
:style="foregroundStyle"
/>
</div>
</div>
</div>
</div>
<div class="modal-progress-bar__buttons">
<OfflineSpeedupButton
v-for="(button, id) in buttons"
:key="id"
:button="button"
:progress="progress"
/>
<div class="modal-progress-bar__buttons">
<OfflineSpeedupButton
v-for="(button, id) in buttons"
:key="id"
:button="button"
:progress="progress"
/>
</div>
</div>
</div>
</div>
@ -71,19 +73,22 @@ export default {
z-index: 8;
}
.modal-progress-bar {
display: flex;
flex-direction: column;
width: 40rem;
.c-modal {
position: fixed;
/* stylelint-disable-next-line unit-allowed-list */
top: 50vh;
/* stylelint-disable-next-line unit-allowed-list */
left: 50vw;
transform: translate(-50%, -50%);
}
.modal-progress-bar {
display: flex;
flex-direction: column;
width: 40rem;
z-index: 3;
justify-content: space-between;
align-items: center;
transform: translate(-50%, -50%);
}
.modal-progress-bar__hbox {

View File

@ -15,7 +15,7 @@ export default {
</script>
<template>
<div>
<div class="c-modal__inner">
<div class="c-modal__header">
<ModalCloseButton @click="closeModal" />
<span

View File

@ -9,21 +9,43 @@ export default {
},
data() {
return {
showModal: false
showModal: false,
positionStyle: {},
};
},
created() {
this.on$(GAME_EVENT.CLOSE_MODAL, this.hide);
},
mounted() {
this.updatePositionStyles();
},
destroyed() {
document.activeElement.blur();
},
methods: {
update() {
const oldShowModal = this.showModal;
// 2.5 is the cutoff point where the screen starts fading (interactivity disabled). However, we specifically
// want to allow glyph customization to appear at the very end (and nothing else)
this.showModal = GameEnd.endState <= END_STATE_MARKERS.INTERACTIVITY_DISABLED ||
this.modal.component.name === "CosmeticSetChoiceModal";
if (this.showModal !== oldShowModal) this.$nextTick(() => this.updatePositionStyles());
this.updatePositionStyles();
},
updatePositionStyles() {
if (!this.$refs.modal) return;
if (!this.showModal || this.$viewModel.theme !== "S12") {
this.positionStyle = {};
return;
}
const w = this.$refs.modal.offsetWidth, h = this.$refs.modal.offsetHeight;
// We need to set position style specifically for S12 because using a transform messes things up and
// makes everything really blurry
this.positionStyle = {
left: `${Math.round(innerWidth / 2 - w / 2)}px`,
top: `${Math.round(innerHeight / 2 - h / 2)}px`,
transform: "none",
};
},
hide() {
if (!this.modal.isOpen) return;
@ -37,7 +59,9 @@ export default {
<template>
<div
v-if="showModal"
ref="modal"
class="c-modal l-modal"
:style="positionStyle"
>
<component
:is="modal.component"

View File

@ -276,7 +276,7 @@ export default {
<br>
<PrimaryButton
v-if="!deleting"
ach-tooltip="This will format the study preset text, for example, changing 'a,b,c|d' to 'a, b, c | d'."
v-tooltip="'This will format the study preset text, for example, changing \'a,b,c|d\' to \'a, b, c | d\'.'"
@click="convertInputShorthands"
>
Format Preset Text

View File

@ -81,7 +81,7 @@ export default {
text-align: left;
border: 0.1rem solid var(--color-text);
border-radius: var(--var-border-radius, 0.4rem);
margin: 1rem;
margin: 1rem 0;
padding: 1.5rem;
}

View File

@ -130,8 +130,13 @@ export default {
.c-center {
display: flex;
flex-direction: column;
align-items: center;
width: 38rem;
align-items: center;
}
.t-s12 .c-center {
width: 50rem;
text-align: center;
}
.c-dropdown-btn {
@ -141,8 +146,8 @@ export default {
}
.c-dropdown-header {
padding: 0.5rem;
height: 5rem;
padding: 0.5rem;
user-select: none;
}

View File

@ -63,4 +63,8 @@ export default {
.l-wrapper {
width: 62rem;
}
.t-s12 .l-wrapper {
width: 65rem;
}
</style>

View File

@ -0,0 +1,146 @@
<script>
import S12Games from "./s12-games";
let isSelectingGame = false;
export default {
name: "S12Games",
data() {
return {
S12Games
};
},
mounted() {
document.body.addEventListener("click", this.clearSelected);
},
beforeDestroy() {
document.body.removeEventListener("click", this.clearSelected);
this.clearSelected();
},
methods: {
clearSelected() {
if (isSelectingGame) return;
S12Games.selected = -1;
},
handleClick(idx) {
// This makes what everything is doing clearer
// eslint-disable-next-line no-negated-condition
if (S12Games.selected !== idx) {
S12Games.selected = idx;
isSelectingGame = true;
setTimeout(() => isSelectingGame = false, 0);
} else {
window.open(S12Games.entries[idx].link);
}
}
}
};
</script>
<template>
<div class="c-s12-games-container">
<div
v-for="(game, idx) in S12Games.entries"
:key="game.name"
class="c-s12-game"
:class="{ 'c-s12-game--selected': S12Games.selected === idx, }"
@click="handleClick(idx)"
>
<div class="c-s12-game__inner">
<img
:src="`images/s12/${game.image}`"
class="c-s12-game__img"
>
<div class="c-s12-game__text">
{{ game.name }}
</div>
</div>
</div>
</div>
</template>
<style scoped>
.c-s12-games-container {
--icon-font-size: 1.1rem;
--icon-line-height: 1.1;
--icon-size: 8rem;
--icon-margin: 0.4rem;
--icon-inner-padding: 0.5rem;
--total-icon-height: calc(
var(--icon-size) + var(--icon-margin) * 2 +
var(--icon-font-size) * var(--icon-line-height) * 2 +
var(--icon-inner-padding) * 2
);
--total-game-width: 10rem;
--game-margin: 0.2rem;
display: flex;
overflow-y: auto;
flex: 1 0 auto;
flex-wrap: wrap;
width: calc(4 * (var(--total-game-width) + var(--game-margin) * 2));
height: 40rem;
user-select: none;
}
.c-s12-game {
overflow: hidden;
width: var(--total-game-width);
height: var(--total-icon-height);
position: relative;
z-index: 0;
margin: var(--game-margin);
}
.c-s12-game__inner {
display: flex;
overflow: hidden;
flex-direction: column;
width: 100%;
position: relative;
align-items: center;
padding: var(--icon-inner-padding);
cursor: pointer;
}
.c-s12-game--selected {
overflow: visible;
z-index: 1;
}
.c-s12-game__inner::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
opacity: 0;
background-image: linear-gradient(rgba(13, 120, 242, 0.2), rgba(13, 120, 242, 0.25));
border: 0.1rem solid #82a5d0;
border-radius: 0.5rem;
box-shadow: inset 0 0 0.2rem 0.1rem rgba(255, 255, 255, 0.7);
transition: opacity 0.2s;
}
.c-s12-game:hover .c-s12-game__inner::before {
opacity: 0.5;
}
.c-s12-game.c-s12-game--selected .c-s12-game__inner::before {
opacity: 1;
}
.c-s12-game__img {
height: var(--icon-size);
margin: var(--icon-margin);
}
.c-s12-game__text {
overflow: hidden;
width: 100%;
text-align: center;
font-family: "Segoe UI", Typewriter;
font-size: var(--icon-font-size);
font-weight: normal;
line-height: var(--icon-line-height);
color: black;
}
</style>

View File

@ -0,0 +1,64 @@
<script>
import ModalWrapper from "@/components/modals/ModalWrapper";
import S12GameEntries from "./S12GameEntries";
import S12Games from "./s12-games";
export default {
name: "S12GamesModal",
components: {
ModalWrapper,
S12GameEntries,
},
data() {
return {
S12Games,
};
},
methods: {
update() {
if (this.$viewModel.theme !== "S12") EventHub.dispatch(GAME_EVENT.CLOSE_MODAL);
}
}
};
</script>
<template>
<ModalWrapper class="c-modal-s12-games">
<div class="c-modal__title">
Games
</div>
<S12GameEntries />
<div class="c-modal-s12-games__magnified-display">
<template v-if="S12Games.selected !== -1">
<img
class="c-modal-s12-games__magnified-display__img"
:src="`images/s12/${S12Games.entries[S12Games.selected].image}`"
>
<b class="c-modal-s12-games__magnified-display__text">
{{ S12Games.entries[S12Games.selected].name }}
</b>
</template>
</div>
</ModalWrapper>
</template>
<style scoped>
.c-modal-s12-games {
display: flex;
width: 64rem;
}
.c-modal-s12-games__magnified-display {
width: 100%;
align-self: stretch;
text-align: center;
border-left: 0.1rem solid #86b2df;
padding: 2rem;
}
.c-modal-s12-games__magnified-display__img {
width: 100%;
margin: 2rem 0 6rem;
}
</style>

View File

@ -0,0 +1,53 @@
export default {
entries: [{
name: "FE000000",
link: "https://dan-simon.github.io/misc/fe000000/",
image: "game--hex-game.png"
},
{
name: "Trimps",
link: "https://trimps.github.io/",
image: "game--trimps.png"
},
{
name: "Mine Defense",
link: "http://scholtek.com/minedefense",
image: "game--mine-defense.png"
},
{
name: "Wizard and Minion Idle",
link: "https://www.kongregate.com/games/Oninou/wami",
image: "game--wami.png"
},
{
name: "Anti-Idle",
link: "https://www.kongregate.com/games/Tukkun/anti-idle-the-game",
image: "game--anti-idle.png"
},
{
name: "Synergism",
link: "https://pseudo-corp.github.io/SynergismOfficial/",
image: "game--synergism.png"
},
{
name: "Universal Paperclips",
link: "https://www.decisionproblem.com/paperclips/",
image: "game--universal-paperclips.png"
},
{
name: "Monies 2",
link: "https://sneekxy.nmtechgroup.com/monies2/",
image: "game--monies2.png"
},
{
name: "The First Alkahistorian",
link: "https://nagshell.github.io/elemental-inception-incremental/",
image: "game--alkahistorian.png"
},
{
name: "Melvor Idle",
link: "https://melvoridle.com/",
image: "game--melvor-idle.svg"
}],
selected: -1,
};

View File

@ -204,6 +204,10 @@ perfectly the same. */
cursor: pointer;
}
.t-s12 .c-mute-button {
color: white;
}
.c-credits-container {
width: 100%;
height: 100%;

View File

@ -114,4 +114,13 @@ export default {
background-repeat: no-repeat;
background-size: cover;
}
.t-s12 .c-background-overlay {
background: url("../../../../public/images/s12-bg.jpg") no-repeat;
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
filter: brightness(0.5);
}
</style>

View File

@ -90,6 +90,10 @@ export default {
pointer-events: auto;
}
.t-s12 .c-new-game-container {
color: white;
}
.c-new-game-button-container {
display: flex;
flex-direction: column;

View File

@ -0,0 +1,146 @@
<script>
import DesktopIcons from "./desktop-icons";
let isSelectingIcon = false;
export default {
name: "DesktopIcons",
data() {
return {
DesktopIcons
};
},
mounted() {
document.body.addEventListener("click", this.clearSelected);
},
beforeDestroy() {
document.body.removeEventListener("click", this.clearSelected);
this.clearSelected();
},
methods: {
clearSelected() {
if (isSelectingIcon) return;
DesktopIcons.selected = -1;
},
handleClick(idx) {
// This makes what everything is doing clearer
// eslint-disable-next-line no-negated-condition
if (DesktopIcons.selected !== idx) {
DesktopIcons.selected = idx;
isSelectingIcon = true;
setTimeout(() => isSelectingIcon = false, 0);
} else {
DesktopIcons.entries[idx].action();
}
}
}
};
</script>
<template>
<div class="c-s12-desktop-icons-container">
<div
v-for="(icon, idx) in DesktopIcons.entries"
:key="icon.name"
class="c-s12-desktop-icon"
:class="{ 'c-s12-desktop-icon--selected': DesktopIcons.selected === idx, }"
@click="handleClick(idx)"
>
<div class="c-s12-desktop-icon__inner">
<img
:src="`images/s12/${icon.image}`"
class="c-s12-desktop-icon__img"
>
<div class="c-s12-desktop-icon__text">
{{ icon.name }}
</div>
</div>
</div>
</div>
</template>
<style scoped>
.c-s12-desktop-icons-container {
--icon-font-size: 1.1rem;
--icon-line-height: 1.1;
--icon-size: 4rem;
--icon-margin: 0.2rem;
--icon-inner-padding: 0.3rem;
--total-icon-height: calc(
var(--icon-size) + var(--icon-margin) * 2 +
var(--icon-font-size) * var(--icon-line-height) * 2 +
var(--icon-inner-padding) * 2
);
display: inline-flex;
flex-direction: column;
flex-wrap: wrap;
height: calc(100% - var(--s12-taskbar-height));
position: absolute;
top: 0;
left: 0;
align-items: flex-start;
user-select: none;
}
.c-s12-desktop-icon {
overflow: hidden;
width: 7rem;
height: var(--total-icon-height);
position: relative;
z-index: 0;
margin: 0.2rem;
}
.c-s12-desktop-icon__inner {
display: flex;
overflow: hidden;
flex-direction: column;
width: 100%;
position: relative;
align-items: center;
padding: var(--icon-inner-padding);
cursor: pointer;
}
.c-s12-desktop-icon--selected {
overflow: visible;
z-index: 1;
}
.c-s12-desktop-icon__inner::before {
content: "";
position: absolute;
inset: 0;
z-index: -1;
opacity: 0;
background-color: rgba(190, 190, 190, 0.3);
background-image: var(--s12-background-gradient);
border: 0.1rem solid white;
border-radius: 0.5rem;
transition: opacity 0.2s;
}
.c-s12-desktop-icon:hover .c-s12-desktop-icon__inner::before {
opacity: 0.5;
}
.c-s12-desktop-icon.c-s12-desktop-icon--selected .c-s12-desktop-icon__inner::before {
opacity: 1;
}
.c-s12-desktop-icon__img {
height: var(--icon-size);
margin: var(--icon-margin);
}
.c-s12-desktop-icon__text {
overflow: hidden;
width: 100%;
font-family: "Segoe UI", Typewriter;
font-size: var(--icon-font-size);
font-weight: normal;
line-height: var(--icon-line-height);
color: white;
text-shadow: 0 0 0.3rem var(--s12-border-color);
}
</style>

View File

@ -0,0 +1,14 @@
# GUIDE TO THE CODE
Corresponding(-ish) components:
- S12Taskbar: The sidebar on modern
- TaskbarIcon: Main tab button
- S12Subtabs: Subtab button(s)
Due to how the backdrop-filter property works, S12Subtabs has to be in a separate container from the
taskbar, which has the unfortunate consequence of likely making the code messier.
Windows.js basically handles everything that needs to be used in between components.
- HoveringTab controls which set of subtabs should be shown at any time.
- TabButtonPositions keeps track of the positions of all "Tab Buttons" (i.e. Taskbar Icons) which are then
used to calculate the position (More specifically, the `left` attr) of the subtabs that show up on hover.

View File

@ -0,0 +1,187 @@
<script>
import { S12Windows } from "./windows";
export default {
name: "S12Subtabs",
props: {
tab: {
type: Object,
required: true
},
},
data() {
return {
isAvailable: true,
isHidden: false,
subtabVisibilities: [],
tabName: "",
S12Windows,
windowWidth: 0,
left: "0px",
useCompact: false,
};
},
methods: {
update() {
this.isAvailable = this.tab.isAvailable;
this.isHidden = this.tab.isHidden;
this.subtabVisibilities = this.tab.subtabs.map(x => x.isAvailable);
this.windowWidth = window.innerWidth;
this.useCompact = this.subtabVisibilities.reduce((a, v) => a + v) * 180 > window.innerWidth - 10;
this.left = this.getSubtabsPosition();
},
isCurrentSubtab(id) {
return player.options.lastOpenSubtab[this.tab.id] === id && !S12Windows.isMinimised;
},
getSubtabsPosition() {
if (!this.$refs.subtabs) return "0px";
const centerPt = S12Windows.tabs.tabButtonPositions[this.tab.id];
const subtabsWidth = this.$refs.subtabs.offsetWidth;
const minLeft = 5 + subtabsWidth / 2, maxLeft = this.windowWidth - minLeft;
// Reference isAvailable and isHidden so this gets updated correctly
return (this.isAvailable, this.isHidden, `${Math.clamp(centerPt, minLeft, maxLeft)}px`);
},
},
};
</script>
<template>
<div
ref="subtabs"
class="c-s12-subtabs"
:class="{
'c-s12-subtabs--show': S12Windows.tabs.hoveringTab === tab.id,
'c-s12-subtabs--compact': useCompact,
}"
:style="{ left }"
@mouseenter="S12Windows.tabs.setHoveringTab(tab)"
@mouseleave="S12Windows.tabs.unsetHoveringTab()"
>
<template
v-for="(subtab, index) in tab.subtabs"
>
<div
v-if="subtabVisibilities[index]"
:key="index"
class="c-s12-subtab-btn"
:class="{ 'c-s12-subtab-btn--active': isCurrentSubtab(subtab.id) }"
@click="subtab.show(true); S12Windows.isMinimised = false; S12Windows.tabs.unsetHoveringTab(true);"
>
<span class="c-s12-subtab-btn__text">
<span
v-if="useCompact"
class="c-s12-subtab-btn__symbol--small"
v-html="subtab.symbol"
/>
{{ subtab.name }}
</span>
<span
v-if="!useCompact"
class="c-s12-subtab-btn__symbol"
v-html="subtab.symbol"
/>
<div
v-if="subtab.hasNotification"
class="fas fa-circle-exclamation l-notification-icon"
/>
</div>
</template>
</div>
</template>
<style scoped>
.c-s12-subtabs {
display: flex;
visibility: hidden;
position: absolute;
bottom: calc(var(--s12-taskbar-height) + 0.5rem);
z-index: 6;
opacity: 0;
background-color: rgba(120, 120, 120, 0.7);
background-image: var(--s12-background-gradient);
border: 0.15rem solid var(--s12-border-color);
border-radius: 0.5rem;
box-shadow: 0 0 1rem 0.2rem var(--s12-border-color),
inset 0 0 0.4rem 0.1rem rgba(255, 255, 255, 0.7);
transform: translate(-50%, 20%);
transition: transform 0.2s, opacity 0.2s, visibility 0.2s;
pointer-events: none;
/* If anyone can figure out why these two aren't working that would be great */
-webkit-backdrop-filter: blur(0.3rem);
backdrop-filter: blur(0.3rem);
}
.c-s12-subtabs--compact {
flex-direction: column;
padding: 0.5rem;
padding-bottom: 0;
}
.c-s12-subtabs--show {
visibility: visible;
opacity: 1;
transform: translate(-50%, 0);
pointer-events: auto;
}
.c-s12-subtab-btn {
display: flex;
flex-direction: column;
width: 17rem;
height: 12rem;
position: relative;
border: 0.1rem solid transparent;
border-radius: 0.5rem;
margin: 0.5rem;
padding: 0.3rem;
transition: background-color 0.5s, border 0.5s;
user-select: none;
cursor: pointer;
}
.c-s12-subtabs--compact .c-s12-subtab-btn {
height: auto;
margin: 0;
margin-bottom: 0.5rem;
padding: 0.6rem;
}
.c-s12-subtab-btn:hover {
background-color: rgba(255, 255, 255, 0.1);
border: 0.1rem solid rgba(255, 255, 255, 0.5);
}
.c-s12-subtab-btn--active {
background-color: rgba(255, 255, 255, 0.4);
border: 0.1rem solid white;
}
.c-s12-subtab-btn--active:hover {
background-color: rgba(255, 255, 255, 0.6);
}
.c-s12-subtab-btn__text {
display: flex;
align-self: flex-start;
color: white;
text-shadow: 0 0 0.5rem var(--s12-border-color);
}
.c-s12-subtab-btn__symbol {
display: flex;
height: 100%;
justify-content: center;
align-items: center;
align-self: center;
font-size: 6rem;
color: white;
text-shadow: 0 0 0.5rem var(--s12-border-color);
}
.c-s12-subtab-btn__symbol--small {
width: 1.4rem;
margin-right: 0.5rem;
}
</style>

View File

@ -0,0 +1,139 @@
<script>
import S12Subtabs from "./S12Subtabs";
import TaskbarIcon from "./TaskbarIcon";
import { S12Windows } from "./windows";
const startupSound = new Audio("audio/s12-startup.mp3");
export default {
name: "S12Taskbar",
components: {
TaskbarIcon,
S12Subtabs,
},
data() {
return {
isHidden: false,
tabVisibilities: [],
S12Windows,
startupSound,
};
},
computed: {
tabs: () => Tabs.newUI
},
methods: {
update() {
this.isHidden = AutomatorData.isEditorFullscreen;
this.tabVisibilities = Tabs.newUI.map(x => !x.isHidden && x.isAvailable);
},
},
};
</script>
<template>
<span
v-if="!isHidden"
>
<div class="c-taskbar">
<img
class="c-start-icon"
src="images/s12/win7-start-menu-inactive.png"
@click="startupSound.play()"
>
<template
v-for="(tab, tabPosition) in tabs"
>
<TaskbarIcon
v-if="tabVisibilities[tabPosition]"
:key="tab.name"
:tab="tab"
:tab-position="tabPosition"
/>
</template>
<div
class="c-s12-show-desktop"
@click="S12Windows.isMinimised = true;"
/>
</div>
<template
v-for="(tab, tabPosition) in tabs"
>
<S12Subtabs
v-if="tabVisibilities[tabPosition]"
:key="tab.name"
:tab="tab"
/>
</template>
</span>
</template>
<style scoped>
.c-taskbar {
display: flex;
width: 100%;
height: 4.5rem;
background-color: rgba(120, 120, 120, 0.15);
background-image:
repeating-linear-gradient(
50deg,
rgba(170, 170, 170, 0.1), rgba(170, 170, 170, 0.1) 2rem,
rgba(255, 255, 255, 0.1) 4rem, rgba(255, 255, 255, 0.1) 5rem,
rgba(170, 170, 170, 0.1) 6rem, rgba(170, 170, 170, 0.1) 8rem
),
linear-gradient(
to right,
rgba(40, 40, 40, 0.4),
transparent 10%,
transparent 70%,
rgba(0, 0, 0, 0.4) 90%
);
border-top: 0.15rem solid var(--s12-border-color);
-webkit-backdrop-filter: blur(0.3rem);
backdrop-filter: blur(0.3rem);
}
.c-taskbar::before {
content: "";
display: inline-block;
width: 110%;
height: 110%;
position: absolute;
box-shadow: inset 0 0 0.3rem 0.1rem rgba(255, 255, 255, 0.5);
margin-right: -5%;
margin-left: -5%;
pointer-events: none;
}
.c-start-icon {
height: 100%;
margin: 0 2rem 0 1rem;
cursor: pointer;
}
.c-s12-show-desktop {
width: 1rem;
height: 100%;
position: absolute; right: 0;
border: 0.15rem solid var(--s12-border-color);
border-style: none none solid solid;
border-radius: 0.2rem 0 0 0.2rem;
cursor: pointer;
}
.c-s12-show-desktop::before {
content: "";
display: block;
width: 200%;
height: 100%;
border-radius: inherit;
box-shadow: inset 0 0 0.5rem 0.1rem rgba(255, 255, 255, 0.5);
transition: box-shadow 0.4s;
}
.c-s12-show-desktop:hover::before {
box-shadow: inset 0 0 0.5rem 0.1rem white;
}
</style>

View File

@ -0,0 +1,176 @@
<script>
import BigCrunchButton from "../BigCrunchButton";
import HeaderBlackHole from "../HeaderBlackHole";
import HeaderChallengeDisplay from "../HeaderChallengeDisplay";
import HeaderChallengeEffects from "../HeaderChallengeEffects";
import HeaderPrestigeGroup from "../HeaderPrestigeGroup";
import NewsTicker from "../NewsTicker";
import BackgroundAnimations from "@/components/BackgroundAnimations";
import GameUiComponentFixed from "@/components/GameUiComponentFixed";
import GameSpeedDisplay from "@/components/GameSpeedDisplay";
import { S12Windows } from "./windows";
export default {
name: "S12Ui",
components: {
BigCrunchButton,
HeaderChallengeDisplay,
HeaderChallengeEffects,
NewsTicker,
HeaderBlackHole,
HeaderPrestigeGroup,
GameSpeedDisplay,
GameUiComponentFixed,
BackgroundAnimations,
},
data() {
return {
bigCrunch: false,
hasReality: false,
newGameKey: "",
tabName: "",
S12Windows,
};
},
computed: {
news() {
return this.$viewModel.news;
},
topPadding() {
return this.$viewModel.news ? "" : "padding-top: 3.9rem";
},
isOldUi() {
return !this.$viewModel.newUI;
},
},
methods: {
update() {
const crunchButtonVisible = !player.break && Player.canCrunch;
this.bigCrunch = crunchButtonVisible && Time.bestInfinityRealTime.totalMinutes > 1;
this.hasReality = PlayerProgress.realityUnlocked();
// This only exists to force a key-swap after pressing the button to start a new game; the news ticker can break
// if it isn't redrawn
this.newGameKey = Pelle.isDoomed;
this.tabName = Tabs.current[this.$viewModel.subtab].name;
},
},
};
</script>
<template>
<div
id="page"
class="c-s12-window__outer"
:class="S12Windows.isMinimised ? 'c-s12-window__outer--minimised' : ''"
>
<link
rel="stylesheet"
type="text/css"
:href="isOldUi ? 'stylesheets/old-ui.css' : 'stylesheets/new-ui-styles.css'"
>
<span
class="c-s12-close-button"
@click="S12Windows.isMinimised = true"
/>
<span class="c-modal__title">
{{ tabName }}
</span>
<div
:key="newGameKey"
class="game-container c-s12-window__inner"
:class="isOldUi ? 'c-old-ui l-old-ui' : ''"
:style="topPadding"
>
<GameUiComponentFixed />
<BackgroundAnimations />
<div class="c-s12-window__content-container">
<NewsTicker
v-if="news"
/>
<BigCrunchButton />
<div
v-if="!bigCrunch"
class="tab-container"
>
<HeaderPrestigeGroup />
<div class="information-header">
<HeaderChallengeDisplay />
<HeaderChallengeEffects />
<GameSpeedDisplay v-if="hasReality" />
<br v-if="hasReality">
<HeaderBlackHole />
</div>
<slot />
</div>
</div>
</div>
</div>
</template>
<style scoped>
#page {
width: 100%;
height: 100%;
position: absolute;
top: 0;
z-index: 1;
background-color: rgba(255, 255, 255, 0.5);
background-image: var(--s12-background-gradient);
margin-top: 0;
padding: 2.4rem 1rem 1rem;
-webkit-backdrop-filter: blur(1rem);
backdrop-filter: blur(1rem);
}
.c-s12-window__outer {
transition: opacity 0.3s, transform 0.4s, visibility 0.3s;
transform-style: preserve-3d;
}
.c-s12-window__outer--minimised {
visibility: hidden;
opacity: 0;
/* stylelint-disable-next-line unit-allowed-list */
transform: rotateX(90deg) scale(0.7);
pointer-events: none;
}
.c-s12-window__inner {
overflow: hidden;
width: 100%;
height: 100%;
position: relative;
z-index: 0;
background-color: #111014;
border: 0.15rem solid var(--s12-border-color);
border-radius: 0.15rem;
box-shadow: 0 0 0.4rem 0.2rem rgba(255, 255, 255, 0.5);
}
.c-old-ui.c-s12-window__inner {
background-color: white;
}
.c-s12-window__content-container {
overflow-x: hidden;
overflow-y: auto;
width: 100%;
height: 100%;
position: relative;
scrollbar-gutter: stable both-edges;
}
.c-modal__title {
font-family: "Segoe UI", Typewriter;
color: black;
}
</style>

View File

@ -0,0 +1,82 @@
<script>
import CelestialQuoteHistoryDisplay from "@/components/modals/celestial-quotes/CelestialQuoteHistoryDisplay";
import CelestialQuoteModal from "@/components/modals/celestial-quotes/CelestialQuoteModal";
import CreditsContainer from "@/components/tabs/celestial-pelle/CreditsContainer";
import FadeAway from "@/components/tabs/celestial-pelle/FadeAway";
import ModalProgressBar from "@/components/modals/ModalProgressBar";
import NewGame from "@/components/tabs/celestial-pelle/NewGame";
import PopupModal from "@/components/modals/PopupModal";
import SpectateGame from "@/components/SpectateGame";
import S12Taskbar from "./S12Taskbar";
export default {
name: "S12UiFixed",
components: {
PopupModal,
ModalProgressBar,
CelestialQuoteModal,
CelestialQuoteHistoryDisplay,
FadeAway,
CreditsContainer,
SpectateGame,
NewGame,
S12Taskbar,
},
data() {
return {
ending: false
};
},
computed: {
view() {
return this.$viewModel;
}
},
methods: {
update() {
this.ending = GameEnd.endState >= END_STATE_MARKERS.FADE_AWAY && !GameEnd.creditsClosed;
}
}
};
</script>
<template>
<span>
<div class="c-game-ui--fixed">
<ModalProgressBar v-if="view.modal.progressBar" />
<CelestialQuoteModal
v-else-if="view.quotes.current"
:quote="view.quotes.current"
/>
<CelestialQuoteHistoryDisplay
v-else-if="view.quotes.history"
:quotes="view.quotes.history"
/>
<PopupModal
v-else-if="view.modal.current"
:modal="view.modal.current"
/>
<FadeAway v-if="ending" />
<CreditsContainer v-if="ending" />
<NewGame v-if="ending" />
<SpectateGame />
</div>
<S12Taskbar />
</span>
</template>
<style scoped>
.c-game-ui--fixed {
display: flex;
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 5;
justify-content: center;
pointer-events: none;
}
</style>

View File

@ -0,0 +1,113 @@
<script>
import { S12Windows } from "./windows";
export default {
name: "TaskbarIcon",
props: {
tab: {
type: Object,
required: true
},
tabPosition: {
type: Number,
required: true
}
},
data() {
return {
isAvailable: true,
isHidden: false,
hasNotification: false,
tabName: "",
S12Windows,
};
},
computed: {
isCurrentTab() {
return this.tab.isOpen && !S12Windows.isMinimised;
}
},
methods: {
update() {
this.isAvailable = this.tab.isAvailable;
this.isHidden = this.tab.isHidden;
this.hasNotification = this.tab.hasNotification;
if (this.tabPosition < Pelle.endTabNames.length) {
this.tabName = Pelle.transitionText(
this.tab.name,
Pelle.endTabNames[this.tabPosition],
Math.clamp(GameEnd.endState - (this.tab.id % 4) / 10, 0, 1)
);
} else {
this.tabName = this.tab.name;
}
S12Windows.tabs.tabButtonPositions[this.tab.id] = this.getSubtabsPosition();
},
getSubtabsPosition() {
if (!this.$refs.taskbarIcon) return "0px";
return this.$refs.taskbarIcon.offsetLeft + this.$refs.taskbarIcon.offsetWidth / 2;
},
},
};
</script>
<template>
<div
ref="taskbarIcon"
:class="{
'c-taskbar-icon': true,
'c-taskbar-icon--active': isCurrentTab
}"
:title="tab.name"
@mouseenter="S12Windows.tabs.setHoveringTab(tab)"
@mouseleave="S12Windows.tabs.unsetHoveringTab()"
@click="tab.show(true); S12Windows.isMinimised = false; S12Windows.tabs.unsetHoveringTab(true);"
>
<img
class="c-taskbar-icon__image"
:src="`images/s12/${tab.key}.png`"
>
<div
v-if="hasNotification"
class="fas fa-circle-exclamation l-notification-icon"
/>
</div>
</template>
<style scoped>
.c-taskbar-icon {
display: flex;
width: 6rem;
height: 100%;
position: relative;
z-index: 2;
justify-content: center;
align-items: center;
background-image: radial-gradient(at 5% -35%, white, transparent 50%);
border: 0.15rem solid var(--s12-border-color);
border-top: none;
border-radius: 0.3rem;
box-shadow: inset 0 0 0.3rem 0.1rem rgba(255, 255, 255, 0.8);
margin-left: 0.4rem;
transition: background-color 0.5s;
cursor: pointer;
}
.c-taskbar-icon:hover {
background-color: rgba(255, 255, 255, 0.35);
}
.c-taskbar-icon--active {
background-color: rgba(255, 255, 255, 0.5);
}
.c-taskbar-icon--active:hover {
background-color: rgba(240, 240, 240, 0.9);
}
.c-taskbar-icon__image {
height: 80%;
border-radius: 1rem;
}
</style>

View File

@ -0,0 +1,34 @@
export default {
entries: [{
name: "Windows Media Player",
action() {
const links = [
// Get trolled
"https://www.youtube.com/watch?v=dQw4w9WgXcQ",
// Rite of spring
"https://youtu.be/rP42C-4zL3w?t=2",
// Aleph 0 which for some reason caught on for a while
"https://www.youtube.com/watch?v=fTaWKbD3UK8",
// "If you have not listened to first suite in E flat by Gustav Holst do it now" -Erf
"https://www.youtube.com/watch?v=fLbP6qpI1YI",
];
window.open(links[Math.floor(Math.random() * links.length)]);
},
image: "desktop--windows-media-player.png"
},
{
name: "Discord",
action() {
window.open("https://discord.gg/ST9NaXa");
},
image: "desktop--discord-logo.png"
},
{
name: "Games",
action() {
Modal.s12Games.show();
},
image: "desktop--games.png"
}],
selected: -1,
};

View File

@ -0,0 +1,20 @@
let subtabTimeoutId;
export const S12Windows = {
isMinimised: false,
tabs: {
hoveringTab: undefined,
setHoveringTab(tab) {
this.hoveringTab = tab.id;
clearTimeout(subtabTimeoutId);
},
unsetHoveringTab(instant = false) {
if (instant) {
this.hoveringTab = undefined;
return;
}
subtabTimeoutId = setTimeout(() => this.hoveringTab = undefined, 1000);
},
tabButtonPositions: [],
}
};