Skip to content

Commit 0bb9636

Browse files
committed
Toggle for tracking
1 parent f9730e2 commit 0bb9636

8 files changed

Lines changed: 101 additions & 9 deletions

File tree

ReplayTimerMod/src/GhostSettings.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,16 @@ public static class GhostSettings
1818

1919
// ── Init ──────────────────────────────────────────────────────────────
2020

21+
private static ConfigEntry<bool>? _trackingEnabled;
22+
2123
public static void Init(ConfigFile config)
2224
{
25+
_trackingEnabled = config.Bind(
26+
section: "Mod",
27+
key: "TrackingEnabled",
28+
defaultValue: true,
29+
description: "Master switch. When false, no rooms are recorded and no PBs are updated.");
30+
2331
_ghostEnabled = config.Bind(
2432
section: "Ghost",
2533
key: "Enabled",
@@ -57,7 +65,12 @@ public static void Init(ConfigFile config)
5765

5866
// ── Properties ────────────────────────────────────────────────────────
5967
// Fall back to hardcoded defaults when Init() hasn't been called yet
60-
// (e.g. in unit-test contexts or before Awake).
68+
69+
public static bool TrackingEnabled
70+
{
71+
get => _trackingEnabled?.Value ?? true;
72+
set { if (_trackingEnabled != null) _trackingEnabled.Value = value; }
73+
}
6174

6275
public static bool GhostEnabled
6376
{

ReplayTimerMod/src/PBManager.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ public static void Init()
3333
return pb;
3434
}
3535

36+
// Returns true if the given time would be stored by Evaluate() - i.e.
37+
// it's either the first run for this key or faster than the existing PB.
38+
public static bool WouldBePB(RoomKey key, float time)
39+
{
40+
if (!pbs.TryGetValue(key, out var existing)) return true; // first run
41+
return time < existing.TotalTime;
42+
}
43+
3644
// ── Evaluate (called after a live run) ────────────────────────────────
3745

3846
public static EvaluationResult Evaluate(RecordedRoom run)

ReplayTimerMod/src/ReplayTimerModPlugin.cs

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,13 @@ private void OnSceneChanged(Scene from, Scene to)
6161

6262
private void OnRoomEnter(string sceneName, string entryFromScene)
6363
{
64+
if (!GhostSettings.TrackingEnabled)
65+
{
66+
// Start playback, but don't record
67+
ghostPlayback.StartPlayback(sceneName, entryFromScene);
68+
return;
69+
}
70+
6471
frameRecorder.StartRecording();
6572
ghostPlayback.StartPlayback(sceneName, entryFromScene);
6673
}
@@ -70,13 +77,30 @@ private void OnRoomExit(string sceneName, string entryFromScene,
7077
{
7178
ghostPlayback.StopPlayback();
7279

80+
if (!GhostSettings.TrackingEnabled)
81+
{
82+
frameRecorder.DiscardRecording();
83+
return;
84+
}
85+
7386
RoomKey key = new RoomKey(sceneName, entryFromScene, exitToScene);
74-
RecordedRoom? recording = frameRecorder.FinishRecording(key, lrTime);
7587

76-
if (recording != null)
88+
// Check before calling FinishRecording so we don't pay the cost of
89+
// frames.ToArray() (up to ~25KB) on every missed attempt. For a
90+
// speedrunner retrying the same room hundreds of times this avoids
91+
// GC pressure that would otherwise cause periodic hitches.
92+
if (PBManager.WouldBePB(key, lrTime))
93+
{
94+
RecordedRoom? recording = frameRecorder.FinishRecording(key, lrTime);
95+
if (recording != null)
96+
{
97+
PBManager.Evaluate(recording);
98+
replayUI.OnPBUpdated();
99+
}
100+
}
101+
else
77102
{
78-
EvaluationResult result = PBManager.Evaluate(recording);
79-
replayUI.OnPBUpdated();
103+
frameRecorder.DiscardRecording();
80104
}
81105
}
82106

ReplayTimerMod/src/UI/ReplayUI.Actions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,19 @@ private void ResetJumpFeedback()
274274

275275
// ── Ghost settings ────────────────────────────────────────────────────
276276

277+
private void OnTrackingToggle()
278+
{
279+
GhostSettings.TrackingEnabled = !GhostSettings.TrackingEnabled;
280+
if (trackingToggleLbl == null) return;
281+
bool on = GhostSettings.TrackingEnabled;
282+
trackingToggleLbl.text = on ? "ON" : "OFF";
283+
trackingToggleLbl.color = on ? UIStyle.Accent : UIStyle.Red;
284+
if (trackingToggleBtnImg != null)
285+
trackingToggleBtnImg.color = on
286+
? UIStyle.Accent with { a = 0.22f }
287+
: UIStyle.Red with { a = 0.22f };
288+
}
289+
277290
private void OnGhostToggle()
278291
{
279292
GhostSettings.GhostEnabled = !GhostSettings.GhostEnabled;

ReplayTimerMod/src/UI/ReplayUI.Build.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ private void BuildRightSubHeader(int bodyY)
203203
x: M, w: statusX - M, h: SUBHDR);
204204
}
205205

206-
// ── Settings strip: Ghost [ON/OFF] | Alpha [-] 0.40 [+] | Color ■■■■■■
206+
// ── Settings strip: Tracking [ON/OFF] | Ghost [ON/OFF] | Alpha [-] 0.40 [+] | Color ■■■■■■
207207
private void BuildSettingsBar()
208208
{
209209
var bar = MakeGO("SettingsBar", panelGO!.transform);
@@ -216,6 +216,27 @@ private void BuildSettingsBar()
216216
int stepW = UIStyle.W(22);
217217
int x = M;
218218

219+
// Tracking: [ON/OFF] - master switch for recording
220+
int trackLblW = UIStyle.W(52);
221+
MakeLbl(bar.transform, "Tracking:", UIStyle.FontSizeSm - 1,
222+
UIStyle.Subtext, TextAnchor.MiddleLeft, x: x, y: 0, w: trackLblW, h: STGSH);
223+
x += trackLblW + M / 2;
224+
225+
var trackingBtn = MakeGO("TrackingToggle", bar.transform);
226+
Img(trackingBtn, GhostSettings.TrackingEnabled
227+
? UIStyle.Accent with { a = 0.22f }
228+
: UIStyle.Red with { a = 0.22f });
229+
Btn(trackingBtn, OnTrackingToggle);
230+
Rect(trackingBtn, x, btnY, UIStyle.W(46), btnH);
231+
trackingToggleLbl = MakeLbl(trackingBtn.transform,
232+
GhostSettings.TrackingEnabled ? "ON" : "OFF", UIStyle.FontSizeSm - 1,
233+
GhostSettings.TrackingEnabled ? UIStyle.Accent : UIStyle.Red,
234+
TextAnchor.MiddleCenter, fill: true);
235+
trackingToggleBtnImg = trackingBtn.GetComponent<Image>();
236+
x += UIStyle.W(46);
237+
238+
x = BarSeparator(bar.transform, x, btnY, btnH);
239+
219240
// Ghost: [ON/OFF]
220241
MakeLbl(bar.transform, "Ghost:", UIStyle.FontSizeSm - 1,
221242
UIStyle.Subtext, TextAnchor.MiddleLeft, x: x, y: 0, w: lblW, h: STGSH);

ReplayTimerMod/src/UI/ReplayUI.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ public partial class ReplayUI
4242
// Set by OnPBUpdated() whenever a new PB is recorded
4343
private bool rebuildPending = false;
4444

45+
private bool wasPaused = false;
46+
4547
// Two-click confirm for the global clear-all button.
4648
private bool clearAllPending = false;
4749
private Image? clearAllBtnImg;
@@ -83,6 +85,8 @@ public partial class ReplayUI
8385
// ── Settings strip live refs ──────────────────────────────────────────
8486
private Text? ghostToggleLbl;
8587
private Text? alphaLbl;
88+
private Text? trackingToggleLbl;
89+
private Image? trackingToggleBtnImg;
8690

8791
// ─────────────────────────────────────────────────────────────────────
8892
// SETUP
@@ -128,16 +132,25 @@ public void Tick()
128132
if (!isSetup) return;
129133

130134
bool paused = IsPaused();
131-
canvasGO!.SetActive(paused);
132135

133-
if (!paused)
136+
if (paused && !wasPaused)
134137
{
138+
canvasGO!.SetActive(true);
139+
tabGO!.SetActive(true);
140+
wasPaused = true;
141+
}
142+
143+
if (!paused && wasPaused)
144+
{
145+
canvasGO!.SetActive(false);
135146
expanded = false;
136147
ResetClearAllConfirm();
148+
wasPaused = false;
137149
return;
138150
}
139151

140-
tabGO!.SetActive(true);
152+
if (!paused) return;
153+
141154
panelGO!.SetActive(expanded);
142155

143156
if (expanded && rebuildPending)
632 Bytes
Binary file not shown.
1.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)