Skip to content

Commit

Permalink
Improve theme selector safeguard, Restore Pre-HDR PR behaviour of deb…
Browse files Browse the repository at this point in the history
…ug setting (#321)

* Improve theme selector safeguard

* Fix debug mode crash

* Improve fault tolerance of screenshot system,
stop substituting warframe process with wfinfo process in debug mode,
restore debug mode making screenshot grab primary screen if game isn't running,
  • Loading branch information
D1firehail authored Sep 22, 2024
1 parent b24bf1a commit fe3bf3f
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 46 deletions.
8 changes: 6 additions & 2 deletions WFInfo/LowLevelListener.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;

namespace WFInfo
{
Expand Down Expand Up @@ -107,12 +109,14 @@ private static IntPtr HookCallbackKB(int nCode, IntPtr wParam, IntPtr lParam) //

protected static void OnKeyAction(Key key)
{
KeyEvent?.Invoke(key);
// Bounce via InvokeAsync, to avoid being in an "input-synchronous call" state which can cause crash on certain actions
Application.Current.Dispatcher.InvokeAsync(() => { KeyEvent?.Invoke(key); });
}

protected static void OnMouseAction(MouseButton key)
{
MouseEvent?.Invoke(key);
// Bounce via InvokeAsync, to avoid being in an "input-synchronous call" state which can cause crash on certain actions
Application.Current.Dispatcher.InvokeAsync(() => { MouseEvent?.Invoke(key); });
}

private static IntPtr HookCallbackM(int nCode, IntPtr wParam, IntPtr lParam) //handels mouse input
Expand Down
5 changes: 5 additions & 0 deletions WFInfo/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,11 @@ public void ActivationKeyPressed(Object key)
StatusUpdate("Starting master it", 0);
Task.Factory.StartNew(() => {
Bitmap bigScreenshot = OCR.CaptureScreenshot();
if (bigScreenshot == null)
{
AddLog("MasterIt activation failed: Screenshot failed");
return;
}
OCR.ProcessProfileScreen(bigScreenshot);
bigScreenshot.Dispose();
});
Expand Down
51 changes: 47 additions & 4 deletions WFInfo/Ocr.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,20 @@ internal static void ProcessRewardScreen(Bitmap file = null)

List<Bitmap> parts;

bigScreenshot = file ?? CaptureScreenshot();
if (file != null)
{
bigScreenshot = file;
} else
{
var screenshot = CaptureScreenshot();
if (screenshot == null)
{
Main.AddLog("Processing failed: Screenshot failed");
return;
}
bigScreenshot = screenshot;
}

try
{
parts = ExtractPartBoxAutomatically(out uiScaling, out _, bigScreenshot);
Expand Down Expand Up @@ -536,6 +549,12 @@ public static WFtheme GetThemeWeighted(out double closestThresh, Bitmap image =
// using (Graphics graphics = Graphics.FromImage(image))
// graphics.CopyFromScreen(window.Left + mostLeft, window.Top + mostTop, 0, 0, new Size(image.Width, image.Height));
image = CaptureScreenshot();

if (image == null)
{
closestThresh = 0;
return WFtheme.UNKNOWN;
}
}


Expand Down Expand Up @@ -639,6 +658,12 @@ internal static void ProcessSnapIt(Bitmap snapItImage, Bitmap fullShot, Point sn
//timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH-mm-ssff", Main.culture);
string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH-mm-ssff", Main.culture);
WFtheme theme = GetThemeWeighted(out _, fullShot);
if (theme == WFtheme.UNKNOWN)
{
Main.AddLog("SnapIt: Theme detection failed");
return;
}

snapItImage.Save(Main.AppPath + @"\Debug\SnapItImage " + timestamp + ".png");
Bitmap snapItImageFiltered = ScaleUpAndFilter(snapItImage, theme, out int[] rowHits, out int[] colHits);
snapItImageFiltered.Save(Main.AppPath + @"\Debug\SnapItImageFiltered " + timestamp + ".png");
Expand Down Expand Up @@ -2467,16 +2492,34 @@ internal static Bitmap CaptureScreenshot()
throw new NotImplementedException($"HDR support option '{_settings.HdrSupport}' does not have a corresponding screenshot service.");
}
}


var image = screenshot.CaptureScreenshot().Result.First();
if (ReferenceEquals(screenshot, _windowsScreenshot) && !screenshot.IsAvailable)
{
Main.AddLog("HDR-compliant screenshot service chosen, but unavailable. Falling back to GDI");
screenshot = _gdiScreenshot;
}


var images = screenshot.CaptureScreenshot().Result;
if (images.Count == 0)
{
Main.AddLog("CaptureScreenshot returned no image. Screenshot type: " + screenshot.GetType().Name);
return null;
}
var image = images.First();
image.Save(Main.AppPath + @"\Debug\FullScreenShot " + DateTime.UtcNow.ToString("yyyy-MM-dd HH-mm-ssff", Main.culture) + ".png");
return image;
}

internal static void SnapScreenshot()
{
Main.snapItOverlayWindow.Populate(CaptureScreenshot());
var image = CaptureScreenshot();
if (image == null)
{
Main.AddLog("SnapIt activation failed: Screenshot failed");
return;
}
Main.snapItOverlayWindow.Populate(image);
Main.snapItOverlayWindow.Left = _window.Window.Left / _window.DpiScaling;
Main.snapItOverlayWindow.Top = _window.Window.Top / _window.DpiScaling;
Main.snapItOverlayWindow.Width = _window.Window.Width / _window.DpiScaling;
Expand Down
16 changes: 14 additions & 2 deletions WFInfo/Services/Screenshot/GdiScreenshotService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,23 @@
using System.Drawing;
using System.Threading.Tasks;
using WFInfo.Services.WindowInfo;
using WFInfo.Settings;

namespace WFInfo.Services.Screenshot
{
public class GdiScreenshotService : IScreenshotService
{
private static IWindowInfoService _window;
private static IReadOnlyApplicationSettings _settings;

public GdiScreenshotService(IWindowInfoService window)
public GdiScreenshotService(IWindowInfoService window, IReadOnlyApplicationSettings settings)
{
_window = window;
_settings = settings;
}

public bool IsAvailable => true;

public Task<List<Bitmap>> CaptureScreenshot()
{
_window.UpdateWindow();
Expand All @@ -24,9 +29,16 @@ public Task<List<Bitmap>> CaptureScreenshot()
int width = window.Width;
int height = window.Height;

if (window == null || window.Width == 0 || window.Height == 0)
if (width == 0 || height == 0)
{
if (!_settings.Debug)
{
return Task.FromResult(new List<Bitmap>());
}

window = _window.Screen.Bounds;
width = window.Width;
height = window.Height;
center = new Point(window.X + window.Width / 2, window.Y + window.Height / 2);

width *= (int)_window.DpiScaling;
Expand Down
2 changes: 2 additions & 0 deletions WFInfo/Services/Screenshot/IScreenshotService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ public interface IScreenshotService
/// </summary>
/// <returns>Captured screenshots</returns>
Task<List<Bitmap>> CaptureScreenshot();

bool IsAvailable { get; }
}
}
2 changes: 2 additions & 0 deletions WFInfo/Services/Screenshot/ImageScreenshotService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ namespace WFInfo.Services.Screenshot
{
public class ImageScreenshotService : IScreenshotService
{
public bool IsAvailable => true;

public async Task<List<Bitmap>> CaptureScreenshot()
{
// Using WinForms for the openFileDialog because it's simpler and much easier
Expand Down
15 changes: 15 additions & 0 deletions WFInfo/Services/Screenshot/WindowsCaptureScreenshotService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,15 @@ public WindowsCaptureScreenshotService(IProcessFinder process, bool useHdr = tru
_process.OnProcessChanged += CreateCaptureSession;
}

public bool IsAvailable { get; private set; }

public Task<List<Bitmap>> CaptureScreenshot()
{
if (!IsAvailable)
{
return Task.FromResult(new List<Bitmap>());
}

Texture2D cpuTexture = null;
int width, height;

Expand Down Expand Up @@ -96,6 +103,14 @@ private void CreateCaptureSession(Process process)
{
_session?.Dispose();
_framePool?.Dispose();
_session = null;
_framePool = null;

IsAvailable = process != null;
if (!IsAvailable)
{
return;
}

_item = CaptureHelper.CreateItemForWindow(process.MainWindowHandle);
_framePool = Direct3D11CaptureFramePool.CreateFreeThreaded(_device, pixelFormat, 2, _item.Size);
Expand Down
40 changes: 6 additions & 34 deletions WFInfo/Services/WarframeProcess/WarframeProcessFinder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using WFInfo.Settings;
Expand Down Expand Up @@ -65,8 +66,6 @@ private void FindProcess()
try
{
bool _ = _warframe.HasExited;
OnProcessChanged?.Invoke(_warframe);
return;
}
catch (System.ComponentModel.Win32Exception e)
{
Expand All @@ -75,16 +74,9 @@ private void FindProcess()
Main.AddLog($"Failed to get Warframe process due to: {e.Message}");
Main.StatusUpdate("Restart Warframe without admin privileges", 1);

// Substitute process for debug purposes
if (_settings.Debug)
{
Main.AddLog($"Substituting Warframe process with WFInfo process for debug purposes.");
_warframe = Process.GetCurrentProcess();
}

OnProcessChanged?.Invoke(_warframe);
return;
}
OnProcessChanged?.Invoke(_warframe);
return;
}
else if (process.MainWindowTitle.Contains("Warframe") && process.MainWindowTitle.Contains("GeForce NOW"))
{
Expand All @@ -100,8 +92,6 @@ private void FindProcess()
try
{
bool _ = _warframe.HasExited;
OnProcessChanged?.Invoke(_warframe);
return;
}
catch (System.ComponentModel.Win32Exception e)
{
Expand All @@ -110,16 +100,9 @@ private void FindProcess()
Main.AddLog($"Failed to get Warframe process due to: {e.Message}");
Main.StatusUpdate("Restart Warframe without admin privileges, or WFInfo with admin privileges", 1);

// Substitute process for debug purposes
if (_settings.Debug)
{
Main.AddLog($"Substituting Warframe process with WFInfo process for debug purposes.");
_warframe = Process.GetCurrentProcess();
}

OnProcessChanged?.Invoke(_warframe);
return;
}
OnProcessChanged?.Invoke(_warframe);
return;
}
}

Expand All @@ -128,17 +111,6 @@ private void FindProcess()
Main.AddLog("Did Not Detect Warframe Process");
Main.StatusUpdate("Unable to Detect Warframe Process", 1);
}
else
{
// Substitute process for debug purposes
if (_settings.Debug)
{
Main.AddLog($"Substituting Warframe process with WFInfo process for debug purposes.");
_warframe = Process.GetCurrentProcess();
}

OnProcessChanged?.Invoke(_warframe);
}
}
}
}
2 changes: 1 addition & 1 deletion WFInfo/Services/WindowInfo/Win32WindowInfoService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace WFInfo.Services.WindowInfo
{
public class Win32WindowInfoService : IWindowInfoService
{
public double DpiScaling { get; private set; }
public double DpiScaling { get; private set; } = 1;
public double ScreenScaling
{
get
Expand Down
22 changes: 22 additions & 0 deletions WFInfo/Settings/SettingsViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -411,10 +411,32 @@ public WFtheme ThemeSelection
get => _settings.ThemeSelection;
set
{
if (_settings.ThemeSelection == value)
{
return;
}

// No need to verify intent when switching to AUTO
if (value != WFtheme.AUTO && !ConfirmThemeChangeIntentional(_settings.ThemeSelection, value))
{
return;
}

_settings.ThemeSelection = value;
RaisePropertyChanged();
}
}

private bool ConfirmThemeChangeIntentional(WFtheme oldTheme, WFtheme newTheme)
{
MessageBoxResult messageBoxResult = MessageBox.Show("You are about to force WFInfo to think you're using the " + newTheme + " theme in-game." + Environment.NewLine + Environment.NewLine
+ "If this is wrong, WFInfo will not be able to do its job." + Environment.NewLine + Environment.NewLine
+ "We STRONGLY recommend setting this to AUTO." + Environment.NewLine + Environment.NewLine
+ "Are you sure?",
"Change of target theme", MessageBoxButton.OKCancel);
return messageBoxResult == MessageBoxResult.OK;
}

public bool CF_usePrimaryHSL { get => _settings.CF_usePrimaryHSL;
set
{
Expand Down
2 changes: 1 addition & 1 deletion WFInfo/Settings/SettingsWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@
BorderBrush="#FF0F0F0F"
ItemsSource="{Binding Source={StaticResource enumWFTheme}}"
SelectedItem="{Binding SettingsViewModel.ThemeSelection}"
Margin="5,4" Template="{DynamicResource ComboBoxTemplate}" Style="{DynamicResource ComboBoxStyle1}" DropDownClosed="ThemeSelectionComboBox_OnDropDownClosed"/>
Margin="5,4" Template="{DynamicResource ComboBoxTemplate}" Style="{DynamicResource ComboBoxStyle1}" SelectionChanged="themeSelectionComboBox_SelectionChanged"/>

<Label Visibility="{Binding SettingsViewModel.OsSupportsHDR, Converter={StaticResource BoolVisibilityConverter}}" Content="HDR" Grid.Column="0" Grid.Row="1"/>
<Label Visibility="{Binding SettingsViewModel.OsSupportsHDR, Converter={StaticResource BoolVisibilityConverter}}" Grid.Row="1" Grid.Column="1" ToolTip="Auto - Detect based on game settings&#x0a;On - Always use HDR capture (will slightly change colors) &#x0a;Off - Always use SDR capture (will result in overblown HDR screenshots) &#x0a;&#x0a;It is recommended to use a custom theme with HDR enabled, this mode only compresses the dynamic color range." Margin="0,5,10,5" Padding="3" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Height="20" VerticalAlignment="Top" HorizontalAlignment="Right" Width="20">
Expand Down
8 changes: 6 additions & 2 deletions WFInfo/Settings/SettingsWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,13 @@ private void ConfigureTheme_button_MouseLeftButtonDown(object sender, MouseButto
ThemeAdjuster.ShowThemeAdjuster();
}

private void ThemeSelectionComboBox_OnDropDownClosed(object sender, EventArgs e)
private void themeSelectionComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
MessageBoxResult messageBoxResult = MessageBox.Show("This option will not change WFInfo screen style. It will force app to think you have selected this theme in Warframe (and will use its pixel colors for item scanning). Unless you know what you're doing, leave Auto selected.", "Change of target theme", System.Windows.MessageBoxButton.OK);
// mismatch only occurs if we intentionally suppress the change in the viewmodel. If that happens, reset selected value
if ((WFtheme)themeSelectionComboBox.SelectedValue != SettingsViewModel.ThemeSelection)
{
themeSelectionComboBox.SelectedValue = SettingsViewModel.ThemeSelection;
}
}
}
}

0 comments on commit fe3bf3f

Please sign in to comment.