mirror of
https://github.com/thepaperpilot/Planar-Pioneers.git
synced 2024-11-28 02:51:51 +00:00
Implemented settings and info modals
This commit is contained in:
parent
82adac7317
commit
829eac7068
21 changed files with 27557 additions and 26956 deletions
53762
package-lock.json
generated
53762
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -10,9 +10,11 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
"vue": "^2.6.11",
|
"vue": "^2.6.11",
|
||||||
|
"vue-select": "^3.11.2",
|
||||||
"vuex": "^3.4.0"
|
"vuex": "^3.4.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/vue-select": "^3.11.1",
|
||||||
"@vue/cli-plugin-babel": "~4.5.0",
|
"@vue/cli-plugin-babel": "~4.5.0",
|
||||||
"@vue/cli-plugin-eslint": "~4.5.0",
|
"@vue/cli-plugin-eslint": "~4.5.0",
|
||||||
"@vue/cli-plugin-vuex": "~4.5.0",
|
"@vue/cli-plugin-vuex": "~4.5.0",
|
||||||
|
|
29
src/App.vue
29
src/App.vue
|
@ -35,24 +35,21 @@ export default {
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
transition-duration: 0.5s;
|
transition-duration: 0.5s;
|
||||||
text-align: center;
|
|
||||||
font-family: "Roboto Mono", monospace;
|
font-family: "Roboto Mono", monospace;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
table-align: center;
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
-webkit-text-size-adjust: none;
|
|
||||||
text-size-adjust: none;
|
text-size-adjust: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
*:focus {
|
*:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
webkit-outline: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-width: 640px;
|
min-width: 640px;
|
||||||
transition: none;
|
transition: none;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body, #app {
|
html, body, #app {
|
||||||
|
@ -65,29 +62,31 @@ h1, h2, h3, b, input {
|
||||||
}
|
}
|
||||||
|
|
||||||
a,
|
a,
|
||||||
|
button,
|
||||||
.link {
|
.link {
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 20px;
|
color: var(--link);
|
||||||
color: #02f2f2;
|
background: none;
|
||||||
cursor: pointer;
|
border: none;
|
||||||
text-decoration: none;
|
cursor: pointer;
|
||||||
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:hover,
|
a:hover,
|
||||||
|
button:hover,
|
||||||
.link:hover {
|
.link:hover {
|
||||||
transform: scale(1.2, 1.2);
|
text-shadow: 5px 0 10px var(--link),
|
||||||
text-shadow: 5px 0 10px #02f2f2,
|
-3px 0 12px var(--link);
|
||||||
-3px 0 12px #02f2f2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#app {
|
#app {
|
||||||
background-color: var(--background);
|
background-color: var(--background);
|
||||||
color: var(--color);
|
color: var(--color);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
120
src/components/system/Info.vue
Normal file
120
src/components/system/Info.vue
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
<template>
|
||||||
|
<Modal :show="show" @close="$emit('closeDialog', 'Info')">
|
||||||
|
<div slot="header" class="info-modal-header">
|
||||||
|
<img class="info-modal-logo" v-if="logo" :src="logo" :alt="title" />
|
||||||
|
<div class="info-modal-title">
|
||||||
|
<h2>{{ title }}</h2>
|
||||||
|
<h4>v{{ versionNumber}}: {{ versionTitle }}</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div slot="body">
|
||||||
|
<div v-if="author">
|
||||||
|
By {{ author }}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
Made in TMT-X, by thepaperpilot with inspiration from Acameada, Jacorb, and Aarex
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<div class="link" @click="$emit('openDialog', 'Changelog')">Changelog</div>
|
||||||
|
<br>
|
||||||
|
<div>
|
||||||
|
<a :href="discordLink" v-if="discordLink !== 'https://discord.gg/WzejVAx'">
|
||||||
|
<img src="images/discord.png" class="info-modal-discord" />
|
||||||
|
{{ discordLink }}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="https://discord.gg/WzejVAx" class="info-modal-discord-link">
|
||||||
|
<img src="images/discord.png" class="info-modal-discord" />
|
||||||
|
The Paper Pilot Community
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="https://discord.gg/F3xveHV" class="info-modal-discord-link">
|
||||||
|
<img src="images/discord.png" class="info-modal-discord" />
|
||||||
|
The Modding Tree
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a href="https://discord.gg/wwQfgPa" class="info-modal-discord-link">
|
||||||
|
<img src="images/discord.png" class="info-modal-discord" />
|
||||||
|
Jacorb's Games
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<div>Time Played: {{ timePlayed }}</div>
|
||||||
|
<div v-if="hotkeys.length > 0">
|
||||||
|
<h4>Hotkeys</h4>
|
||||||
|
<div v-for="key in hotkeys" :key="key.key">
|
||||||
|
{{ key.key }}: {{ key.description }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Modal from './Modal.vue';
|
||||||
|
import modInfo from '../../data/mod.js';
|
||||||
|
import { formatTime } from '../../util/bignum.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Info',
|
||||||
|
data() {
|
||||||
|
const { title, logo, author, discordName, discordLink, versionNumber, versionTitle } = modInfo;
|
||||||
|
return { title, logo, author, discordName, discordLink, versionNumber, versionTitle };
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
show: Boolean
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Modal
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
timePlayed() {
|
||||||
|
return formatTime(this.$store.state.timePlayed);
|
||||||
|
},
|
||||||
|
hotkeys() {
|
||||||
|
// TODO check layer is unlocked and hotkey is unlocked
|
||||||
|
return this.$root.hotkeys.filter(hotkey => hotkey || true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.info-modal-header {
|
||||||
|
display: flex;
|
||||||
|
margin: -20px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
background: var(--secondary-background);
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-modal-header * {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-modal-logo {
|
||||||
|
height: 4em;
|
||||||
|
width: 4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-modal-title {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-modal-discord-link {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-modal-discord {
|
||||||
|
height: 2em;
|
||||||
|
margin: 0;
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
99
src/components/system/Modal.vue
Normal file
99
src/components/system/Modal.vue
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
<template>
|
||||||
|
<transition name="modal">
|
||||||
|
<div class="modal-mask" v-show="show" v-on:pointerdown.self="$emit('close')">
|
||||||
|
<div class="modal-wrapper">
|
||||||
|
<div class="modal-container">
|
||||||
|
|
||||||
|
<div class="modal-header">
|
||||||
|
<slot name="header">
|
||||||
|
default header
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<slot name="body">
|
||||||
|
default body
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
<slot name="footer">
|
||||||
|
<div class="modal-default-footer">
|
||||||
|
<div class="modal-default-flex-grow"></div>
|
||||||
|
<button class="modal-default-button" @click="$emit('close')">
|
||||||
|
Close
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Modal',
|
||||||
|
props: {
|
||||||
|
show: Boolean
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.modal-mask {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 9998;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-wrapper {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-container {
|
||||||
|
width: 400px;
|
||||||
|
max-width: calc(95vw - 40px);
|
||||||
|
background-color: var(--background);
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
text-align: left;
|
||||||
|
border: var(--modal-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-default-footer {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-default-flex-grow {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-enter {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-leave-active {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-enter .modal-container,
|
||||||
|
.modal-leave-active .modal-container {
|
||||||
|
-webkit-transform: scale(1.1);
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,46 +1,49 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="nav" v-if="useHeader">
|
<div>
|
||||||
<img v-if="banner" :src="banner" height="100%" :alt="title" />
|
<div class="nav" v-if="useHeader">
|
||||||
<div v-else class="title">{{ title }}</div>
|
<img v-if="banner" :src="banner" height="100%" :alt="title" />
|
||||||
<div class="version" @click="showTab('changelog-tab')">v{{ version }}</div>
|
<div v-else class="title">{{ title }}</div>
|
||||||
<div style="flex-grow: 1"></div>
|
<div class="version" @click="openDialog('Changelog')">v{{ version }}</div>
|
||||||
<div class="discord">
|
<div style="flex-grow: 1"></div>
|
||||||
<img src="images/discord.png" @click="window.open(discordLink, 'mywindow')" />
|
<div class="discord">
|
||||||
<ul class="discord-links">
|
<img src="images/discord.png" @click="window.open(discordLink, 'mywindow')" />
|
||||||
<li v-if="discordLink !== 'https://discord.gg/WzejVAx'">
|
<ul class="discord-links">
|
||||||
<a :href="discordLink" target="_blank">{{ discordName }}</a>
|
<li v-if="discordLink !== 'https://discord.gg/WzejVAx'">
|
||||||
</li>
|
<a :href="discordLink" target="_blank">{{ discordName }}</a>
|
||||||
<li><a href="https://discord.gg/WzejVAx" target="_blank">TMT-X Server</a></li>
|
</li>
|
||||||
<li><a href="https://discord.gg/F3xveHV" target="_blank">TMT Server</a></li>
|
<li><a href="https://discord.gg/WzejVAx" target="_blank">The Paper Pilot Community</a></li>
|
||||||
<li><a href="http://discord.gg/wwQfgPa" target="_blank">TPT Server</a></li>
|
<li><a href="https://discord.gg/F3xveHV" target="_blank">The Modding Tree</a></li>
|
||||||
</ul>
|
<li><a href="http://discord.gg/wwQfgPa" target="_blank">Jacorb's Games</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="info" @click="openDialog('Info')"><br/>i</div>
|
||||||
|
<img class="options" src="images/options_wheel.png" @click="openDialog('Options')" />
|
||||||
</div>
|
</div>
|
||||||
<div v-if="tab !== 'info-tab'" class="info" @click="showTab('info-tab')"><br/>i</div>
|
<div v-else>
|
||||||
<img v-if="tab !== 'options-tab'" class="options" src="images/options_wheel.png"
|
<div class="discord overlay">
|
||||||
@click="showTab('options-tab')" />
|
<img src="images/discord.png" @click="openDiscord" />
|
||||||
</div>
|
<ul class="discord-links">
|
||||||
<div v-else>
|
<li v-if="discordLink !== 'https://discord.gg/WzejVAx'">
|
||||||
<div class="discord overlay">
|
<a :href="discordLink" target="_blank">{{ discordName }}</a>
|
||||||
<img src="images/discord.png" @click="openDiscord" />
|
</li>
|
||||||
<ul class="discord-links">
|
<li><a href="https://discord.gg/WzejVAx" target="_blank">The Paper Pilot Community</a></li>
|
||||||
<li v-if="discordLink !== 'https://discord.gg/WzejVAx'">
|
<li><a href="https://discord.gg/F3xveHV" target="_blank">The Modding Tree</a></li>
|
||||||
<a :href="discordLink" target="_blank">{{ discordName }}</a>
|
<li><a href="http://discord.gg/wwQfgPa" target="_blank">Jacorb's Games</a></li>
|
||||||
</li>
|
</ul>
|
||||||
<li><a href="https://discord.gg/WzejVAx" target="_blank">TMT-X Server</a></li>
|
</div>
|
||||||
<li><a href="https://discord.gg/F3xveHV" target="_blank">TMT Server</a></li>
|
<div class="info overlay" @click="openDialog('Info')"><br/>i</div>
|
||||||
<li><a href="http://discord.gg/wwQfgPa" target="_blank">TPT Server</a></li>
|
<img class="options overlay" src="images/options_wheel.png" @click="openDialog('Options')" />
|
||||||
</ul>
|
<div class="version overlay" @click="openDialog('Changelog')">v{{ version }}</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="tab !== 'info-tab'" class="info overlay" @click="showTab('info-tab')"><br/>i</div>
|
<Info :show="showInfo" @openDialog="openDialog" @closeDialog="closeDialog" />
|
||||||
<img v-if="tab !== 'options-tab'" class="options overlay" src="images/options_wheel.png"
|
<Options :show="showOptions" @closeDialog="closeDialog" />
|
||||||
@click="showTab('options-tab')" />
|
|
||||||
<div class="version overlay" @click="showTab('changelog-tab')">v{{ version }}</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex';
|
|
||||||
import modInfo from '../../data/mod.js';
|
import modInfo from '../../data/mod.js';
|
||||||
|
import Info from './Info';
|
||||||
|
import Options from './Options';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Nav',
|
name: 'Nav',
|
||||||
|
@ -51,17 +54,24 @@ export default {
|
||||||
title: modInfo.title,
|
title: modInfo.title,
|
||||||
discordName: modInfo.discordName,
|
discordName: modInfo.discordName,
|
||||||
discordLink: modInfo.discordLink,
|
discordLink: modInfo.discordLink,
|
||||||
version: modInfo.versionNumber
|
version: modInfo.versionNumber,
|
||||||
|
showInfo: false,
|
||||||
|
showOptions: false,
|
||||||
|
showChangelog: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: mapState([ 'tab' ]),
|
components: {
|
||||||
|
Info, Options
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openDiscord() {
|
openDiscord() {
|
||||||
window.open(this.discordLink, 'mywindow');
|
window.open(this.discordLink, 'mywindow');
|
||||||
},
|
},
|
||||||
showTab(tab) {
|
openDialog(dialog) {
|
||||||
console.log("TODO show tab", tab);
|
this[`show${dialog}`] = true;
|
||||||
// tabs.splice(1, tabs.length, tab);
|
},
|
||||||
|
closeDialog(dialog) {
|
||||||
|
this[`show${dialog}`] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -69,13 +79,12 @@ export default {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.nav {
|
.nav {
|
||||||
background-color: var(--background_nav);
|
background-color: var(--secondary-background);
|
||||||
display: flex;
|
display: flex;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
z-index: 9999999;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +94,10 @@ export default {
|
||||||
margin-left: 12px;
|
margin-left: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
.discord {
|
.discord {
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
@ -105,11 +118,11 @@ export default {
|
||||||
.discord-links {
|
.discord-links {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 45px;
|
top: 45px;
|
||||||
padding: 30px;
|
padding: 20px;
|
||||||
right: -280px;
|
right: -280px;
|
||||||
width: 200px;
|
width: 200px;
|
||||||
transition: right .25s ease;
|
transition: right .25s ease;
|
||||||
background: var(--background_nav);
|
background: var(--secondary-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
.discord.overlay .discord-links {
|
.discord.overlay .discord-links {
|
||||||
|
@ -119,6 +132,10 @@ export default {
|
||||||
transition: left .25s ease;
|
transition: left .25s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.discord-links li {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
.discord:not(.overlay):hover .discord-links {
|
.discord:not(.overlay):hover .discord-links {
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
91
src/components/system/Options.vue
Normal file
91
src/components/system/Options.vue
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<template>
|
||||||
|
<Modal :show="show" @close="$emit('closeDialog', 'Options')">
|
||||||
|
<div slot="header">
|
||||||
|
<h2>Options</h2>
|
||||||
|
</div>
|
||||||
|
<div slot="body">
|
||||||
|
<div class="actions">
|
||||||
|
<button @click="save">Manually Save</button>
|
||||||
|
<button @click="exportSave">Export</button>
|
||||||
|
<button @click="importSave" class="danger">Import</button>
|
||||||
|
<button @click="hardReset" class="danger">Hard Reset</button>
|
||||||
|
</div>
|
||||||
|
<Toggle title="Autosave" :value="autosave" @change="toggleOption('autosave')" />
|
||||||
|
<Toggle title="Offline Production" :value="offlineProd" @change="toggleOption('offlineProd')" />
|
||||||
|
<Toggle title="Show TPS" :value="showTPS" @change="toggleOption('showTPS')" />
|
||||||
|
<Select title="Theme" :options="themes" :value="theme" @change="setTheme" default="default" />
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Modal from './Modal.vue';
|
||||||
|
import Toggle from './fields/Toggle.vue';
|
||||||
|
import Select from './fields/Select.vue';
|
||||||
|
import themes from '../../data/themes.js';
|
||||||
|
import { camelToTitle } from '../../util/common.js';
|
||||||
|
import { mapState } from 'vuex';
|
||||||
|
import { SET_SETTING } from '../../store/mutations.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Options',
|
||||||
|
props: {
|
||||||
|
show: Boolean
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
themes: Object.keys(themes).map(theme => ({ label: camelToTitle(theme), value: theme }))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Modal, Toggle, Select
|
||||||
|
},
|
||||||
|
computed: mapState([ "autosave", "offlineProd", "showTPS", "theme" ]),
|
||||||
|
methods: {
|
||||||
|
toggleOption(option) {
|
||||||
|
this.$store.commit(SET_SETTING, { setting: option });
|
||||||
|
},
|
||||||
|
setTheme(theme) {
|
||||||
|
this.$store.commit(SET_SETTING, { setting: "theme", value: theme });
|
||||||
|
},
|
||||||
|
save() {
|
||||||
|
|
||||||
|
},
|
||||||
|
hardReset() {
|
||||||
|
|
||||||
|
},
|
||||||
|
exportSave() {
|
||||||
|
|
||||||
|
},
|
||||||
|
importSave() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions * {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger {
|
||||||
|
border: solid 2px var(--danger);
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.danger::after {
|
||||||
|
content: "!";
|
||||||
|
color: white;
|
||||||
|
background: var(--danger);
|
||||||
|
padding: 2px;
|
||||||
|
margin-left: 6px;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -23,6 +23,6 @@ export default {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
z-index: 10000000;
|
z-index: 100;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
<div class="tabs">
|
<div class="tabs">
|
||||||
<div v-for="(tab, index) in tabs" class="tab" :key="index">
|
<div v-for="(tab, index) in tabs" class="tab" :key="index">
|
||||||
<button v-if="index > 0" class="goBack" @click="goBack(index)">←</button>
|
<button v-if="index > 0" class="goBack" @click="goBack(index)">←</button>
|
||||||
{{ tab }}
|
<component :is="layers[tab].component" :index="index" v-if="tab in layers && layers[tab].component" />
|
||||||
|
<tab-layer :layer="tab" :index="index" v-else-if="tab in layers" />
|
||||||
|
<component :is="tab" :index="index" v-else />
|
||||||
<div class="separator" v-if="index !== tabs.length - 1"></div>
|
<div class="separator" v-if="index !== tabs.length - 1"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -10,13 +12,19 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapState } from 'vuex';
|
import { mapState } from 'vuex';
|
||||||
|
import { SET_TABS } from '../../store/mutations.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Tabs',
|
name: 'Tabs',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
layers: this.$root.layers
|
||||||
|
};
|
||||||
|
},
|
||||||
computed: mapState([ 'tabs' ]),
|
computed: mapState([ 'tabs' ]),
|
||||||
methods: {
|
methods: {
|
||||||
goBack(/* index */) {
|
goBack(index) {
|
||||||
// TODO tabs.splice(index)
|
this.$store.commit(SET_TABS, this.$store.state.tabs.slice(0, index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -56,4 +64,9 @@ export default {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.goBack:hover {
|
||||||
|
transform: scale(1.1, 1.1);
|
||||||
|
text-shadow: 0 0 7px var(--color);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
67
src/components/system/fields/Select.vue
Normal file
67
src/components/system/fields/Select.vue
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<template>
|
||||||
|
<div class="field">
|
||||||
|
<span class="field-title">{{ title }}</span>
|
||||||
|
<v-select :options="options" :value="value" @input="setSelected" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import vSelect from 'vue-select';
|
||||||
|
import './fields.css';
|
||||||
|
import 'vue-select/dist/vue-select.css';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Select',
|
||||||
|
props: {
|
||||||
|
title: String,
|
||||||
|
options: Array, // https://vue-select.org/guide/options.html#options-prop
|
||||||
|
value: String,
|
||||||
|
default: String
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
vSelect
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setSelected(option) {
|
||||||
|
const value = option?.value || this.default;
|
||||||
|
this.$emit('change', value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
span {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.v-select {
|
||||||
|
width: 50%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-select .vs__dropdown-toggle {
|
||||||
|
border-color: rgba(var(--color), .26);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-select .vs__selected {
|
||||||
|
color: var(--color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-select .vs__clear,
|
||||||
|
.v-select .vs__open-indicator {
|
||||||
|
fill: var(--color);
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-select .vs__dropdown-menu {
|
||||||
|
background: var(--background);
|
||||||
|
border-color: rgba(var(--color), .26);
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-select .vs__dropdown-option {
|
||||||
|
color: var(--color);
|
||||||
|
}
|
||||||
|
</style>
|
99
src/components/system/fields/Toggle.vue
Normal file
99
src/components/system/fields/Toggle.vue
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
<template>
|
||||||
|
<label class="field">
|
||||||
|
<input type="checkbox" class="toggle" :checked="value" @input="handleInput" />
|
||||||
|
<span>{{ title }}</span>
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import './fields.css';
|
||||||
|
|
||||||
|
// Reference: https://codepen.io/finnhvman/pen/pOeyjE
|
||||||
|
export default {
|
||||||
|
name: 'Toggle',
|
||||||
|
props: {
|
||||||
|
title: String,
|
||||||
|
value: Boolean
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleInput(e) {
|
||||||
|
this.$emit('change', e.target.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.field {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
appearance: none;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* track */
|
||||||
|
span::before {
|
||||||
|
content: "";
|
||||||
|
float: right;
|
||||||
|
margin: 5px 0 5px 10px;
|
||||||
|
border-radius: 7px;
|
||||||
|
width: 36px;
|
||||||
|
height: 14px;
|
||||||
|
background-color: rgba(0, 0, 0, 0.38);
|
||||||
|
vertical-align: top;
|
||||||
|
transition: background-color 0.2s, opacity 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* thumb */
|
||||||
|
span::after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
right: 16px;
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
background-color: white;
|
||||||
|
box-shadow: 0 3px 1px -2px rgba(0, 0, 0, 0.2), 0 2px 2px 0 rgba(0, 0, 0, 0.14), 0 1px 5px 0 rgba(0, 0, 0, 0.12);
|
||||||
|
transition: background-color 0.2s, transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + span::before {
|
||||||
|
background-color: rgba(33, 150, 243, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked + span::after {
|
||||||
|
background-color: rgb(33, 150, 243);
|
||||||
|
transform: translateX(16px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* active */
|
||||||
|
input:active + span::before {
|
||||||
|
background-color: rgba(33, 150, 243, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked:active + span::before {
|
||||||
|
background-color: rgba(0, 0, 0, 0.38);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disabled */
|
||||||
|
input:disabled + span {
|
||||||
|
color: black;
|
||||||
|
opacity: 0.38;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:disabled + span::before {
|
||||||
|
background-color: rgba(0, 0, 0, 0.38);
|
||||||
|
}
|
||||||
|
|
||||||
|
input:checked:disabled + span::before {
|
||||||
|
background-color: rgba(33, 150, 243, 0.6);
|
||||||
|
}
|
||||||
|
</style>
|
8
src/components/system/fields/fields.css
Normal file
8
src/components/system/fields/fields.css
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
.field {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
height: 2em;
|
||||||
|
margin: 10px 0;
|
||||||
|
user-select: none;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
9
src/data/layers.js
Normal file
9
src/data/layers.js
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
// TODO create example layer and import it
|
||||||
|
|
||||||
|
export const layers = {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hotkeys = [
|
||||||
|
|
||||||
|
];
|
|
@ -1,14 +1,12 @@
|
||||||
// import TreeTab from '../components/system/TreeTab.vue';
|
|
||||||
// Import Decimal and numberUtils from a different file to globally change which big num library gets used
|
// Import Decimal and numberUtils from a different file to globally change which big num library gets used
|
||||||
import Decimal, * as numberUtils from '../util/break_eternity.js';
|
import Decimal, * as numberUtils from '../util/break_eternity.js';
|
||||||
|
|
||||||
export default {
|
const modInfo = {
|
||||||
// General Info
|
// General Info
|
||||||
title: "The Modding Tree X",
|
title: "The Modding Tree X",
|
||||||
banner: null,
|
|
||||||
id: "tmt-x",
|
id: "tmt-x",
|
||||||
author: "thepaperpilot",
|
author: "thepaperpilot",
|
||||||
discordName: "TMT-X Server",
|
discordName: "TMT-X",
|
||||||
discordLink: "https://discord.gg/WzejVAx",
|
discordLink: "https://discord.gg/WzejVAx",
|
||||||
|
|
||||||
// Gameplay Options
|
// Gameplay Options
|
||||||
|
@ -17,10 +15,14 @@ export default {
|
||||||
points: new Decimal(10),
|
points: new Decimal(10),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// TODO getPointGen or some abstract version?
|
|
||||||
hasWon() {
|
hasWon() {
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
update(delta) {
|
||||||
|
let gain = new Decimal(1);
|
||||||
|
// TODO add gain to player.deltas
|
||||||
|
gain.times(delta);
|
||||||
|
},
|
||||||
|
|
||||||
// Version
|
// Version
|
||||||
versionNumber: "0.0",
|
versionNumber: "0.0",
|
||||||
|
@ -28,8 +30,11 @@ export default {
|
||||||
|
|
||||||
// UI options
|
// UI options
|
||||||
allowSmall: false,
|
allowSmall: false,
|
||||||
useHeader: true,
|
defaultDecimalsShown: 2,
|
||||||
//defaultTab: TreeTab
|
useHeader: false,
|
||||||
|
banner: null,
|
||||||
|
logo: null,
|
||||||
|
initialTabs: ["tree-tab", "info-tab", "dummy"],
|
||||||
|
|
||||||
// Advanced Options
|
// Advanced Options
|
||||||
/* eslint-disable-next-line no-unused-vars */
|
/* eslint-disable-next-line no-unused-vars */
|
||||||
|
@ -38,3 +43,7 @@ export default {
|
||||||
bigNum: { Decimal, ...numberUtils },
|
bigNum: { Decimal, ...numberUtils },
|
||||||
maxTickLength: 3600
|
maxTickLength: 3600
|
||||||
};
|
};
|
||||||
|
|
||||||
|
document.title = modInfo.title;
|
||||||
|
|
||||||
|
export default modInfo;
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
const defaultTheme = {
|
const defaultTheme = {
|
||||||
"--background": "#0f0f0f",
|
"--background": "#0f0f0f",
|
||||||
"--background_tooltip": "rgba(0, 0, 0, 0.75)",
|
"--background-tooltip": "rgba(0, 0, 0, 0.75)",
|
||||||
"--background_nav": "#0f0f0f",
|
"--secondary-background": "#0f0f0f",
|
||||||
"--color": "#dfdfdf",
|
"--color": "#dfdfdf",
|
||||||
"--points": "#ffffff",
|
"--points": "#ffffff",
|
||||||
"--locked": "#bf8f8f",
|
"--locked": "#bf8f8f",
|
||||||
"--link": "#02f2f2",
|
"--link": "#02f2f2",
|
||||||
"--separator": "#dfdfdf"
|
"--separator": "#dfdfdf",
|
||||||
|
"--border-radius": "25%",
|
||||||
|
"--danger": "rgb(220, 53, 69)",
|
||||||
|
"--modal-border": "solid 2px var(--color)"
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -14,14 +17,16 @@ export default {
|
||||||
paper: {
|
paper: {
|
||||||
...defaultTheme,
|
...defaultTheme,
|
||||||
"--background": "#2a323d",
|
"--background": "#2a323d",
|
||||||
"--background_nav": "#333c4a",
|
"--secondary-background": "#333c4a",
|
||||||
"--separator": "#333c4a"
|
"--separator": "#333c4a",
|
||||||
|
"--border-radius": "4px",
|
||||||
|
"--modal-border": ""
|
||||||
},
|
},
|
||||||
aquad: {
|
aqua: {
|
||||||
...defaultTheme,
|
...defaultTheme,
|
||||||
"--background": "#001f3f",
|
"--background": "#001f3f",
|
||||||
"--background_tooltip": "rgba(0, 15, 31, 0.75)",
|
"--background-tooltip": "rgba(0, 15, 31, 0.75)",
|
||||||
"--background_nav": "#001f3f",
|
"--secondary-background": "#001f3f",
|
||||||
"--color": "#bfdfff",
|
"--color": "#bfdfff",
|
||||||
"--points": "#dfefff",
|
"--points": "#dfefff",
|
||||||
"--locked": "#c4a7b3",
|
"--locked": "#c4a7b3",
|
||||||
|
|
11
src/main.js
11
src/main.js
|
@ -1,12 +1,17 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
import store from './store';
|
import store from './store';
|
||||||
|
import { layers, hotkeys } from './data/layers.js';
|
||||||
|
|
||||||
|
// Setup
|
||||||
Vue.config.productionTip = false;
|
Vue.config.productionTip = false;
|
||||||
|
|
||||||
window.player = store.state;
|
window.player = store.state;
|
||||||
|
|
||||||
new Vue({
|
// Create Vue
|
||||||
|
window.vue = new Vue({
|
||||||
store,
|
store,
|
||||||
render: h => h(App)
|
render: h => h(App),
|
||||||
|
data: { layers, hotkeys }
|
||||||
}).$mount('#app');
|
}).$mount('#app');
|
||||||
|
|
||||||
|
// Start game loop
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import { getInitialStore } from '../util/load.js';
|
import { getInitialStore } from '../util/load.js';
|
||||||
|
import mutations from './mutations';
|
||||||
|
|
||||||
Vue.use(Vuex)
|
Vue.use(Vuex)
|
||||||
|
|
||||||
export default new Vuex.Store({
|
export default new Vuex.Store({
|
||||||
state: getInitialStore(),
|
state: getInitialStore(),
|
||||||
mutations: {
|
mutations
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
},
|
|
||||||
modules: {
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
16
src/store/mutations.js
Normal file
16
src/store/mutations.js
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
import Vue from 'vue';
|
||||||
|
|
||||||
|
export const SET_TABS = 'SET_TABS';
|
||||||
|
export const SET_SETTING = 'SET_SETTING';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
[SET_TABS](state, tabs) {
|
||||||
|
Vue.set(state, 'tabs', tabs);
|
||||||
|
},
|
||||||
|
[SET_SETTING](state, { setting, value }) {
|
||||||
|
if (value == null) {
|
||||||
|
value = !state[setting];
|
||||||
|
}
|
||||||
|
state[setting] = value;
|
||||||
|
}
|
||||||
|
};
|
|
@ -12,7 +12,7 @@ export function exponentialFormat(num, precision, mantissa = true) {
|
||||||
m = decimalOne;
|
m = decimalOne;
|
||||||
e = e.add(1);
|
e = e.add(1);
|
||||||
}
|
}
|
||||||
e = (e.gte(1e9) ? format(e, 3) : (e.gte(10000) ? commaFormat(e, 0) : e.toStringWithDecimalPlaces(0)))
|
e = (e.gte(1e9) ? format(e, Math.max(Math.max(precision, 3), modInfo.defaultDecimalsShown)) : (e.gte(10000) ? commaFormat(e, 0) : e.toStringWithDecimalPlaces(0)))
|
||||||
if (mantissa) {
|
if (mantissa) {
|
||||||
return m.toStringWithDecimalPlaces(precision)+"e"+e;
|
return m.toStringWithDecimalPlaces(precision)+"e"+e;
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,12 +42,13 @@ export function regularFormat(num, precision) {
|
||||||
return (0).toFixed(precision);
|
return (0).toFixed(precision);
|
||||||
}
|
}
|
||||||
if (num.mag < 0.1 && precision !== 0) {
|
if (num.mag < 0.1 && precision !== 0) {
|
||||||
precision = Math.max(precision, 4);
|
precision = Math.max(Math.max(precision, 4), modInfo.defaultDecimalsShown);
|
||||||
}
|
}
|
||||||
return num.toStringWithDecimalPlaces(precision);
|
return num.toStringWithDecimalPlaces(precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function format(decimal, precision=2, small) {
|
export function format(decimal, precision = null, small) {
|
||||||
|
if (precision == null) precision = modInfo.defaultDecimalsShown;
|
||||||
small = small || modInfo.allowSmall;
|
small = small || modInfo.allowSmall;
|
||||||
decimal = new Decimal(decimal);
|
decimal = new Decimal(decimal);
|
||||||
if (isNaN(decimal.sign)||isNaN(decimal.layer)||isNaN(decimal.mag)) {
|
if (isNaN(decimal.sign)||isNaN(decimal.layer)||isNaN(decimal.mag)) {
|
||||||
|
@ -96,10 +97,10 @@ export function formatWhole(decimal) {
|
||||||
return "-"+formatWhole(decimal.neg());
|
return "-"+formatWhole(decimal.neg());
|
||||||
}
|
}
|
||||||
if (decimal.gte(1e9)) {
|
if (decimal.gte(1e9)) {
|
||||||
return format(decimal, 2);
|
return format(decimal);
|
||||||
}
|
}
|
||||||
if (decimal.lte(0.98) && !decimal.eq(0)) {
|
if (decimal.lte(0.98) && !decimal.eq(0)) {
|
||||||
return format(decimal, 2);
|
return format(decimal);
|
||||||
}
|
}
|
||||||
return format(decimal, 0);
|
return format(decimal, 0);
|
||||||
}
|
}
|
||||||
|
@ -128,7 +129,7 @@ export function toPlaces(x, precision, maxAccepted) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Will also display very small numbers
|
// Will also display very small numbers
|
||||||
export function formatSmall(x, precision=2) {
|
export function formatSmall(x, precision = null) {
|
||||||
return format(x, precision, true);
|
return format(x, precision, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
src/util/common.js
Normal file
6
src/util/common.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
// Reference: https://stackoverflow.com/questions/7225407/convert-camelcasetext-to-sentence-case-text
|
||||||
|
export function camelToTitle(camel) {
|
||||||
|
let title = camel.replace(/([A-Z])/g, " $1");
|
||||||
|
title = title.charAt(0).toUpperCase() + title.slice(1);
|
||||||
|
return title;
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import modInfo from '../data/mod.js';
|
||||||
|
|
||||||
export function getInitialStore() {
|
export function getInitialStore() {
|
||||||
return {
|
return {
|
||||||
tabs: ["tree-tab", "info-tab", "dummy"],
|
tabs: modInfo.initialTabs.slice(),
|
||||||
time: Date.now(),
|
time: Date.now(),
|
||||||
autosave: true,
|
autosave: true,
|
||||||
offlineProd: true,
|
offlineProd: true,
|
||||||
|
@ -11,6 +11,7 @@ export function getInitialStore() {
|
||||||
hasNaN: false,
|
hasNaN: false,
|
||||||
lastTenTicks: [],
|
lastTenTicks: [],
|
||||||
showTPS: true,
|
showTPS: true,
|
||||||
|
theme: "paper",
|
||||||
...modInfo.getStartingData()
|
...modInfo.getStartingData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue