forked from profectus/Profectus
Settings overhaul
This commit is contained in:
parent
d3f5e3bed7
commit
e0e325e048
10 changed files with 140 additions and 32 deletions
|
@ -42,7 +42,7 @@
|
|||
</Tooltip>
|
||||
</div>
|
||||
<div @click="options?.open()">
|
||||
<Tooltip display="Options" :direction="Direction.Down" xoffset="-66px">
|
||||
<Tooltip display="Settings" :direction="Direction.Down" xoffset="-66px">
|
||||
<span class="material-icons">settings</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
@ -59,7 +59,7 @@
|
|||
</Tooltip>
|
||||
</div>
|
||||
<div @click="options?.open()">
|
||||
<Tooltip display="Options" :direction="Direction.Right">
|
||||
<Tooltip display="Settings" :direction="Direction.Right">
|
||||
<span class="material-icons">settings</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
|
|
@ -2,18 +2,27 @@
|
|||
<Modal v-model="isOpen">
|
||||
<template v-slot:header>
|
||||
<div class="header">
|
||||
<h2>Options</h2>
|
||||
<h2>Settings</h2>
|
||||
<div class="option-tabs">
|
||||
<button :class="{selected: isTab('behaviour')}" @click="setTab('behaviour')">Behaviour</button>
|
||||
<button :class="{selected: isTab('appearance')}" @click="setTab('appearance')">Appearance</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-slot:body>
|
||||
<Select title="Theme" :options="themes" v-model="theme" />
|
||||
<component :is="settingFieldsComponent" />
|
||||
<Toggle title="Show TPS" v-model="showTPS" />
|
||||
<hr />
|
||||
<Toggle title="Unthrottled" v-model="unthrottled" />
|
||||
<Toggle :title="offlineProdTitle" v-model="offlineProd" />
|
||||
<Toggle :title="autosaveTitle" v-model="autosave" />
|
||||
<Toggle v-if="projInfo.enablePausing" :title="isPausedTitle" v-model="isPaused" />
|
||||
<div v-if="isTab('behaviour')">
|
||||
<Toggle :title="unthrottledTitle" v-model="unthrottled" />
|
||||
<Toggle v-if="projInfo.enablePausing" :title="isPausedTitle" v-model="isPaused" />
|
||||
<Toggle :title="offlineProdTitle" v-model="offlineProd" />
|
||||
<Toggle :title="autosaveTitle" v-model="autosave" />
|
||||
<FeedbackButton v-if="!autosave" class="button save-button" @click="save()">Manually save</FeedbackButton>
|
||||
</div>
|
||||
<div v-if="isTab('appearance')">
|
||||
<Select :title="themeTitle" :options="themes" v-model="theme" />
|
||||
<component :is="settingFieldsComponent" />
|
||||
<Toggle :title="showTPSTitle" v-model="showTPS" />
|
||||
<Toggle :title="alignModifierUnitsTitle" v-model="alignUnits" />
|
||||
</div>
|
||||
</template>
|
||||
</Modal>
|
||||
</template>
|
||||
|
@ -21,20 +30,34 @@
|
|||
<script setup lang="tsx">
|
||||
import Modal from "components/Modal.vue";
|
||||
import projInfo from "data/projInfo.json";
|
||||
import { save } from "util/save";
|
||||
import rawThemes from "data/themes";
|
||||
import { jsx } from "features/feature";
|
||||
import Tooltip from "features/tooltips/Tooltip.vue";
|
||||
import player from "game/player";
|
||||
import settings, { settingFields } from "game/settings";
|
||||
import { camelToTitle } from "util/common";
|
||||
import { camelToTitle, Direction } from "util/common";
|
||||
import { coerceComponent, render } from "util/vue";
|
||||
import { computed, ref, toRefs } from "vue";
|
||||
import Select from "./fields/Select.vue";
|
||||
import Toggle from "./fields/Toggle.vue";
|
||||
import FeedbackButton from "./fields/FeedbackButton.vue";
|
||||
|
||||
const isOpen = ref(false);
|
||||
const currentTab = ref("behaviour");
|
||||
|
||||
function isTab(tab: string): boolean {
|
||||
return tab == currentTab.value;
|
||||
}
|
||||
|
||||
function setTab(tab: string) {
|
||||
currentTab.value = tab;
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
isTab,
|
||||
setTab,
|
||||
save,
|
||||
open() {
|
||||
isOpen.value = true;
|
||||
}
|
||||
|
@ -49,7 +72,7 @@ const settingFieldsComponent = computed(() => {
|
|||
return coerceComponent(jsx(() => (<>{settingFields.map(render)}</>)));
|
||||
});
|
||||
|
||||
const { showTPS, theme, unthrottled } = toRefs(settings);
|
||||
const { showTPS, theme, unthrottled, alignUnits } = toRefs(settings);
|
||||
const { autosave, offlineProd } = toRefs(player);
|
||||
const isPaused = computed({
|
||||
get() {
|
||||
|
@ -60,30 +83,85 @@ const isPaused = computed({
|
|||
}
|
||||
});
|
||||
|
||||
const unthrottledTitle = jsx(() => (
|
||||
<span class="option-title">
|
||||
Unthrottled
|
||||
<desc>Allow the game to run as fast as possible. Not battery friendly.</desc>
|
||||
</span>
|
||||
));
|
||||
const offlineProdTitle = jsx(() => (
|
||||
<span>
|
||||
Offline Production<Tooltip display="Save-specific">*</Tooltip>
|
||||
<span class="option-title">
|
||||
Offline Production<Tooltip display="Save-specific" direction={Direction.Right}>*</Tooltip>
|
||||
<desc>Simulate production that occurs while the game is closed.</desc>
|
||||
</span>
|
||||
));
|
||||
const autosaveTitle = jsx(() => (
|
||||
<span>
|
||||
Autosave<Tooltip display="Save-specific">*</Tooltip>
|
||||
<span class="option-title">
|
||||
Autosave<Tooltip display="Save-specific" direction={Direction.Right}>*</Tooltip>
|
||||
<desc>Automatically save the game every second or when the game is closed.</desc>
|
||||
</span>
|
||||
));
|
||||
const isPausedTitle = jsx(() => (
|
||||
<span>
|
||||
Pause game<Tooltip display="Save-specific">*</Tooltip>
|
||||
<span class="option-title">
|
||||
Pause game<Tooltip display="Save-specific" direction={Direction.Right}>*</Tooltip>
|
||||
<desc>Stop everything from moving.</desc>
|
||||
</span>
|
||||
));
|
||||
const themeTitle = jsx(() => (
|
||||
<span class="option-title">
|
||||
Theme
|
||||
<desc>How the game looks.</desc>
|
||||
</span>
|
||||
));
|
||||
const showTPSTitle = jsx(() => (
|
||||
<span class="option-title">
|
||||
Show TPS
|
||||
<desc>Show TPS meter at the bottom-left corner of the page.</desc>
|
||||
</span>
|
||||
));
|
||||
const alignModifierUnitsTitle = jsx(() => (
|
||||
<span class="option-title">
|
||||
Align modifier units
|
||||
<desc>Align numbers to the beginning of the unit in modifier view.</desc>
|
||||
</span>
|
||||
));
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.header {
|
||||
<style>
|
||||
.option-tabs {
|
||||
border-bottom: 2px solid var(--outline);
|
||||
margin-top: 10px;
|
||||
margin-bottom: -10px;
|
||||
}
|
||||
|
||||
*:deep() .tooltip-container {
|
||||
.option-tabs button {
|
||||
background-color: transparent;
|
||||
color: var(--foreground);
|
||||
margin-bottom: -2px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
padding: 5px 20px;
|
||||
border: none;
|
||||
border-bottom: 2px solid var(--foreground);
|
||||
}
|
||||
|
||||
.option-tabs button:not(.selected) {
|
||||
border-bottom-color: transparent;
|
||||
}
|
||||
|
||||
.option-title .tooltip-container {
|
||||
display: inline;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.option-title desc {
|
||||
display: block;
|
||||
opacity: 0.6;
|
||||
font-size: small;
|
||||
width: 300px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.save-button {
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -8,10 +8,13 @@
|
|||
}
|
||||
|
||||
.modifier-amount {
|
||||
flex-basis: 100px;
|
||||
flex-shrink: 0;
|
||||
text-align: right;
|
||||
}
|
||||
:not(:first-of-type, :last-of-type) > .modifier-amount::after {
|
||||
content: var(--unit);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.modifier-description {
|
||||
flex-grow: 1;
|
||||
|
|
|
@ -87,6 +87,10 @@ function onUpdate(value: SelectOption) {
|
|||
background-color: var(--bought);
|
||||
}
|
||||
|
||||
.vue-input input {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.vue-input input::placeholder {
|
||||
color: var(--link);
|
||||
}
|
||||
|
|
|
@ -43,14 +43,16 @@ input {
|
|||
|
||||
span {
|
||||
width: 100%;
|
||||
padding-right: 41px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* track */
|
||||
input + span::before {
|
||||
content: "";
|
||||
float: right;
|
||||
margin: 5px 0 5px 10px;
|
||||
position: absolute;
|
||||
top: calc(50% - 7px);
|
||||
right: 0px;
|
||||
border-radius: 7px;
|
||||
width: 36px;
|
||||
height: 14px;
|
||||
|
@ -64,7 +66,7 @@ input + span::before {
|
|||
input + span::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
top: calc(50% - 10px);
|
||||
right: 16px;
|
||||
border-radius: 50%;
|
||||
width: 20px;
|
||||
|
|
|
@ -13,6 +13,7 @@ import type { Modifier } from "game/modifiers";
|
|||
import type { Persistent } from "game/persistence";
|
||||
import { DefaultValue, persistent } from "game/persistence";
|
||||
import player from "game/player";
|
||||
import settings from "game/settings";
|
||||
import type { DecimalSource } from "util/bignum";
|
||||
import Decimal, { format, formatSmall, formatTime } from "util/bignum";
|
||||
import type { WithRequired } from "util/common";
|
||||
|
@ -335,7 +336,12 @@ export function createCollapsibleModifierSections(
|
|||
return (
|
||||
<>
|
||||
{hasPreviousSection ? <br /> : null}
|
||||
<div>
|
||||
<div
|
||||
style={{
|
||||
"--unit":
|
||||
settings.alignUnits && s.unit != null ? "'" + s.unit + "'" : ""
|
||||
}}
|
||||
>
|
||||
{header}
|
||||
<br />
|
||||
{modifiers}
|
||||
|
|
|
@ -313,7 +313,12 @@ globalBus.on("loadSettings", settings => {
|
|||
registerSettingField(
|
||||
jsx(() => (
|
||||
<Toggle
|
||||
title="Hide Maxed Challenges"
|
||||
title={jsx(() => (
|
||||
<span class="option-title">
|
||||
Hide maxed challenges
|
||||
<desc>Hide challenges that have been fully completed.</desc>
|
||||
</span>
|
||||
))}
|
||||
onUpdate:modelValue={value => (settings.hideChallenges = value)}
|
||||
modelValue={settings.hideChallenges}
|
||||
/>
|
||||
|
|
|
@ -221,7 +221,12 @@ const msDisplayOptions = Object.values(MilestoneDisplay).map(option => ({
|
|||
registerSettingField(
|
||||
jsx(() => (
|
||||
<Select
|
||||
title="Show Milestones"
|
||||
title={jsx(() => (
|
||||
<span class="option-title">
|
||||
Show milestones
|
||||
<desc>Select which milestones to display based on criterias.</desc>
|
||||
</span>
|
||||
))}
|
||||
options={msDisplayOptions}
|
||||
onUpdate:modelValue={value => (settings.msDisplay = value as MilestoneDisplay)}
|
||||
modelValue={settings.msDisplay}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import "components/common/modifiers.css";
|
||||
import type { CoercableComponent } from "features/feature";
|
||||
import { jsx } from "features/feature";
|
||||
import settings from "game/settings";
|
||||
import type { DecimalSource } from "util/bignum";
|
||||
import Decimal, { formatSmall } from "util/bignum";
|
||||
import type { WithRequired } from "util/common";
|
||||
|
@ -326,7 +327,7 @@ export function createModifierSection({
|
|||
}: ModifierSectionOptions) {
|
||||
const total = modifier.apply(base ?? 1);
|
||||
return (
|
||||
<div>
|
||||
<div style={{ "--unit": settings.alignUnits && unit != null ? "'" + unit + "'" : "" }}>
|
||||
<h3>
|
||||
{title}
|
||||
{subtitle == null ? null : <span class="subtitle"> ({subtitle})</span>}
|
||||
|
|
|
@ -18,6 +18,8 @@ export interface Settings {
|
|||
theme: Themes;
|
||||
/** Whether or not to cap the project at 20 ticks per second. */
|
||||
unthrottled: boolean;
|
||||
/** Whether to align modifiers to the unit. */
|
||||
alignUnits: boolean;
|
||||
}
|
||||
|
||||
const state = reactive<Partial<Settings>>({
|
||||
|
@ -25,7 +27,8 @@ const state = reactive<Partial<Settings>>({
|
|||
saves: [],
|
||||
showTPS: true,
|
||||
theme: Themes.Nordic,
|
||||
unthrottled: false
|
||||
unthrottled: false,
|
||||
alignUnits: false
|
||||
});
|
||||
|
||||
watch(
|
||||
|
@ -57,7 +60,8 @@ export const hardResetSettings = (window.hardResetSettings = () => {
|
|||
active: "",
|
||||
saves: [],
|
||||
showTPS: true,
|
||||
theme: Themes.Nordic
|
||||
theme: Themes.Nordic,
|
||||
alignUnits: false
|
||||
};
|
||||
globalBus.emit("loadSettings", settings);
|
||||
Object.assign(state, settings);
|
||||
|
|
Loading…
Reference in a new issue