ok-script 0.0.67__tar.gz → 0.0.69__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ok-script-0.0.67 → ok-script-0.0.69}/PKG-INFO +1 -1
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/HwndWindow.py +69 -16
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/adb/DeviceManager.py +25 -14
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/feature/Box.py +10 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/feature/FeatureSet.py +18 -8
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/feature/FindFeature.py +5 -5
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/firebase/FireBaseAnalytics.py +82 -4
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/App.py +1 -1
- {ok-script-0.0.67/ok/capture/adb → ok-script-0.0.69/ok/gui}/StartController.py +2 -1
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/debug/DebugTab.py +24 -0
- ok-script-0.0.69/ok/gui/debug/FrameWidget.py +93 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/overlay/OverlayWindow.py +9 -4
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/resources.py +588 -517
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/OneTimeTaskTab.py +1 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/StartLoadingDialog.py +1 -1
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/ocr/OCR.py +27 -7
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/task/ExecutorOperation.py +6 -11
- {ok-script-0.0.67 → ok-script-0.0.69}/ok_script.egg-info/PKG-INFO +1 -1
- {ok-script-0.0.67 → ok-script-0.0.69}/ok_script.egg-info/SOURCES.txt +1 -1
- {ok-script-0.0.67 → ok-script-0.0.69}/setup.py +1 -1
- ok-script-0.0.67/ok/gui/debug/FrameWidget.py +0 -58
- {ok-script-0.0.67 → ok-script-0.0.69}/README.md +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/OK.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/alas/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/alas/emulator_base.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/alas/emulator_windows.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/alas/platform_base.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/alas/platform_windows.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/alas/utils.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/BaseCaptureMethod.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/adb/ADBCaptureMethod.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/adb/WindowsCaptureFactory.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/adb/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/adb/bin/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/image/ImageCaptureMethod.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/image/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/windows/BaseWindowsCaptureMethod.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/windows/BitBltCaptureMethod.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/windows/DesktopDuplicationCaptureMethod.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/windows/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/windows/d3d11.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/windows/dump.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/windows/utils.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/capture/windows/window.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/color/Color.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/color/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/config/Config.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/config/InfoDict.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/config/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/feature/Feature.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/feature/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/firebase/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/Communicate.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/MainWindow.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/MessageWindow.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/TabTitles.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/about/AboutTab.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/about/HttpTextEdit.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/about/VersionCard.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/about/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/common/OKIcon.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/common/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/common/config.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/common/style_sheet.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/debug/AspectRatioWidget.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/debug/InfoWidget.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/debug/LoggerWidget.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/debug/Screenshot.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/debug/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/i18n/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/i18n/path.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/i18n/update.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/icon/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/icon/icon.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/overlay/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/qss/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/settings/SettingTab.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/settings/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/start/SelectCaptureListView.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/start/StartCard.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/start/StartTab.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/start/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/ConfigItemFactory.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/LabelAndDropDown.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/LabelAndList.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/LabelAndWidget.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/ModifyListDialog.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/ModifyListItem.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/StartButton.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/TaskCard.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/TaskOpButton.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/TooltipTableWidget.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/TriggerTaskTab.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/tasks/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/util/Alert.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/util/InitWorker.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/util/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/Card.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/EmptyCard.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/FramelessDialog.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/ListTableWidgetItem.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/StatusBar.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/Tab.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/TabWidget.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/YesNonWidgetItem.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/gui/widget/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/interaction/ADBInteraction.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/interaction/BaseInteraction.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/interaction/DoNothingInteraction.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/interaction/Win32Interaction.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/interaction/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/logging/Logger.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/logging/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/ocr/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Media/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Security/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/Storage/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/Windows/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/delegate.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/export.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/idldsl.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/inspectable.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/roapi.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/types.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/rotypes/winstring.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/save/BlackBarProcessor.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/save/PostProcessor.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/save/SaveByInterval.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/save/SaveByKeyPress.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/save/SaveMethodBase.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/save/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/scene/FeatureScene.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/scene/Scene.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/scene/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/stats/StreamStats.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/stats/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/task/BaseTask.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/task/OneTimeTask.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/task/TaskExecutor.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/task/TriggerTask.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/task/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/update/GithubMultiDownloader.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/update/Updater.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/update/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/update/gen_md5.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/util/Handler.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/util/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/util/exit_event.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/util/json.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/util/list.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/util/path.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/util/thread.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/util/win32_process.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok/util/yaml.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok_script.egg-info/dependency_links.txt +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok_script.egg-info/requires.txt +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/ok_script.egg-info/top_level.txt +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/setup.cfg +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/tests/__init__.py +0 -0
- {ok-script-0.0.67 → ok-script-0.0.69}/tests/test_updater.py +0 -0
|
@@ -50,8 +50,7 @@ class HwndWindow:
|
|
|
50
50
|
self.title = title
|
|
51
51
|
self.stop_event = threading.Event()
|
|
52
52
|
self.visible = False
|
|
53
|
-
self.
|
|
54
|
-
self.do_update_window_size()
|
|
53
|
+
self.update_window(title, exe_name, frame_width, frame_height)
|
|
55
54
|
self.thread = threading.Thread(target=self.update_window_size, name="update_window_size")
|
|
56
55
|
self.thread.start()
|
|
57
56
|
|
|
@@ -68,14 +67,21 @@ class HwndWindow:
|
|
|
68
67
|
def stop(self):
|
|
69
68
|
self.stop_event.set()
|
|
70
69
|
|
|
70
|
+
def update_window(self, title, exe_name, frame_width, frame_height):
|
|
71
|
+
self.title = title
|
|
72
|
+
self.exe_name = exe_name
|
|
73
|
+
self.update_frame_size(frame_width, frame_height)
|
|
74
|
+
|
|
71
75
|
def update_frame_size(self, width, height):
|
|
72
76
|
logger.debug(f"update_frame_size:{self.frame_width}x{self.frame_height} to {width}x{height}")
|
|
73
77
|
if width != self.frame_width or height != self.frame_height:
|
|
78
|
+
self.hwnd = None
|
|
74
79
|
self.frame_width = width
|
|
75
80
|
self.frame_height = height
|
|
76
81
|
if width > 0 and height > 0:
|
|
77
82
|
self.frame_aspect_ratio = width / height
|
|
78
|
-
logger.debug(f"HwndWindow: frame ratio:
|
|
83
|
+
logger.debug(f"HwndWindow: frame ratio: width: {width}, height: {height}")
|
|
84
|
+
self.do_update_window_size()
|
|
79
85
|
|
|
80
86
|
def update_window_size(self):
|
|
81
87
|
while not self.app_exit_event.is_set() and not self.stop_event.is_set():
|
|
@@ -95,7 +101,7 @@ class HwndWindow:
|
|
|
95
101
|
name, self.hwnd, self.exe_full_path, self.real_x_offset, self.real_y_offset, self.real_width, self.real_height = find_hwnd(
|
|
96
102
|
self.title,
|
|
97
103
|
self.exe_name,
|
|
98
|
-
self.
|
|
104
|
+
self.frame_width, self.frame_height)
|
|
99
105
|
self.exists = self.hwnd is not None
|
|
100
106
|
if self.hwnd is not None:
|
|
101
107
|
self.exists = win32gui.IsWindow(self.hwnd)
|
|
@@ -147,10 +153,11 @@ class HwndWindow:
|
|
|
147
153
|
return f"title:{self.title}_{self.exe_name}_{self.width}x{self.height}_{self.hwnd}_{self.exists}_{self.visible}"
|
|
148
154
|
|
|
149
155
|
|
|
150
|
-
def find_hwnd(title, exe_name,
|
|
156
|
+
def find_hwnd(title, exe_name, frame_width, frame_height):
|
|
151
157
|
results = []
|
|
152
158
|
if exe_name is None and title is None:
|
|
153
159
|
return None, None, None, 0, 0, 0, 0
|
|
160
|
+
frame_aspect_ratio = frame_width / frame_height if frame_height != 0 else 0
|
|
154
161
|
|
|
155
162
|
def callback(hwnd, lParam):
|
|
156
163
|
if win32gui.IsWindowVisible(hwnd) and win32gui.IsWindowEnabled(hwnd):
|
|
@@ -173,7 +180,6 @@ def find_hwnd(title, exe_name, frame_aspect_ratio=0):
|
|
|
173
180
|
|
|
174
181
|
win32gui.EnumWindows(callback, None)
|
|
175
182
|
biggest = None
|
|
176
|
-
ratio_match = None
|
|
177
183
|
if len(results) > 0:
|
|
178
184
|
for result in results:
|
|
179
185
|
from ok.capture.windows.BitBltCaptureMethod import bit_blt_test_hwnd
|
|
@@ -189,17 +195,46 @@ def find_hwnd(title, exe_name, frame_aspect_ratio=0):
|
|
|
189
195
|
x_offset = 0
|
|
190
196
|
y_offset = 0
|
|
191
197
|
real_width, real_height = biggest[2], biggest[3]
|
|
192
|
-
if
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
real_height = ratio_match[3]
|
|
198
|
+
if biggest is not None and frame_aspect_ratio != 0:
|
|
199
|
+
matching_child = enum_child_windows(biggest, frame_aspect_ratio)
|
|
200
|
+
if matching_child is not None:
|
|
201
|
+
x_offset, y_offset, real_width, real_height = matching_child
|
|
197
202
|
logger.debug(f'find_hwnd {results} {biggest} {x_offset, y_offset, real_width, real_height}')
|
|
198
203
|
return biggest[6], biggest[0], biggest[1], x_offset, y_offset, real_width, real_height,
|
|
199
204
|
else:
|
|
200
205
|
return None, None, None, 0, 0, 0, 0
|
|
201
206
|
|
|
202
207
|
|
|
208
|
+
def enum_child_windows(biggest, frame_aspect_ratio):
|
|
209
|
+
ratio_match = []
|
|
210
|
+
"""
|
|
211
|
+
A function to enumerate all child windows of the given parent window handle
|
|
212
|
+
and print their handle and window title.
|
|
213
|
+
"""
|
|
214
|
+
|
|
215
|
+
def child_callback(hwnd, _):
|
|
216
|
+
visible = win32gui.IsWindowVisible(hwnd)
|
|
217
|
+
parent = win32gui.GetParent(hwnd)
|
|
218
|
+
rect = win32gui.GetWindowRect(hwnd)
|
|
219
|
+
logger.debug(f'find_hwnd child_callback {visible} {biggest[0]} {parent} {rect}')
|
|
220
|
+
if visible and parent == biggest[0]:
|
|
221
|
+
real_width = rect[2] - rect[0]
|
|
222
|
+
real_height = rect[3] - rect[1]
|
|
223
|
+
ratio = real_width / real_height
|
|
224
|
+
difference = abs(ratio - frame_aspect_ratio)
|
|
225
|
+
support = difference <= 0.01 * frame_aspect_ratio
|
|
226
|
+
percent = (real_width * real_height) / (biggest[2] * biggest[3])
|
|
227
|
+
if support and percent >= 0.7:
|
|
228
|
+
x_offset = rect[0] - biggest[4]
|
|
229
|
+
y_offset = rect[1] - biggest[5]
|
|
230
|
+
ratio_match.append((x_offset, y_offset, real_width, real_height))
|
|
231
|
+
return True
|
|
232
|
+
|
|
233
|
+
win32gui.EnumChildWindows(biggest[0], child_callback, None)
|
|
234
|
+
if len(ratio_match) > 0:
|
|
235
|
+
return ratio_match[0]
|
|
236
|
+
|
|
237
|
+
|
|
203
238
|
def get_exe_by_hwnd(hwnd):
|
|
204
239
|
# Get the process ID associated with the window
|
|
205
240
|
_, pid = win32process.GetWindowThreadProcessId(hwnd)
|
|
@@ -230,10 +265,28 @@ def enum_windows(emulator_path=None):
|
|
|
230
265
|
return windows
|
|
231
266
|
|
|
232
267
|
|
|
268
|
+
#
|
|
269
|
+
# def enum_child_windows(parent_handle):
|
|
270
|
+
# """
|
|
271
|
+
# A function to enumerate all child windows of the given parent window handle
|
|
272
|
+
# and print their handle and window title.
|
|
273
|
+
# """
|
|
274
|
+
#
|
|
275
|
+
# def callback(hwnd, _):
|
|
276
|
+
# if win32gui.IsWindowVisible(hwnd) and win32gui.GetParent(hwnd) == parent_handle:
|
|
277
|
+
# rect = win32gui.GetWindowRect(hwnd)
|
|
278
|
+
# width = rect[2] - rect[0]
|
|
279
|
+
# height = rect[3] - rect[1]
|
|
280
|
+
# print(f"Child HWND: {hwnd} - Window Text: {win32gui.GetWindowText(hwnd)} {rect} {width} {height}")
|
|
281
|
+
# return True
|
|
282
|
+
#
|
|
283
|
+
# win32gui.EnumChildWindows(parent_handle, callback, None)
|
|
284
|
+
|
|
285
|
+
|
|
233
286
|
if __name__ == '__main__':
|
|
234
287
|
print(find_hwnd("MuMu模拟器12", None))
|
|
235
|
-
hwnd_window = HwndWindow(threading.Event(), None, 'D:\\MuMuPlayer-12.0\\shell\\MuMuPlayer.exe', 16, 9)
|
|
236
|
-
from ok.capture.windows.BitBltCaptureMethod import BitBltCaptureMethod
|
|
237
|
-
|
|
238
|
-
method = BitBltCaptureMethod(hwnd_window)
|
|
239
|
-
method.get_frame()
|
|
288
|
+
# hwnd_window = HwndWindow(threading.Event(), None, 'D:\\MuMuPlayer-12.0\\shell\\MuMuPlayer.exe', 16, 9)
|
|
289
|
+
# from ok.capture.windows.BitBltCaptureMethod import BitBltCaptureMethod
|
|
290
|
+
#
|
|
291
|
+
# method = BitBltCaptureMethod(hwnd_window)
|
|
292
|
+
# method.get_frame()
|
|
@@ -25,6 +25,7 @@ class DeviceManager:
|
|
|
25
25
|
self.interaction = None
|
|
26
26
|
self.device_dict = {}
|
|
27
27
|
self.exit_event = exit_event
|
|
28
|
+
self.resolution_dict = {}
|
|
28
29
|
if windows_capture_config is not None:
|
|
29
30
|
self.hwnd = HwndWindow(exit_event, windows_capture_config.get('title'),
|
|
30
31
|
windows_capture_config.get('exe'))
|
|
@@ -73,7 +74,7 @@ class DeviceManager:
|
|
|
73
74
|
def update_pc_device(self):
|
|
74
75
|
if self.windows_capture_config is not None:
|
|
75
76
|
name, hwnd, full_path, x, y, width, height = find_hwnd(self.windows_capture_config.get('title'),
|
|
76
|
-
self.windows_capture_config.get('exe'))
|
|
77
|
+
self.windows_capture_config.get('exe'), 0, 0)
|
|
77
78
|
nick = name or self.windows_capture_config.get('exe')
|
|
78
79
|
pc_device = {"address": "", "imei": 'pc', "device": "windows",
|
|
79
80
|
"model": "", "nick": nick, "width": width,
|
|
@@ -98,7 +99,7 @@ class DeviceManager:
|
|
|
98
99
|
|
|
99
100
|
if self.exit_event.is_set():
|
|
100
101
|
return
|
|
101
|
-
self.
|
|
102
|
+
self.do_start()
|
|
102
103
|
|
|
103
104
|
logger.debug(f'refresh {self.device_dict}')
|
|
104
105
|
|
|
@@ -112,10 +113,11 @@ class DeviceManager:
|
|
|
112
113
|
found = True
|
|
113
114
|
break
|
|
114
115
|
if not found:
|
|
116
|
+
height, width = self.get_resolution(adb_device)
|
|
115
117
|
logger.debug(f'refresh_phones found an phone {adb_device}')
|
|
116
118
|
phone_device = {"address": adb_device.serial, "device": "adb", "connected": True, "imei": imei,
|
|
117
119
|
"nick": adb_device.prop.model or imei,
|
|
118
|
-
"resolution":
|
|
120
|
+
"resolution": f'{width}x{height}'}
|
|
119
121
|
self.device_dict[imei] = phone_device
|
|
120
122
|
|
|
121
123
|
def refresh_emulators(self):
|
|
@@ -124,8 +126,9 @@ class DeviceManager:
|
|
|
124
126
|
installed_emulators = manager.all_emulator_instances
|
|
125
127
|
for emulator in installed_emulators:
|
|
126
128
|
adb_device = self.adb_connect(emulator.serial)
|
|
129
|
+
width, height = self.get_resolution(adb_device)
|
|
127
130
|
name, hwnd, full_path, x, y, width, height = find_hwnd(None,
|
|
128
|
-
emulator.path)
|
|
131
|
+
emulator.path, width, height)
|
|
129
132
|
connected = adb_device is not None and name is not None
|
|
130
133
|
emulator_device = {"address": emulator.serial, "device": "adb",
|
|
131
134
|
"full_path": emulator.path, "connected": connected,
|
|
@@ -142,9 +145,12 @@ class DeviceManager:
|
|
|
142
145
|
device = self.device
|
|
143
146
|
width, height = 0, 0
|
|
144
147
|
if device is not None:
|
|
148
|
+
if resolution := self.resolution_dict.get(device.serial):
|
|
149
|
+
return resolution
|
|
145
150
|
frame = do_screencap(device)
|
|
146
151
|
if frame is not None:
|
|
147
152
|
height, width, _ = frame.shape
|
|
153
|
+
self.resolution_dict[device.serial] = (width, height)
|
|
148
154
|
return height, width
|
|
149
155
|
|
|
150
156
|
def set_preferred_device(self, imei=None, index=-1):
|
|
@@ -156,7 +162,12 @@ class DeviceManager:
|
|
|
156
162
|
preferred = self.device_dict.get(imei)
|
|
157
163
|
if preferred is None:
|
|
158
164
|
if len(self.device_dict) > 0:
|
|
159
|
-
|
|
165
|
+
connected_device = None
|
|
166
|
+
for device in self.device_dict.values():
|
|
167
|
+
if device.get('connected') or connected_device is None:
|
|
168
|
+
connected_device = device
|
|
169
|
+
logger.info(f'first start use first or connected device {connected_device}')
|
|
170
|
+
preferred = connected_device
|
|
160
171
|
imei = preferred['imei']
|
|
161
172
|
else:
|
|
162
173
|
logger.warning(f'no devices')
|
|
@@ -204,8 +215,7 @@ class DeviceManager:
|
|
|
204
215
|
if self.hwnd is None:
|
|
205
216
|
self.hwnd = HwndWindow(self.exit_event, title, exe, frame_width, frame_height)
|
|
206
217
|
else:
|
|
207
|
-
self.hwnd.
|
|
208
|
-
self.hwnd.update_title_and_exe(title, exe)
|
|
218
|
+
self.hwnd.update_window(title, exe, frame_width, frame_height)
|
|
209
219
|
|
|
210
220
|
def use_windows_capture(self, override_config=None, require_bg=False, use_bit_blt_only=False):
|
|
211
221
|
if not override_config:
|
|
@@ -238,13 +248,14 @@ class DeviceManager:
|
|
|
238
248
|
if self.config.get('capture') == "windows":
|
|
239
249
|
self.ensure_hwnd(None, preferred.get('full_path'), width, height)
|
|
240
250
|
self.use_windows_capture({'can_bit_blt': True}, require_bg=True, use_bit_blt_only=True)
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
self.capture_method
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
251
|
+
else:
|
|
252
|
+
if not isinstance(self.capture_method, ADBCaptureMethod):
|
|
253
|
+
logger.debug(f'use adb capture')
|
|
254
|
+
if self.capture_method is not None:
|
|
255
|
+
self.capture_method.close()
|
|
256
|
+
self.capture_method = ADBCaptureMethod(self, self.exit_event, width=width,
|
|
257
|
+
height=height)
|
|
258
|
+
if self.debug and preferred.get('full_path'):
|
|
248
259
|
self.ensure_hwnd(None, preferred.get('full_path'), width, height)
|
|
249
260
|
elif self.hwnd is not None:
|
|
250
261
|
self.hwnd.stop()
|
|
@@ -250,3 +250,13 @@ def boxes_to_map_by_list_of_names(boxes: list[Box], name_list: list[str]) -> dic
|
|
|
250
250
|
box_dict[box.name] = box
|
|
251
251
|
if len(box_dict) == len(name_list):
|
|
252
252
|
return box_dict
|
|
253
|
+
|
|
254
|
+
|
|
255
|
+
def relative_box(frame_width, frame_height, x, y, to_x=1, to_y=1, width=0, height=0, name=None):
|
|
256
|
+
if width == 0:
|
|
257
|
+
width = to_x - x
|
|
258
|
+
if height == 0:
|
|
259
|
+
height = to_y - y
|
|
260
|
+
return Box(int(x * frame_width), int(y * frame_height),
|
|
261
|
+
int(width * frame_width), int(height * frame_height),
|
|
262
|
+
name=name)
|
|
@@ -143,7 +143,8 @@ class FeatureSet:
|
|
|
143
143
|
return boxes[0]
|
|
144
144
|
|
|
145
145
|
def find_feature(self, mat: np.ndarray, category_name: str, horizontal_variance: float = 0,
|
|
146
|
-
vertical_variance: float = 0, threshold: float = 0, use_gray_scale: bool = False
|
|
146
|
+
vertical_variance: float = 0, threshold: float = 0, use_gray_scale: bool = False, x=-1, y=-1,
|
|
147
|
+
to_x=-1, to_y=-1, width=-1, height=-1) -> List[Box]:
|
|
147
148
|
"""
|
|
148
149
|
Find a feature within a given variance.
|
|
149
150
|
|
|
@@ -168,15 +169,24 @@ class FeatureSet:
|
|
|
168
169
|
vertical_variance = self.default_vertical_variance
|
|
169
170
|
if category_name not in self.feature_dict:
|
|
170
171
|
raise ValueError(f"FeatureSet: {category_name} not found in featureDict")
|
|
171
|
-
|
|
172
172
|
feature = self.feature_dict[category_name]
|
|
173
173
|
feature_width, feature_height = feature.width, feature.height
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
174
|
+
if x != -1 and y != -1:
|
|
175
|
+
frame_height, frame_width, *_ = mat.shape
|
|
176
|
+
if width == -1:
|
|
177
|
+
width = to_x - x
|
|
178
|
+
if height == -1:
|
|
179
|
+
height = to_y - y
|
|
180
|
+
search_x1 = int(x * frame_width)
|
|
181
|
+
search_y1 = int(y * frame_height)
|
|
182
|
+
search_x2 = int((x + width) * frame_width)
|
|
183
|
+
search_y2 = int((y + height) * frame_height)
|
|
184
|
+
else:
|
|
185
|
+
# Define search area using variance
|
|
186
|
+
search_x1 = max(0, int(feature.x - self.width * horizontal_variance))
|
|
187
|
+
search_y1 = max(0, int(feature.y - self.height * vertical_variance))
|
|
188
|
+
search_x2 = min(self.width, int(feature.x + feature_width + self.width * horizontal_variance))
|
|
189
|
+
search_y2 = min(self.height, int(feature.y + feature_height + self.height * vertical_variance))
|
|
180
190
|
|
|
181
191
|
search_area = mat[search_y1:search_y2, search_x1:search_x2, :3]
|
|
182
192
|
# Crop the search area from the image
|
|
@@ -11,11 +11,11 @@ class FindFeature:
|
|
|
11
11
|
self.executor = None
|
|
12
12
|
|
|
13
13
|
def find_feature(self, feature_name, horizontal_variance=0, vertical_variance=0, threshold=0,
|
|
14
|
-
use_gray_scale=False) -> List[Box]:
|
|
14
|
+
use_gray_scale=False, x=-1, y=-1, to_x=-1, to_y=-1, width=-1, height=-1) -> List[Box]:
|
|
15
15
|
if self.executor.frame is None:
|
|
16
16
|
return list()
|
|
17
17
|
return self.feature_set.find_feature(self.executor.frame, feature_name, horizontal_variance, vertical_variance,
|
|
18
|
-
threshold, use_gray_scale)
|
|
18
|
+
threshold, use_gray_scale, x, y, to_x, to_y, width, height)
|
|
19
19
|
|
|
20
20
|
def get_box_by_name(self, name):
|
|
21
21
|
return self.feature_set.get_box_by_name(name)
|
|
@@ -33,9 +33,9 @@ class FindFeature:
|
|
|
33
33
|
setattr(self, feature, result)
|
|
34
34
|
return ret
|
|
35
35
|
|
|
36
|
-
def
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
def wait_click_feature(self, feature, horizontal_variance=0, vertical_variance=0, threshold=0, relative_x=0.5,
|
|
37
|
+
relative_y=0.5,
|
|
38
|
+
time_out=0, pre_action=None, post_action=None):
|
|
39
39
|
box = self.wait_until(lambda: self.find_one(feature, horizontal_variance, vertical_variance, threshold),
|
|
40
40
|
time_out,
|
|
41
41
|
pre_action,
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import ctypes
|
|
1
2
|
import json
|
|
3
|
+
import locale
|
|
4
|
+
import random
|
|
5
|
+
import time
|
|
2
6
|
import uuid
|
|
7
|
+
from urllib.parse import urlencode
|
|
3
8
|
|
|
4
9
|
import requests
|
|
5
10
|
import wmi
|
|
@@ -10,6 +15,8 @@ from ok.util.Handler import Handler
|
|
|
10
15
|
|
|
11
16
|
FIREBASE_ENDPOINT = 'https://www.google-analytics.com/mp/collect'
|
|
12
17
|
|
|
18
|
+
GTAG_ENDPOINT = "https://www.google-analytics.com/g/collect"
|
|
19
|
+
|
|
13
20
|
logger = get_logger(__name__)
|
|
14
21
|
|
|
15
22
|
|
|
@@ -20,8 +27,9 @@ class FireBaseAnalytics:
|
|
|
20
27
|
self.app_config = app_config
|
|
21
28
|
self._config = None
|
|
22
29
|
self._handler = Handler(exit_event, __name__)
|
|
23
|
-
self._handler.post(self.
|
|
30
|
+
self._handler.post(self.send_gtag, 0)
|
|
24
31
|
self._user_properties = None
|
|
32
|
+
self._fv = 1
|
|
25
33
|
|
|
26
34
|
@property
|
|
27
35
|
def user_properties(self):
|
|
@@ -64,8 +72,10 @@ class FireBaseAnalytics:
|
|
|
64
72
|
}
|
|
65
73
|
return self._user_properties
|
|
66
74
|
|
|
67
|
-
|
|
68
|
-
|
|
75
|
+
#
|
|
76
|
+
# def report_open(self):
|
|
77
|
+
# self._handler.post(self.send_gtag, 5)
|
|
78
|
+
# # self.send_event('app_open', {'version': self.app_config.get('version'), 'debug': self.app_config.get('debug')})
|
|
69
79
|
|
|
70
80
|
@property
|
|
71
81
|
def client_id(self):
|
|
@@ -73,8 +83,66 @@ class FireBaseAnalytics:
|
|
|
73
83
|
self._config = Config({'client_id': ''}, self.app_config.get("config_folder") or "config", 'statistics')
|
|
74
84
|
if not self._config.get('client_id'):
|
|
75
85
|
self._config['client_id'] = get_unique_client_id()
|
|
86
|
+
else:
|
|
87
|
+
self._fv = 0
|
|
76
88
|
return self._config.get('client_id')
|
|
77
89
|
|
|
90
|
+
def send_gtag(self):
|
|
91
|
+
# Define the parameters in a dictionary
|
|
92
|
+
params = {
|
|
93
|
+
'v': '2',
|
|
94
|
+
'tid': self.measurement_id,
|
|
95
|
+
'gtm': '45je4630v9186643593za200',
|
|
96
|
+
'_p': random_number(),
|
|
97
|
+
# 'gcd': '13l3l3l3l1',
|
|
98
|
+
'npa': '0',
|
|
99
|
+
'dma': '0',
|
|
100
|
+
'tag_exp': '0',
|
|
101
|
+
'cid': self.client_id,
|
|
102
|
+
'ul': locale.getdefaultlocale()[0],
|
|
103
|
+
'sr': get_screen_resolution(),
|
|
104
|
+
'uaa': 'x86',
|
|
105
|
+
'uab': '64',
|
|
106
|
+
# 'uafvl': 'Microsoft Edge;125.0.2535.85|Chromium;125.0.6422.142|Not.A/Brand;24.0.0.0',
|
|
107
|
+
'uamb': '0',
|
|
108
|
+
'uam': '',
|
|
109
|
+
'uap': 'Windows',
|
|
110
|
+
'uapv': '15.0.0',
|
|
111
|
+
'uaw': '0',
|
|
112
|
+
'are': '1',
|
|
113
|
+
'frm': '0',
|
|
114
|
+
'pscdl': 'noapi',
|
|
115
|
+
'_s': '1',
|
|
116
|
+
'sid': int(time.time()),
|
|
117
|
+
'sct': '1',
|
|
118
|
+
'seg': '1',
|
|
119
|
+
'dl': 'https://ok-script.com/',
|
|
120
|
+
'dt': 'AppStartGTAG2',
|
|
121
|
+
'en': 'page_view',
|
|
122
|
+
'_ee': '1',
|
|
123
|
+
'ep.version': self.app_config.get('version')
|
|
124
|
+
# 'tfd': '5133'
|
|
125
|
+
}
|
|
126
|
+
if self._fv:
|
|
127
|
+
params['_fv'] = self._fv
|
|
128
|
+
|
|
129
|
+
# Send the GET request
|
|
130
|
+
|
|
131
|
+
headers = {
|
|
132
|
+
'Content-Type': 'application/json',
|
|
133
|
+
'Origin': 'https://ok-script.com',
|
|
134
|
+
'Referer': 'https://ok-script.com/'
|
|
135
|
+
}
|
|
136
|
+
query_string = urlencode(params)
|
|
137
|
+
|
|
138
|
+
response = requests.post(f'{GTAG_ENDPOINT}', data=params)
|
|
139
|
+
|
|
140
|
+
logger.debug(f'send gtag {GTAG_ENDPOINT}?{query_string}')
|
|
141
|
+
if response.status_code == 204:
|
|
142
|
+
logger.debug(f'Successfully sent gtag')
|
|
143
|
+
else:
|
|
144
|
+
logger.debug(f'Failed to send event: {response.status_code} - {response.text}')
|
|
145
|
+
|
|
78
146
|
def send_event(self, event_name, params=None):
|
|
79
147
|
if params is None:
|
|
80
148
|
params = dict()
|
|
@@ -107,7 +175,17 @@ class FireBaseAnalytics:
|
|
|
107
175
|
|
|
108
176
|
|
|
109
177
|
def get_unique_client_id():
|
|
110
|
-
return
|
|
178
|
+
return f'{random_number()}.{random_number()}'
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def random_number():
|
|
182
|
+
return random.randint(0, 2147483647)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def get_screen_resolution():
|
|
186
|
+
user32 = ctypes.windll.user32
|
|
187
|
+
screensize = user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)
|
|
188
|
+
return f"{screensize[0]}x{screensize[1]}"
|
|
111
189
|
|
|
112
190
|
|
|
113
191
|
if __name__ == '__main__':
|
|
@@ -8,11 +8,11 @@ from qfluentwidgets import FluentTranslator, qconfig, Theme
|
|
|
8
8
|
|
|
9
9
|
import ok
|
|
10
10
|
import ok.gui.resources
|
|
11
|
-
from ok.capture.adb.StartController import StartController
|
|
12
11
|
from ok.firebase.FireBaseAnalytics import FireBaseAnalytics
|
|
13
12
|
from ok.gui.Communicate import communicate
|
|
14
13
|
from ok.gui.MainWindow import MainWindow
|
|
15
14
|
from ok.gui.MessageWindow import MessageWindow
|
|
15
|
+
from ok.gui.StartController import StartController
|
|
16
16
|
from ok.gui.i18n.path import i18n_path
|
|
17
17
|
from ok.gui.overlay.OverlayWindow import OverlayWindow
|
|
18
18
|
from ok.logging.Logger import get_logger
|
|
@@ -26,7 +26,7 @@ class StartController(QObject):
|
|
|
26
26
|
|
|
27
27
|
def do_start(self, task=None):
|
|
28
28
|
communicate.starting_emulator.emit(False, None, 30)
|
|
29
|
-
self.device_manager.do_refresh(
|
|
29
|
+
self.device_manager.do_refresh()
|
|
30
30
|
|
|
31
31
|
device = self.device_manager.get_preferred_device()
|
|
32
32
|
|
|
@@ -37,6 +37,7 @@ class StartController(QObject):
|
|
|
37
37
|
execute(path)
|
|
38
38
|
wait_until = time.time() + 30
|
|
39
39
|
while not self.exit_event.is_set():
|
|
40
|
+
self.device_manager.do_refresh()
|
|
40
41
|
error = self.check_device_error()
|
|
41
42
|
if error is None:
|
|
42
43
|
break
|
|
@@ -12,6 +12,7 @@ from ok.gui.util.Alert import alert_info, alert_error
|
|
|
12
12
|
from ok.gui.widget.Tab import Tab
|
|
13
13
|
from ok.interaction.DoNothingInteraction import DoNothingInteraction
|
|
14
14
|
from ok.logging.Logger import get_logger, exception_to_str
|
|
15
|
+
from ok.ocr.OCR import OCR
|
|
15
16
|
from ok.util.Handler import Handler
|
|
16
17
|
|
|
17
18
|
logger = get_logger(__name__)
|
|
@@ -44,6 +45,10 @@ class DebugTab(Tab):
|
|
|
44
45
|
capture_button.clicked.connect(lambda: self.handler.post(self.capture))
|
|
45
46
|
layout.addWidget(capture_button)
|
|
46
47
|
|
|
48
|
+
ocr_button = PushButton("OCR")
|
|
49
|
+
ocr_button.clicked.connect(lambda: self.handler.post(self.ocr))
|
|
50
|
+
layout.addWidget(ocr_button)
|
|
51
|
+
|
|
47
52
|
open_log_folder = PushButton(self.tr("Open Logs"))
|
|
48
53
|
|
|
49
54
|
call_task_widget = QWidget()
|
|
@@ -116,6 +121,25 @@ class DebugTab(Tab):
|
|
|
116
121
|
self.config['target_function'] = func_name
|
|
117
122
|
alert_info(self.tr(f"call success: {result}"))
|
|
118
123
|
|
|
124
|
+
def ocr(self):
|
|
125
|
+
if not ok.gui.executor.ocr:
|
|
126
|
+
alert_error(self.tr('No OCR configured'))
|
|
127
|
+
return
|
|
128
|
+
if ok.gui.device_manager.capture_method is not None:
|
|
129
|
+
logger.info(f'ok.gui.device_manager.capture_method {ok.gui.device_manager.capture_method}')
|
|
130
|
+
capture = str(ok.gui.device_manager.capture_method)
|
|
131
|
+
frame = ok.gui.device_manager.capture_method.do_get_frame()
|
|
132
|
+
if frame is not None:
|
|
133
|
+
ocr = OCR()
|
|
134
|
+
ocr.executor = ok.gui.executor
|
|
135
|
+
result = ocr.ocr(frame=frame)
|
|
136
|
+
self.update_result_text.emit(str(result))
|
|
137
|
+
alert_info(self.tr(f"OCR success: {result}"))
|
|
138
|
+
else:
|
|
139
|
+
alert_error(self.tr('Capture returned None'))
|
|
140
|
+
else:
|
|
141
|
+
alert_error(self.tr('No Capture Available or Selected'))
|
|
142
|
+
|
|
119
143
|
def task_changed(self, text):
|
|
120
144
|
self.config['target_task'] = text
|
|
121
145
|
task = ok.gui.executor.get_task_by_class_name(text)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import win32api
|
|
4
|
+
from PySide6.QtCore import Qt, QPoint, QTimer
|
|
5
|
+
from PySide6.QtGui import QPainter, QColor, QPen, QFont, QGuiApplication
|
|
6
|
+
from PySide6.QtWidgets import QWidget
|
|
7
|
+
|
|
8
|
+
import ok.gui
|
|
9
|
+
from ok.gui.Communicate import communicate
|
|
10
|
+
from ok.logging.Logger import get_logger
|
|
11
|
+
|
|
12
|
+
logger = get_logger(__name__)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class FrameWidget(QWidget):
|
|
16
|
+
def __init__(self):
|
|
17
|
+
super(FrameWidget, self).__init__()
|
|
18
|
+
self._visible = True
|
|
19
|
+
self._mouse_position = QPoint(0, 0)
|
|
20
|
+
self.setMouseTracking(True)
|
|
21
|
+
communicate.update_overlay.connect(self.update)
|
|
22
|
+
# Start a timer to update mouse position using Windows API
|
|
23
|
+
self.timer = QTimer(self)
|
|
24
|
+
self.timer.timeout.connect(self.update_mouse_position)
|
|
25
|
+
self.timer.start(1000) # Update every 50 milliseconds
|
|
26
|
+
self.mouse_font = QFont()
|
|
27
|
+
self.mouse_font.setPointSize(10) # Adjust the size as needed
|
|
28
|
+
screen = QGuiApplication.primaryScreen()
|
|
29
|
+
self.scaling = screen.devicePixelRatio()
|
|
30
|
+
communicate.update_overlay.connect(self.update)
|
|
31
|
+
|
|
32
|
+
def update_mouse_position(self):
|
|
33
|
+
try:
|
|
34
|
+
x, y = win32api.GetCursorPos()
|
|
35
|
+
relative = self.mapFromGlobal(QPoint(x / self.scaling, y / self.scaling))
|
|
36
|
+
if self._mouse_position != relative and relative.x() > 0 and relative.y() > 0 and self._visible:
|
|
37
|
+
self._mouse_position = relative
|
|
38
|
+
self.update()
|
|
39
|
+
except Exception as e:
|
|
40
|
+
logger.warning(f'GetCursorPos exception {e}')
|
|
41
|
+
|
|
42
|
+
def frame_ratio(self):
|
|
43
|
+
if ok.gui.device_manager.width == 0:
|
|
44
|
+
return 1
|
|
45
|
+
return self.width() / ok.gui.device_manager.width
|
|
46
|
+
|
|
47
|
+
def paintEvent(self, event):
|
|
48
|
+
if not self._visible:
|
|
49
|
+
return
|
|
50
|
+
painter = QPainter(self)
|
|
51
|
+
self.paint_border(painter)
|
|
52
|
+
self.paint_boxes(painter)
|
|
53
|
+
self.paint_mouse_position(painter)
|
|
54
|
+
|
|
55
|
+
def paint_boxes(self, painter):
|
|
56
|
+
pen = QPen() # Set the brush to red color
|
|
57
|
+
pen.setWidth(2) # Set the width of the pen (border thickness)
|
|
58
|
+
painter.setPen(pen) # Apply the pen to the painter
|
|
59
|
+
painter.setBrush(Qt.NoBrush) # Ensure no fill
|
|
60
|
+
|
|
61
|
+
frame_ratio = self.frame_ratio()
|
|
62
|
+
for key, value in ok.gui.ok.screenshot.ui_dict.items():
|
|
63
|
+
boxes = value[0]
|
|
64
|
+
pen.setColor(value[2])
|
|
65
|
+
painter.setPen(pen)
|
|
66
|
+
for box in boxes:
|
|
67
|
+
width = box.width * frame_ratio
|
|
68
|
+
height = box.height * frame_ratio
|
|
69
|
+
x = box.x * frame_ratio
|
|
70
|
+
y = box.y * frame_ratio
|
|
71
|
+
painter.drawRect(x, y, width, height)
|
|
72
|
+
painter.drawText(x, y + height + 12, f"{box.name or key}_{round(box.confidence * 100)}")
|
|
73
|
+
|
|
74
|
+
def paint_border(self, painter):
|
|
75
|
+
pen = QPen(QColor(255, 0, 0, 255)) # Solid red color for the border
|
|
76
|
+
pen.setWidth(1) # Set the border width
|
|
77
|
+
painter.setPen(pen)
|
|
78
|
+
# Draw the border around the widget
|
|
79
|
+
painter.drawRect(0, 0, self.width() - 1, self.height() - 1)
|
|
80
|
+
|
|
81
|
+
def paint_mouse_position(self, painter):
|
|
82
|
+
x_percent = self._mouse_position.x() / self.width()
|
|
83
|
+
y_percent = self._mouse_position.y() / self.height()
|
|
84
|
+
x, y = self._mouse_position.x() * 2, self._mouse_position.y() * 2
|
|
85
|
+
text = f"({x}, {y}, {x_percent:.2f}, {y_percent:.2f})"
|
|
86
|
+
painter.setFont(self.mouse_font)
|
|
87
|
+
|
|
88
|
+
painter.setPen(QPen(QColor(255, 0, 0, 255), 1))
|
|
89
|
+
painter.drawText(20, 20, text)
|
|
90
|
+
#
|
|
91
|
+
# # Draw the black text
|
|
92
|
+
# painter.setPen(QPen(QColor(0, 0, 0), 2))
|
|
93
|
+
# painter.drawText(10, 10, text)
|