Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 46 additions & 20 deletions STROOP.Core/CoreLoop.cs
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
using System.Diagnostics;
using System.Runtime.InteropServices;
using Windows.Win32;

namespace STROOP.Core;

public class CoreLoop
{
private List<double> _fpsTimes = new List<double>();
private Queue<long> _frameTimes = new Queue<long>();
private byte[] _ram;
private object _mStreamProcess = new object();

public double FpsInPractice => _fpsTimes.Count == 0 ? 0 : 1 / _fpsTimes.Average();
public double lastFrameTime => _fpsTimes.Count == 0 ? double.NaN : _fpsTimes.Last();
public double FpsInPractice => _frameTimes.Count == 0 ? 0 : Stopwatch.Frequency / _frameTimes.Average();
public double lastFrameTime => _frameTimes.Count == 0 ? double.NaN : _frameTimes.Last() / (double)Stopwatch.Frequency;

public void Run(CancellationToken cancellationToken, Action handleEvents, Func<double> getTargetedFps)
public void Run(CancellationToken cancellationToken, Action handleEvents, Func<double> getTargetedRefreshRate)
{
Stopwatch frameStopwatch = Stopwatch.StartNew();
using var _ = new HighResTimer(1); // request ~1ms resolution

// since computation of the time to wait for takes time itself, compensate with a few ticks
const int BUFFER_TICKS = 1000;

long ticksPerTwoMs = 2 * Stopwatch.Frequency / 1000;

Stopwatch frameStopwatch = new Stopwatch();
Queue<long> extraTime = new Queue<long>();
extraTime.Enqueue(0);

while (!cancellationToken.IsCancellationRequested)
{
double timeToWait;
long ticksPerFrame = (long)(Stopwatch.Frequency * getTargetedRefreshRate());

frameStopwatch.Restart();
lock (_mStreamProcess)
{
ProcessStream.Instance.RefreshRam();
Expand All @@ -26,23 +39,36 @@ public void Run(CancellationToken cancellationToken, Action handleEvents, Func<d

handleEvents();

// Calculate delay to match correct FPS
frameStopwatch.Stop();
double timePassed = frameStopwatch.ElapsedTicks / (double)Stopwatch.Frequency;
timeToWait = getTargetedFps() - timePassed;
timeToWait = Math.Max(timeToWait, 0);
while (frameStopwatch.ElapsedTicks < ticksPerFrame - ticksPerTwoMs)
Thread.Sleep(1);
do
Thread.Yield();
while (frameStopwatch.ElapsedTicks < ticksPerFrame - extraTime.Average());

long frameTicks = frameStopwatch.ElapsedTicks;
// Calculate Fps
while (_fpsTimes.Count() >= 10)
_fpsTimes.RemoveAt(0);
_fpsTimes.Add(timePassed + timeToWait);

frameStopwatch.Restart();
while (_frameTimes.Count() >= 10)
_frameTimes.Dequeue();
_frameTimes.Enqueue(frameStopwatch.ElapsedTicks);

if (timeToWait > 0)
Thread.Sleep(new TimeSpan((long)(timeToWait * 10000000)));
else
Thread.Yield();
while (extraTime.Count() >= 10)
extraTime.Dequeue();
extraTime.Enqueue(frameStopwatch.ElapsedTicks - frameTicks + BUFFER_TICKS);
}
}
}
file class HighResTimer : IDisposable
{
readonly uint _period;

public HighResTimer(uint periodMs)
{
_period = periodMs;
PInvoke.timeBeginPeriod(_period);
}

public void Dispose()
{
PInvoke.timeEndPeriod(_period);
}
}
3 changes: 3 additions & 0 deletions STROOP.Win32/NativeMethods.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
IsWow64Process

PSAPI_WORKING_SET_EX_INFORMATION
MEMORY_BASIC_INFORMATION

Check warning on line 15 in STROOP.Win32/NativeMethods.txt

View workflow job for this annotation

GitHub Actions / debug-build

This API is only available when targeting a specific CPU architecture. AnyCPU cannot generate this API.

CHARFORMAT2A
CFE_EFFECTS
Expand All @@ -24,3 +24,6 @@
GetAsyncKeyState
GetSystemMetrics
SYSTEM_METRICS_INDEX

timeBeginPeriod
timeEndPeriod
26 changes: 9 additions & 17 deletions STROOP/Tabs/MapTab/DataUtil/HoverDatas.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using OpenTK.Mathematics;
using STROOP.Core;
using STROOP.Tabs.MapTab.Views;

namespace STROOP.Tabs.MapTab.MapObjects
{
Expand All @@ -22,13 +23,9 @@ public PointHoverData(MapObject parent)
this.parent = parent;
}

public virtual void LeftClick(Vector3 position)
{
}
public virtual void LeftClick(Vector3 position) { }

public virtual void RightClick(Vector3 position)
{
}
public virtual void RightClick(Vector3 position) { }

public virtual DragMask CanDrag() => parent.dragMask;

Expand All @@ -45,11 +42,8 @@ public void DragTo(Vector3 newPosition, bool setY)
SetPosition(newPosition);
}

public virtual void Pivot(MapTab tab)
{
tab.graphics.view.camera3DMode = MapView.Camera3DMode.FocusOnPositionAngle;
tab.graphics.view.focusPositionAngle = PositionAngle.Custom(GetPosition(), 0);
}
protected virtual void Pivot(MapTab tab)
=> (tab.graphics.currentView as PivotingView)?.Pivot(PositionAngle.Custom(GetPosition(), 0));

public virtual void AddContextMenuItems(MapTab tab, ContextMenuStrip menu)
{
Expand Down Expand Up @@ -114,7 +108,7 @@ public virtual void AddContextMenuItems(MapTab tab, ContextMenuStrip menu)
);
myItem.DropDownItems.Add(makeReferencePointItem);

if (tab.graphics.view.mode != MapView.ViewMode.TopDown)
if (tab.graphics.viewMode != MapGraphics.ViewMode.TopDown)
{
var pivotItem = new ToolStripMenuItem("Make Pivot Point");
pivotItem.Click += (_, __) => Pivot(tab);
Expand All @@ -129,9 +123,7 @@ protected class MapObjectHoverData : PointHoverData, IPositionCalculatorProvider
{
public PositionAngle currentPositionAngle;

public MapObjectHoverData(MapObject parent) : base(parent)
{
}
public MapObjectHoverData(MapObject parent) : base(parent) { }

protected override void SetPosition(Vector3 position)
{
Expand All @@ -144,11 +136,11 @@ protected override void SetPosition(Vector3 position)

protected override Vector3 GetPosition() => currentPositionAngle?.position ?? Vector3.Zero;

public override void Pivot(MapTab tab)
protected override void Pivot(MapTab tab)
{
if (currentPositionAngle == null)
return;
tab.graphics.view.Pivot(currentPositionAngle);
(tab.graphics.currentView as PivotingView)?.Pivot(currentPositionAngle);
}

public override string ToString() => currentPositionAngle.ToString();
Expand Down
34 changes: 17 additions & 17 deletions STROOP/Tabs/MapTab/MapGraphics.LegacyControlScheme.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ private void UpdateCenter()
if (!isMainMap)
return;

if (view.mode == MapView.ViewMode.ThreeDimensional)
if (viewMode == ViewMode.ThreeDimensional)
return;

if (mapTab.radioButtonMapControllersCenterBestFit.Checked)
Expand All @@ -93,14 +93,14 @@ private void UpdateCenter()
{
case MapCenter.BestFit:
RectangleF rectangle = MapViewScaleWasCourseDefault ? mapTab.GetMapLayout().Coordinates : MAX_COURSE_SIZE;
view.position.X = rectangle.X + rectangle.Width / 2;
view.position.Z = rectangle.Y + rectangle.Height / 2;
currentView.position.X = rectangle.X + rectangle.Width / 2;
currentView.position.Z = rectangle.Y + rectangle.Height / 2;
break;
case MapCenter.Origin:
view.position = new Vector3(0.5f);
currentView.position = new Vector3(0.5f);
break;
case MapCenter.Mario:
view.position = new Vector3(Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.XOffset),
currentView.position = new Vector3(Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.XOffset),
Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.YOffset),
Config.Stream.GetSingle(MarioConfig.StructAddress + MarioConfig.ZOffset));
break;
Expand All @@ -109,36 +109,36 @@ private void UpdateCenter()
mapTab.textBoxMapControllersCenterCustom.LastSubmittedText);
if (posAngle != null)
{
view.position = posAngle.position;
currentView.position = posAngle.position;
break;
}

List<string> stringValues = ParsingUtilities.ParseStringList(
mapTab.textBoxMapControllersCenterCustom.LastSubmittedText, replaceComma: false);
if (stringValues.Count >= 3)
{
view.position.X = ParsingUtilities.ParseFloatNullable(stringValues[0]) ?? 0;
view.position.Y = ParsingUtilities.ParseFloatNullable(stringValues[1]) ?? 0;
view.position.Z = ParsingUtilities.ParseFloatNullable(stringValues[2]) ?? 0;
currentView.position.X = ParsingUtilities.ParseFloatNullable(stringValues[0]) ?? 0;
currentView.position.Y = ParsingUtilities.ParseFloatNullable(stringValues[1]) ?? 0;
currentView.position.Z = ParsingUtilities.ParseFloatNullable(stringValues[2]) ?? 0;
}
else if (stringValues.Count >= 2)
{
view.position.X = ParsingUtilities.ParseFloatNullable(stringValues[0]) ?? 0;
view.position.Z = ParsingUtilities.ParseFloatNullable(stringValues[1]) ?? 0;
currentView.position.X = ParsingUtilities.ParseFloatNullable(stringValues[0]) ?? 0;
currentView.position.Z = ParsingUtilities.ParseFloatNullable(stringValues[1]) ?? 0;
}
else if (stringValues.Count == 1)
{
view.position = new Vector3(ParsingUtilities.ParseFloatNullable(stringValues[0]) ?? 0);
currentView.position = new Vector3(ParsingUtilities.ParseFloatNullable(stringValues[0]) ?? 0);
}
else
view.position = new Vector3();
currentView.position = new Vector3();

break;
}

if (MapViewCenter != MapCenter.Custom)
{
mapTab.textBoxMapControllersCenterCustom.SubmitTextLoosely($"{view.position.X}; {view.position.Y}; {view.position.Z}");
mapTab.textBoxMapControllersCenterCustom.SubmitTextLoosely($"{currentView.position.X}; {currentView.position.Y}; {currentView.position.Z}");
}
}

Expand Down Expand Up @@ -243,9 +243,9 @@ public void ChangeCenter(int xSign, int zSign, object value)
(float xOffsetRotated, float zOffsetRotated) = ((float, float))MoreMath.RotatePointAboutPointAnAngularDistance(
xOffset, zOffset, 0, 0, MapViewAngleValue);
float multiplier = MapViewCenterChangeByPixels ? 1 / MapViewScaleValue : 1;
float newCenterXValue = view.position.X + xOffsetRotated * multiplier;
float newCenterZValue = view.position.Z + zOffsetRotated * multiplier;
mapTab.textBoxMapControllersCenterCustom.SubmitText($"{newCenterXValue}; {view.position.Y}; {newCenterZValue}");
float newCenterXValue = currentView.position.X + xOffsetRotated * multiplier;
float newCenterZValue = currentView.position.Z + zOffsetRotated * multiplier;
mapTab.textBoxMapControllersCenterCustom.SubmitText($"{newCenterXValue}; {currentView.position.Y}; {newCenterZValue}");
}

public void ChangeAngle(int sign, object value)
Expand Down
Loading
Loading