ok-script 0.0.96__tar.gz → 0.0.98__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.
Files changed (183) hide show
  1. {ok-script-0.0.96 → ok-script-0.0.98}/PKG-INFO +1 -1
  2. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/HwndWindow.py +10 -6
  3. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/adb/ADBCaptureMethod.py +1 -18
  4. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/adb/DeviceManager.py +82 -27
  5. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +6 -4
  6. {ok-script-0.0.96 → ok-script-0.0.98}/ok/color/Color.py +6 -1
  7. {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/Box.py +3 -0
  8. {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/FeatureSet.py +2 -2
  9. {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/FindFeature.py +16 -5
  10. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/App.py +0 -7
  11. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/DebugTab.py +30 -2
  12. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/LogWindow.py +11 -9
  13. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/OneTimeTaskTab.py +1 -1
  14. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/TaskCard.py +6 -6
  15. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/TriggerTaskTab.py +1 -1
  16. {ok-script-0.0.96 → ok-script-0.0.98}/ok/interaction/Win32Interaction.py +1 -1
  17. {ok-script-0.0.96 → ok-script-0.0.98}/ok/ocr/OCR.py +2 -2
  18. {ok-script-0.0.96 → ok-script-0.0.98}/ok/task/ExecutorOperation.py +6 -5
  19. {ok-script-0.0.96 → ok-script-0.0.98}/ok/task/TaskExecutor.py +24 -7
  20. {ok-script-0.0.96 → ok-script-0.0.98}/ok_script.egg-info/PKG-INFO +1 -1
  21. {ok-script-0.0.96 → ok-script-0.0.98}/setup.py +1 -1
  22. {ok-script-0.0.96 → ok-script-0.0.98}/README.md +0 -0
  23. {ok-script-0.0.96 → ok-script-0.0.98}/ok/OK.py +0 -0
  24. {ok-script-0.0.96 → ok-script-0.0.98}/ok/__init__.py +0 -0
  25. {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/__init__.py +0 -0
  26. {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/emulator_base.py +0 -0
  27. {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/emulator_windows.py +0 -0
  28. {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/platform_base.py +0 -0
  29. {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/platform_windows.py +0 -0
  30. {ok-script-0.0.96 → ok-script-0.0.98}/ok/alas/utils.py +0 -0
  31. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/BaseCaptureMethod.py +0 -0
  32. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/__init__.py +0 -0
  33. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/adb/WindowsCaptureFactory.py +0 -0
  34. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/adb/__init__.py +0 -0
  35. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/adb/bin/__init__.py +0 -0
  36. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/image/ImageCaptureMethod.py +0 -0
  37. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/image/__init__.py +0 -0
  38. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/BaseWindowsCaptureMethod.py +0 -0
  39. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/BitBltCaptureMethod.py +0 -0
  40. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/DesktopDuplicationCaptureMethod.py +0 -0
  41. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/__init__.py +0 -0
  42. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/d3d11.py +0 -0
  43. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/dump.py +0 -0
  44. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/utils.py +0 -0
  45. {ok-script-0.0.96 → ok-script-0.0.98}/ok/capture/windows/window.py +0 -0
  46. {ok-script-0.0.96 → ok-script-0.0.98}/ok/color/__init__.py +0 -0
  47. {ok-script-0.0.96 → ok-script-0.0.98}/ok/config/Config.py +0 -0
  48. {ok-script-0.0.96 → ok-script-0.0.98}/ok/config/InfoDict.py +0 -0
  49. {ok-script-0.0.96 → ok-script-0.0.98}/ok/config/__init__.py +0 -0
  50. {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/CompressCoco.py +0 -0
  51. {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/Feature.py +0 -0
  52. {ok-script-0.0.96 → ok-script-0.0.98}/ok/feature/__init__.py +0 -0
  53. {ok-script-0.0.96 → ok-script-0.0.98}/ok/firebase/Analytics.py +0 -0
  54. {ok-script-0.0.96 → ok-script-0.0.98}/ok/firebase/__init__.py +0 -0
  55. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/Communicate.py +0 -0
  56. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/MainWindow.py +0 -0
  57. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/MessageWindow.py +0 -0
  58. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/StartController.py +0 -0
  59. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/TabTitles.py +0 -0
  60. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/__init__.py +0 -0
  61. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/about/AboutTab.py +0 -0
  62. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/about/HttpTextEdit.py +0 -0
  63. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/about/VersionCard.py +0 -0
  64. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/about/__init__.py +0 -0
  65. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/common/OKIcon.py +0 -0
  66. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/common/__init__.py +0 -0
  67. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/common/config.py +0 -0
  68. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/common/style_sheet.py +0 -0
  69. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/AspectRatioWidget.py +0 -0
  70. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/FrameWidget.py +0 -0
  71. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/InfoWidget.py +0 -0
  72. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/Screenshot.py +0 -0
  73. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/debug/__init__.py +0 -0
  74. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/i18n/__init__.py +0 -0
  75. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/i18n/path.py +0 -0
  76. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/i18n/update.py +0 -0
  77. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/icon/__init__.py +0 -0
  78. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/icon/icon.py +0 -0
  79. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/overlay/OverlayWindow.py +0 -0
  80. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/overlay/__init__.py +0 -0
  81. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/qss/__init__.py +0 -0
  82. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/resources.py +0 -0
  83. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/settings/SettingTab.py +0 -0
  84. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/settings/__init__.py +0 -0
  85. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/start/SelectCaptureListView.py +0 -0
  86. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/start/StartCard.py +0 -0
  87. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/start/StartTab.py +0 -0
  88. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/start/__init__.py +0 -0
  89. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/ConfigItemFactory.py +0 -0
  90. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
  91. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
  92. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndDropDown.py +0 -0
  93. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
  94. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndList.py +0 -0
  95. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
  96. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
  97. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/LabelAndWidget.py +0 -0
  98. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/ModifyListDialog.py +0 -0
  99. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/ModifyListItem.py +0 -0
  100. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/StartButton.py +0 -0
  101. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/TaskOpButton.py +0 -0
  102. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/TaskTab.py +0 -0
  103. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/TooltipTableWidget.py +0 -0
  104. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/tasks/__init__.py +0 -0
  105. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/util/Alert.py +0 -0
  106. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/util/InitWorker.py +0 -0
  107. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/util/__init__.py +0 -0
  108. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/Card.py +0 -0
  109. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/EmptyCard.py +0 -0
  110. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/FramelessDialog.py +0 -0
  111. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/ListTableWidgetItem.py +0 -0
  112. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
  113. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/StartLoadingDialog.py +0 -0
  114. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/StatusBar.py +0 -0
  115. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/Tab.py +0 -0
  116. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/TabWidget.py +0 -0
  117. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
  118. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/YesNonWidgetItem.py +0 -0
  119. {ok-script-0.0.96 → ok-script-0.0.98}/ok/gui/widget/__init__.py +0 -0
  120. {ok-script-0.0.96 → ok-script-0.0.98}/ok/interaction/ADBInteraction.py +0 -0
  121. {ok-script-0.0.96 → ok-script-0.0.98}/ok/interaction/BaseInteraction.py +0 -0
  122. {ok-script-0.0.96 → ok-script-0.0.98}/ok/interaction/DoNothingInteraction.py +0 -0
  123. {ok-script-0.0.96 → ok-script-0.0.98}/ok/interaction/__init__.py +0 -0
  124. {ok-script-0.0.96 → ok-script-0.0.98}/ok/logging/Logger.py +0 -0
  125. {ok-script-0.0.96 → ok-script-0.0.98}/ok/logging/__init__.py +0 -0
  126. {ok-script-0.0.96 → ok-script-0.0.98}/ok/ocr/__init__.py +0 -0
  127. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
  128. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
  129. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
  130. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
  131. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
  132. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
  133. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
  134. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
  135. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
  136. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Media/__init__.py +0 -0
  137. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
  138. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Security/__init__.py +0 -0
  139. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
  140. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/Storage/__init__.py +0 -0
  141. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/Windows/__init__.py +0 -0
  142. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/__init__.py +0 -0
  143. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/delegate.py +0 -0
  144. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/export.py +0 -0
  145. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/idldsl.py +0 -0
  146. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/inspectable.py +0 -0
  147. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/roapi.py +0 -0
  148. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/types.py +0 -0
  149. {ok-script-0.0.96 → ok-script-0.0.98}/ok/rotypes/winstring.py +0 -0
  150. {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/BlackBarProcessor.py +0 -0
  151. {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/PostProcessor.py +0 -0
  152. {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/SaveByInterval.py +0 -0
  153. {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/SaveByKeyPress.py +0 -0
  154. {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/SaveMethodBase.py +0 -0
  155. {ok-script-0.0.96 → ok-script-0.0.98}/ok/save/__init__.py +0 -0
  156. {ok-script-0.0.96 → ok-script-0.0.98}/ok/scene/FeatureScene.py +0 -0
  157. {ok-script-0.0.96 → ok-script-0.0.98}/ok/scene/Scene.py +0 -0
  158. {ok-script-0.0.96 → ok-script-0.0.98}/ok/scene/__init__.py +0 -0
  159. {ok-script-0.0.96 → ok-script-0.0.98}/ok/stats/StreamStats.py +0 -0
  160. {ok-script-0.0.96 → ok-script-0.0.98}/ok/stats/__init__.py +0 -0
  161. {ok-script-0.0.96 → ok-script-0.0.98}/ok/task/BaseTask.py +0 -0
  162. {ok-script-0.0.96 → ok-script-0.0.98}/ok/task/TriggerTask.py +0 -0
  163. {ok-script-0.0.96 → ok-script-0.0.98}/ok/task/__init__.py +0 -0
  164. {ok-script-0.0.96 → ok-script-0.0.98}/ok/update/GithubMultiDownloader.py +0 -0
  165. {ok-script-0.0.96 → ok-script-0.0.98}/ok/update/Updater.py +0 -0
  166. {ok-script-0.0.96 → ok-script-0.0.98}/ok/update/__init__.py +0 -0
  167. {ok-script-0.0.96 → ok-script-0.0.98}/ok/update/gen_md5.py +0 -0
  168. {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/Handler.py +0 -0
  169. {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/__init__.py +0 -0
  170. {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/exit_event.py +0 -0
  171. {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/json.py +0 -0
  172. {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/list.py +0 -0
  173. {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/path.py +0 -0
  174. {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/thread.py +0 -0
  175. {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/win32_process.py +0 -0
  176. {ok-script-0.0.96 → ok-script-0.0.98}/ok/util/yaml.py +0 -0
  177. {ok-script-0.0.96 → ok-script-0.0.98}/ok_script.egg-info/SOURCES.txt +0 -0
  178. {ok-script-0.0.96 → ok-script-0.0.98}/ok_script.egg-info/dependency_links.txt +0 -0
  179. {ok-script-0.0.96 → ok-script-0.0.98}/ok_script.egg-info/requires.txt +0 -0
  180. {ok-script-0.0.96 → ok-script-0.0.98}/ok_script.egg-info/top_level.txt +0 -0
  181. {ok-script-0.0.96 → ok-script-0.0.98}/setup.cfg +0 -0
  182. {ok-script-0.0.96 → ok-script-0.0.98}/tests/__init__.py +0 -0
  183. {ok-script-0.0.96 → ok-script-0.0.98}/tests/test_updater.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ok-script
3
- Version: 0.0.96
3
+ Version: 0.0.98
4
4
  Summary: Automation with Computer Vision for Python
5
5
  Home-page: https://github.com/ok-oldking/ok-script
6
6
  Author: ok-oldking
@@ -243,13 +243,17 @@ def enum_child_windows(biggest, frame_aspect_ratio):
243
243
 
244
244
  def get_exe_by_hwnd(hwnd):
245
245
  # Get the process ID associated with the window
246
- _, pid = win32process.GetWindowThreadProcessId(hwnd)
246
+ try:
247
+ _, pid = win32process.GetWindowThreadProcessId(hwnd)
247
248
 
248
- # Get the process name and executable path
249
- if pid > 0:
250
- process = psutil.Process(pid)
251
- return process.name(), process.exe(), process.cmdline()
252
- else:
249
+ # Get the process name and executable path
250
+ if pid > 0:
251
+ process = psutil.Process(pid)
252
+ return process.name(), process.exe(), process.cmdline()
253
+ else:
254
+ return None, None, None
255
+ except Exception as e:
256
+ logger.error('get_exe_by_hwnd error', e)
253
257
  return None, None, None
254
258
 
255
259
 
@@ -1,5 +1,4 @@
1
1
  # original https://github.com/Toufool/AutoSplit/blob/master/src/capture_method/WindowsGraphicsCaptureMethod.py
2
- import cv2
3
2
  import numpy as np
4
3
  from typing_extensions import override
5
4
 
@@ -26,7 +25,7 @@ class ADBCaptureMethod(BaseCaptureMethod):
26
25
  def screencap(self):
27
26
  if self.exit_event.is_set():
28
27
  return None
29
- frame = do_screencap(self.device_manager.device)
28
+ frame = self.device_manager.do_screencap(self.device_manager.device)
30
29
  if frame is not None:
31
30
  self._connected = True
32
31
  else:
@@ -37,19 +36,3 @@ class ADBCaptureMethod(BaseCaptureMethod):
37
36
  if not self._connected and self.device_manager.device is not None:
38
37
  self.screencap()
39
38
  return self._connected and self.device_manager.device is not None
40
-
41
-
42
- def do_screencap(device) -> np.ndarray | None:
43
- if device is None:
44
- return None
45
- try:
46
- png_bytes = device.shell("screencap -p", encoding=None)
47
- if png_bytes is not None and len(png_bytes) > 0:
48
- image_data = np.frombuffer(png_bytes, dtype=np.uint8)
49
- image = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
50
- if image is not None:
51
- return image
52
- else:
53
- logger.error(f"Screencap image decode error, probably disconnected")
54
- except Exception as e:
55
- logger.error('screencap', e)
@@ -1,8 +1,13 @@
1
- from adbutils import AdbTimeout, AdbError
1
+ import os
2
+ import threading
3
+
4
+ import cv2
5
+ import numpy as np
6
+ from adbutils import AdbError
2
7
 
3
8
  from ok.alas.platform_windows import get_emulator_exe
4
9
  from ok.capture.HwndWindow import HwndWindow, find_hwnd
5
- from ok.capture.adb.ADBCaptureMethod import ADBCaptureMethod, do_screencap
10
+ from ok.capture.adb.ADBCaptureMethod import ADBCaptureMethod
6
11
  from ok.capture.adb.WindowsCaptureFactory import update_capture_method
7
12
  from ok.config.Config import Config
8
13
  from ok.gui.Communicate import communicate
@@ -19,6 +24,7 @@ class DeviceManager:
19
24
  def __init__(self, app_config, exit_event=None):
20
25
  self._device = None
21
26
  self._adb = None
27
+ self._adb_lock = threading.Lock()
22
28
  supported_resolution = app_config.get(
23
29
  'supported_resolution', {})
24
30
  self.supported_ratio = parse_ratio(supported_resolution.get('ratio'))
@@ -47,11 +53,39 @@ class DeviceManager:
47
53
 
48
54
  @property
49
55
  def adb(self):
50
- if self._adb is None:
51
- import adbutils
52
- self._adb = adbutils.AdbClient(host="127.0.0.1")
53
- logger.debug(f'connect adb')
54
- return self._adb
56
+ with self._adb_lock:
57
+ if self._adb is None:
58
+ import adbutils
59
+ logger.debug(f'init adb')
60
+ from adbutils._utils import _get_bin_dir
61
+ bin_dir = _get_bin_dir()
62
+ exe = os.path.join(bin_dir, "adb.exe" if os.name == 'nt' else 'adb')
63
+ from adbutils._utils import _is_valid_exe
64
+ if os.path.isfile(exe) and _is_valid_exe(exe):
65
+ os.environ['ADBUTILS_ADB_PATH'] = exe
66
+ logger.info(f'set ADBUTILS_ADB_PATH {os.getenv("ADBUTILS_ADB_PATH")}')
67
+ else:
68
+ logger.error(f'set ADBUTILS_ADB_PATH failed {exe}')
69
+ self._adb = adbutils.AdbClient(host="127.0.0.1", socket_timeout=4)
70
+ try:
71
+ self._adb.device_list()
72
+ except AdbError as e:
73
+ self.try_kill_adb(e)
74
+ return self._adb
75
+
76
+ def try_kill_adb(self, e=None):
77
+ logger.error('try kill adb server', e)
78
+ import psutil
79
+ for proc in psutil.process_iter():
80
+ # Check whether the process name matches
81
+ if proc.name() == 'adb.exe' or proc.name() == 'adb':
82
+ logger.info(f'kill adb by process name {proc.cmdline()}')
83
+ try:
84
+ proc.kill()
85
+ except Exception as e:
86
+ logger.error(f'kill adb server failed', e)
87
+ logger.info('try kill adb end')
88
+ # self._adb.server_kill()
55
89
 
56
90
  def adb_connect(self, addr, try_connect=True):
57
91
  try:
@@ -67,11 +101,12 @@ class DeviceManager:
67
101
  logger.debug(f'adb_connect already connected {addr}')
68
102
  return device
69
103
  if try_connect:
70
- self.adb.connect(addr, timeout=3)
104
+ self.adb.connect(addr, timeout=5)
71
105
  logger.debug(f'adb_connect {addr}')
72
106
  return self.adb_connect(addr, try_connect=False)
73
- except AdbTimeout as e:
74
- logger.error(f"adb connect error try kill server {addr}", e)
107
+ except AdbError as e:
108
+ logger.error(f"adb connect error {addr}", e)
109
+ self.try_kill_adb(e)
75
110
  except Exception as e:
76
111
  logger.error(f"adb connect error return none {addr}", e)
77
112
 
@@ -137,11 +172,12 @@ class DeviceManager:
137
172
  from ok.alas.emulator_windows import EmulatorManager
138
173
  manager = EmulatorManager()
139
174
  installed_emulators = manager.all_emulator_instances
175
+ logger.info(f'installed emulators {installed_emulators}')
140
176
  for emulator in installed_emulators:
141
177
  preferred = self.get_preferred_device()
142
178
  if current and preferred is not None and preferred['imei'] != emulator.name:
143
179
  logger.debug(f"refresh current only skip others {preferred['imei']} != {emulator.name}")
144
- break
180
+ continue
145
181
  adb_device = self.adb_connect(emulator.serial)
146
182
  width, height = self.get_resolution(adb_device) if adb_device is not None else 0, 0
147
183
  name, hwnd, full_path, x, y, width, height = find_hwnd(None,
@@ -164,7 +200,7 @@ class DeviceManager:
164
200
  if device is not None:
165
201
  if resolution := self.resolution_dict.get(device.serial):
166
202
  return resolution
167
- frame = do_screencap(device)
203
+ frame = self.do_screencap(device)
168
204
  if frame is not None:
169
205
  height, width, _ = frame.shape
170
206
  if self.supported_ratio is None or abs(width / height - self.supported_ratio) < 0.01:
@@ -198,15 +234,43 @@ class DeviceManager:
198
234
  self.start()
199
235
  logger.debug(f'preferred device: {preferred}')
200
236
 
201
- @staticmethod
202
- def adb_get_imei(device):
237
+ def shell_device(self, device, *args, **kwargs):
238
+ kwargs.setdefault('timeout', 5)
203
239
  try:
204
- return device.shell("settings get secure android_id") or device.shell(
205
- "service call iphonesubinfo 4") or device.prop.model
240
+ return device.shell(*args, **kwargs)
241
+ except AdbError as e:
242
+ logger.error(f"adb shell AdbError try kill server {device}", e)
243
+ self.try_kill_adb(e)
244
+ addr = self.get_preferred_device()['address']
245
+ self.refresh_emulators()
246
+ self.refresh_phones()
247
+ new_addr = self.get_preferred_device()['address']
248
+ logger.error(f"shell_wrapper error occurred, try refresh_emulators {addr} {new_addr}", e)
249
+ device = self.adb_connect(device.serial)
250
+ return device.shell(*args, **kwargs)
206
251
  except Exception as e:
207
- logger.error(f"adb_get_imei error maybe offline {device}")
252
+ logger.error(f"adb shell error maybe offline {device}", e)
208
253
  return None
209
254
 
255
+ def adb_get_imei(self, device):
256
+ return (self.shell_device(device, "settings get secure android_id") or
257
+ self.shell_device(device, "service call iphonesubinfo 4") or device.prop.model)
258
+
259
+ def do_screencap(self, device) -> np.ndarray | None:
260
+ if device is None:
261
+ return None
262
+ try:
263
+ png_bytes = self.shell_device(device, "screencap -p", encoding=None)
264
+ if png_bytes is not None and len(png_bytes) > 0:
265
+ image_data = np.frombuffer(png_bytes, dtype=np.uint8)
266
+ image = cv2.imdecode(image_data, cv2.IMREAD_COLOR)
267
+ if image is not None:
268
+ return image
269
+ else:
270
+ logger.error(f"Screencap image decode error, probably disconnected")
271
+ except Exception as e:
272
+ logger.error('screencap', e)
273
+
210
274
  def get_preferred_device(self):
211
275
  imei = self.config.get("preferred")
212
276
  preferred = self.device_dict.get(imei)
@@ -331,19 +395,10 @@ class DeviceManager:
331
395
 
332
396
  def shell(self, *args, **kwargs):
333
397
  # Set default timeout to 5 if not provided
334
- kwargs.setdefault('timeout', 5)
335
398
 
336
399
  device = self.device
337
400
  if device is not None:
338
- try:
339
- return device.shell(*args, **kwargs)
340
- except AdbError as e:
341
- logger.debug(f'shell adb error {args} {e}')
342
- except Exception as e:
343
- addr = self.get_preferred_device()['address']
344
- self.refresh_emulators()
345
- new_addr = self.get_preferred_device()['address']
346
- logger.error(f"shell_wrapper error occurred, try refresh_emulators {addr} {new_addr}", e)
401
+ return self.shell_device(device, *args, **kwargs)
347
402
  else:
348
403
  raise Exception('Device is none')
349
404
 
@@ -51,11 +51,12 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
51
51
 
52
52
  def convert_dx_frame(self):
53
53
  frame = self.last_dx_frame
54
- self.last_dx_frame = None
55
54
  if not frame:
56
- logger.warning('convert_dx_frame self.last_dx_frame is none')
55
+ # logger.warning('convert_dx_frame self.last_dx_frame is none')
57
56
  return None
58
-
57
+ start = time.time()
58
+ dx_time = self.last_frame_time
59
+ self.last_dx_frame = None
59
60
  need_reset_framepool = False
60
61
  if frame.ContentSize.Width != self.last_size.Width or frame.ContentSize.Height != self.last_size.Height:
61
62
  need_reset_framepool = True
@@ -94,6 +95,7 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
94
95
  (desc.Height, mapinfo.RowPitch // 4, 4))[
95
96
  :, :desc.Width].copy()
96
97
  self.immediatedc.Unmap(cputex, 0)
98
+ # logger.debug(f'frame latency {(time.time() - start):.3f} {(time.time() - dx_time):.3f}')
97
99
  return img
98
100
  except OSError as e:
99
101
  if e.winerror == d3d11.DXGI_ERROR_DEVICE_REMOVED or e.winerror == d3d11.DXGI_ERROR_DEVICE_RESET:
@@ -150,7 +152,7 @@ class WindowsGraphicsCaptureMethod(BaseWindowsCaptureMethod):
150
152
  self.evtoken = item.add_Closed(delegate)
151
153
  self.frame_pool = Direct3D11CaptureFramePool.CreateFreeThreaded(self.rtdevice,
152
154
  DirectXPixelFormat.B8G8R8A8UIntNormalized,
153
- 2, item.Size)
155
+ 1, item.Size)
154
156
  self.session = self.frame_pool.CreateCaptureSession(item)
155
157
  pool = self.frame_pool
156
158
  pool.add_FrameArrived(
@@ -104,6 +104,11 @@ def find_color_rectangles(image, color_range, min_width, min_height, max_width=-
104
104
  raise ValueError("Image not found or path is incorrect")
105
105
  if box is not None:
106
106
  image = image[box.y:box.y + box.height, box.x:box.x + box.width, :3]
107
+ x_offset = box.x
108
+ y_offset = box.y
109
+ else:
110
+ x_offset = 0
111
+ y_offset = 0
107
112
 
108
113
  # Convert color range to BGR format for OpenCV
109
114
  lower_bound = np.array([color_range['b'][0], color_range['g'][0], color_range['r'][0]], dtype="uint8")
@@ -139,7 +144,7 @@ def find_color_rectangles(image, color_range, min_width, min_height, max_width=-
139
144
  if percent >= threshold:
140
145
  # Store the result
141
146
  results.append(
142
- Box(x, y, w, h, confidence=percent)
147
+ Box(x + x_offset, y + y_offset, w, h, confidence=percent)
143
148
  )
144
149
 
145
150
  return results
@@ -95,6 +95,9 @@ class Box:
95
95
  return Box(self.x + x_offset, self.y + y_offset, self.width + width_offset, self.height + height_offset,
96
96
  self.confidence, name or self.name)
97
97
 
98
+ def crop_frame(self, frame):
99
+ return frame[self.y:self.y + self.height, self.x:self.x + self.width]
100
+
98
101
  def center(self):
99
102
  return self.x + self.width / 2, self.y + self.height / 2
100
103
 
@@ -174,7 +174,7 @@ class FeatureSet:
174
174
  template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)
175
175
  if category_name.startswith('edge_'):
176
176
  search_area = cv2.cvtColor(search_area, cv2.COLOR_BGR2GRAY)
177
- # search_area = cv2.Canny(search_area, self.canny_lower, self.canny_higher)
177
+ search_area = cv2.Canny(search_area, self.canny_lower, self.canny_higher)
178
178
  elif category_name.startswith('gray_'):
179
179
  search_area = cv2.cvtColor(search_area, cv2.COLOR_BGR2GRAY)
180
180
 
@@ -258,7 +258,7 @@ def read_from_json(coco_json, width=-1, height=-1, canny_lower=50, canny_upper=1
258
258
  if ok_compressed:
259
259
  if category_name.startswith('edge_'):
260
260
  image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
261
- # image = cv2.Canny(image, canny_lower, canny_upper)
261
+ image = cv2.Canny(image, canny_lower, canny_upper)
262
262
  elif category_name.startswith('gray_'):
263
263
  image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
264
264
  feature_dict[category_name] = Feature(image, x, y)
@@ -31,13 +31,24 @@ class FindFeature:
31
31
  setattr(self, feature, result)
32
32
  return ret
33
33
 
34
+ def wait_feature(self, feature, horizontal_variance=0, vertical_variance=0, threshold=0, wait_until_before_delay=-1,
35
+ time_out=0, pre_action=None, post_action=None, use_gray_scale=False, box=None,
36
+ raise_if_not_found=False):
37
+ return self.wait_until(
38
+ lambda: self.find_one(feature, horizontal_variance, vertical_variance, threshold,
39
+ use_gray_scale=use_gray_scale, box=box),
40
+ time_out,
41
+ pre_action,
42
+ post_action, wait_until_before_delay, raise_if_not_found)
43
+
34
44
  def wait_click_feature(self, feature, horizontal_variance=0, vertical_variance=0, threshold=0, relative_x=0.5,
35
45
  relative_y=0.5,
36
- time_out=0, pre_action=None, post_action=None):
37
- box = self.wait_until(lambda: self.find_one(feature, horizontal_variance, vertical_variance, threshold),
38
- time_out,
39
- pre_action,
40
- post_action)
46
+ time_out=0, pre_action=None, post_action=None, box=None, raise_if_not_found=True):
47
+ box = self.wait_until(
48
+ lambda: self.find_one(feature, horizontal_variance, vertical_variance, threshold, box=box),
49
+ time_out,
50
+ pre_action,
51
+ post_action, raise_if_not_found)
41
52
  if box is not None:
42
53
  self.click_box(box, relative_x, relative_y)
43
54
  return True
@@ -47,7 +47,6 @@ class App:
47
47
  self.loading_window = None
48
48
  self.overlay_window = None
49
49
  self.main_window = None
50
- self.log_window = None
51
50
  self.exit_event = exit_event
52
51
  self.icon = QIcon(self.config.get('gui_icon') or ":/icon/icon.ico")
53
52
  if self.config.get('analytics'):
@@ -98,12 +97,6 @@ class App:
98
97
  if self.overlay and ok.gui.device_manager.hwnd is not None:
99
98
  self.overlay_window = OverlayWindow(ok.gui.device_manager.hwnd)
100
99
 
101
- if self.config.get('debug'):
102
- from ok.gui.debug.LogWindow import LogWindow
103
- self.log_window = LogWindow(self.config)
104
- self.log_window.show()
105
- logger.debug('showing log_window')
106
-
107
100
  self.main_window = MainWindow(self.config, self.icon, self.title, self.version, self.overlay, self.about,
108
101
  self.exit_event)
109
102
  # Set the window title here
@@ -29,6 +29,9 @@ class DebugTab(Tab):
29
29
 
30
30
  self.config = Config({'target_task': "", 'target_images': [], 'target_function': ""},
31
31
  app_config.get('config_folder'), 'debug')
32
+ self.log_window_config = Config({'width': 800, 'height': 300, 'x': 0, 'y': 0, 'keyword': '',
33
+ 'level': 'ALL', 'show': True},
34
+ app_config.get('config_folder'), 'log_window')
32
35
  tool_widget = QWidget()
33
36
  layout = FlowLayout(tool_widget, False)
34
37
 
@@ -53,7 +56,14 @@ class DebugTab(Tab):
53
56
  ocr_button.clicked.connect(lambda: self.handler.post(self.ocr))
54
57
  layout.addWidget(ocr_button)
55
58
 
56
- open_log_folder = PushButton(self.tr("Open Logs"))
59
+ self.log_window = None
60
+
61
+ log_window_button = PushButton(self.tr("Open Logs"))
62
+ log_window_button.clicked.connect(self.toggle_log_window)
63
+ layout.addWidget(log_window_button)
64
+
65
+ if self.log_window_config.get('show'):
66
+ self.toggle_log_window()
57
67
 
58
68
  call_task_widget = QWidget()
59
69
  call_task_container = QVBoxLayout(call_task_widget)
@@ -98,6 +108,22 @@ class DebugTab(Tab):
98
108
  self.handler.post(self.bind_hot_keys)
99
109
  self.handler.post(self.check_hotkey, 0.1)
100
110
 
111
+ ok.gui.app.app.aboutToQuit.connect(self.unregister)
112
+
113
+ def toggle_log_window(self):
114
+ if self.log_window is None:
115
+ from ok.gui.debug.LogWindow import LogWindow
116
+ self.log_window = LogWindow(self.log_window_config)
117
+ self.log_window.show()
118
+ self.log_window_config['show'] = True
119
+ elif self.log_window.isVisible():
120
+ self.log_window.hide()
121
+ self.log_window_config['show'] = False
122
+ else:
123
+ self.log_window_config['show'] = True
124
+ self.log_window.show()
125
+ logger.debug('showing log_window')
126
+
101
127
  def check_hotkey(self):
102
128
  # Example event type, you should use the appropriate QEvent.Type for your case
103
129
  msg = wintypes.MSG()
@@ -127,8 +153,10 @@ class DebugTab(Tab):
127
153
  logger.debug("Failed to register hotkey for Alt+Ctrl+S")
128
154
  logger.debug('bind_hot_keys')
129
155
 
130
- def __del__(self):
156
+ @staticmethod
157
+ def unregister():
131
158
  # Unregister the hotkeys
159
+ logger.debug('Unregister the hotkeys')
132
160
  windll.user32.UnregisterHotKey(None, 1)
133
161
  windll.user32.UnregisterHotKey(None, 2)
134
162
 
@@ -4,7 +4,6 @@ from PySide6.QtWidgets import QWidget, \
4
4
  QStyledItemDelegate, QListView, QVBoxLayout, QHBoxLayout, QAbstractItemView, QComboBox, QLineEdit, QLabel, \
5
5
  QPushButton
6
6
 
7
- from ok.config.Config import Config
8
7
  from ok.gui.Communicate import communicate
9
8
 
10
9
  LOG_BG_TRANS = 80
@@ -70,9 +69,6 @@ class LogModel(QAbstractListModel):
70
69
  self.do_filter_logs()
71
70
  self.endInsertRows()
72
71
 
73
- # self.layoutChanged.emit()
74
- # self.log_list.scrollToBottom()
75
-
76
72
  def do_filter_logs(self):
77
73
 
78
74
  keyword = self.current_keyword.lower()
@@ -109,15 +105,13 @@ level_severity = {v: k for k, v in log_levels.items()}
109
105
 
110
106
 
111
107
  class LogWindow(QWidget):
112
- def __init__(self, app_config):
108
+ def __init__(self, config):
113
109
  super().__init__()
114
110
  self.setWindowTitle('Log Viewer')
115
111
  self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool)
116
112
  self.setAttribute(Qt.WA_TranslucentBackground)
117
113
 
118
- self.config = Config({'width': 800, 'height': 300, 'x': 0, 'y': 0,
119
- 'level': 'ALL'},
120
- app_config.get('config_folder'), 'log_window')
114
+ self.config = config
121
115
  self.setGeometry(self.config['x'], self.config['y'], self.config['width'], self.config['height'])
122
116
 
123
117
  self.old_pos = None
@@ -139,6 +133,8 @@ class LogWindow(QWidget):
139
133
 
140
134
  self.keyword_filter = QLineEdit()
141
135
  self.keyword_filter.setPlaceholderText("Filter by keyword")
136
+ if keyword := self.config.get('keyword'):
137
+ self.keyword_filter.setText(keyword)
142
138
  self.keyword_filter.textChanged.connect(self.filter_logs)
143
139
 
144
140
  self.drag_button = QLabel(self.tr("Drag"))
@@ -162,6 +158,11 @@ class LogWindow(QWidget):
162
158
  self.log_list.setModel(self.log_model)
163
159
 
164
160
  communicate.log.connect(self.add_log)
161
+ self.filter_logs()
162
+
163
+ def close(self):
164
+ super().close()
165
+ self.config['show'] = False
165
166
 
166
167
  def add_log(self, level_no, message):
167
168
  # print('add_log', level_no, message)
@@ -170,8 +171,9 @@ class LogWindow(QWidget):
170
171
 
171
172
  def filter_logs(self):
172
173
  level = self.level_filter.currentText()
173
- self.config['level'] = level
174
174
  keyword = self.keyword_filter.text()
175
+ self.config['keyword'] = keyword
176
+ self.config['level'] = level
175
177
  self.log_model.filter_logs(level, keyword)
176
178
 
177
179
  def mousePressEvent(self, event):
@@ -13,7 +13,7 @@ class OneTimeTaskTab(TaskTab):
13
13
  super().__init__()
14
14
 
15
15
  for task in ok.gui.executor.onetime_tasks:
16
- task_card = TaskCard(task)
16
+ task_card = TaskCard(task, True)
17
17
  self.addWidget(task_card)
18
18
 
19
19
  def in_current_list(self, task):
@@ -7,19 +7,19 @@ from ok.gui.Communicate import communicate
7
7
  from ok.gui.common.OKIcon import OKIcon
8
8
  from ok.gui.tasks.ConfigItemFactory import config_widget
9
9
  from ok.task.BaseTask import BaseTask
10
- from ok.task.TriggerTask import TriggerTask
11
10
 
12
11
 
13
12
  class TaskCard(ExpandSettingCard):
14
- def __init__(self, task: BaseTask):
13
+ def __init__(self, task: BaseTask, onetime):
15
14
  super().__init__(FluentIcon.INFO, task.name, task.description)
16
15
  self.task = task
16
+ self.onetime = onetime
17
17
  if task.default_config:
18
18
  self.reset_config = PushButton(FluentIcon.CANCEL, self.tr("Reset Config"), self)
19
19
  self.addWidget(self.reset_config)
20
20
  self.reset_config.clicked.connect(self.reset_clicked)
21
21
 
22
- if not isinstance(task, TriggerTask):
22
+ if onetime:
23
23
  self.task_buttons = TaskButtons(self.task)
24
24
  self.addWidget(self.task_buttons)
25
25
  else:
@@ -49,10 +49,10 @@ class TaskCard(ExpandSettingCard):
49
49
 
50
50
  def update_buttons(self, task):
51
51
  if task == self.task:
52
- if isinstance(task, TriggerTask):
53
- self.enable_button.setChecked(task.enabled)
54
- else:
52
+ if self.onetime:
55
53
  self.task_buttons.update_buttons()
54
+ else:
55
+ self.enable_button.setChecked(task.enabled)
56
56
 
57
57
  def check_changed(self, checked):
58
58
  if checked:
@@ -13,7 +13,7 @@ class TriggerTaskTab(TaskTab):
13
13
  super().__init__()
14
14
 
15
15
  for task in ok.gui.executor.trigger_tasks:
16
- task_card = TaskCard(task)
16
+ task_card = TaskCard(task, False)
17
17
  self.addWidget(task_card)
18
18
 
19
19
  def in_current_list(self, task):
@@ -20,7 +20,7 @@ class Win32Interaction(BaseInteraction):
20
20
  if not is_admin():
21
21
  logger.error(f"You must be an admin to use Win32Interaction")
22
22
 
23
- def send_key(self, key, down_time=0.02):
23
+ def send_key(self, key, down_time=0.01):
24
24
  if not self.capture.clickable():
25
25
  logger.error(f"can't click on {key}, because capture is not clickable")
26
26
  return
@@ -12,7 +12,7 @@ logger = get_logger(__name__)
12
12
 
13
13
  class OCR:
14
14
  executor = None
15
- ocr_default_threshold = 0.5
15
+ ocr_default_threshold = 0.8
16
16
  ocr_target_height = 0
17
17
 
18
18
  def ocr(self, x=0, y=0, to_x=1, to_y=1, match: str | List[str] | Pattern[str] | List[Pattern[str]] | None = None,
@@ -75,7 +75,7 @@ class OCR:
75
75
  communicate.emit_draw_box("ocr", detected_boxes, "red")
76
76
  communicate.emit_draw_box("ocr_zone", box, "blue")
77
77
  logger.debug(
78
- f"ocr_zone {box} found result: {len(detected_boxes)}) time: {(time.time() - start):.2f} scale_factor: {scale_factor:.2f}")
78
+ f"ocr_zone {box} found result: {detected_boxes}) time: {(time.time() - start):.2f} scale_factor: {scale_factor:.2f}")
79
79
  if not detected_boxes and ocr_boxes:
80
80
  logger.info(f'ocr detected but no match: {match} {ocr_boxes}')
81
81
  return sort_boxes(detected_boxes)
@@ -138,7 +138,7 @@ class ExecutorOperation:
138
138
  def move_relative(self, x, y):
139
139
  self.executor.interaction.move_relative(x, y)
140
140
 
141
- def click_box(self, box: Box | List[Box] = None, relative_x=0.5, relative_y=0.5, raise_if_not_found=True,
141
+ def click_box(self, box: Box | List[Box] = None, relative_x=0.5, relative_y=0.5, raise_if_not_found=False,
142
142
  move_back=False):
143
143
  if isinstance(box, list):
144
144
  if len(box) > 0:
@@ -156,7 +156,6 @@ class ExecutorOperation:
156
156
  return self.executor.wait_scene(scene_type, time_out, pre_action, post_action)
157
157
 
158
158
  def sleep(self, timeout):
159
- self.executor.reset_scene()
160
159
  self.executor.sleep(timeout)
161
160
 
162
161
  def send_key(self, key, down_time=0.02):
@@ -174,10 +173,12 @@ class ExecutorOperation:
174
173
  self.executor.reset_scene()
175
174
  self.executor.interaction.send_key_up(key)
176
175
 
177
- def wait_until(self, condition, time_out=0, pre_action=None, post_action=None, wait_until_before_delay=0):
178
- return self.executor.wait_condition(condition, time_out, pre_action, post_action, wait_until_before_delay)
176
+ def wait_until(self, condition, time_out=0, pre_action=None, post_action=None, wait_until_before_delay=-1,
177
+ raise_if_not_found=False):
178
+ return self.executor.wait_condition(condition, time_out, pre_action, post_action, wait_until_before_delay,
179
+ raise_if_not_found)
179
180
 
180
- def wait_click_box(self, condition, time_out=0, pre_action=None, post_action=None, raise_if_not_found=True):
181
+ def wait_click_box(self, condition, time_out=0, pre_action=None, post_action=None, raise_if_not_found=False):
181
182
  target = self.wait_until(condition, time_out, pre_action, post_action)
182
183
  self.click_box(box=target, raise_if_not_found=raise_if_not_found)
183
184
  return target