Skip to content

Commit

Permalink
Add Setting for Manual Game Time Input Mode
Browse files Browse the repository at this point in the history
This allows the user to choose between specifying segment times and
split times when using the manual game timer.

Changelog: When using the **Manual Game Time Input**, you can now choose
between specifying **Segment Times** and **Split Times**.
  • Loading branch information
CryZe committed Oct 24, 2024
1 parent ca5f527 commit fa585d0
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 45 deletions.
2 changes: 1 addition & 1 deletion livesplit-core
Submodule livesplit-core updated 39 files
+6 −5 Cargo.toml
+6 −0 capi/src/time_span.rs
+9 −5 crates/livesplit-auto-splitting/Cargo.toml
+31 −21 crates/livesplit-auto-splitting/README.md
+30 −19 crates/livesplit-auto-splitting/src/lib.rs
+16 −9 crates/livesplit-auto-splitting/src/runtime/api/process.rs
+6 −6 crates/livesplit-auto-splitting/src/runtime/api/runtime.rs
+103 −7 crates/livesplit-auto-splitting/src/runtime/api/wasi.rs
+42 −26 crates/livesplit-auto-splitting/src/runtime/mod.rs
+19 −3 crates/livesplit-auto-splitting/src/timer.rs
+3 −2 crates/livesplit-auto-splitting/tests/sandboxing.rs
+3 −3 crates/livesplit-hotkey/Cargo.toml
+74 −47 crates/livesplit-hotkey/src/linux/x11_impl.rs
+3 −3 crates/livesplit-hotkey/src/windows/mod.rs
+44 −21 src/auto_splitting/mod.rs
+1 −1 src/component/separator.rs
+2 −2 src/hotkey_system.rs
+4 −4 src/layout/parser/font_resolving/gdi.rs
+4 −4 src/rendering/default_text_engine/mod.rs
+3 −1 src/rendering/entity.rs
+4 −8 src/rendering/svg.rs
+134 −0 src/run/parser/flitter.rs
+0 −78 src/run/parser/flitter/mod.rs
+0 −419 src/run/parser/flitter/s_expressions.rs
+7 −7 src/run/parser/splitterino.rs
+1 −1 src/settings/layout_background.rs
+111 −1 src/timing/formatter/complete.rs
+105 −1 src/timing/formatter/days.rs
+113 −12 src/timing/formatter/delta.rs
+140 −1 src/timing/formatter/regular.rs
+117 −6 src/timing/formatter/segment_time.rs
+174 −5 src/timing/formatter/timer.rs
+2 −0 src/timing/mod.rs
+132 −50 src/timing/time_span.rs
+8 −19 src/util/ascii_char.rs
+5 −2 tests/rendering.rs
+81 −0 tests/run_files/flitter.json
+1 −2 tests/run_files/mod.rs
+0 −8 tests/split_parsing.rs
6 changes: 5 additions & 1 deletion src/storage/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { openDB, IDBPDatabase } from "idb";
import { Option, assert } from "../util/OptionUtil";
import { RunRef, Run, TimingMethod } from "../livesplit-core";
import { GeneralSettings } from "../ui/MainSettings";
import { GeneralSettings, MANUAL_GAME_TIME_SETTINGS_DEFAULT } from "../ui/MainSettings";
import { FRAME_RATE_AUTOMATIC } from "../util/FrameRate";

export type HotkeyConfigSettings = unknown;
Expand Down Expand Up @@ -249,6 +249,10 @@ export async function loadGeneralSettings(): Promise<GeneralSettings> {

const isTauri = window.__TAURI__ != null;

if (generalSettings.showManualGameTime === true) {
generalSettings.showManualGameTime = MANUAL_GAME_TIME_SETTINGS_DEFAULT;
}

return {
frameRate: generalSettings.frameRate ?? FRAME_RATE_AUTOMATIC,
showControlButtons: generalSettings.showControlButtons ?? !isTauri,
Expand Down
4 changes: 4 additions & 0 deletions src/ui/LSOCommandSink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,10 @@ export class LSOCommandSink {
layoutEditor.updateLayoutState(layoutState, imageCache, this.timer);
}

public currentTime(): TimeRef {
return this.timer.currentTime();
}

public currentSplitIndex(): number {
return this.timer.currentSplitIndex();
}
Expand Down
125 changes: 84 additions & 41 deletions src/ui/MainSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,24 @@ import "../css/SettingsEditor.scss";
export interface GeneralSettings {
frameRate: FrameRateSetting,
showControlButtons: boolean,
showManualGameTime: boolean,
showManualGameTime: ManualGameTimeSettings | false,
saveOnReset: boolean,
speedrunComIntegration: boolean,
splitsIoIntegration: boolean,
serverUrl?: string,
alwaysOnTop?: boolean,
}

export interface ManualGameTimeSettings {
mode: string,
}

export const MANUAL_GAME_TIME_MODE_SEGMENT_TIMES = "Segment Times";
export const MANUAL_GAME_TIME_MODE_SPLIT_TIMES = "Split Times";
export const MANUAL_GAME_TIME_SETTINGS_DEFAULT: ManualGameTimeSettings = {
mode: MANUAL_GAME_TIME_MODE_SEGMENT_TIMES,
};

export interface Props {
generalSettings: GeneralSettings,
hotkeyConfig: HotkeyConfig,
Expand Down Expand Up @@ -62,6 +72,63 @@ export class MainSettings extends React.Component<Props, State> {
}

private renderView() {
const generalFields = [
{
text: "Frame Rate",
tooltip: "Determines the frame rate at which to display the timer. \"Battery Aware\" tries determining the type of device and charging status to select a good frame rate. \"Match Screen\" makes the timer match the screen's refresh rate.",
value: {
CustomCombobox: {
value: this.state.generalSettings.frameRate === FRAME_RATE_MATCH_SCREEN ? FRAME_RATE_MATCH_SCREEN : this.state.generalSettings.frameRate === FRAME_RATE_BATTERY_AWARE ? FRAME_RATE_BATTERY_AWARE : this.state.generalSettings.frameRate.toString() + " FPS",
list: [FRAME_RATE_BATTERY_AWARE, "30 FPS", "60 FPS", "120 FPS", FRAME_RATE_MATCH_SCREEN],
mandatory: true,
}
},
},
{
text: "Save On Reset",
tooltip: "Determines whether to automatically save the splits when resetting the timer.",
value: {
Bool: this.state.generalSettings.saveOnReset,
},
},
{
text: "Show Control Buttons",
tooltip: "Determines whether to show buttons beneath the timer that allow controlling it. When disabled, you have to use the hotkeys instead.",
value: { Bool: this.state.generalSettings.showControlButtons },
},
{
text: "Show Manual Game Time Input",
tooltip: "Shows a text box beneath the timer that allows you to manually input the game time. You start the timer and do splits by pressing the Enter key in the text box. Make sure to compare against \"Game Time\".",
value: { Bool: this.state.generalSettings.showManualGameTime !== false },
},
];

let manualGameTimeModeIndex = 0;
if (this.state.generalSettings.showManualGameTime) {
manualGameTimeModeIndex = generalFields.length;
generalFields.push({
text: "Manual Game Time Mode",
tooltip: "Determines whether to input the manual game time as segment times or split times.",
value: {
CustomCombobox: {
value: this.state.generalSettings.showManualGameTime.mode,
list: [MANUAL_GAME_TIME_MODE_SEGMENT_TIMES, MANUAL_GAME_TIME_MODE_SPLIT_TIMES],
mandatory: false,
}
},
});
}

let alwaysOnTopIndex = 0;
if (window.__TAURI__ != null) {
alwaysOnTopIndex = generalFields.length;
generalFields.push({
text: "Always On Top",
tooltip: "Keeps the window always on top of other windows.",
value: { Bool: this.state.generalSettings.alwaysOnTop! },
});
}

return (
<div className="settings-editor">
<h2>Hotkeys</h2>
Expand All @@ -84,41 +151,7 @@ export class MainSettings extends React.Component<Props, State> {
context="settings-editor-general"
factory={new JsonSettingValueFactory()}
state={{
fields: [
{
text: "Frame Rate",
tooltip: "Determines the frame rate at which to display the timer. \"Battery Aware\" tries determining the type of device and charging status to select a good frame rate. \"Match Screen\" makes the timer match the screen's refresh rate.",
value: {
CustomCombobox: {
value: this.state.generalSettings.frameRate === FRAME_RATE_MATCH_SCREEN ? FRAME_RATE_MATCH_SCREEN : this.state.generalSettings.frameRate === FRAME_RATE_BATTERY_AWARE ? FRAME_RATE_BATTERY_AWARE : this.state.generalSettings.frameRate.toString() + " FPS",
list: [FRAME_RATE_BATTERY_AWARE, "30 FPS", "60 FPS", "120 FPS", FRAME_RATE_MATCH_SCREEN],
mandatory: true,
}
},
},
{
text: "Show Control Buttons",
tooltip: "Determines whether to show buttons beneath the timer that allow controlling it. When disabled, you have to use the hotkeys instead.",
value: { Bool: this.state.generalSettings.showControlButtons },
},
{
text: "Show Manual Game Time Input",
tooltip: "Shows a text box beneath the timer that allows you to manually input the game time. You start the timer and do splits by pressing the Enter key in the text box. Make sure to compare against \"Game Time\".",
value: { Bool: this.state.generalSettings.showManualGameTime },
},
{
text: "Save On Reset",
tooltip: "Determines whether to automatically save the splits when resetting the timer.",
value: {
Bool: this.state.generalSettings.saveOnReset,
},
},
...((window.__TAURI__ != null) ? [{
text: "Always On Top",
tooltip: "Keeps the window always on top of other windows.",
value: { Bool: this.state.generalSettings.alwaysOnTop! },
}] : []),
],
fields: generalFields,
}}
editorUrlCache={this.props.urlCache}
allComparisons={this.props.allComparisons}
Expand All @@ -143,7 +176,7 @@ export class MainSettings extends React.Component<Props, State> {
this.setState({
generalSettings: {
...this.state.generalSettings,
showControlButtons: value.Bool,
saveOnReset: value.Bool,
},
});
}
Expand All @@ -153,7 +186,7 @@ export class MainSettings extends React.Component<Props, State> {
this.setState({
generalSettings: {
...this.state.generalSettings,
showManualGameTime: value.Bool,
showControlButtons: value.Bool,
},
});
}
Expand All @@ -163,19 +196,29 @@ export class MainSettings extends React.Component<Props, State> {
this.setState({
generalSettings: {
...this.state.generalSettings,
saveOnReset: value.Bool,
showManualGameTime: value.Bool ?
MANUAL_GAME_TIME_SETTINGS_DEFAULT : false,
},
});
}
break;
case 4:
if ("Bool" in value) {
default:
if (index === alwaysOnTopIndex && "Bool" in value) {
this.setState({
generalSettings: {
...this.state.generalSettings,
alwaysOnTop: value.Bool,
},
});
} else if (index === manualGameTimeModeIndex && "String" in value) {
this.setState({
generalSettings: {
...this.state.generalSettings,
showManualGameTime: {
mode: value.String,
},
},
});
}
break;
}
Expand Down
12 changes: 10 additions & 2 deletions src/ui/TimerView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import DragUpload from "./DragUpload";
import Layout from "../layout/Layout";
import { UrlCache } from "../util/UrlCache";
import { WebRenderer } from "../livesplit-core/livesplit_core";
import { GeneralSettings } from "./MainSettings";
import { GeneralSettings, MANUAL_GAME_TIME_MODE_SEGMENT_TIMES } from "./MainSettings";
import { LiveSplitServer } from "../api/LiveSplitServer";
import { LSOCommandSink } from "./LSOCommandSink";

Expand Down Expand Up @@ -73,6 +73,8 @@ export class TimerView extends React.Component<Props, State> {
}

private renderView() {
const showManualGameTime = this.props.generalSettings.showManualGameTime;

return <DragUpload
importLayout={(file) => this.props.callbacks.importLayoutFromFile(file)}
importSplits={(file) => this.props.callbacks.importSplitsFromFile(file)}
Expand Down Expand Up @@ -167,7 +169,7 @@ export class TimerView extends React.Component<Props, State> {
</div>
}
{
this.props.generalSettings.showManualGameTime && <div className="buttons" style={{ width: this.props.layoutWidth }}>
showManualGameTime && <div className="buttons" style={{ width: this.props.layoutWidth }}>
<input
type="text"
className="manual-game-time"
Expand All @@ -191,6 +193,12 @@ export class TimerView extends React.Component<Props, State> {
} else {
using gameTime = TimeSpan.parse(this.state.manualGameTime);
if (gameTime !== null) {
if (showManualGameTime.mode === MANUAL_GAME_TIME_MODE_SEGMENT_TIMES) {
const currentGameTime = timer.currentTime().gameTime();
if (currentGameTime !== null) {
gameTime.addAssign(currentGameTime);
}
}
timer.setGameTimeInner(gameTime);
timer.split();
this.setState({ manualGameTime: "" });
Expand Down

0 comments on commit fa585d0

Please sign in to comment.