Find D2R window using win32api instead of pattern matching (#453)

This commit is contained in:
Vladimir Makaev
2022-01-18 20:32:35 +01:00
committed by GitHub
parent c939877c7b
commit b890ff266f
4 changed files with 63 additions and 24 deletions
+45 -21
View File
@@ -5,6 +5,7 @@ import time
from logger import Logger
from typing import Tuple
from config import Config
from utils import misc
from utils.misc import load_template
import os
@@ -24,12 +25,42 @@ class Screen:
self._config = Config()
self._monitor_roi = self._sct.monitors[monitor_idx]
# auto find offests
self.found_offsets = False
position = None
if self._config.general["find_window_via_win32_api"] :
Logger.debug("Using WinAPI to search for window under D2R.exe process")
position = self.find_window_via_winapi()
if position is None:
Logger.debug("Can't find any window owned by D2R.exe falling back to matching via assets. Make sure D2R is in focus and you are on the hero selection screen")
if position is None:
position = self.find_window_via_assets(wait)
if position is not None:
self._set_window_position(*position)
else:
if self._config.general["info_screenshots"]:
cv2.imwrite("./info_screenshots/error_d2r_window_not_found_" + time.strftime("%Y%m%d_%H%M%S") + ".png", self.grab())
Logger.error("Could not find hero selection or template for ingame, shutting down")
Logger.error("Could not determine window offset. Please make sure you have the D2R window " +
f"focused and that you are on the hero selection screen when pressing {self._config.general['resume_key']}")
def _set_window_position(self, offset_x: int, offset_y: int):
Logger.debug(f"Set offsets: left {offset_x}px, top {offset_y}px")
self._monitor_roi["top"] += offset_y
self._monitor_roi["left"] += offset_x
self._monitor_x_range = (self._monitor_roi["left"] + 10, self._monitor_roi["left"] + self._monitor_roi["width"] - 10)
self._monitor_y_range = (self._monitor_roi["top"] + 10, self._monitor_roi["top"] + self._monitor_roi["height"] - 10)
self._monitor_roi["width"] = self._config.ui_pos["screen_width"]
self._monitor_roi["height"] = self._config.ui_pos["screen_height"]
self.found_offsets = True
def find_window_via_assets(self, wait: int) -> Tuple[int, int]:
template = load_template(f"assets/templates/main_menu_top_left.png", 1.0)
template_ingame = load_template(f"assets/templates/window_ingame_offset_reference.png", 1.0)
start = time.time()
self.found_offsets = False
Logger.info("Searching for window offsets. Make sure D2R is in focus and you are on the hero selection screen")
debug_max_val = 0
start = time.time()
while time.time() - start < wait:
img = self.grab()
self._sct = mss()
@@ -53,25 +84,18 @@ class Screen:
if max_val < 0.93:
Logger.warning(f"Your template match score to calc corner was lower then usual ({max_val*100:.1f}% confidence). " +
"You might run into template matching issues along the way!")
offset_left, offset_top = max_pos
Logger.debug(f"Set offsets: left {offset_left}px, top {offset_top}px")
self._monitor_roi["top"] += offset_top
self._monitor_roi["left"] += offset_left
self._monitor_x_range = (self._monitor_roi["left"] + 10, self._monitor_roi["left"] + self._monitor_roi["width"] - 10)
self._monitor_y_range = (self._monitor_roi["top"] + 10, self._monitor_roi["top"] + self._monitor_roi["height"] - 10)
self._monitor_roi["width"] = self._config.ui_pos["screen_width"]
self._monitor_roi["height"] = self._config.ui_pos["screen_height"]
self.found_offsets = True
break
if not self.found_offsets:
if self._config.general["info_screenshots"]:
cv2.imwrite("./info_screenshots/error_d2r_window_not_found_" + time.strftime("%Y%m%d_%H%M%S") + ".png", self.grab())
Logger.error("Could not find hero selection or template for ingame, shutting down")
Logger.error(f"The max score that could be found was: ({debug_max_val*100:.1f}% confidence)")
Logger.error("Could not determine window offset. Please make sure you have the D2R window " +
f"focused and that you are on the hero selection screen when pressing {self._config.general['resume_key']}")
return max_pos
Logger.error(f"The max score that could be found was: ({debug_max_val*100:.1f}% confidence)")
return None
def find_window_via_winapi(self) -> Tuple[int, int]:
position = misc.find_d2r_window()
if position is None:
return None
offset_x, offset_y, _, _ = position
return offset_x, offset_y
def convert_monitor_to_screen(self, screen_coord: Tuple[float, float]) -> Tuple[float, float]:
return (screen_coord[0] - self._monitor_roi["left"], screen_coord[1] - self._monitor_roi["top"])