SHA256
41 lines
2.2 KiB
C#
41 lines
2.2 KiB
C#
using ADOFAIRenderer.Core;
|
|
using HarmonyLib;
|
|
|
|
namespace ADOFAIRenderer.Patch.Engine;
|
|
|
|
/// <summary>
|
|
/// Makes the async input clock offset follow the render clock immediately.
|
|
/// <para>
|
|
/// Patched member: <c>AsyncInputUtils.UpdateOffsetTime(long fixDivider = 1)</c>. The async input system maps wall-clock ticks
|
|
/// (<c>AsyncInputManager.currFrameTick</c> = <c>DateTime.Now.Ticks</c>, 100 ns units) to conductor time with
|
|
/// <c>AsyncInputManager.offsetTick</c> = currFrameTick - <c>scrConductor.dspTime</c> * 10^7. With <c>fixDivider</c> 1 the
|
|
/// offset is set directly; otherwise it moves by 1 / fixDivider of the difference per call. <c>scrConductor</c> calls it every
|
|
/// frame with divider 100 (damped); <c>scrController</c> calls it with divider 1.
|
|
/// </para>
|
|
/// <para>
|
|
/// Active while <see cref="RenderManager.IsActive"/> (stage >= OnScene). From stage Render the conductor time follows the
|
|
/// patched <c>AudioSettings.dspTime</c> (offline render clock, a fixed step per frame independent of wall-clock time), so the
|
|
/// difference changes every frame; the damped update would lag behind it. The prefix always applies the divider-1 update.
|
|
/// </para>
|
|
/// <para>Reference: https://learn.microsoft.com/en-us/dotnet/api/system.datetime.ticks</para>
|
|
/// </summary>
|
|
[HarmonyPatch(typeof(AsyncInputUtils), "UpdateOffsetTime")]
|
|
// ReSharper disable once InconsistentNaming
|
|
public static class AsyncInputPatches
|
|
{
|
|
/// <summary>
|
|
/// Prefix of <c>AsyncInputUtils.UpdateOffsetTime</c>. While rendering, sets <c>offsetTick</c> to
|
|
/// currFrameTick - dspTime * 10^7 (10^7 = 100 ns ticks per second) and <c>offsetTickUpdated</c> to true, for any divider.
|
|
/// </summary>
|
|
/// <returns>True to run the original method (not rendering); false to skip it (rendering).</returns>
|
|
[HarmonyPrefix]
|
|
// ReSharper disable once InconsistentNaming
|
|
public static bool Prefix()
|
|
{
|
|
if (!RenderManager.IsActive) return true;
|
|
// Force offsetTick to match instantly without 1/100 damping division when rendering
|
|
AsyncInputManager.offsetTick = AsyncInputManager.currFrameTick - (long)(scrConductor.instance.dspTime * 10000000.0);
|
|
AsyncInputManager.offsetTickUpdated = true;
|
|
return false; // Skip the original damped offset calculation
|
|
}
|
|
} |