From 66a4d68202be838136cdace9314a35baa179295e Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Sat, 1 Aug 2026 10:28:32 +0200 Subject: [PATCH 1/9] stabilize core loop timing --- STROOP.Core/CoreLoop.cs | 66 +++++++++++++++++++++++----------- STROOP.Win32/NativeMethods.txt | 3 ++ 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/STROOP.Core/CoreLoop.cs b/STROOP.Core/CoreLoop.cs index 993babbb3..adc7e5915 100644 --- a/STROOP.Core/CoreLoop.cs +++ b/STROOP.Core/CoreLoop.cs @@ -1,23 +1,36 @@ using System.Diagnostics; +using System.Runtime.InteropServices; +using Windows.Win32; namespace STROOP.Core; public class CoreLoop { - private List _fpsTimes = new List(); + private Queue _frameTimes = new Queue(); 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 getTargetedFps) + public void Run(CancellationToken cancellationToken, Action handleEvents, Func 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 extraTime = new Queue(); + extraTime.Enqueue(0); while (!cancellationToken.IsCancellationRequested) { - double timeToWait; + long ticksPerFrame = (long)(Stopwatch.Frequency * getTargetedRefreshRate()); + + frameStopwatch.Restart(); lock (_mStreamProcess) { ProcessStream.Instance.RefreshRam(); @@ -26,23 +39,36 @@ public void Run(CancellationToken cancellationToken, Action handleEvents, Func= 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); + } +} diff --git a/STROOP.Win32/NativeMethods.txt b/STROOP.Win32/NativeMethods.txt index 7087d42e1..2428bfdb1 100644 --- a/STROOP.Win32/NativeMethods.txt +++ b/STROOP.Win32/NativeMethods.txt @@ -24,3 +24,6 @@ SendMessage GetAsyncKeyState GetSystemMetrics SYSTEM_METRICS_INDEX + +timeBeginPeriod +timeEndPeriod From ff5b0453b68a17453848f3943aa85a91019cebfb Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Mon, 31 Aug 2026 19:32:02 +0200 Subject: [PATCH 2/9] fix 2D Distance crash --- STROOP/Utilities/VariableSelectionUtilities.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/STROOP/Utilities/VariableSelectionUtilities.cs b/STROOP/Utilities/VariableSelectionUtilities.cs index da7f48168..add91f6b2 100644 --- a/STROOP/Utilities/VariableSelectionUtilities.cs +++ b/STROOP/Utilities/VariableSelectionUtilities.cs @@ -241,8 +241,8 @@ void createDistanceMathOperationVariable(bool use3D) { var x1 = values[0]; var y1 = values[1]; - var x2 = values[3]; - var y2 = values[4]; + var x2 = values[2]; + var y2 = values[3]; var min = values.Min(x => x.Length); var result = new List(min); for (int i = 0; i < min; i++) From 8798b8809a0580ba3409dfd37c10fa75e274a9a0 Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Mon, 31 Aug 2026 21:55:39 +0200 Subject: [PATCH 3/9] render all tape measure diffs in all view modes --- .../MapTab/MapObjects/MapTapeMeasureObject.cs | 44 +++++++++++++------ STROOP/Tabs/MapTab/Renderers/TextRenderer.cs | 4 +- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs index 1c54a087a..492b7255a 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs @@ -16,7 +16,7 @@ public interface IPositionCalculatorProvider } [ObjectDescription("Tape Measure", "Custom")] - public class MapTapeMeasureObject : MapLineObject + public class MapTapeMeasureObject : MapObject { class TapeHoverData : IHoverData { @@ -104,6 +104,19 @@ public void AddContextMenuItems(MapTab tab, ContextMenuStrip menu) } } + // display options for the following in order: x, y, xy, z, xz, yz, xyz + static (Color color, bool[] farAlignment)[] textDisplay = + [ + (Color.FromArgb(255, 100, 100), [false, false, false]), + (Color.LightGreen, [false, true, false]), + (Color.Yellow, [true, false, false]), + (Color.LightBlue, [false, false, false]), + (Color.Pink, [false, true, false]), + (Color.Cyan, [true, true, false]), + (Color.LightGray, [true, true, false]), + ]; + + Vector3 a, b; Func aProvider, bProvider; @@ -136,13 +149,11 @@ protected override ContextMenuStrip GetContextMenuStrip(MapTracker targetTracker public override string GetName() => "Tape Measure"; - protected override List GetVertices(MapGraphics graphics) => - new List(new[] { aProvider?.Invoke() ?? a, bProvider?.Invoke() ?? b }); - - protected override void Draw3D(MapGraphics graphics) + protected override void DrawTopDown(MapGraphics graphics) { graphics.drawLayers[(int)MapGraphics.DrawLayers.FillBuffers].Add(() => { + var verticalTextAlignmentIndex = (int)graphics.viewMode; Vector3 _a = aProvider?.Invoke() ?? a; Vector3 _b = bProvider?.Invoke() ?? b; List ends = new List(); @@ -158,20 +169,19 @@ protected override void Draw3D(MapGraphics graphics) new Vector3(1, float.NaN, float.NaN), new Vector3(1, float.NaN, 1), }); - Color[] colors = new[] { Color.FromArgb(255, 100, 100), Color.LightGreen, Color.Yellow, Color.LightBlue, Color.Pink, Color.Cyan, Color.LightGray }; foreach (var end in ends) { string nameString = ""; var p1 = _a; var p2 = _b; - int colorIndex = 0; + int displayIndex = 0; if (!float.IsNaN(end.X)) p1.X = p2.X = end.X == 0 ? p1.X : p2.X; else { nameString += "x"; - colorIndex |= 1; + displayIndex |= 1; } if (!float.IsNaN(end.Y)) @@ -179,7 +189,7 @@ protected override void Draw3D(MapGraphics graphics) else { nameString += "y"; - colorIndex |= 2; + displayIndex |= 2; } if (!float.IsNaN(end.Z)) @@ -187,16 +197,24 @@ protected override void Draw3D(MapGraphics graphics) else { nameString += "z"; - colorIndex |= 4; + displayIndex |= 4; } - var lineColor = colors[colorIndex - 1]; - graphics.lineRenderer.Add(p1, p2, OpenTKUtilities.ColorToVec4(lineColor), OutlineWidth); - graphics.textRenderer.AddText($"{nameString}: {(p1 - p2).Length}", (p1 + p2) * 0.5f, lineColor, StringAlignment.Far); + var t = textDisplay[displayIndex - 1]; + graphics.lineRenderer.Add(p1, p2, OpenTKUtilities.ColorToVec4(t.color), OutlineWidth); + graphics.textRenderer.AddText( + $"{nameString}: {(p1 - p2).Length}", + (p1 + p2) * 0.5f, t.color, + StringAlignment.Far, + lineAlignment: t.farAlignment[verticalTextAlignmentIndex] ? StringAlignment.Far : StringAlignment.Near + ); } }); } + protected override void DrawOrthogonal(MapGraphics graphics) + => DrawTopDown(graphics); + public override IHoverData GetHoverData(MapGraphics graphics, ref Vector3 position) { float magicConst = 15; diff --git a/STROOP/Tabs/MapTab/Renderers/TextRenderer.cs b/STROOP/Tabs/MapTab/Renderers/TextRenderer.cs index b278fd38e..75265724d 100644 --- a/STROOP/Tabs/MapTab/Renderers/TextRenderer.cs +++ b/STROOP/Tabs/MapTab/Renderers/TextRenderer.cs @@ -127,7 +127,7 @@ public override void SetDrawCalls(MapGraphics graphics) }); } - public void AddText(string text, Vector3 position, Color color, StringAlignment alignment, Font font = null) + public void AddText(string text, Vector3 position, Color color, StringAlignment alignment, Font font = null, StringAlignment lineAlignment = StringAlignment.Near) { var graphics = AccessScope.content.graphics; var ssp = Vector4.TransformRow(new Vector4(position.X, position.Y, position.Z, 1.0f), graphics.ViewMatrix); @@ -142,7 +142,7 @@ public void AddText(string text, Vector3 position, Color color, StringAlignment value = text, brush = GetBrush(color), font = font ?? Fonts.medium, - format = new StringFormat() { Alignment = alignment }, + format = new StringFormat() { Alignment = alignment, LineAlignment = lineAlignment }, position = new PointF((screenspacePoint.X + 1) * targetImage.Width / 2f, (-screenspacePoint.Y + 1) * targetImage.Height / 2f), }); } From 414aff0c1a6075a8fe96f50bdbac04a45674722a Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Mon, 31 Aug 2026 22:21:30 +0200 Subject: [PATCH 4/9] add UI toggles for shown tape measure dimensions --- .../MapTab/MapObjects/MapTapeMeasureObject.cs | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs index 492b7255a..ffcd176af 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs @@ -40,13 +40,9 @@ public void DragTo(Vector3 newPosition, bool setY) parent.targetTracker.textBoxSize.Text = (parent.Size = (parent.a - parent.b).Length).ToString(); } - public void SetLookAt(Vector3 lookAt) - { - } + public void SetLookAt(Vector3 lookAt) { } - public void LeftClick(Vector3 position) - { - } + public void LeftClick(Vector3 position) { } public void RightClick(Vector3 position) { @@ -116,6 +112,7 @@ public void AddContextMenuItems(MapTab tab, ContextMenuStrip menu) (Color.LightGray, [true, true, false]), ]; + ToolStripMenuItem[] itemsShownMeasurements = new ToolStripMenuItem[8]; Vector3 a, b; @@ -131,6 +128,14 @@ public MapTapeMeasureObject() a = new Vector3(currentMapTab.graphics.view.position.X - 50, 0, currentMapTab.graphics.view.position.Z); b = new Vector3(currentMapTab.graphics.view.position.X + 50, 0, currentMapTab.graphics.view.position.Z); hoverData = new TapeHoverData(this); + for (int mask = 1; mask <= 8; mask++) + { + var item = new ToolStripMenuItem($"Show {((mask & 1) != 0 ? "x" : "")}{((mask & 2) != 0 ? "y" : "")}{((mask & 4) != 0 ? "z" : "")}"); + item.Click += (_, __) => item.Checked = !item.Checked; + itemsShownMeasurements[mask - 1] = item; + } + foreach (int index in new [] { 0, 1, 3, 4 }) + itemsShownMeasurements[index].Checked = true; } MapTracker targetTracker; @@ -142,6 +147,8 @@ protected override ContextMenuStrip GetContextMenuStrip(MapTracker targetTracker var _contextMenuStrip = base.GetContextMenuStrip(targetTracker); _contextMenuStrip.Items.Cast().FirstOrDefault(x => x.Text == "Enable dragging")?.PerformClick(); + _contextMenuStrip.Items.Add(new ToolStripSeparator()); + _contextMenuStrip.Items.AddRange(itemsShownMeasurements); return _contextMenuStrip; } @@ -200,14 +207,17 @@ protected override void DrawTopDown(MapGraphics graphics) displayIndex |= 4; } - var t = textDisplay[displayIndex - 1]; - graphics.lineRenderer.Add(p1, p2, OpenTKUtilities.ColorToVec4(t.color), OutlineWidth); - graphics.textRenderer.AddText( - $"{nameString}: {(p1 - p2).Length}", - (p1 + p2) * 0.5f, t.color, - StringAlignment.Far, - lineAlignment: t.farAlignment[verticalTextAlignmentIndex] ? StringAlignment.Far : StringAlignment.Near - ); + if (itemsShownMeasurements[--displayIndex].Checked) + { + var t = textDisplay[displayIndex]; + graphics.lineRenderer.Add(p1, p2, OpenTKUtilities.ColorToVec4(t.color), OutlineWidth); + graphics.textRenderer.AddText( + $"{nameString}: {(p1 - p2).Length}", + (p1 + p2) * 0.5f, t.color, + StringAlignment.Far, + lineAlignment: t.farAlignment[verticalTextAlignmentIndex] ? StringAlignment.Far : StringAlignment.Near + ); + } } }); } From faaee66787e41807a43db912d048b9845f7e8c8f Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Fri, 31 Jul 2026 23:55:42 +0200 Subject: [PATCH 5/9] Decouple map tab view modes --- STROOP/Tabs/MapTab/DataUtil/HoverDatas.cs | 26 +-- .../MapTab/MapGraphics.LegacyControlScheme.cs | 34 +-- STROOP/Tabs/MapTab/MapGraphics.cs | 219 ++++++++++-------- .../MapObjects/MapBruteforceTriangles.cs | 2 +- .../Tabs/MapTab/MapObjects/MapCircleObject.cs | 2 +- .../MapTab/MapObjects/MapCustomCameraPath.cs | 14 +- .../MapTab/MapObjects/MapCustomIconPoints.cs | 6 +- .../MapTab/MapObjects/MapCylinderObject.cs | 2 +- .../Tabs/MapTab/MapObjects/MapGhostObject.cs | 2 +- .../MapTab/MapObjects/MapGridlinesObject.cs | 6 +- .../MapObjects/MapHorizontalTriangleObject.cs | 4 +- .../MapTab/MapObjects/MapIconPointObject.cs | 10 +- .../MapTab/MapObjects/MapIwerlipsesObject.cs | 2 +- .../MapObjects/MapMultipleObjectsObject.cs | 2 +- .../Tabs/MapTab/MapObjects/MapNearbyUnits.cs | 6 +- .../MapObjects/MapNextPositionsObject.cs | 2 +- STROOP/Tabs/MapTab/MapObjects/MapObject.cs | 14 +- .../MapObjects/MapPreviousPositionsObject.cs | 2 +- .../Tabs/MapTab/MapObjects/MapQuadObject.cs | 2 +- .../MapTab/MapObjects/MapTapeMeasureObject.cs | 10 +- .../MapTab/MapObjects/MapTriangleObject.cs | 8 +- .../Tabs/MapTab/MapObjects/MapWallObject.cs | 2 +- STROOP/Tabs/MapTab/MapPopout.cs | 2 +- STROOP/Tabs/MapTab/MapTab.cs | 59 +++-- STROOP/Tabs/MapTab/MapView.cs | 50 ---- .../Tabs/MapTab/Renderers/GeometryRenderer.cs | 2 +- .../MapTab/Renderers/TransparencyRenderer.cs | 2 +- .../Tabs/MapTab/Renderers/TriangleRenderer.cs | 2 +- STROOP/Tabs/MapTab/Views/View3D.cs | 32 +++ STROOP/Tabs/MapTab/Views/ViewBase.cs | 27 +++ STROOP/Tabs/MapTab/Views/ViewOrthogonal.cs | 15 ++ STROOP/Tabs/MapTab/Views/ViewTopDown.cs | 8 + 32 files changed, 309 insertions(+), 267 deletions(-) delete mode 100644 STROOP/Tabs/MapTab/MapView.cs create mode 100644 STROOP/Tabs/MapTab/Views/View3D.cs create mode 100644 STROOP/Tabs/MapTab/Views/ViewBase.cs create mode 100644 STROOP/Tabs/MapTab/Views/ViewOrthogonal.cs create mode 100644 STROOP/Tabs/MapTab/Views/ViewTopDown.cs diff --git a/STROOP/Tabs/MapTab/DataUtil/HoverDatas.cs b/STROOP/Tabs/MapTab/DataUtil/HoverDatas.cs index e88f5c3ef..a911bbc6e 100644 --- a/STROOP/Tabs/MapTab/DataUtil/HoverDatas.cs +++ b/STROOP/Tabs/MapTab/DataUtil/HoverDatas.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using OpenTK.Mathematics; using STROOP.Core; +using STROOP.Tabs.MapTab.Views; namespace STROOP.Tabs.MapTab.MapObjects { @@ -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; @@ -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) { @@ -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); @@ -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) { @@ -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(); diff --git a/STROOP/Tabs/MapTab/MapGraphics.LegacyControlScheme.cs b/STROOP/Tabs/MapTab/MapGraphics.LegacyControlScheme.cs index 24b390123..b2671bc4d 100644 --- a/STROOP/Tabs/MapTab/MapGraphics.LegacyControlScheme.cs +++ b/STROOP/Tabs/MapTab/MapGraphics.LegacyControlScheme.cs @@ -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) @@ -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; @@ -109,7 +109,7 @@ private void UpdateCenter() mapTab.textBoxMapControllersCenterCustom.LastSubmittedText); if (posAngle != null) { - view.position = posAngle.position; + currentView.position = posAngle.position; break; } @@ -117,28 +117,28 @@ private void UpdateCenter() 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}"); } } @@ -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) diff --git a/STROOP/Tabs/MapTab/MapGraphics.cs b/STROOP/Tabs/MapTab/MapGraphics.cs index 1a233767f..3046817ec 100644 --- a/STROOP/Tabs/MapTab/MapGraphics.cs +++ b/STROOP/Tabs/MapTab/MapGraphics.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using OpenTK; using OpenTK.Graphics.OpenGL; using System.Windows.Forms; using System.Drawing; @@ -12,6 +11,7 @@ using STROOP.Extensions; using STROOP.Structs; using STROOP.Structs.Configurations; +using STROOP.Tabs.MapTab.Views; using STROOP.Utilities; namespace STROOP.Tabs.MapTab @@ -31,6 +31,13 @@ public enum DrawLayers Overlay, } + public enum ViewMode + { + TopDown, + Orthogonal, + ThreeDimensional + } + static Vector3 ProjectOnLineSegment(Vector3 p, Vector3 A, Vector3 B) { Vector3 d = B - A; @@ -49,14 +56,6 @@ public bool HoverOrthogonal(Vector3 position, float radius) return (projectedPos.Xy - mousePosition2D).LengthSquared < (radius * radius); } - public bool Hover3D(Vector3 position, float radius) - { - var lineEnd = cursorOnMap - ? mapCursorPosition - : view.position + Vector3.Normalize(mapCursorPosition - view.position) * 10000; - return ((ProjectOnLineSegment(position, view.position, lineEnd) - position).Length < radius); - } - public readonly List[] drawLayers; public Renderers.RendererCollection rendererCollection { get; private set; } @@ -155,28 +154,42 @@ private enum MapAngle public readonly GLControl glControl; public readonly MapTab mapTab; - public readonly MapView view; + + public ViewMode viewMode = ViewMode.TopDown; + + public ViewBase currentView => viewMode switch + { + ViewMode.TopDown => viewTopDown, + ViewMode.Orthogonal => viewOrthogonal, + ViewMode.ThreeDimensional => view3D, + }; + + public readonly ViewTopDown viewTopDown = new(); + public readonly ViewOrthogonal viewOrthogonal = new(); + public readonly View3D view3D = new(); public float MapViewRadius => (float)MoreMath.GetHypotenuse(glControl.Width / 2, glControl.Height / 2) / MapViewScaleValue; + public bool drawCylinderOutlines = false; + public float MapViewXMin { - get => view.position.X - MapViewRadius * glControl.AspectRatio; + get => currentView.position.X - MapViewRadius * glControl.AspectRatio; } public float MapViewXMax { - get => view.position.X + MapViewRadius * glControl.AspectRatio; + get => currentView.position.X + MapViewRadius * glControl.AspectRatio; } public float MapViewZMin { - get => view.position.Z - MapViewRadius; + get => currentView.position.Z - MapViewRadius; } public float MapViewZMax { - get => view.position.Z + MapViewRadius; + get => currentView.position.Z + MapViewRadius; } public static readonly int MAX_COURSE_SIZE_X_MIN = -8191; @@ -204,7 +217,7 @@ public Vector2 mousePosition2D public bool cursorOnMap = false; Vector3 normalAtCursor; public float cursorViewPlaneDist = 1000; - public bool fixCursorPlane => view.mode == MapView.ViewMode.ThreeDimensional && keyboardControls.IsShiftDown(); + public bool fixCursorPlane => viewMode == ViewMode.ThreeDimensional && keyboardControls.IsShiftDown(); public float nearClip { get; private set; } public float farClip { get; private set; } @@ -237,7 +250,6 @@ public MapGraphics(MapTab mapTab, GLControl glControl, Func ge glControl.MouseDown += (_, _) => glControl.Focus(); keyboardControls = new(glControl); - view = new MapView(); drawLayers = new List[Enum.GetNames(typeof(DrawLayers)).Length]; for (int i = 0; i < drawLayers.Length; i++) drawLayers[i] = new List(); @@ -393,6 +405,7 @@ public void CleanUp() GL.DeleteFramebuffer(presentFrameBuffer); getContext().MakeCurrent(); } + transparencyRenderer.CleanUp(); DeleteMainSurfaces(); } @@ -431,12 +444,12 @@ private void OnPaint() if (levelTrianglesFor3DMap == null || mapTab.NeedsGeometryRefresh()) levelTrianglesFor3DMap = TriangleUtilities.GetLevelTriangles(); - if (view.mode == MapView.ViewMode.ThreeDimensional) + if (currentView == view3D) { GL.ClearDepth(1); GL.Clear(ClearBufferMask.DepthBufferBit); - if (view.display3DLevelGeometry) + if (view3D.display3DLevelGeometry) drawLayers[(int)DrawLayers.FillBuffers].Insert(0, () => { foreach (var t in levelTrianglesFor3DMap) @@ -490,63 +503,63 @@ private void UpdateMapView() ); - float zFar = view.mode == MapView.ViewMode.TopDown || float.IsNaN(view.orthoRelativeFarPlane) ? 100000 : view.orthoRelativeFarPlane; - float zNear = view.mode == MapView.ViewMode.TopDown || float.IsNaN(view.orthoRelativeNearPlane) ? -100000 : view.orthoRelativeNearPlane; + float zFar = viewMode == ViewMode.TopDown || float.IsNaN(viewOrthogonal.orthoRelativeFarPlane) ? 100000 : viewOrthogonal.orthoRelativeFarPlane; + float zNear = viewMode == ViewMode.TopDown || float.IsNaN(viewOrthogonal.orthoRelativeNearPlane) ? -100000 : viewOrthogonal.orthoRelativeNearPlane; zFar = Math.Max(zNear + 0.0001f, zFar); Matrix4 othoDepth = Matrix4.CreateOrthographic(2, 2, zNear, zFar); - switch (view.mode) + switch (viewMode) { - case MapView.ViewMode.TopDown: + case ViewMode.TopDown: BillboardMatrix = swapYZ; - ViewMatrix = Matrix4.CreateTranslation(new Vector3(-view.position.X, 0, -view.position.Z)) + ViewMatrix = Matrix4.CreateTranslation(new Vector3(-currentView.position.X, 0, -currentView.position.Z)) * swapYZ * Matrix4.CreateRotationZ((float)(Math.PI + MoreMath.AngleUnitsToRadians(MapViewAngleValue))) * Matrix4.CreateScale(scale / glControl.AspectRatio, -scale, 1) * othoDepth; break; - case MapView.ViewMode.Orthogonal: + case ViewMode.Orthogonal: float cool = (float)MoreMath.AngleUnitsToRadians(MapViewAngleValue); BillboardMatrix = Matrix4.CreateRotationY(cool); - float d = -Vector3.Dot(-BillboardMatrix.Row2.Xyz, view.focusPositionAngle.position); + float d = -Vector3.Dot(-BillboardMatrix.Row2.Xyz, viewOrthogonal.focusPositionAngle.position); orthographicZero = (-BillboardMatrix.Row2.Xyz, d); - worldspaceNearPlane = (-BillboardMatrix.Row2.Xyz, d + view.orthoRelativeNearPlane); - worldspaceFarPlane = (BillboardMatrix.Row2.Xyz, d - view.orthoRelativeFarPlane); + worldspaceNearPlane = (-BillboardMatrix.Row2.Xyz, d + viewOrthogonal.orthoRelativeNearPlane); + worldspaceFarPlane = (BillboardMatrix.Row2.Xyz, d - viewOrthogonal.orthoRelativeFarPlane); ViewMatrix = - Matrix4.CreateTranslation(-view.focusPositionAngle.position) + Matrix4.CreateTranslation(-viewOrthogonal.focusPositionAngle.position) * Matrix4.CreateRotationY(-cool) - * Matrix4.CreateTranslation(-view.orthoOffset.X, -view.orthoOffset.Y, 0) + * Matrix4.CreateTranslation(-viewOrthogonal.orthoOffset.X, -viewOrthogonal.orthoOffset.Y, 0) * Matrix4.CreateScale(scale / glControl.AspectRatio, scale, 1) * othoDepth; break; - case MapView.ViewMode.ThreeDimensional: - Vector3 target = view.focusPositionAngle.position; - Vector3 viewDirection = view.ComputeViewDirection(); + case ViewMode.ThreeDimensional: + Vector3 target = view3D.focusPositionAngle.position; + Vector3 viewDirection = currentView.ComputeViewDirection(); if (float.IsNaN(viewDirection.X)) viewDirection = new Vector3(0, 0, 1); - switch (view.camera3DMode) + switch (view3D.camera3DMode) { - case MapView.Camera3DMode.InGame: - view.position = new Vector3(Models.DataModels.Camera.X, Models.DataModels.Camera.Y, Models.DataModels.Camera.Z); - view.yaw = (float)MoreMath.AngleUnitsToRadians(Models.DataModels.Camera.FacingYaw); - view.pitch = (float)MoreMath.AngleUnitsToRadians(-Models.DataModels.Camera.FacingPitch); - target = view.position + viewDirection; + case View3D.Camera3DMode.InGame: + view3D.position = new Vector3(Models.DataModels.Camera.X, Models.DataModels.Camera.Y, Models.DataModels.Camera.Z); + view3D.yaw = (float)MoreMath.AngleUnitsToRadians(Models.DataModels.Camera.FacingYaw); + view3D.pitch = (float)MoreMath.AngleUnitsToRadians(-Models.DataModels.Camera.FacingPitch); + target = currentView.position + viewDirection; break; - case MapView.Camera3DMode.FocusOnPositionAngle: - view.position = target - viewDirection / (float)Math.Exp(-view.camera3DDistanceController * 0.1f); + case View3D.Camera3DMode.FocusOnPositionAngle: + currentView.position = target - viewDirection / (float)Math.Exp(-view3D.camera3DDistanceController * 0.1f); break; - case MapView.Camera3DMode.Free: - target = view.position + viewDirection * (mapCursorPosition - view.position).Length; + case View3D.Camera3DMode.Free: + target = currentView.position + viewDirection * (mapCursorPosition - currentView.position).Length; break; } - nearClip = Math.Max(1, Math.Min(50, (target - view.position).Length / 100)); + nearClip = Math.Max(1, Math.Min(50, (target - currentView.position).Length / 100)); farClip = nearClip * 5000; - ViewMatrix = Matrix4.LookAt(view.position, target, new Vector3(0, 1, 0)); + ViewMatrix = Matrix4.LookAt(currentView.position, target, new Vector3(0, 1, 0)); var mat = Matrix4.Invert(ViewMatrix); mat.Row3 = new Vector4(0, 0, 0, 1); BillboardMatrix = mat; @@ -567,7 +580,7 @@ bool FindClosestIntersection(Vector3 rayOrigin, Vector3 rayDirection, out Vector float closestDistance = float.PositiveInfinity, newDistance; foreach (var t in levelTrianglesFor3DMap) if (t.Intersect(rayOrigin, viewDirection, out Vector3 newIntersection, out Vector3 newNormal) - && (newDistance = (newIntersection - view.position).LengthSquared) < closestDistance) + && (newDistance = (newIntersection - currentView.position).LengthSquared) < closestDistance) { closestDistance = newDistance; intersection = newIntersection; @@ -579,7 +592,7 @@ bool FindClosestIntersection(Vector3 rayOrigin, Vector3 rayDirection, out Vector public void UpdateCursor() { - if (view.mode != MapView.ViewMode.ThreeDimensional) + if (viewMode != ViewMode.ThreeDimensional) { var e = glControl.PointToClient(Cursor.Position); mapCursorPosition = Vector3.TransformPosition(new Vector3(2.0f * e.X / glControl.Width - 1, 1 - 2.0f * e.Y / glControl.Height, 0), Matrix4.Invert(ViewMatrix)); @@ -596,18 +609,26 @@ public void UpdateCursor() if (float.IsNaN(dir.X)) dir = new Vector3(0, 0, 1); if (!fixCursorPlane - && (cursorOnMap = FindClosestIntersection(view.position + dir, dir, out Vector3 closestIntersection, out hoverTriangle))) + && (cursorOnMap = FindClosestIntersection(currentView.position + dir, dir, out Vector3 closestIntersection, out hoverTriangle))) { normalAtCursor = new Vector3(hoverTriangle.NormX, hoverTriangle.NormY, hoverTriangle.NormZ); mapCursorPosition = closestIntersection; - cursorViewPlaneDist = Vector3.Dot(mapCursorPosition - view.position, -BillboardMatrix.Row2.Xyz); + cursorViewPlaneDist = Vector3.Dot(mapCursorPosition - currentView.position, -BillboardMatrix.Row2.Xyz); } else - mapCursorPosition = view.position + dir * cursorViewPlaneDist; + mapCursorPosition = currentView.position + dir * cursorViewPlaneDist; } } } + public bool Hover3D(Vector3 position, float radius) + { + var lineEnd = cursorOnMap + ? mapCursorPosition + : currentView.position + Vector3.Normalize(mapCursorPosition - currentView.position) * 10000; + return ((ProjectOnLineSegment(position, currentView.position, lineEnd) - position).Length < radius); + } + private int _dragStartMouseX = 0; private int _dragStartMouseY = 0; private Vector3 _translateStartCenter = new Vector3(0); @@ -627,15 +648,15 @@ private void OnMouseDown(object sender, MouseEventArgs e) _rotateStartAngle = MapViewAngleValue; _dragStartMouseX = e.X; _dragStartMouseY = e.Y; - _translateStartCenter = view.position; - _translateStartOrthoOffset = view.orthoOffset; - _dragStartYaw = view.yaw; - _dragStartPitch = view.pitch; + _translateStartCenter = currentView.position; + _translateStartOrthoOffset = viewOrthogonal.orthoOffset; + _dragStartYaw = currentView.yaw; + _dragStartPitch = currentView.pitch; _rotatePivot = mapCursorPosition; - Matrix4 viewOrientation = view.ComputeViewOrientation(); - _rotateDiff = Vector3.TransformPosition(view.position - mapCursorPosition, Matrix4.Invert(viewOrientation)); + Matrix4 viewOrientation = currentView.ComputeViewOrientation(); + _rotateDiff = Vector3.TransformPosition(currentView.position - mapCursorPosition, Matrix4.Invert(viewOrientation)); - view.movementSpeed = (mapCursorPosition - view.position).Length * 0.5f; + currentView.movementSpeed = (mapCursorPosition - currentView.position).Length * 0.5f; break; case MouseButtons.Right: mouseDown[1] = true; @@ -644,8 +665,8 @@ private void OnMouseDown(object sender, MouseEventArgs e) mouseDown[2] = true; _dragStartMouseX = e.X; _dragStartMouseY = e.Y; - _dragStartYaw = view.yaw; - _dragStartPitch = view.pitch; + _dragStartYaw = currentView.yaw; + _dragStartPitch = currentView.pitch; break; } @@ -681,7 +702,7 @@ private void OnMouseMove(object sender, MouseEventArgs e) for (int i = 0; i < mouseDown.Length; i++) mouseDown[i] &= MouseUtility.IsMouseDown(i); - if (view.mode != MapView.ViewMode.ThreeDimensional) + if (viewMode != ViewMode.ThreeDimensional) mapCursorPosition = Vector3.TransformPosition(new Vector3(2.0f * e.X / glControl.Width - 1, 1 - 2.0f * e.Y / glControl.Height, 0), Matrix4.Invert(ViewMatrix)); using (new AccessScope(mapTab)) @@ -699,7 +720,7 @@ private void OnMouseMove(object sender, MouseEventArgs e) } else if (hover.CanDrag() != DragMask.None) { - hover.DragTo(mapCursorPosition, view.mode != MapView.ViewMode.TopDown); + hover.DragTo(mapCursorPosition, viewMode != ViewMode.TopDown); return; } } @@ -707,24 +728,24 @@ private void OnMouseMove(object sender, MouseEventArgs e) if (mouseDown[2]) { - if (view.mode == MapView.ViewMode.ThreeDimensional) + if (viewMode == ViewMode.ThreeDimensional) { int pixelDiffX = e.X - _dragStartMouseX; int pixelDiffY = e.Y - _dragStartMouseY; - float mul = 10.0f / (float)Math.Log((view.position - _rotatePivot).Length); + float mul = 10.0f / (float)Math.Log((currentView.position - _rotatePivot).Length); float diffX = pixelDiffX / (float)glControl.Width * 2 * mul; float diffY = pixelDiffY / (float)glControl.Height * 2 * mul; if (float.IsNaN(diffX) || float.IsNaN(diffY)) throw null; - if (view.camera3DMode == MapView.Camera3DMode.Free) + if (view3D.camera3DMode == View3D.Camera3DMode.Free) { - view.yaw = _dragStartYaw - diffX; - view.pitch = Math.Max(-(float)Math.PI * 0.499f, Math.Min((float)Math.PI * 0.499f, _dragStartPitch + diffY)); + view3D.yaw = _dragStartYaw - diffX; + view3D.pitch = Math.Max(-(float)Math.PI * 0.499f, Math.Min((float)Math.PI * 0.499f, _dragStartPitch + diffY)); } - else if (view.camera3DMode == MapView.Camera3DMode.FocusOnPositionAngle) + else if (view3D.camera3DMode == View3D.Camera3DMode.FocusOnPositionAngle) { - view.yaw = _dragStartYaw + diffX; - view.pitch = Math.Max(-(float)Math.PI * 0.499f, Math.Min((float)Math.PI * 0.499f, _dragStartPitch - diffY)); + view3D.yaw = _dragStartYaw + diffX; + view3D.pitch = Math.Max(-(float)Math.PI * 0.499f, Math.Min((float)Math.PI * 0.499f, _dragStartPitch - diffY)); } } } @@ -739,38 +760,38 @@ private void OnMouseMove(object sender, MouseEventArgs e) pixelDiffY = mapTab.MaybeReverse(pixelDiffY); float unitDiffX = pixelDiffX / MapViewScaleValue; float unitDiffY = pixelDiffY / MapViewScaleValue; - switch (view.mode) + switch (viewMode) { - case MapView.ViewMode.TopDown: + case ViewMode.TopDown: { (float rotatedX, float rotatedY) = ((float, float)) MoreMath.RotatePointAboutPointAnAngularDistance( unitDiffX, unitDiffY, 0, 0, MapViewAngleValue); - view.position.X = _translateStartCenter.X - rotatedX; - view.position.Z = _translateStartCenter.Z - rotatedY; - SetCustomCenter($"{view.position.X}; {view.position.Y}; {view.position.Z}"); + currentView.position.X = _translateStartCenter.X - rotatedX; + currentView.position.Z = _translateStartCenter.Z - rotatedY; + SetCustomCenter($"{currentView.position.X}; {currentView.position.Y}; {currentView.position.Z}"); break; } - case MapView.ViewMode.Orthogonal: + case ViewMode.Orthogonal: { - view.orthoOffset = _translateStartOrthoOffset + new Vector2(-unitDiffX, unitDiffY); + viewOrthogonal.orthoOffset = _translateStartOrthoOffset + new Vector2(-unitDiffX, unitDiffY); break; } - case MapView.ViewMode.ThreeDimensional: - if (view.camera3DMode != MapView.Camera3DMode.InGame) + case ViewMode.ThreeDimensional: + if (view3D.camera3DMode != View3D.Camera3DMode.InGame) { - float mul = 10.0f / (float)Math.Log((view.position - _rotatePivot).Length); + float mul = 10.0f / (float)Math.Log((currentView.position - _rotatePivot).Length); float diffX = pixelDiffX / (float)glControl.Width * 2 * mul; float diffY = pixelDiffY / (float)glControl.Height * 2 * mul; if (float.IsNaN(diffX) || float.IsNaN(diffY)) throw null; - view.yaw = _dragStartYaw + diffX; - view.pitch = Math.Max(-(float)Math.PI * 0.499f, Math.Min((float)Math.PI * 0.499f, _dragStartPitch - diffY)); + view3D.yaw = _dragStartYaw + diffX; + view3D.pitch = Math.Max(-(float)Math.PI * 0.499f, Math.Min((float)Math.PI * 0.499f, _dragStartPitch - diffY)); - if (view.camera3DMode == MapView.Camera3DMode.Free) + if (view3D.camera3DMode == View3D.Camera3DMode.Free) { - var dir = Vector3.TransformPosition(_rotateDiff, view.ComputeViewOrientation()); - view.position = _rotatePivot + dir; + var dir = Vector3.TransformPosition(_rotateDiff, currentView.ComputeViewOrientation()); + currentView.position = _rotatePivot + dir; } } @@ -779,9 +800,9 @@ private void OnMouseMove(object sender, MouseEventArgs e) } else { - switch (view.mode) + switch (viewMode) { - case MapView.ViewMode.TopDown: + case ViewMode.TopDown: { double oldAngle = Math.Atan2(glControl.Height / 2 - _dragStartMouseY, _dragStartMouseX - glControl.Width / 2); double thingAngle = Math.Atan2(glControl.Height / 2 - e.Y, e.X - glControl.Width / 2); @@ -790,7 +811,7 @@ private void OnMouseMove(object sender, MouseEventArgs e) SetCustomAngle(MapViewAngleValue); break; } - case MapView.ViewMode.Orthogonal: + case ViewMode.Orthogonal: { float newAngle = _rotateStartAngle - (e.X - _dragStartMouseX) * 128; newAngle %= 0x10000; @@ -804,12 +825,12 @@ private void OnMouseMove(object sender, MouseEventArgs e) SetCustomAngle(MapViewAngleValue); break; } - case MapView.ViewMode.ThreeDimensional: + case ViewMode.ThreeDimensional: { - view.camera3DMode = MapView.Camera3DMode.Free; - float dx = -(float)(e.X - _dragStartMouseX) / glControl.Height * view.movementSpeed; - float dy = (float)(e.Y - _dragStartMouseY) / glControl.Height * view.movementSpeed; - view.position = _translateStartCenter + BillboardMatrix.Row0.Xyz * dx + BillboardMatrix.Row1.Xyz * dy; + view3D.camera3DMode = View3D.Camera3DMode.Free; + float dx = -(float)(e.X - _dragStartMouseX) / glControl.Height * currentView.movementSpeed; + float dy = (float)(e.Y - _dragStartMouseY) / glControl.Height * currentView.movementSpeed; + currentView.position = _translateStartCenter + BillboardMatrix.Row0.Xyz * dx + BillboardMatrix.Row1.Xyz * dy; break; } } @@ -820,16 +841,16 @@ private void OnMouseMove(object sender, MouseEventArgs e) private void OnScroll(object sender, MouseEventArgs e) { int delta = e.Delta > 0 ? 1 : -1; - if (view.mode == MapView.ViewMode.ThreeDimensional) + if (viewMode == ViewMode.ThreeDimensional) { - if (view.camera3DMode == MapView.Camera3DMode.FocusOnPositionAngle) - view.camera3DDistanceController = Math.Max(0.0f, Math.Min(100, view.camera3DDistanceController - delta)); - else if (view.camera3DMode == MapView.Camera3DMode.Free) + if (view3D.camera3DMode == View3D.Camera3DMode.FocusOnPositionAngle) + view3D.camera3DDistanceController = Math.Max(0.0f, Math.Min(100, view3D.camera3DDistanceController - delta)); + else if (view3D.camera3DMode == View3D.Camera3DMode.Free) { - var diff = mapCursorPosition - view.position; + var diff = mapCursorPosition - currentView.position; if (Vector3.Dot(diff, normalAtCursor) < 0) - view.movementSpeed = diff.Length * 0.5f; - view.position += Vector3.Normalize(mapCursorPosition - view.position) * delta * view.movementSpeed / 5; + currentView.movementSpeed = diff.Length * 0.5f; + currentView.position += Vector3.Normalize(mapCursorPosition - currentView.position) * delta * currentView.movementSpeed / 5; } } else @@ -860,7 +881,7 @@ public void UpdateFlyingControls(double frameTime) { relativeMovement.Normalize(); float movement = (float)frameTime * (keyboardControls.IsShiftDown() ? 100 : 2000); - view.position += (right * relativeMovement.X + up * relativeMovement.Y + forwards * relativeMovement.Z) * movement; + currentView.position += (right * relativeMovement.X + up * relativeMovement.Y + forwards * relativeMovement.Z) * movement; } } } diff --git a/STROOP/Tabs/MapTab/MapObjects/MapBruteforceTriangles.cs b/STROOP/Tabs/MapTab/MapObjects/MapBruteforceTriangles.cs index 88ca57dad..3e9b75d02 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapBruteforceTriangles.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapBruteforceTriangles.cs @@ -143,7 +143,7 @@ protected override void DrawTopDown(MapGraphics graphics) new Vector4(Color.R / 255f, Color.G / 255f, Color.B / 255f, OpacityByte / 255f), new Vector4(OutlineColor.R / 255f, OutlineColor.G / 255f, OutlineColor.B / 255f, OutlineColor.A / 255f), OutlineWidth, - graphics.view.mode != MapView.ViewMode.TopDown); + graphics.viewMode != MapGraphics.ViewMode.TopDown); } }); } diff --git a/STROOP/Tabs/MapTab/MapObjects/MapCircleObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapCircleObject.cs index e65a41164..53c1c80eb 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapCircleObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapCircleObject.cs @@ -26,7 +26,7 @@ protected override void DrawTopDown(MapGraphics graphics) { var transform = graphics.BillboardMatrix * Matrix4.CreateScale(dim.radius) * Matrix4.CreateTranslation(dim.centerX, 0, dim.centerZ); graphics.circleRenderer.AddInstance( - graphics.view.mode != MapView.ViewMode.TopDown, + graphics.viewMode != MapGraphics.ViewMode.TopDown, transform, OutlineWidth, color, diff --git a/STROOP/Tabs/MapTab/MapObjects/MapCustomCameraPath.cs b/STROOP/Tabs/MapTab/MapObjects/MapCustomCameraPath.cs index 2385ab27d..47df8e707 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapCustomCameraPath.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapCustomCameraPath.cs @@ -57,8 +57,8 @@ public override void AddContextMenuItems(MapTab tab, ContextMenuStrip menu) var alignPositionItem = new ToolStripMenuItem("Align with view"); alignPositionItem.Click += (_, __) => { - currentKeyFrame.position = tab.graphics.view.position; - currentKeyFrame.targetPoint.position = tab.graphics.view.position + tab.graphics.view.ComputeViewDirection() * 400; + currentKeyFrame.position = tab.graphics.currentView.position; + currentKeyFrame.targetPoint.position = tab.graphics.currentView.position + tab.graphics.currentView.ComputeViewDirection() * 400; }; var waitForItem = new ToolStripMenuItem("Wait for... (adjust timings)"); @@ -211,18 +211,18 @@ protected override void DrawTopDown(MapGraphics graphics) foreach (var a in keyFrames) { DrawIcon(graphics, - graphics.view.mode == MapView.ViewMode.ThreeDimensional, + graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional, (float)a.X, (float)a.Y, (float)a.Z, Rotates ? (float)a.Angle : 0x8000 - graphics.MapViewAngleValue, GetInternalImage()?.Value, new Vector4(1, 1, 1, actualHoverData.currentKeyFrame == a ? ObjectUtilities.HoverAlpha() : 1)); float desiredDiameter = Size * 2; - if (graphics.view.mode == MapView.ViewMode.ThreeDimensional) + if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) desiredDiameter *= Get3DIconScale(graphics, (float)a.targetPoint.X, (float)a.targetPoint.Y, (float)a.targetPoint.Z); graphics.circleRenderer.AddInstance( - graphics.view.mode == MapView.ViewMode.ThreeDimensional, + graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional, graphics.BillboardMatrix * Matrix4.CreateScale(desiredDiameter) * Matrix4.CreateTranslation(a.targetPoint.position), 1, new Vector4(0.5f, 0.5f, 0.5f, 0.5f), @@ -245,8 +245,8 @@ protected override ContextMenuStrip GetContextMenuStrip(MapTracker targetTracker itemAddKeyframe.Click += (_, __) => { var f = new KeyFrame(); - f.position = targetTracker.mapTab.graphics.view.position; - f.targetPoint.position = targetTracker.mapTab.graphics.view.position + targetTracker.mapTab.graphics.view.ComputeViewDirection() * 400; + f.position = targetTracker.mapTab.graphics.currentView.position; + f.targetPoint.position = targetTracker.mapTab.graphics.currentView.position + targetTracker.mapTab.graphics.currentView.ComputeViewDirection() * 400; keyFrames.Add(f); }; _contextMenuStrip.Items.Add(itemAddKeyframe); diff --git a/STROOP/Tabs/MapTab/MapObjects/MapCustomIconPoints.cs b/STROOP/Tabs/MapTab/MapObjects/MapCustomIconPoints.cs index 84e725012..ce96d2222 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapCustomIconPoints.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapCustomIconPoints.cs @@ -64,9 +64,9 @@ void CreateNewPoint(MapTab mapTab) { if (mapTab == null) return; - var newPointPos = mapTab.graphics.view.position; - if (mapTab.graphics.view.mode == MapView.ViewMode.ThreeDimensional) - newPointPos += mapTab.graphics.view.ComputeViewDirection() * 50; + var newPointPos = mapTab.graphics.currentView.position; + if (mapTab.graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) + newPointPos += mapTab.graphics.currentView.ComputeViewDirection() * 50; positionAngles.Add(PositionAngle.Custom(newPointPos)); } diff --git a/STROOP/Tabs/MapTab/MapObjects/MapCylinderObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapCylinderObject.cs index f677287a8..efdf43a09 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapCylinderObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapCylinderObject.cs @@ -27,7 +27,7 @@ protected override void DrawOrthogonal(MapGraphics graphics) var color = new Vector4(Color.R / 255.0f, Color.G / 255.0f, Color.B / 255.0f, (float)Opacity); foreach (var dim in Get3DDimensions()) { - var dist = (graphics.view.focusPositionAngle.position.Xz - new Vector2(dim.centerX, dim.centerZ)).Length; + var dist = (graphics.viewOrthogonal.focusPositionAngle.position.Xz - new Vector2(dim.centerX, dim.centerZ)).Length; dist /= dim.radius; var scale = System.Math.Sqrt(1 - dist * dist); if (!double.IsNaN(scale)) diff --git a/STROOP/Tabs/MapTab/MapObjects/MapGhostObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapGhostObject.cs index cfba3ed99..952f15da5 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapGhostObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapGhostObject.cs @@ -26,7 +26,7 @@ protected override void DrawTopDown(MapGraphics graphics) foreach (var pa in positionAngleProvider()) if (pa is GhostTab.Ghost.GhostPositionAngle a) { - var transparent = graphics.view.mode == MapView.ViewMode.ThreeDimensional; + var transparent = graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional; var alpha = hoverData.currentPositionAngle == a ? ObjectUtilities.HoverAlpha() : 1; var angle = Rotates ? (float)a.Angle : 0x8000 - graphics.MapViewAngleValue; diff --git a/STROOP/Tabs/MapTab/MapObjects/MapGridlinesObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapGridlinesObject.cs index 857f615c5..b2818b25c 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapGridlinesObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapGridlinesObject.cs @@ -22,7 +22,7 @@ protected override Vector4 GetColor(MapGraphics graphics) { var c = base.GetColor(graphics); float maxSize = 4 * OutlineWidth; - if (graphics.view.mode == MapView.ViewMode.TopDown && graphics.pixelsPerUnit.Y < maxSize / Size) + if (graphics.viewMode == MapGraphics.ViewMode.TopDown && graphics.pixelsPerUnit.Y < maxSize / Size) c.W *= (graphics.pixelsPerUnit.Y * Size - 2) / (maxSize - 2); return c; } @@ -88,7 +88,7 @@ protected override List GetVertices(MapGraphics graphics) graphics.mapCursorPosition, _hExpanse, _vExpanse, - graphics.view.mode == MapView.ViewMode.ThreeDimensional ? 1 : float.NaN, + graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional ? 1 : float.NaN, _verticalLineDistance); return vertices; } @@ -111,7 +111,7 @@ protected void AddVerticesToPositionAngle( float hExpanse = horizontalExpanse * Size; float vExpanse = verticalExpanse * Size; - if (graphics.view.mode == MapView.ViewMode.TopDown) + if (graphics.viewMode == MapGraphics.ViewMode.TopDown) { if (graphics.pixelsPerUnit.X < 2 / Size || graphics.pixelsPerUnit.Y < 2 / Size) return; diff --git a/STROOP/Tabs/MapTab/MapObjects/MapHorizontalTriangleObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapHorizontalTriangleObject.cs index b2fdab302..af22e3c10 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapHorizontalTriangleObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapHorizontalTriangleObject.cs @@ -31,7 +31,7 @@ protected MapHorizontalTriangleObject(ObjectCreateParams creationParameters) public override IHoverData GetHoverData(MapGraphics graphics, ref Vector3 position) { - if (graphics.view.mode == MapView.ViewMode.TopDown) + if (graphics.viewMode == MapGraphics.ViewMode.TopDown) foreach (var tri in GetTrianglesWithinDist()) { if (tri.GetTruncatedHeightOnTriangleIfInsideTriangle(graphics.mapCursorPosition.X, graphics.mapCursorPosition.Z) != null) @@ -82,7 +82,7 @@ protected override void DrawTopDown(MapGraphics graphics) new Vector4(Color.R / 255f, Color.G / 255f, Color.B / 255f, OpacityByte / 255f), new Vector4(OutlineColor.R / 255f, OutlineColor.G / 255f, OutlineColor.B / 255f, OutlineColor.A / 255f), OutlineWidth, - graphics.view.mode != MapView.ViewMode.TopDown); + graphics.viewMode != MapGraphics.ViewMode.TopDown); } }); } diff --git a/STROOP/Tabs/MapTab/MapObjects/MapIconPointObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapIconPointObject.cs index 1dc2c01f6..8b34d10e3 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapIconPointObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapIconPointObject.cs @@ -17,7 +17,7 @@ protected override void DrawTopDown(MapGraphics graphics) { foreach (var a in positionAngleProvider()) DrawIcon(graphics, - graphics.view.mode == MapView.ViewMode.ThreeDimensional, + graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional, (float)a.X, (float)a.Y, (float)a.Z, Rotates ? (float)a.Angle : 0x8000 - graphics.MapViewAngleValue, GetInternalImage()?.Value, @@ -38,7 +38,7 @@ public override IHoverData GetHoverData(MapGraphics graphics, ref Vector3 positi { hoverData.currentPositionAngle = null; foreach (var a in positionAngleProvider()) - if (graphics.view.mode == MapView.ViewMode.TopDown) + if (graphics.viewMode == MapGraphics.ViewMode.TopDown) { if (graphics.HoverTopDown(new Vector3((float)a.X, cursorPos.Y, (float)a.Z), radius)) { @@ -46,7 +46,7 @@ public override IHoverData GetHoverData(MapGraphics graphics, ref Vector3 positi break; } } - else if (graphics.view.mode == MapView.ViewMode.Orthogonal) + else if (graphics.viewMode == MapGraphics.ViewMode.Orthogonal) { if (graphics.HoverOrthogonal(a.position, radius)) { @@ -54,12 +54,12 @@ public override IHoverData GetHoverData(MapGraphics graphics, ref Vector3 positi break; } } - else if (graphics.view.mode == MapView.ViewMode.ThreeDimensional) + else if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) { var rad = Size * Get3DIconScale(graphics, (float)a.X, (float)a.Y, (float)a.Z); if (graphics.Hover3D(a.position, rad)) { - var newDist = (a.position - graphics.view.position).LengthSquared; + var newDist = (a.position - graphics.currentView.position).LengthSquared; if (closestDist > newDist) { hoverData.currentPositionAngle = a; diff --git a/STROOP/Tabs/MapTab/MapObjects/MapIwerlipsesObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapIwerlipsesObject.cs index cf00ffc25..cb7bed783 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapIwerlipsesObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapIwerlipsesObject.cs @@ -64,7 +64,7 @@ protected override void DrawTopDown(MapGraphics graphics) var outlineColor = OpenTKUtilities.ColorToVec4(OutlineColor); foreach (var transform in _ellipseTransforms) graphics.circleRenderer.AddInstance( - graphics.view.mode != MapView.ViewMode.TopDown, + graphics.viewMode != MapGraphics.ViewMode.TopDown, transform, OutlineWidth, color, diff --git a/STROOP/Tabs/MapTab/MapObjects/MapMultipleObjectsObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapMultipleObjectsObject.cs index 7dcf6f659..f6d20e0f0 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapMultipleObjectsObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapMultipleObjectsObject.cs @@ -83,7 +83,7 @@ protected override void DrawTopDown(MapGraphics graphics) List<(float x, float y, float z, float angle, Lazy tex, float alpha)> data = GetData(); data.Reverse(); foreach (var d in data) - DrawIcon(graphics, graphics.view.mode != MapView.ViewMode.TopDown, d.x, d.y, d.z, d.angle, d.tex.Value, new Vector4(1, 1, 1, d.alpha)); + DrawIcon(graphics, graphics.viewMode != MapGraphics.ViewMode.TopDown, d.x, d.y, d.z, d.angle, d.tex.Value, new Vector4(1, 1, 1, d.alpha)); }); } diff --git a/STROOP/Tabs/MapTab/MapObjects/MapNearbyUnits.cs b/STROOP/Tabs/MapTab/MapObjects/MapNearbyUnits.cs index f9d1cc8a3..c21268ab0 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapNearbyUnits.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapNearbyUnits.cs @@ -106,7 +106,7 @@ void DrawHorizontalPieces(MapGraphics graphics, (int x, int z) offset, float[,] * Matrix4.CreateScale(0.5f) * Matrix4.CreateTranslation(x + offset.x + 0.5f, vs[x, z], z + offset.z + 0.5f); graphics.circleRenderer.AddInstance( - graphics.view.mode != MapView.ViewMode.TopDown, + graphics.viewMode != MapGraphics.ViewMode.TopDown, transform, OutlineWidth, color, @@ -148,7 +148,7 @@ void DrawVerticalPieces(MapGraphics graphics, (int x, int z) offset, float[,] vs * Matrix4.CreateTranslation(x + offset.x + 1, (high + low) * 0.5f, z + offset.z + 0.5f); if (low != high) graphics.circleRenderer.AddInstance( - graphics.view.mode != MapView.ViewMode.TopDown, + graphics.viewMode != MapGraphics.ViewMode.TopDown, transform, OutlineWidth, colorX, @@ -163,7 +163,7 @@ void DrawVerticalPieces(MapGraphics graphics, (int x, int z) offset, float[,] vs * Matrix4.CreateTranslation(x + offset.x + 0.5f, (high + low) * 0.5f, z + offset.z + 1); if (low != high) graphics.circleRenderer.AddInstance( - graphics.view.mode != MapView.ViewMode.TopDown, + graphics.viewMode != MapGraphics.ViewMode.TopDown, transform, OutlineWidth, colorX, diff --git a/STROOP/Tabs/MapTab/MapObjects/MapNextPositionsObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapNextPositionsObject.cs index 182098627..29f1c1a72 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapNextPositionsObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapNextPositionsObject.cs @@ -39,7 +39,7 @@ protected override void DrawTopDown(MapGraphics graphics) List<(float x, float y, float z, float angle, Lazy tex)> data = GetData(); data.Reverse(); foreach (var dataPoint in data) - DrawIcon(graphics, graphics.view.mode == MapView.ViewMode.ThreeDimensional, dataPoint.x, dataPoint.y, dataPoint.z, dataPoint.angle, dataPoint.tex?.Value, new Vector4(1)); + DrawIcon(graphics, graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional, dataPoint.x, dataPoint.y, dataPoint.z, dataPoint.angle, dataPoint.tex?.Value, new Vector4(1)); }); } diff --git a/STROOP/Tabs/MapTab/MapObjects/MapObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapObject.cs index a3b23efd5..64ff05e98 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapObject.cs @@ -187,7 +187,7 @@ protected MapObject(ObjectCreateParams creationParameters) this.creationParameters = creationParameters; } - public static float Get3DIconScale(MapGraphics graphics, float x, float y, float z) => (0.5f * (float)Math.Tan(1) * (new Vector3(x, y, z) - graphics.view.position).Length) / graphics.glControl.Height; + public static float Get3DIconScale(MapGraphics graphics, float x, float y, float z) => (0.5f * (float)Math.Tan(1) * (new Vector3(x, y, z) - graphics.currentView.position).Length) / graphics.glControl.Height; public void DrawIcon( MapGraphics graphics, @@ -198,7 +198,7 @@ public void DrawIcon( DrawIcon( graphics, sortTransparent, - x, y, z, graphics.view.mode != MapView.ViewMode.TopDown ? 0x8000 : angle, + x, y, z, graphics.viewMode != MapGraphics.ViewMode.TopDown ? 0x8000 : angle, Size, image, color); @@ -214,7 +214,7 @@ public static void DrawIcon( if (image == null) return; float desiredDiameter = size * 2; - if (graphics.view.mode == MapView.ViewMode.ThreeDimensional) + if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) desiredDiameter *= Get3DIconScale(graphics, x, y, z); else if (!graphics.MapViewScaleIconSizes) desiredDiameter /= graphics.MapViewScaleValue; @@ -234,15 +234,15 @@ public static void DrawIcon( public void Draw(MapGraphics graphics) { - switch (graphics.view.mode) + switch (graphics.viewMode) { - case MapView.ViewMode.TopDown: + case MapGraphics.ViewMode.TopDown: DrawTopDown(graphics); break; - case MapView.ViewMode.Orthogonal: + case MapGraphics.ViewMode.Orthogonal: DrawOrthogonal(graphics); break; - case MapView.ViewMode.ThreeDimensional: + case MapGraphics.ViewMode.ThreeDimensional: Draw3D(graphics); break; } diff --git a/STROOP/Tabs/MapTab/MapObjects/MapPreviousPositionsObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapPreviousPositionsObject.cs index e4c61f4d2..9f95a386c 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapPreviousPositionsObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapPreviousPositionsObject.cs @@ -75,7 +75,7 @@ protected override void DrawTopDown(MapGraphics graphics) foreach (var dataPoint in data) DrawIcon( graphics, - graphics.view.mode == MapView.ViewMode.ThreeDimensional, + graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional, dataPoint.x, dataPoint.y, dataPoint.z, dataPoint.angle, dataPoint.tex.Value, new Vector4(1)); diff --git a/STROOP/Tabs/MapTab/MapObjects/MapQuadObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapQuadObject.cs index 85dd661a3..58ac398d5 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapQuadObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapQuadObject.cs @@ -24,7 +24,7 @@ protected override void DrawTopDown(MapGraphics graphics) * Matrix4.CreateScale((quad.xMax - quad.xMin) * 0.5f, 1, (quad.zMax - quad.zMin) * 0.5f) * Matrix4.CreateTranslation((quad.xMin + quad.xMax) * 0.5f, quad.y, (quad.zMin + quad.zMax) * 0.5f); graphics.circleRenderer.AddInstance( - graphics.view.mode != MapView.ViewMode.TopDown, + graphics.viewMode != MapGraphics.ViewMode.TopDown, transform, OutlineWidth, color, diff --git a/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs index ffcd176af..e95fd6c6b 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapTapeMeasureObject.cs @@ -125,8 +125,8 @@ public MapTapeMeasureObject() { OutlineColor = Color.Orange; OutlineWidth = 3; - a = new Vector3(currentMapTab.graphics.view.position.X - 50, 0, currentMapTab.graphics.view.position.Z); - b = new Vector3(currentMapTab.graphics.view.position.X + 50, 0, currentMapTab.graphics.view.position.Z); + a = new Vector3(currentMapTab.graphics.currentView.position.X - 50, 0, currentMapTab.graphics.currentView.position.Z); + b = new Vector3(currentMapTab.graphics.currentView.position.X + 50, 0, currentMapTab.graphics.currentView.position.Z); hoverData = new TapeHoverData(this); for (int mask = 1; mask <= 8; mask++) { @@ -230,7 +230,7 @@ public override IHoverData GetHoverData(MapGraphics graphics, ref Vector3 positi float magicConst = 15; Vector3 _a = aProvider?.Invoke() ?? a; Vector3 _b = bProvider?.Invoke() ?? b; - if (graphics.view.mode == MapView.ViewMode.TopDown) + if (graphics.viewMode == MapGraphics.ViewMode.TopDown) { var rad = (magicConst / graphics.MapViewScaleValue); if (graphics.HoverTopDown(_a, rad)) @@ -246,9 +246,9 @@ public override IHoverData GetHoverData(MapGraphics graphics, ref Vector3 positi return hoverData; } } - else if (graphics.view.mode == MapView.ViewMode.ThreeDimensional) + else if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) { - bool prioritizeA = (_a - graphics.view.position).LengthSquared < (_b - graphics.view.position).LengthSquared; + bool prioritizeA = (_a - graphics.currentView.position).LengthSquared < (_b - graphics.currentView.position).LengthSquared; bool hoverA = graphics.Hover3D(_a, magicConst * Get3DIconScale(graphics, _a.X, _a.Y, _a.Z)); bool hoverB = graphics.Hover3D(_b, magicConst * Get3DIconScale(graphics, _b.X, _b.Y, _b.Z)); if (hoverA && (!hoverB || prioritizeA)) diff --git a/STROOP/Tabs/MapTab/MapObjects/MapTriangleObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapTriangleObject.cs index 6796bcc48..790a71484 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapTriangleObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapTriangleObject.cs @@ -61,7 +61,7 @@ public void AddContextMenuItems(MapTab tab, ContextMenuStrip menu) { if (triangle != null) { - if (tab.graphics.view.mode == MapView.ViewMode.TopDown) + if (tab.graphics.viewMode == MapGraphics.ViewMode.TopDown) { float y = triangle.IsWall() ? mapCursorOnRightClick.Y : (float)triangle.GetHeightOnTriangle(mapCursorOnRightClick.X, mapCursorOnRightClick.Z); CopyUtilities.CopyPosition(new Vector3(mapCursorOnRightClick.X, y, mapCursorOnRightClick.Z)); @@ -164,7 +164,7 @@ public override void Update() public override IHoverData GetHoverData(MapGraphics graphics, ref Vector3 position) { - if (graphics.view.mode == MapView.ViewMode.ThreeDimensional) + if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) { if (graphics.hoverTriangle != null && _bufferedTris.Any(_ => _.Address == graphics.hoverTriangle.Address)) { @@ -231,7 +231,7 @@ protected override void DrawOrthogonal(MapGraphics graphics) var baseColor = new Vector4(Color.R / 255f, Color.G / 255f, Color.B / 255f, OpacityByte / 255f); foreach (var tri in GetTrianglesWithinDist()) { - if (graphics.view.displayOrthoLevelGeometry) + if (graphics.viewOrthogonal.displayOrthoLevelGeometry) graphics.triangleRenderer.Add( tri.p1, tri.p2, @@ -265,7 +265,7 @@ protected override void Draw3D(MapGraphics graphics) baseColor.W = OpacityByte / 255f; var projectionColor = new Vector4(baseColor.Xyz, _projectionAlphaMultiplier * baseColor.W); - if (!graphics.view.display3DLevelGeometry) + if (!graphics.view3D.display3DLevelGeometry) graphics.triangleRenderer.Add( tri.p1, tri.p2, diff --git a/STROOP/Tabs/MapTab/MapObjects/MapWallObject.cs b/STROOP/Tabs/MapTab/MapObjects/MapWallObject.cs index a7415ec4d..8be83bd2f 100644 --- a/STROOP/Tabs/MapTab/MapObjects/MapWallObject.cs +++ b/STROOP/Tabs/MapTab/MapObjects/MapWallObject.cs @@ -46,7 +46,7 @@ protected override ContextMenuStrip GetContextMenuStrip(MapTracker targetTracker public override IHoverData GetHoverData(MapGraphics graphics, ref Vector3 position) { - if (graphics.view.mode == MapView.ViewMode.TopDown) + if (graphics.viewMode == MapGraphics.ViewMode.TopDown) foreach (var tri in GetTrianglesWithinDist()) { var dat = MapUtilities.Get2DWallDataFromTri(tri); diff --git a/STROOP/Tabs/MapTab/MapPopout.cs b/STROOP/Tabs/MapTab/MapPopout.cs index 5375bac8c..c9e087620 100644 --- a/STROOP/Tabs/MapTab/MapPopout.cs +++ b/STROOP/Tabs/MapTab/MapPopout.cs @@ -28,7 +28,7 @@ public MapPopout(MapTab tab) graphics = new MapGraphics(tab, glControl, () => tab.graphics.glControl.Context); graphics.MapViewAngleValue = tab.graphics.MapViewAngleValue; graphics.MapViewScaleValue = tab.graphics.MapViewScaleValue; - graphics.view.position = tab.graphics.view.position; + graphics.currentView.position = tab.graphics.currentView.position; Shown += (_, __) => { using (new AccessScope(tab)) diff --git a/STROOP/Tabs/MapTab/MapTab.cs b/STROOP/Tabs/MapTab/MapTab.cs index 10dd5b85a..1078fef57 100644 --- a/STROOP/Tabs/MapTab/MapTab.cs +++ b/STROOP/Tabs/MapTab/MapTab.cs @@ -15,6 +15,7 @@ using OpenTK.Mathematics; using STROOP.Core; using STROOP.Core.Utilities; +using STROOP.Tabs.MapTab.Views; using STROOP.Variables.SM64MemoryLayout; using STROOP.Variables.Utilities; @@ -506,14 +507,10 @@ void ShowRightClickMenu() contextMenu.Items.Add(copyPositionItem); contextMenu.Items.Add(new ToolStripSeparator()); - if (graphics.view.mode == MapView.ViewMode.ThreeDimensional) + if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) { var pivotPositionItem = new ToolStripMenuItem("Pivot This Position"); - pivotPositionItem.Click += (e, args) => - { - graphics.view.camera3DMode = MapView.Camera3DMode.FocusOnPositionAngle; - graphics.view.focusPositionAngle = PositionAngle.Custom(onClickPosition); - }; + pivotPositionItem.Click += (_, _) => (graphics.currentView as PivotingView)?.Pivot(PositionAngle.Custom(onClickPosition)); contextMenu.Items.Add(pivotPositionItem); contextMenu.Items.Add(new ToolStripSeparator()); } @@ -584,18 +581,18 @@ void AddViewModeContextMenu() itemRefreshLevelGeometry.Click += (__, ___) => RequireGeometryUpdate(); ctx.Items.Add(itemRefreshLevelGeometry); - if (graphics.view.mode == MapView.ViewMode.ThreeDimensional) + if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) { ctx.Items.Add(new ToolStripSeparator()); var itemDisplayLevelGeometry = new ToolStripMenuItem("Display Level Geometry"); - itemDisplayLevelGeometry.Checked = graphics.view.display3DLevelGeometry; - itemDisplayLevelGeometry.Click += (__, ___) => itemDisplayLevelGeometry.Checked = graphics.view.display3DLevelGeometry = !graphics.view.display3DLevelGeometry; + itemDisplayLevelGeometry.Checked = graphics.view3D.display3DLevelGeometry; + itemDisplayLevelGeometry.Click += (__, ___) => itemDisplayLevelGeometry.Checked = graphics.view3D.display3DLevelGeometry = !graphics.view3D.display3DLevelGeometry; ctx.Items.Add(itemDisplayLevelGeometry); var itemDisplayCylinderOutlines = new ToolStripMenuItem("Draw Cylinder Outlines"); - itemDisplayCylinderOutlines.Checked = graphics.view.drawCylinderOutlines; - itemDisplayCylinderOutlines.Click += (__, ___) => itemDisplayCylinderOutlines.Checked = graphics.view.drawCylinderOutlines = !graphics.view.drawCylinderOutlines; + itemDisplayCylinderOutlines.Checked = graphics.drawCylinderOutlines; + itemDisplayCylinderOutlines.Click += (__, ___) => itemDisplayCylinderOutlines.Checked = graphics.drawCylinderOutlines = !graphics.drawCylinderOutlines; ctx.Items.Add(itemDisplayCylinderOutlines); ctx.Items.Add(new ToolStripSeparator()); @@ -603,23 +600,23 @@ void AddViewModeContextMenu() var itemCameraModeInGame = new ToolStripMenuItem("In-Game View"); var itemCameraModePivot = new ToolStripMenuItem("Pivot"); var itemCameraModeFree = new ToolStripMenuItem("Free"); - itemCameraModeInGame.Checked = graphics.view.camera3DMode == MapView.Camera3DMode.InGame; - itemCameraModePivot.Checked = graphics.view.camera3DMode == MapView.Camera3DMode.FocusOnPositionAngle; - itemCameraModeFree.Checked = graphics.view.camera3DMode == MapView.Camera3DMode.Free; + itemCameraModeInGame.Checked = graphics.view3D.camera3DMode == View3D.Camera3DMode.InGame; + itemCameraModePivot.Checked = graphics.view3D.camera3DMode == View3D.Camera3DMode.FocusOnPositionAngle; + itemCameraModeFree.Checked = graphics.view3D.camera3DMode == View3D.Camera3DMode.Free; itemCameraModeInGame.Click += (__, ___) => { - graphics.view.camera3DMode = MapView.Camera3DMode.InGame; + graphics.view3D.camera3DMode = View3D.Camera3DMode.InGame; itemCameraModePivot.Checked = itemCameraModeFree.Checked = !(itemCameraModeInGame.Checked = true); }; itemCameraModePivot.Click += (__, ___) => { - graphics.view.camera3DMode = MapView.Camera3DMode.FocusOnPositionAngle; + graphics.view3D.camera3DMode = View3D.Camera3DMode.FocusOnPositionAngle; itemCameraModeInGame.Checked = itemCameraModeFree.Checked = !(itemCameraModePivot.Checked = true); }; itemCameraModeFree.Click += (__, ___) => { - graphics.view.camera3DMode = MapView.Camera3DMode.Free; + graphics.view3D.camera3DMode = View3D.Camera3DMode.Free; itemCameraModeInGame.Checked = itemCameraModePivot.Checked = !(itemCameraModeInGame.Checked = true); }; ctx.Items.Add(itemCameraModeInGame); @@ -634,31 +631,31 @@ void AddViewModeContextMenu() ctx.Items.Add(itemFollowInGame); } - if (graphics.view.mode == MapView.ViewMode.Orthogonal) + if (graphics.viewMode == MapGraphics.ViewMode.Orthogonal) { ctx.Items.Add(new ToolStripSeparator()); var itemDisplayLevelGeometry = new ToolStripMenuItem("Display Triangle Tracker Geometry"); - itemDisplayLevelGeometry.Checked = graphics.view.displayOrthoLevelGeometry; - itemDisplayLevelGeometry.Click += (__, ___) => itemDisplayLevelGeometry.Checked = graphics.view.displayOrthoLevelGeometry = !graphics.view.displayOrthoLevelGeometry; + itemDisplayLevelGeometry.Checked = graphics.viewOrthogonal.displayOrthoLevelGeometry; + itemDisplayLevelGeometry.Click += (__, ___) => itemDisplayLevelGeometry.Checked = graphics.viewOrthogonal.displayOrthoLevelGeometry = !graphics.viewOrthogonal.displayOrthoLevelGeometry; ctx.Items.Add(itemDisplayLevelGeometry); var itemSetRelativeNearPlane = new ToolStripMenuItem("Set Relative Near Plane"); itemSetRelativeNearPlane.Click += (__, ___) => - graphics.view.orthoRelativeNearPlane = (float)DialogUtilities.GetDoubleFromDialog(0, labelText: "Enter relative near plane value."); + graphics.viewOrthogonal.orthoRelativeNearPlane = (float)DialogUtilities.GetDoubleFromDialog(0, labelText: "Enter relative near plane value."); ctx.Items.Add(itemSetRelativeNearPlane); var itemClearRelativeNearPlane = new ToolStripMenuItem("Clear Relative Near Plane"); - itemClearRelativeNearPlane.Click += (__, ___) => graphics.view.orthoRelativeNearPlane = float.NaN; + itemClearRelativeNearPlane.Click += (__, ___) => graphics.viewOrthogonal.orthoRelativeNearPlane = float.NaN; ctx.Items.Add(itemClearRelativeNearPlane); var itemSetRelativeFarPlane = new ToolStripMenuItem("Set Relative Far Plane"); itemSetRelativeFarPlane.Click += (__, ___) => - graphics.view.orthoRelativeFarPlane = (float)DialogUtilities.GetDoubleFromDialog(0, labelText: "Enter relative far plane value."); + graphics.viewOrthogonal.orthoRelativeFarPlane = (float)DialogUtilities.GetDoubleFromDialog(0, labelText: "Enter relative far plane value."); ctx.Items.Add(itemSetRelativeFarPlane); var itemClearRelativeFarPlane = new ToolStripMenuItem("Clear Relative Far Plane"); - itemClearRelativeFarPlane.Click += (__, ___) => graphics.view.orthoRelativeFarPlane = float.NaN; + itemClearRelativeFarPlane.Click += (__, ___) => graphics.viewOrthogonal.orthoRelativeFarPlane = float.NaN; ctx.Items.Add(itemClearRelativeFarPlane); } @@ -683,7 +680,7 @@ public void UpdateHover() var newHover = tracker.mapObject.GetHoverData(graphics, ref newCursor); if (graphics.fixCursorPlane) { - graphics.cursorViewPlaneDist = Vector3.Dot(graphics.view.ComputeViewDirection(), (newCursor - graphics.view.position)); + graphics.cursorViewPlaneDist = Vector3.Dot(graphics.currentView.ComputeViewDirection(), (newCursor - graphics.currentView.position)); graphics.UpdateCursor(); } @@ -742,13 +739,13 @@ public override void Update(bool active) } } - if (graphics.view.mode == MapView.ViewMode.ThreeDimensional && makeInGameCameraFollow) + if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional && makeInGameCameraFollow) { Config.Stream.SetValue(3, CamHackConfig.StructAddress + CamHackConfig.CameraModeOffset); - Config.Stream.SetValue(graphics.view.position.X, CamHackConfig.StructAddress + CamHackConfig.CameraXOffset); - Config.Stream.SetValue(graphics.view.position.Y, CamHackConfig.StructAddress + CamHackConfig.CameraYOffset); - Config.Stream.SetValue(graphics.view.position.Z, CamHackConfig.StructAddress + CamHackConfig.CameraZOffset); - var target = graphics.view.position + graphics.view.ComputeViewDirection(); + Config.Stream.SetValue(graphics.currentView.position.X, CamHackConfig.StructAddress + CamHackConfig.CameraXOffset); + Config.Stream.SetValue(graphics.currentView.position.Y, CamHackConfig.StructAddress + CamHackConfig.CameraYOffset); + Config.Stream.SetValue(graphics.currentView.position.Z, CamHackConfig.StructAddress + CamHackConfig.CameraZOffset); + var target = graphics.currentView.position + graphics.currentView.ComputeViewDirection(); Config.Stream.SetValue(target.X, CamHackConfig.StructAddress + CamHackConfig.FocusXOffset); Config.Stream.SetValue(target.Y, CamHackConfig.StructAddress + CamHackConfig.FocusYOffset); Config.Stream.SetValue(target.Z, CamHackConfig.StructAddress + CamHackConfig.FocusZOffset); @@ -979,7 +976,7 @@ void SaveTrackerConfig(string targetFileName) private void comboBoxViewMode_SelectedIndexChanged(object sender, EventArgs e) { - graphics.view.mode = (MapView.ViewMode)comboBoxViewMode.SelectedIndex; + graphics.viewMode = (MapGraphics.ViewMode)comboBoxViewMode.SelectedIndex; } } } diff --git a/STROOP/Tabs/MapTab/MapView.cs b/STROOP/Tabs/MapTab/MapView.cs deleted file mode 100644 index 4c27d90b0..000000000 --- a/STROOP/Tabs/MapTab/MapView.cs +++ /dev/null @@ -1,50 +0,0 @@ -using STROOP.Utilities; -using OpenTK; -using OpenTK.Mathematics; - -namespace STROOP.Tabs.MapTab -{ - public class MapView - { - public enum ViewMode - { - TopDown, - Orthogonal, - ThreeDimensional - } - - public enum Camera3DMode - { - InGame, - FocusOnPositionAngle, - Free, - } - - public MapGraphics MapGraphics; - public ViewMode mode = ViewMode.TopDown; - public Camera3DMode camera3DMode = Camera3DMode.FocusOnPositionAngle; - public PositionAngle focusPositionAngle = PositionAngle.Mario; - public Vector2 orthoOffset = Vector2.Zero; - public float orthoRelativeNearPlane = float.NaN, orthoRelativeFarPlane = float.NaN; - public bool displayOrthoLevelGeometry = true; - public bool display3DLevelGeometry = true; - public bool drawCylinderOutlines = false; - - public Vector3 position; - public float yaw, pitch, camera3DDistanceController = 50; - public float movementSpeed = 2000.0f; - - public Matrix4 ComputeViewOrientation() => Matrix4.CreateRotationX(pitch) * Matrix4.CreateRotationY(yaw); - public Vector3 ComputeViewDirection() => Vector3.TransformPosition(new Vector3(0, 0, 1), ComputeViewOrientation()); - - public void Pivot(PositionAngle pivotPoint) - { - camera3DMode = Camera3DMode.FocusOnPositionAngle; - focusPositionAngle = pivotPoint; - var d = focusPositionAngle.position - position; - yaw = (float)(System.Math.PI / 2 - System.Math.Atan2(d.Z, d.X)); - pitch = (float)-System.Math.Atan2(d.Y, System.Math.Sqrt(d.X * d.X + d.Z * d.Z)); - camera3DDistanceController = 10 * (float)(System.Math.Log(d.Length)); - } - } -} diff --git a/STROOP/Tabs/MapTab/Renderers/GeometryRenderer.cs b/STROOP/Tabs/MapTab/Renderers/GeometryRenderer.cs index 415bf7477..d7039837b 100644 --- a/STROOP/Tabs/MapTab/Renderers/GeometryRenderer.cs +++ b/STROOP/Tabs/MapTab/Renderers/GeometryRenderer.cs @@ -227,7 +227,7 @@ void DrawGeometry() public override void SetDrawCalls(MapGraphics graphics) { instances.Clear(); - if (graphics.view.drawCylinderOutlines) + if (graphics.drawCylinderOutlines) graphics.drawLayers[(int)MapGraphics.DrawLayers.FillBuffersRedirect].Add(() => { foreach (var instance in instances) diff --git a/STROOP/Tabs/MapTab/Renderers/TransparencyRenderer.cs b/STROOP/Tabs/MapTab/Renderers/TransparencyRenderer.cs index fc17cb56c..f38e78546 100644 --- a/STROOP/Tabs/MapTab/Renderers/TransparencyRenderer.cs +++ b/STROOP/Tabs/MapTab/Renderers/TransparencyRenderer.cs @@ -157,7 +157,7 @@ public void SetUniforms(int shader) public override void SetDrawCalls(MapGraphics graphics) { - if (graphics.view.mode != MapView.ViewMode.TopDown) + if (graphics.viewMode != MapGraphics.ViewMode.TopDown) graphics.drawLayers[(int)MapGraphics.DrawLayers.Transparency].Add(() => { var error = GL.GetError(); diff --git a/STROOP/Tabs/MapTab/Renderers/TriangleRenderer.cs b/STROOP/Tabs/MapTab/Renderers/TriangleRenderer.cs index 91f9ce636..98fcd2ae7 100644 --- a/STROOP/Tabs/MapTab/Renderers/TriangleRenderer.cs +++ b/STROOP/Tabs/MapTab/Renderers/TriangleRenderer.cs @@ -137,7 +137,7 @@ public override void SetDrawCalls(MapGraphics graphics) return; WriteDataToBuffer(); - if (graphics.view.mode == MapView.ViewMode.ThreeDimensional) + if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) { GL.Enable(EnableCap.DepthTest); GL.DepthFunc(DepthFunction.Lequal); diff --git a/STROOP/Tabs/MapTab/Views/View3D.cs b/STROOP/Tabs/MapTab/Views/View3D.cs new file mode 100644 index 000000000..7a5f29192 --- /dev/null +++ b/STROOP/Tabs/MapTab/Views/View3D.cs @@ -0,0 +1,32 @@ +using OpenTK.Mathematics; +using STROOP.Utilities; + +namespace STROOP.Tabs.MapTab.Views; + +public class View3D : ViewBase, PivotingView +{ + public enum Camera3DMode + { + InGame, + FocusOnPositionAngle, + Free, + } + + public Camera3DMode camera3DMode = Camera3DMode.FocusOnPositionAngle; + public float camera3DDistanceController = 50; + public bool display3DLevelGeometry = true; + + public PositionAngle focusPositionAngle { get; set; } = PositionAngle.Mario; + + void PivotingView.Pivot(PositionAngle pivotPoint) + { + focusPositionAngle = pivotPoint; + camera3DMode = Camera3DMode.FocusOnPositionAngle; + var d = focusPositionAngle.position - position; + yaw = (float)(System.Math.PI / 2 - System.Math.Atan2(d.Z, d.X)); + pitch = (float)-System.Math.Atan2(d.Y, System.Math.Sqrt(d.X * d.X + d.Z * d.Z)); + camera3DDistanceController = 10 * (float)(System.Math.Log(d.Length)); + } + + public override Matrix4 ComputeViewOrientation() => Matrix4.CreateRotationX(pitch) * Matrix4.CreateRotationY(yaw); +} diff --git a/STROOP/Tabs/MapTab/Views/ViewBase.cs b/STROOP/Tabs/MapTab/Views/ViewBase.cs new file mode 100644 index 000000000..63c2365a0 --- /dev/null +++ b/STROOP/Tabs/MapTab/Views/ViewBase.cs @@ -0,0 +1,27 @@ +using OpenTK.Mathematics; +using STROOP.Utilities; + +namespace STROOP.Tabs.MapTab.Views; + +public interface PivotingView +{ + public PositionAngle focusPositionAngle { get; protected set; } + public void Pivot(PositionAngle pivotPoint) => focusPositionAngle = pivotPoint; +} + +public abstract class ViewBase +{ + // TODO: consider what this is (ab)used for + public Vector3 position; + + // TODO: split between keyboard and mouse inputs as well as radial vs linear? + /// Displacement in units per t, where t is either seconds for keyboard keys or some number of pixels for mouse movement. + public float movementSpeed = 2000.0f; + + // TODO: remove from here by using inheritance for mouse events properly + public float yaw, pitch; + + public abstract Matrix4 ComputeViewOrientation(); + + public Vector3 ComputeViewDirection() => ComputeViewOrientation().Row2.Xyz; +} diff --git a/STROOP/Tabs/MapTab/Views/ViewOrthogonal.cs b/STROOP/Tabs/MapTab/Views/ViewOrthogonal.cs new file mode 100644 index 000000000..bcd35ee7a --- /dev/null +++ b/STROOP/Tabs/MapTab/Views/ViewOrthogonal.cs @@ -0,0 +1,15 @@ +using OpenTK.Mathematics; +using STROOP.Utilities; + +namespace STROOP.Tabs.MapTab.Views; + +public class ViewOrthogonal : ViewBase, PivotingView +{ + public Vector2 orthoOffset = Vector2.Zero; + public float orthoRelativeNearPlane = float.NaN, orthoRelativeFarPlane = float.NaN; + public bool displayOrthoLevelGeometry = true; + + public override Matrix4 ComputeViewOrientation() => Matrix4.CreateRotationX(pitch) * Matrix4.CreateRotationY(yaw); + + public PositionAngle focusPositionAngle { get; set; } = PositionAngle.Mario; +} diff --git a/STROOP/Tabs/MapTab/Views/ViewTopDown.cs b/STROOP/Tabs/MapTab/Views/ViewTopDown.cs new file mode 100644 index 000000000..680e46ff9 --- /dev/null +++ b/STROOP/Tabs/MapTab/Views/ViewTopDown.cs @@ -0,0 +1,8 @@ +using OpenTK.Mathematics; + +namespace STROOP.Tabs.MapTab.Views; + +public class ViewTopDown : ViewBase +{ + public override Matrix4 ComputeViewOrientation() => Matrix4.CreateRotationY(yaw); +} From e8ab1e109f91ceca786d7c6ab756cbec172cfa08 Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Thu, 6 Aug 2026 06:32:01 +0200 Subject: [PATCH 6/9] manage multiple views via context menu --- STROOP/Tabs/MapTab/MapGraphics.cs | 10 ++++-- STROOP/Tabs/MapTab/MapTab.cs | 54 +++++++++++++++++++++++++--- STROOP/Tabs/MapTab/Views/ViewBase.cs | 2 ++ 3 files changed, 59 insertions(+), 7 deletions(-) diff --git a/STROOP/Tabs/MapTab/MapGraphics.cs b/STROOP/Tabs/MapTab/MapGraphics.cs index 3046817ec..bcd36025c 100644 --- a/STROOP/Tabs/MapTab/MapGraphics.cs +++ b/STROOP/Tabs/MapTab/MapGraphics.cs @@ -13,6 +13,7 @@ using STROOP.Structs.Configurations; using STROOP.Tabs.MapTab.Views; using STROOP.Utilities; +using System.Linq; namespace STROOP.Tabs.MapTab { @@ -164,9 +165,9 @@ private enum MapAngle ViewMode.ThreeDimensional => view3D, }; - public readonly ViewTopDown viewTopDown = new(); - public readonly ViewOrthogonal viewOrthogonal = new(); - public readonly View3D view3D = new(); + public ViewTopDown viewTopDown; + public ViewOrthogonal viewOrthogonal; + public View3D view3D; public float MapViewRadius => (float)MoreMath.GetHypotenuse(glControl.Width / 2, glControl.Height / 2) / MapViewScaleValue; @@ -247,6 +248,9 @@ public MapGraphics(MapTab mapTab, GLControl glControl, Func ge this.mapTab = mapTab; this.glControl = glControl; this.getContext = getContext; + view3D = mapTab.views3D.First(); + viewTopDown = mapTab.viewsTopDown.First(); + viewOrthogonal = mapTab.viewsOrthogonal.First(); glControl.MouseDown += (_, _) => glControl.Focus(); keyboardControls = new(glControl); diff --git a/STROOP/Tabs/MapTab/MapTab.cs b/STROOP/Tabs/MapTab/MapTab.cs index 1078fef57..ad5c3964d 100644 --- a/STROOP/Tabs/MapTab/MapTab.cs +++ b/STROOP/Tabs/MapTab/MapTab.cs @@ -6,8 +6,6 @@ using STROOP.Utilities; using System.Windows.Forms; using System.Drawing; -using OpenTK; -using OpenTK.Graphics; using STROOP.Structs.Configurations; using STROOP.Tabs.MapTab.MapObjects; using System.Xml.Linq; @@ -87,6 +85,10 @@ static IEnumerable EnumerateTypes(Func filter) public override HashSet selection => _selection; + public List viewsTopDown = [new() { name = "Mario" }]; + public List viewsOrthogonal = [new() { name = "Mario" }]; + public List views3D = [new() { name = "Mario" }]; + public MapTab() { InitializeComponent(); @@ -170,7 +172,6 @@ public void Load2D() public MapLayout GetMapLayout(object mapLayoutChoice = null) => (mapLayoutChoice ?? comboBoxMapOptionsLevel.SelectedItem) as MapLayout ?? MapAssociations.GetBestMap(); - bool displayingExtendedBoundaries = false; bool needsGeometryRefresh, _needsGeometryRefreshInternal; public bool NeedsGeometryRefresh() => needsGeometryRefresh; @@ -249,7 +250,7 @@ void InitAddTrackerButton() toolStripItem.Click += (sender, e) => addNewTracker(); return toolStripItem; } - )); + )); } } @@ -500,6 +501,7 @@ private void InitializeControls() void ShowRightClickMenu() { + contextMenu?.Dispose(); contextMenu = new ContextMenuStrip(); var onClickPosition = graphics.mapCursorPosition; var copyPositionItem = new ToolStripMenuItem("Copy Cursor Position"); @@ -533,9 +535,53 @@ void ShowRightClickMenu() }; contextMenu.Items.Add(openPopoutItem); + AddViewContextMenuItems(contextMenu, graphics); + contextMenu.Show(Cursor.Position); } + public void AddViewContextMenuItems(ContextMenuStrip contextMenu, MapGraphics mapGraphics) + { + contextMenu.Items.Add(new ToolStripSeparator()); + var rootItem = new ToolStripMenuItem("View"); + foreach (var (mode, list, field) in (IEnumerable<(MapGraphics.ViewMode, IEnumerable, FieldInfo)>) + [ + (MapGraphics.ViewMode.TopDown, viewsTopDown, typeof(MapGraphics).GetField(nameof(MapGraphics.viewTopDown))), + (MapGraphics.ViewMode.Orthogonal, viewsOrthogonal, typeof(MapGraphics).GetField(nameof(MapGraphics.viewOrthogonal))), + (MapGraphics.ViewMode.ThreeDimensional, views3D, typeof(MapGraphics).GetField(nameof(MapGraphics.view3D))), + ]) + { + var modeItem = new ToolStripMenuItem(mode.ToString()); + modeItem.Click += (_, _) => mapGraphics.viewMode = mode; + var currentView = (ViewBase)field.GetValue(mapGraphics); + foreach (var view in list) + { + var viewItem = new ToolStripMenuItem(view.name) { Checked = currentView == view }; + viewItem.Click += (_, _) => + { + mapGraphics.viewMode = mode; + field.SetValue(mapGraphics, view); + }; + modeItem.DropDownItems.Add(viewItem); + } + + var newItem = new ToolStripMenuItem("add ..."); + newItem.Click += (_, _) => + { + var newView = (ViewBase)Activator.CreateInstance(field.FieldType); + foreach (var newField in field.FieldType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + newField.SetValue(newView, newField.GetValue(currentView)); + newView.name = DialogUtilities.GetStringFromDialog("Custom", "Enter a Name") ?? ""; + field.SetValue(mapGraphics, newView); + mapGraphics.viewMode = mode; + list.GetType().GetMethod(nameof(IList.Add)).Invoke(list, [newView]); + }; + modeItem.DropDownItems.Add(newItem); + rootItem.DropDownItems.Add(modeItem); + } + contextMenu.Items.Add(rootItem); + } + private void LoadDefaultTrackers() { if (!System.IO.File.Exists(DEFAULT_TRACKER_FILE)) diff --git a/STROOP/Tabs/MapTab/Views/ViewBase.cs b/STROOP/Tabs/MapTab/Views/ViewBase.cs index 63c2365a0..288bc0bfa 100644 --- a/STROOP/Tabs/MapTab/Views/ViewBase.cs +++ b/STROOP/Tabs/MapTab/Views/ViewBase.cs @@ -11,6 +11,8 @@ public interface PivotingView public abstract class ViewBase { + public string name = "Custom"; + // TODO: consider what this is (ab)used for public Vector3 position; From a28ffcbeb580e541cc58a2efcbdfbf917c08e1d2 Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Thu, 6 Aug 2026 07:23:51 +0200 Subject: [PATCH 7/9] add view context menu to map popouts as well --- STROOP/Tabs/MapTab/MapPopout.cs | 38 +++++++++++++++++++++++++-------- STROOP/Tabs/MapTab/MapTab.cs | 29 +++++++++++++------------ 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/STROOP/Tabs/MapTab/MapPopout.cs b/STROOP/Tabs/MapTab/MapPopout.cs index c9e087620..cc8619546 100644 --- a/STROOP/Tabs/MapTab/MapPopout.cs +++ b/STROOP/Tabs/MapTab/MapPopout.cs @@ -2,6 +2,7 @@ using System.Windows.Forms; using OpenTK.GLControl; using STROOP.Core; +using STROOP.Utilities; namespace STROOP.Tabs.MapTab { @@ -9,31 +10,50 @@ public partial class MapPopout : Form { GLControl glControl; MapGraphics graphics; + MapTab mapTab; - public MapPopout(MapTab tab) + public MapPopout(MapTab mapTab) { + this.mapTab = mapTab; InitializeComponent(); - ClientSize = tab.graphics.glControl.ClientRectangle.Size; + ClientSize = mapTab.graphics.glControl.ClientRectangle.Size; // Own GL context, but sharing resources with the main map's context so we can present the // shared color texture the main context renders into. See issue #39. glControl = new GLControl() { APIVersion = new Version(3, 3), - SharedContext = tab.graphics.glControl, + SharedContext = mapTab.graphics.glControl, }; glControl.Bounds = ClientRectangle; glControl.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom; Controls.Add(glControl); // Render in the main map's (shared) context; present into our own context (handled in MapGraphics). - graphics = new MapGraphics(tab, glControl, () => tab.graphics.glControl.Context); - graphics.MapViewAngleValue = tab.graphics.MapViewAngleValue; - graphics.MapViewScaleValue = tab.graphics.MapViewScaleValue; - graphics.currentView.position = tab.graphics.currentView.position; + graphics = new MapGraphics(mapTab, glControl, () => mapTab.graphics.glControl.Context); + graphics.MapViewAngleValue = mapTab.graphics.MapViewAngleValue; + graphics.MapViewScaleValue = mapTab.graphics.MapViewScaleValue; + graphics.currentView.position = mapTab.graphics.currentView.position; Shown += (_, __) => { - using (new AccessScope(tab)) - graphics.Load(() => tab.graphics.rendererCollection); + using (new AccessScope(mapTab)) + graphics.Load(() => mapTab.graphics.rendererCollection); }; + + glControl.MouseDown += (sender, e) => + { + if (e.Button == MouseButtons.Right) + ShowRightClickMenu(); + }; + } + + ContextMenuStrip contextMenu; + void ShowRightClickMenu() + { + contextMenu?.Dispose(); + contextMenu = new ContextMenuStrip(); + + mapTab.AddViewContextMenuItems(contextMenu, graphics); + + contextMenu.Show(Cursor.Position); } public void Redraw() => glControl.Invalidate(); diff --git a/STROOP/Tabs/MapTab/MapTab.cs b/STROOP/Tabs/MapTab/MapTab.cs index ad5c3964d..3df3ca592 100644 --- a/STROOP/Tabs/MapTab/MapTab.cs +++ b/STROOP/Tabs/MapTab/MapTab.cs @@ -503,19 +503,6 @@ void ShowRightClickMenu() { contextMenu?.Dispose(); contextMenu = new ContextMenuStrip(); - var onClickPosition = graphics.mapCursorPosition; - var copyPositionItem = new ToolStripMenuItem("Copy Cursor Position"); - copyPositionItem.Click += (e, args) => CopyUtilities.CopyPosition(onClickPosition); - contextMenu.Items.Add(copyPositionItem); - contextMenu.Items.Add(new ToolStripSeparator()); - - if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) - { - var pivotPositionItem = new ToolStripMenuItem("Pivot This Position"); - pivotPositionItem.Click += (_, _) => (graphics.currentView as PivotingView)?.Pivot(PositionAngle.Custom(onClickPosition)); - contextMenu.Items.Add(pivotPositionItem); - contextMenu.Items.Add(new ToolStripSeparator()); - } foreach (var a in hoverData) a.AddContextMenuItems(this, contextMenu); @@ -535,6 +522,8 @@ void ShowRightClickMenu() }; contextMenu.Items.Add(openPopoutItem); + contextMenu.Items.Add(new ToolStripSeparator()); + AddViewContextMenuItems(contextMenu, graphics); contextMenu.Show(Cursor.Position); @@ -542,7 +531,19 @@ void ShowRightClickMenu() public void AddViewContextMenuItems(ContextMenuStrip contextMenu, MapGraphics mapGraphics) { - contextMenu.Items.Add(new ToolStripSeparator()); + var onClickPosition = graphics.mapCursorPosition; + var copyPositionItem = new ToolStripMenuItem("Copy Cursor Position"); + copyPositionItem.Click += (e, args) => CopyUtilities.CopyPosition(onClickPosition); + contextMenu.Items.Add(copyPositionItem); + + if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) + { + var pivotPositionItem = new ToolStripMenuItem("Pivot This Position"); + pivotPositionItem.Click += (_, _) => (graphics.currentView as PivotingView)?.Pivot(PositionAngle.Custom(onClickPosition)); + contextMenu.Items.Add(pivotPositionItem); + contextMenu.Items.Add(new ToolStripSeparator()); + } + var rootItem = new ToolStripMenuItem("View"); foreach (var (mode, list, field) in (IEnumerable<(MapGraphics.ViewMode, IEnumerable, FieldInfo)>) [ From 1c0b1c8c6cb6f65566d5301ddfcb368d13aa2d1a Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Fri, 7 Aug 2026 18:00:42 +0200 Subject: [PATCH 8/9] update flying controls on all popouts as well --- STROOP/Tabs/MapTab/MapPopout.cs | 3 +-- STROOP/Tabs/MapTab/MapTab.cs | 7 +++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/STROOP/Tabs/MapTab/MapPopout.cs b/STROOP/Tabs/MapTab/MapPopout.cs index cc8619546..44f4d4e8d 100644 --- a/STROOP/Tabs/MapTab/MapPopout.cs +++ b/STROOP/Tabs/MapTab/MapPopout.cs @@ -2,14 +2,13 @@ using System.Windows.Forms; using OpenTK.GLControl; using STROOP.Core; -using STROOP.Utilities; namespace STROOP.Tabs.MapTab { public partial class MapPopout : Form { GLControl glControl; - MapGraphics graphics; + public readonly MapGraphics graphics; MapTab mapTab; public MapPopout(MapTab mapTab) diff --git a/STROOP/Tabs/MapTab/MapTab.cs b/STROOP/Tabs/MapTab/MapTab.cs index 3df3ca592..0f2bd9462 100644 --- a/STROOP/Tabs/MapTab/MapTab.cs +++ b/STROOP/Tabs/MapTab/MapTab.cs @@ -715,8 +715,11 @@ public void UpdateHover() { using (new AccessScope(this)) { - if (Form.ActiveForm != null && glControlMap2D.ClientRectangle.Contains(glControlMap2D.PointToClient(Cursor.Position))) - graphics.UpdateFlyingControls(Config.CoreLoop.lastFrameTime); + if (Form.ActiveForm != null) + foreach (var g in popouts.Select(x => x.graphics).Append(graphics)) + if (g.glControl.ClientRectangle.Contains(g.glControl.PointToClient(Cursor.Position))) + g.UpdateFlyingControls(Config.CoreLoop.lastFrameTime); + if (!graphics.IsMouseDown(0)) { var newCursor = graphics.mapCursorPosition; From 26c01a5ff1124066bf186edf211d286d54e7dac4 Mon Sep 17 00:00:00 2001 From: FramePerfection <1663221+FramePerfection@users.noreply.github.com> Date: Fri, 7 Aug 2026 18:32:49 +0200 Subject: [PATCH 9/9] add hovering capabilities to popouts --- STROOP/Tabs/MapTab/MapGraphics.cs | 103 ++++++++++++++++++- STROOP/Tabs/MapTab/MapPopout.cs | 13 +-- STROOP/Tabs/MapTab/MapTab.Designer.cs | 2 +- STROOP/Tabs/MapTab/MapTab.cs | 140 ++++---------------------- 4 files changed, 124 insertions(+), 134 deletions(-) diff --git a/STROOP/Tabs/MapTab/MapGraphics.cs b/STROOP/Tabs/MapTab/MapGraphics.cs index bcd36025c..362734ab0 100644 --- a/STROOP/Tabs/MapTab/MapGraphics.cs +++ b/STROOP/Tabs/MapTab/MapGraphics.cs @@ -14,6 +14,7 @@ using STROOP.Tabs.MapTab.Views; using STROOP.Utilities; using System.Linq; +using System.Reflection; namespace STROOP.Tabs.MapTab { @@ -57,6 +58,9 @@ public bool HoverOrthogonal(Vector3 position, float radius) return (projectedPos.Xy - mousePosition2D).LengthSquared < (radius * radius); } + public bool IsContextMenuOpen() => contextMenu != null && contextMenu.Visible; + ContextMenuStrip contextMenu; + public readonly List[] drawLayers; public Renderers.RendererCollection rendererCollection { get; private set; } @@ -676,7 +680,7 @@ private void OnMouseDown(object sender, MouseEventArgs e) using (new AccessScope(mapTab)) { - mapTab.UpdateHover(); + UpdateHover(); foreach (var data in mapTab.hoverData) if (e.Button == MouseButtons.Left) data.LeftClick(mapCursorPosition); @@ -685,6 +689,31 @@ private void OnMouseDown(object sender, MouseEventArgs e) } } + public void UpdateHover() + { + using (new AccessScope(mapTab)) + { + if (!IsMouseDown(0)) + { + var newCursor = mapCursorPosition; + mapTab.hoverData.Clear(); + foreach (var tracker in mapTab.flowLayoutPanelMapTrackers.EnumerateTrackers()) + if (tracker.IsVisible) + { + var newHover = tracker.mapObject.GetHoverData(this, ref newCursor); + if (fixCursorPlane) + { + cursorViewPlaneDist = Vector3.Dot(currentView.ComputeViewDirection(), newCursor - currentView.position); + UpdateCursor(); + } + + if (newHover != null) + mapTab.hoverData.Add(newHover); + } + } + } + } + private void OnMouseUp(object sender, MouseEventArgs e) { switch (e.Button) @@ -888,5 +917,77 @@ public void UpdateFlyingControls(double frameTime) currentView.position += (right * relativeMovement.X + up * relativeMovement.Y + forwards * relativeMovement.Z) * movement; } } + + public void RecreateContextMenu(Action addAdditionalItems = null) + { + contextMenu?.Dispose(); + contextMenu = new ContextMenuStrip(); + + foreach (var a in mapTab.hoverData) + a.AddContextMenuItems(mapTab, contextMenu); + + if (mapTab.hoverData.Count > 0) + contextMenu.Items.Add(new ToolStripSeparator()); + + AddViewContextMenuItems(contextMenu); + + addAdditionalItems?.Invoke(contextMenu); + + contextMenu.Show(Cursor.Position); + } + + public void AddViewContextMenuItems(ContextMenuStrip contextMenu) + { + var onClickPosition = mapCursorPosition; + var copyPositionItem = new ToolStripMenuItem("Copy Cursor Position"); + copyPositionItem.Click += (_, _) => CopyUtilities.CopyPosition(onClickPosition); + contextMenu.Items.Add(copyPositionItem); + + if (viewMode == ViewMode.ThreeDimensional) + { + var pivotPositionItem = new ToolStripMenuItem("Pivot This Position"); + pivotPositionItem.Click += (_, _) => (currentView as PivotingView)?.Pivot(PositionAngle.Custom(onClickPosition)); + contextMenu.Items.Add(pivotPositionItem); + contextMenu.Items.Add(new ToolStripSeparator()); + } + + var rootItem = new ToolStripMenuItem("View"); + foreach (var (mode, list, field) in (IEnumerable<(ViewMode, IEnumerable, FieldInfo)>) + [ + (ViewMode.TopDown, mapTab.viewsTopDown, typeof(MapGraphics).GetField(nameof(viewTopDown))), + (ViewMode.Orthogonal, mapTab.viewsOrthogonal, typeof(MapGraphics).GetField(nameof(viewOrthogonal))), + (ViewMode.ThreeDimensional, mapTab.views3D, typeof(MapGraphics).GetField(nameof(view3D))), + ]) + { + var modeItem = new ToolStripMenuItem(mode.ToString()); + modeItem.Click += (_, _) => viewMode = mode; + var currentView = (ViewBase)field.GetValue(this); + foreach (var view in list) + { + var viewItem = new ToolStripMenuItem(view.name) { Checked = currentView == view }; + viewItem.Click += (_, _) => + { + viewMode = mode; + field.SetValue(this, view); + }; + modeItem.DropDownItems.Add(viewItem); + } + + var newItem = new ToolStripMenuItem("add ..."); + newItem.Click += (_, _) => + { + var newView = (ViewBase)Activator.CreateInstance(field.FieldType); + foreach (var newField in field.FieldType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) + newField.SetValue(newView, newField.GetValue(currentView)); + newView.name = DialogUtilities.GetStringFromDialog("Custom", "Enter a Name") ?? ""; + field.SetValue(this, newView); + viewMode = mode; + list.GetType().GetMethod(nameof(IList.Add)).Invoke(list, [newView]); + }; + modeItem.DropDownItems.Add(newItem); + rootItem.DropDownItems.Add(modeItem); + } + contextMenu.Items.Add(rootItem); + } } } diff --git a/STROOP/Tabs/MapTab/MapPopout.cs b/STROOP/Tabs/MapTab/MapPopout.cs index 44f4d4e8d..8f02d0a7d 100644 --- a/STROOP/Tabs/MapTab/MapPopout.cs +++ b/STROOP/Tabs/MapTab/MapPopout.cs @@ -40,21 +40,10 @@ public MapPopout(MapTab mapTab) glControl.MouseDown += (sender, e) => { if (e.Button == MouseButtons.Right) - ShowRightClickMenu(); + graphics.RecreateContextMenu(); }; } - ContextMenuStrip contextMenu; - void ShowRightClickMenu() - { - contextMenu?.Dispose(); - contextMenu = new ContextMenuStrip(); - - mapTab.AddViewContextMenuItems(contextMenu, graphics); - - contextMenu.Show(Cursor.Position); - } - public void Redraw() => glControl.Invalidate(); protected override void OnClosed(EventArgs e) diff --git a/STROOP/Tabs/MapTab/MapTab.Designer.cs b/STROOP/Tabs/MapTab/MapTab.Designer.cs index df9faed94..d95a0d7ce 100644 --- a/STROOP/Tabs/MapTab/MapTab.Designer.cs +++ b/STROOP/Tabs/MapTab/MapTab.Designer.cs @@ -1150,7 +1150,7 @@ private void InitializeComponent() internal System.Windows.Forms.Label labelMapDataMapSubName; internal System.Windows.Forms.Label labelMapDataMapName; internal System.Windows.Forms.Label labelMapDataPuCoordinates; - private Tabs.MapTab.MapTrackerFlowLayoutPanel flowLayoutPanelMapTrackers; + internal Tabs.MapTab.MapTrackerFlowLayoutPanel flowLayoutPanelMapTrackers; private System.Windows.Forms.ComboBox comboBoxViewMode; internal System.Windows.Forms.ComboBox comboBoxMapOptionsLevel; internal System.Windows.Forms.Label labelViewMode; diff --git a/STROOP/Tabs/MapTab/MapTab.cs b/STROOP/Tabs/MapTab/MapTab.cs index 0f2bd9462..939ef5865 100644 --- a/STROOP/Tabs/MapTab/MapTab.cs +++ b/STROOP/Tabs/MapTab/MapTab.cs @@ -492,95 +492,19 @@ private void InitializeControls() glControlMap2D.MouseDown += (sender, e) => { if (e.Button == MouseButtons.Right) - ShowRightClickMenu(); - }; - } - - bool IsContextMenuOpen() => contextMenu != null && contextMenu.Visible; - ContextMenuStrip contextMenu; - - void ShowRightClickMenu() - { - contextMenu?.Dispose(); - contextMenu = new ContextMenuStrip(); - - foreach (var a in hoverData) - a.AddContextMenuItems(this, contextMenu); - - if (hoverData.Count > 0) - { - contextMenu.Items.Add(new ToolStripSeparator()); - } - - var openPopoutItem = new ToolStripMenuItem("Open Popout"); - openPopoutItem.Click += (e, args) => - { - var popout = new MapPopout(this) { Owner = FindForm() }; - popout.Show(); - popout.FormClosed += (_, __) => popouts.Remove(popout); - popouts.Add(popout); - }; - contextMenu.Items.Add(openPopoutItem); - - contextMenu.Items.Add(new ToolStripSeparator()); - - AddViewContextMenuItems(contextMenu, graphics); - - contextMenu.Show(Cursor.Position); - } - - public void AddViewContextMenuItems(ContextMenuStrip contextMenu, MapGraphics mapGraphics) - { - var onClickPosition = graphics.mapCursorPosition; - var copyPositionItem = new ToolStripMenuItem("Copy Cursor Position"); - copyPositionItem.Click += (e, args) => CopyUtilities.CopyPosition(onClickPosition); - contextMenu.Items.Add(copyPositionItem); - - if (graphics.viewMode == MapGraphics.ViewMode.ThreeDimensional) - { - var pivotPositionItem = new ToolStripMenuItem("Pivot This Position"); - pivotPositionItem.Click += (_, _) => (graphics.currentView as PivotingView)?.Pivot(PositionAngle.Custom(onClickPosition)); - contextMenu.Items.Add(pivotPositionItem); - contextMenu.Items.Add(new ToolStripSeparator()); - } - - var rootItem = new ToolStripMenuItem("View"); - foreach (var (mode, list, field) in (IEnumerable<(MapGraphics.ViewMode, IEnumerable, FieldInfo)>) - [ - (MapGraphics.ViewMode.TopDown, viewsTopDown, typeof(MapGraphics).GetField(nameof(MapGraphics.viewTopDown))), - (MapGraphics.ViewMode.Orthogonal, viewsOrthogonal, typeof(MapGraphics).GetField(nameof(MapGraphics.viewOrthogonal))), - (MapGraphics.ViewMode.ThreeDimensional, views3D, typeof(MapGraphics).GetField(nameof(MapGraphics.view3D))), - ]) - { - var modeItem = new ToolStripMenuItem(mode.ToString()); - modeItem.Click += (_, _) => mapGraphics.viewMode = mode; - var currentView = (ViewBase)field.GetValue(mapGraphics); - foreach (var view in list) - { - var viewItem = new ToolStripMenuItem(view.name) { Checked = currentView == view }; - viewItem.Click += (_, _) => + graphics.RecreateContextMenu(contextMenu => { - mapGraphics.viewMode = mode; - field.SetValue(mapGraphics, view); - }; - modeItem.DropDownItems.Add(viewItem); - } - - var newItem = new ToolStripMenuItem("add ..."); - newItem.Click += (_, _) => - { - var newView = (ViewBase)Activator.CreateInstance(field.FieldType); - foreach (var newField in field.FieldType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) - newField.SetValue(newView, newField.GetValue(currentView)); - newView.name = DialogUtilities.GetStringFromDialog("Custom", "Enter a Name") ?? ""; - field.SetValue(mapGraphics, newView); - mapGraphics.viewMode = mode; - list.GetType().GetMethod(nameof(IList.Add)).Invoke(list, [newView]); - }; - modeItem.DropDownItems.Add(newItem); - rootItem.DropDownItems.Add(modeItem); - } - contextMenu.Items.Add(rootItem); + var openPopoutItem = new ToolStripMenuItem("Open Popout"); + openPopoutItem.Click += (_, _) => + { + var popout = new MapPopout(this) { Owner = FindForm() }; + popout.Show(); + popout.FormClosed += (_, __) => popouts.Remove(popout); + popouts.Add(popout); + }; + contextMenu.Items.Add(openPopoutItem); + }); + }; } private void LoadDefaultTrackers() @@ -711,36 +635,6 @@ void AddViewModeContextMenu() }; } - public void UpdateHover() - { - using (new AccessScope(this)) - { - if (Form.ActiveForm != null) - foreach (var g in popouts.Select(x => x.graphics).Append(graphics)) - if (g.glControl.ClientRectangle.Contains(g.glControl.PointToClient(Cursor.Position))) - g.UpdateFlyingControls(Config.CoreLoop.lastFrameTime); - - if (!graphics.IsMouseDown(0)) - { - var newCursor = graphics.mapCursorPosition; - hoverData.Clear(); - foreach (var tracker in flowLayoutPanelMapTrackers.EnumerateTrackers()) - if (tracker.IsVisible) - { - var newHover = tracker.mapObject.GetHoverData(graphics, ref newCursor); - if (graphics.fixCursorPlane) - { - graphics.cursorViewPlaneDist = Vector3.Dot(graphics.currentView.ComputeViewDirection(), (newCursor - graphics.currentView.position)); - graphics.UpdateCursor(); - } - - if (newHover != null) - hoverData.Add(newHover); - } - } - } - } - public override void Update(bool active) { if (!_isLoaded2D) return; @@ -767,8 +661,14 @@ public override void Update(bool active) RequireGeometryUpdate(); } - if (!IsContextMenuOpen()) - UpdateHover(); + if (Form.ActiveForm != null) + foreach (var g in popouts.Select(x => x.graphics).Append(graphics)) + if (!g.IsContextMenuOpen() && g.glControl.ClientRectangle.Contains(g.glControl.PointToClient(Cursor.Position))) + { + g.UpdateFlyingControls(Config.CoreLoop.lastFrameTime); + g.UpdateHover(); + } + using (new AccessScope(this)) { flowLayoutPanelMapTrackers.UpdateControl();