Skip to content

Commit dcfcf7f

Browse files
committed
Refactor AIManager and CaptureManager for improved clarity
Removed KDTree and replaced with linear search Enhance AIManager.cs with new properties for AI detection coordinates and configuration. Move SessionOptions initialization to LoadModelAsync for better encapsulation. Improve exception handling organization and ensure AI loop starts only if the model is loaded successfully. Update CheckSprayRelease logic for clarity. Introduce directXBitmap in CaptureManager.cs to manage DirectX captures and improve bitmap handling in GetFrame to reduce memory leaks. Overall, these changes enhance code structure, readability, and maintainability.
1 parent 2a4301e commit dcfcf7f

File tree

2 files changed

+108
-75
lines changed

2 files changed

+108
-75
lines changed

Aimmy2/AILogic/AIManager.cs

Lines changed: 66 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,7 @@ public void RequestSizeChange(int newSize)
6060
private KalmanPrediction kalmanPrediction;
6161
private WiseTheFoxPrediction wtfpredictionManager;
6262

63-
private SessionOptions sessionOptions = new()
64-
{
65-
EnableCpuMemArena = true,
66-
EnableMemoryPattern = false,
67-
GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_ALL,
68-
ExecutionMode = ExecutionMode.ORT_PARALLEL
69-
70-
};
63+
7164

7265
// Display-aware properties
7366
private int ScreenWidth => DisplayManager.ScreenWidth;
@@ -102,9 +95,12 @@ public void RequestSizeChange(int newSize)
10295
private int iterationCount = 0;
10396
private long totalTime = 0;
10497

98+
99+
//AI Detection Coordinates
105100
private int detectedX { get; set; }
106101
private int detectedY { get; set; }
107102

103+
// current target
108104
public double AIConf = 0;
109105
private static int targetX, targetY;
110106

@@ -123,6 +119,7 @@ public void RequestSizeChange(int newSize)
123119

124120

125121
private readonly CaptureManager _captureManager = new();
122+
126123
#endregion Variables
127124

128125
#region Benchmarking
@@ -261,6 +258,14 @@ private async Task InitializeModel(string modelPath)
261258
{
262259
try
263260
{
261+
using SessionOptions sessionOptions = new()
262+
{
263+
EnableCpuMemArena = true,
264+
EnableMemoryPattern = false,
265+
GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_ALL,
266+
ExecutionMode = ExecutionMode.ORT_PARALLEL
267+
};
268+
264269
if (!failure)
265270
{
266271
switch (Dictionary.dropdownState["Execution Provider"])
@@ -309,6 +314,8 @@ private async Task InitializeModel(string modelPath)
309314
//return; // Exit early if validation fails
310315
}
311316
}
317+
#region Handling Exceptions
318+
//(There are many precautions here because users are not very careful with their installations)
312319
catch (OnnxRuntimeException ex)
313320
{
314321
string? message = null, title = null;
@@ -358,19 +365,20 @@ private async Task InitializeModel(string modelPath)
358365
Log(LogLevel.Error, $"Error loading the model: {ex.Message}", true);
359366
_onnxModel?.Dispose();
360367
}
368+
#endregion
361369
finally
362370
{
363371
if (_onnxModel?.OutputMetadata != null && _onnxModel.OutputMetadata.Count > 0)
364372
{
365373
Log(LogLevel.Info, "Starting AI Loop", false);
366-
// Begin the loop
367374
_isAiLoopRunning = true;
368-
_aiLoopThread = new Thread(AiLoop)
375+
_aiLoopThread = new Thread(AiLoop)
369376
{
370377
IsBackground = true,
371-
Priority = ThreadPriority.AboveNormal // Higher priority for AI thread
378+
Priority = ThreadPriority.AboveNormal
372379
};
373380
_aiLoopThread.Start();
381+
// Begin the loop
374382
}
375383
else
376384
{
@@ -562,7 +570,7 @@ private static bool ShouldProcess() =>
562570
Dictionary.toggleState["Show Detected Player"] ||
563571
Dictionary.toggleState["Auto Trigger"];
564572

565-
private async void AiLoop()
573+
private async void AiLoop()
566574
{
567575
Stopwatch stopwatch = new();
568576
DetectedPlayerWindow? DetectedPlayerOverlay = Dictionary.DetectedPlayerOverlay;
@@ -580,8 +588,6 @@ private async void AiLoop()
580588
}
581589

582590
stopwatch.Restart();
583-
584-
// Handle any pending display changes
585591
_captureManager.HandlePendingDisplayChanges();
586592

587593
using (Benchmark("AILoopIteration"))
@@ -644,10 +650,14 @@ private async void AiLoop()
644650
[MethodImpl(MethodImplOptions.AggressiveInlining)]
645651
private async Task AutoTrigger()
646652
{
653+
// if auto trigger is disabled,
654+
// or if the aim keybinds are not held,
655+
// or if constant AI tracking is enabled,
656+
// we check for spray release and return
647657
if (!Dictionary.toggleState["Auto Trigger"] ||
648-
!(InputBindingManager.IsHoldingBinding("Aim Keybind") ||
649-
!(InputBindingManager.IsHoldingBinding("Second Aim Keybind"))) ||
650-
Dictionary.toggleState["Constant AI Tracking"])
658+
!(InputBindingManager.IsHoldingBinding("Aim Keybind") && !InputBindingManager.IsHoldingBinding("Second Aim Keybind")) ||
659+
Dictionary.toggleState["Constant AI Tracking"]) // this logic is a bit weird, but it works.
660+
// but it might need to be revised
651661
{
652662
CheckSprayRelease();
653663
return;
@@ -682,14 +692,17 @@ private async Task AutoTrigger()
682692
if (!Dictionary.toggleState["Aim Assist"] || !Dictionary.toggleState["Show Detected Player"]) return;
683693

684694
}
685-
private void CheckSprayRelease()
695+
private void CheckSprayRelease()
686696
{
687697
if (!Dictionary.toggleState["Spray Mode"]) return;
688698

699+
// if auto trigger is disabled, we reset the spray state
700+
// if the aim keybinds are not held, we reset the spray state
689701
bool shouldSpray = Dictionary.toggleState["Auto Trigger"] &&
690-
((InputBindingManager.IsHoldingBinding("Aim Keybind") || InputBindingManager.IsHoldingBinding("Second Aim Keybind")) ||
691-
Dictionary.toggleState["Constant AI Tracking"]);
702+
(InputBindingManager.IsHoldingBinding("Aim Keybind") && InputBindingManager.IsHoldingBinding("Second Aim Keybind")); //||
703+
//Dictionary.toggleState["Constant AI Tracking"];
692704

705+
// spray mode might need to be revised.
693706
if (!shouldSpray)
694707
{
695708
MouseManager.ResetSprayState();
@@ -921,21 +934,39 @@ private void HandlePredictions(KalmanPrediction kalmanPrediction, Prediction clo
921934
(KDpoints, KDPredictions) = PrepareKDTreeData(outputTensor, detectionBox, fovMinX, fovMaxX, fovMinY, fovMaxY);
922935
}
923936

937+
results.Dispose(); // fix memory leak
938+
924939
if (KDpoints.Count == 0 || KDPredictions.Count == 0)
925940
{
926941
SaveFrame(frame);
927942
return null;
928943
}
929944

930-
KDTree<double, Prediction> tree;
931-
Tuple<double[], Prediction>[]? nearest;
932-
using (Benchmark("KDTreeOperations"))
945+
//KDTree<double, Prediction> tree;
946+
//Tuple<double[], Prediction>[]? nearest;
947+
//using (Benchmark("KDTreeOperations"))
948+
//{
949+
// tree = new KDTree<double, Prediction>(2, KDpoints.ToArray(), KDPredictions.ToArray(), L2Norm_Squared_Double);
950+
// nearest = tree.NearestNeighbors(new double[] { IMAGE_SIZE / 2.0, IMAGE_SIZE / 2.0 }, 1);
951+
//}
952+
953+
//Prediction? bestCandidate = (nearest.Length > 0) ? nearest[0].Item2 : null;
954+
955+
Prediction? bestCandidate = null;
956+
double bestDistSq = double.MaxValue;
957+
double center = IMAGE_SIZE / 2.0;
958+
959+
using (Benchmark("LinearSearch"))
933960
{
934-
tree = new KDTree<double, Prediction>(2, KDpoints.ToArray(), KDPredictions.ToArray(), L2Norm_Squared_Double);
935-
nearest = tree.NearestNeighbors(new double[] { IMAGE_SIZE / 2.0, IMAGE_SIZE / 2.0 }, 1);
936-
}
961+
foreach (var p in KDPredictions)
962+
{
963+
var dx = p.CenterXTranslated * IMAGE_SIZE - center; // or use x_center from KDpoints
964+
var dy = p.CenterYTranslated * IMAGE_SIZE - center;
965+
double d2 = dx * dx + dy * dy; // dx^2 + dy^2
937966

938-
Prediction? bestCandidate = (nearest.Length > 0) ? nearest[0].Item2 : null;
967+
if (d2 < bestDistSq) { bestDistSq = d2; bestCandidate = p; }
968+
}
969+
}
939970

940971
Prediction? finalTarget = HandleStickyAim(bestCandidate, KDPredictions);
941972
if (finalTarget != null)
@@ -945,6 +976,7 @@ private void HandlePredictions(KalmanPrediction kalmanPrediction, Prediction clo
945976
return finalTarget;
946977
}
947978

979+
frame.Dispose();
948980
return null;
949981
}
950982
private Prediction? HandleStickyAim(Prediction? bestCandidate, List<Prediction> KDPredictions)
@@ -991,7 +1023,9 @@ private void UpdateDetectionBox(Prediction target, Rectangle detectionBox)
9911023
CenterXTranslated = target.CenterXTranslated;
9921024
CenterYTranslated = target.CenterYTranslated;
9931025
}
994-
private (List<double[]>, List<Prediction>) PrepareKDTreeData(Tensor<float> outputTensor, Rectangle detectionBox,
1026+
private (List<double[]>, List<Prediction>) PrepareKDTreeData(
1027+
Tensor<float> outputTensor,
1028+
Rectangle detectionBox,
9951029
float fovMinX, float fovMaxX, float fovMinY, float fovMaxY)
9961030
{
9971031
float minConfidence = (float)Dictionary.sliderSettings["AI Minimum Confidence"] / 100.0f;
@@ -1052,8 +1086,10 @@ private void UpdateDetectionBox(Prediction target, Rectangle detectionBox)
10521086
Confidence = bestConfidence,
10531087
ClassId = bestClassId,
10541088
ClassName = _modelClasses.GetValueOrDefault(bestClassId, $"Class_{bestClassId}"),
1055-
CenterXTranslated = (x_center - detectionBox.Left) / IMAGE_SIZE,
1056-
CenterYTranslated = (y_center - detectionBox.Top) / IMAGE_SIZE,
1089+
CenterXTranslated = x_center / IMAGE_SIZE, // !! CenterXTranslated is normalized to [0, 1]
1090+
CenterYTranslated = y_center / IMAGE_SIZE,
1091+
//CenterXTranslated = (x_center - detectionBox.Left) / IMAGE_SIZE,
1092+
//CenterYTranslated = (y_center - detectionBox.Top) / IMAGE_SIZE,
10571093
ScreenCenterX = detectionBox.Left + x_center,
10581094
ScreenCenterY = detectionBox.Top + y_center
10591095
};
@@ -1070,7 +1106,6 @@ private void UpdateDetectionBox(Prediction target, Rectangle detectionBox)
10701106
#endregion AI
10711107

10721108
#region Screen Capture
1073-
10741109
private void SaveFrame(Bitmap frame, Prediction? DoLabel = null)
10751110
{
10761111
// Only save frames if "Collect Data While Playing" is enabled
@@ -1103,9 +1138,6 @@ private void SaveFrame(Bitmap frame, Prediction? DoLabel = null)
11031138
File.WriteAllText(labelPath, $"{DoLabel.ClassId} {x} {y} {width} {height}");
11041139
}
11051140
}
1106-
1107-
1108-
11091141
#endregion Screen Capture
11101142

11111143

@@ -1132,15 +1164,13 @@ public void Dispose()
11321164
PrintBenchmarks();
11331165

11341166
// Dispose DXGI objects
1135-
_captureManager.DisposeDxgiResources();
11361167
_captureManager.Dispose();
11371168

11381169
// Clean up other resources
11391170
_reusableInputArray = null;
11401171
_reusableInputs = null;
11411172
_onnxModel?.Dispose();
11421173
_modeloptions?.Dispose();
1143-
_captureManager.screenCaptureBitmap?.Dispose();
11441174
}
11451175
}
11461176
public class Prediction

0 commit comments

Comments
 (0)