From 0c9bc63a368b44fb1a21393e8593303a866f8b63 Mon Sep 17 00:00:00 2001 From: psyGamer Date: Sat, 22 Feb 2025 13:39:28 +0100 Subject: [PATCH] refactor: Display current TAS input in Info HUD again --- .../Source/EverestInterop/InfoHUD/InfoHud.cs | 2 +- .../Source/InfoHUD/GameInfo.cs | 69 +++++++++++++++---- 2 files changed, 58 insertions(+), 13 deletions(-) diff --git a/CelesteTAS-EverestInterop/Source/EverestInterop/InfoHUD/InfoHud.cs b/CelesteTAS-EverestInterop/Source/EverestInterop/InfoHUD/InfoHud.cs index 2a077a0f..97b5a12b 100644 --- a/CelesteTAS-EverestInterop/Source/EverestInterop/InfoHUD/InfoHud.cs +++ b/CelesteTAS-EverestInterop/Source/EverestInterop/InfoHUD/InfoHud.cs @@ -181,7 +181,7 @@ private static void WriteTasInput(StringBuilder stringBuilder) { string FormatInputFrame(InputFrame inputFrame) { return - $"{(inputFrame.Line + 1).ToString().PadLeft(linePadLeft)}: {string.Empty.PadLeft(framesPadLeft - inputFrame.Frames.ToString().Length)}{inputFrame}"; + $"{(inputFrame.Line + 1).ToString().PadLeft(linePadLeft)}: {string.Empty.PadLeft(framesPadLeft - inputFrame.Frames.ToString().Length)}{inputFrame.ToString().TrimStart()}"; } if (previous != null) { diff --git a/CelesteTAS-EverestInterop/Source/InfoHUD/GameInfo.cs b/CelesteTAS-EverestInterop/Source/InfoHUD/GameInfo.cs index 8a6d961d..851a8f79 100644 --- a/CelesteTAS-EverestInterop/Source/InfoHUD/GameInfo.cs +++ b/CelesteTAS-EverestInterop/Source/InfoHUD/GameInfo.cs @@ -9,6 +9,7 @@ using System.Linq; using System.Text; using TAS.Gameplay; +using TAS.Input; using TAS.ModInterop; using TAS.Module; using TAS.Utils; @@ -32,14 +33,9 @@ public static IEnumerable Query(Target target, bool forceAllowCodeExecut #endif switch (target) { case Target.InGameHud: { - yield return TAS.GameInfo.HudInfo; - yield return "==="; - - // TODO: - // if (TasSettings.InfoTasInput) { - // WriteTasInput(stringBuilder); - // } - + if (TasSettings.InfoTasInput && tasInput.Value is { } input && !string.IsNullOrEmpty(input)) { + yield return input; + } if (TasSettings.InfoGame && levelStatus.Value is { } status && sessionData.Value is { } session) { yield return $"{status}\n[{session.RoomName}] Timer: {session.ChapterTime}"; } @@ -66,7 +62,7 @@ public static IEnumerable Query(Target target, bool forceAllowCodeExecut } case Target.Studio: { - if (TasSettings.InfoGame && levelStatus.Value is { } status && sessionData.Value is { } session) { + if (levelStatus.Value is { } status && sessionData.Value is { } session) { yield return $"{status}\n[{session.RoomName}] Timer: {session.ChapterTime}"; } if (InfoMouse.Info.Value is { } infoMouse) { @@ -178,6 +174,7 @@ private static void ResetCache() { levelStatusExact.Reset(); } + tasInput.Reset(); sessionData.Reset(); if (customInfoTemplateHash != TasSettings.InfoCustomTemplate.GetHashCode()) { @@ -219,6 +216,8 @@ private static void OnLevelTransition(Level level, LevelData next, Vector2 direc } // Caches of calculations for the current frame + private static LazyValue tasInput = new(QueryTasInput); + private static LazyValue levelStatus = new(QueryDisplayLevelStatus); private static LazyValue levelStatusExact = new(QueryExactLevelStatus); private static LazyValue<(string RoomName, string ChapterTime)?> sessionData = new(QuerySessionData); @@ -237,6 +236,52 @@ private static void OnLevelTransition(Level level, LevelData next, Vector2 direc // Kept to reduce allocations private static readonly StringBuilder builder = new(); + private static string? QueryTasInput() { + var controller = Manager.Controller; + var inputs = controller.Inputs; + + if (!Manager.Running || controller.CurrentFrameInTas < 0 || controller.CurrentFrameInTas >= inputs.Count) { + return null; + } + + // The current input is the next executed input, but we want the previously executed input + var current = controller.Current; + if (controller.CurrentFrameInTas >= 1 && current != controller.Previous) { + current = controller.Previous!; + } + + var previous = current.Previous; + var next = current.Next; + + // Align all visible inputs + int maxLine = Math.Max(current.Line, Math.Max(previous?.Line ?? 0, next?.Line ?? 0)) + 1; + int maxLineLen = maxLine.Digits(); + + int maxFrames = Math.Max(current.Frames, Math.Max(previous?.Frames ?? 0, next?.Frames ?? 0)); + int maxFramesLen = maxFrames.Digits(); + + builder.Clear(); + + if (previous != null) { + builder.AppendLine(FormatInput(previous)); + } + + string currentStr = FormatInput(current); + int currFrameLen = controller.CurrentFrameInInput.Digits(); + int inputWidth = Math.Max(20, currentStr.Length + currFrameLen + 2); + builder.AppendLine($"{currentStr.PadRight(inputWidth - currFrameLen)}{controller.CurrentFrameInInput}{current.RepeatString}"); + + if (next != null) { + builder.AppendLine(FormatInput(next)); + } + + return builder.TrimEnd().ToString(); + + string FormatInput(InputFrame input) { + return $"{(input.Line + 1).ToString().PadLeft(maxLineLen)}: {new string(' ', maxFramesLen - input.Frames.Digits())}{input.ToString().TrimStart()}"; + } + } + private static string? QueryDisplayLevelStatus() => QueryLevelStatus(exact: false); private static string? QueryExactLevelStatus() => QueryLevelStatus(exact: true); @@ -449,19 +494,19 @@ private static string FormatState(StateMachine stateMachine) { return name; } - public static string FormatTime(long ticks) { + private static string FormatTime(long ticks) { var timeSpan = TimeSpan.FromTicks(ticks); long frames = ticks / Engine.RawDeltaTime.SecondsToTicks(); return $"{timeSpan.ShortGameplayFormat()}({frames})"; } - public static float ConvertSpeedUnit(float speed, SpeedUnit unit) { + private static float ConvertSpeedUnit(float speed, SpeedUnit unit) { return unit == SpeedUnit.PixelPerSecond ? speed * Engine.TimeRateB : speed * Engine.RawDeltaTime * Engine.TimeRateB; } - public static Vector2 ConvertSpeedUnit(Vector2 speed, SpeedUnit unit) { + private static Vector2 ConvertSpeedUnit(Vector2 speed, SpeedUnit unit) { return unit == SpeedUnit.PixelPerSecond ? speed * Engine.TimeRateB : speed * Engine.RawDeltaTime * Engine.TimeRateB;