ok-script 0.0.96__tar.gz → 0.0.97__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.97}/PKG-INFO +1 -1
  2. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/HwndWindow.py +10 -6
  3. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/adb/DeviceManager.py +2 -1
  4. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +6 -4
  5. {ok-script-0.0.96 → ok-script-0.0.97}/ok/color/Color.py +6 -1
  6. {ok-script-0.0.96 → ok-script-0.0.97}/ok/feature/Box.py +3 -0
  7. {ok-script-0.0.96 → ok-script-0.0.97}/ok/feature/FeatureSet.py +2 -2
  8. {ok-script-0.0.96 → ok-script-0.0.97}/ok/feature/FindFeature.py +16 -5
  9. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/App.py +0 -7
  10. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/debug/DebugTab.py +30 -2
  11. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/debug/LogWindow.py +11 -9
  12. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/OneTimeTaskTab.py +1 -1
  13. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/TaskCard.py +6 -6
  14. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/TriggerTaskTab.py +1 -1
  15. {ok-script-0.0.96 → ok-script-0.0.97}/ok/interaction/Win32Interaction.py +1 -1
  16. {ok-script-0.0.96 → ok-script-0.0.97}/ok/ocr/OCR.py +2 -2
  17. {ok-script-0.0.96 → ok-script-0.0.97}/ok/task/ExecutorOperation.py +6 -5
  18. {ok-script-0.0.96 → ok-script-0.0.97}/ok/task/TaskExecutor.py +24 -7
  19. {ok-script-0.0.96 → ok-script-0.0.97}/ok_script.egg-info/PKG-INFO +1 -1
  20. {ok-script-0.0.96 → ok-script-0.0.97}/setup.py +1 -1
  21. {ok-script-0.0.96 → ok-script-0.0.97}/README.md +0 -0
  22. {ok-script-0.0.96 → ok-script-0.0.97}/ok/OK.py +0 -0
  23. {ok-script-0.0.96 → ok-script-0.0.97}/ok/__init__.py +0 -0
  24. {ok-script-0.0.96 → ok-script-0.0.97}/ok/alas/__init__.py +0 -0
  25. {ok-script-0.0.96 → ok-script-0.0.97}/ok/alas/emulator_base.py +0 -0
  26. {ok-script-0.0.96 → ok-script-0.0.97}/ok/alas/emulator_windows.py +0 -0
  27. {ok-script-0.0.96 → ok-script-0.0.97}/ok/alas/platform_base.py +0 -0
  28. {ok-script-0.0.96 → ok-script-0.0.97}/ok/alas/platform_windows.py +0 -0
  29. {ok-script-0.0.96 → ok-script-0.0.97}/ok/alas/utils.py +0 -0
  30. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/BaseCaptureMethod.py +0 -0
  31. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/__init__.py +0 -0
  32. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/adb/ADBCaptureMethod.py +0 -0
  33. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/adb/WindowsCaptureFactory.py +0 -0
  34. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/adb/__init__.py +0 -0
  35. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/adb/bin/__init__.py +0 -0
  36. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/image/ImageCaptureMethod.py +0 -0
  37. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/image/__init__.py +0 -0
  38. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/windows/BaseWindowsCaptureMethod.py +0 -0
  39. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/windows/BitBltCaptureMethod.py +0 -0
  40. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/windows/DesktopDuplicationCaptureMethod.py +0 -0
  41. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/windows/__init__.py +0 -0
  42. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/windows/d3d11.py +0 -0
  43. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/windows/dump.py +0 -0
  44. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/windows/utils.py +0 -0
  45. {ok-script-0.0.96 → ok-script-0.0.97}/ok/capture/windows/window.py +0 -0
  46. {ok-script-0.0.96 → ok-script-0.0.97}/ok/color/__init__.py +0 -0
  47. {ok-script-0.0.96 → ok-script-0.0.97}/ok/config/Config.py +0 -0
  48. {ok-script-0.0.96 → ok-script-0.0.97}/ok/config/InfoDict.py +0 -0
  49. {ok-script-0.0.96 → ok-script-0.0.97}/ok/config/__init__.py +0 -0
  50. {ok-script-0.0.96 → ok-script-0.0.97}/ok/feature/CompressCoco.py +0 -0
  51. {ok-script-0.0.96 → ok-script-0.0.97}/ok/feature/Feature.py +0 -0
  52. {ok-script-0.0.96 → ok-script-0.0.97}/ok/feature/__init__.py +0 -0
  53. {ok-script-0.0.96 → ok-script-0.0.97}/ok/firebase/Analytics.py +0 -0
  54. {ok-script-0.0.96 → ok-script-0.0.97}/ok/firebase/__init__.py +0 -0
  55. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/Communicate.py +0 -0
  56. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/MainWindow.py +0 -0
  57. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/MessageWindow.py +0 -0
  58. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/StartController.py +0 -0
  59. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/TabTitles.py +0 -0
  60. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/__init__.py +0 -0
  61. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/about/AboutTab.py +0 -0
  62. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/about/HttpTextEdit.py +0 -0
  63. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/about/VersionCard.py +0 -0
  64. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/about/__init__.py +0 -0
  65. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/common/OKIcon.py +0 -0
  66. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/common/__init__.py +0 -0
  67. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/common/config.py +0 -0
  68. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/common/style_sheet.py +0 -0
  69. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/debug/AspectRatioWidget.py +0 -0
  70. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/debug/FrameWidget.py +0 -0
  71. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/debug/InfoWidget.py +0 -0
  72. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/debug/Screenshot.py +0 -0
  73. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/debug/__init__.py +0 -0
  74. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/i18n/__init__.py +0 -0
  75. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/i18n/path.py +0 -0
  76. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/i18n/update.py +0 -0
  77. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/icon/__init__.py +0 -0
  78. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/icon/icon.py +0 -0
  79. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/overlay/OverlayWindow.py +0 -0
  80. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/overlay/__init__.py +0 -0
  81. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/qss/__init__.py +0 -0
  82. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/resources.py +0 -0
  83. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/settings/SettingTab.py +0 -0
  84. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/settings/__init__.py +0 -0
  85. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/start/SelectCaptureListView.py +0 -0
  86. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/start/StartCard.py +0 -0
  87. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/start/StartTab.py +0 -0
  88. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/start/__init__.py +0 -0
  89. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/ConfigItemFactory.py +0 -0
  90. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
  91. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
  92. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/LabelAndDropDown.py +0 -0
  93. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
  94. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/LabelAndList.py +0 -0
  95. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
  96. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
  97. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/LabelAndWidget.py +0 -0
  98. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/ModifyListDialog.py +0 -0
  99. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/ModifyListItem.py +0 -0
  100. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/StartButton.py +0 -0
  101. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/TaskOpButton.py +0 -0
  102. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/TaskTab.py +0 -0
  103. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/TooltipTableWidget.py +0 -0
  104. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/tasks/__init__.py +0 -0
  105. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/util/Alert.py +0 -0
  106. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/util/InitWorker.py +0 -0
  107. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/util/__init__.py +0 -0
  108. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/Card.py +0 -0
  109. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/EmptyCard.py +0 -0
  110. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/FramelessDialog.py +0 -0
  111. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/ListTableWidgetItem.py +0 -0
  112. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
  113. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/StartLoadingDialog.py +0 -0
  114. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/StatusBar.py +0 -0
  115. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/Tab.py +0 -0
  116. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/TabWidget.py +0 -0
  117. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
  118. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/YesNonWidgetItem.py +0 -0
  119. {ok-script-0.0.96 → ok-script-0.0.97}/ok/gui/widget/__init__.py +0 -0
  120. {ok-script-0.0.96 → ok-script-0.0.97}/ok/interaction/ADBInteraction.py +0 -0
  121. {ok-script-0.0.96 → ok-script-0.0.97}/ok/interaction/BaseInteraction.py +0 -0
  122. {ok-script-0.0.96 → ok-script-0.0.97}/ok/interaction/DoNothingInteraction.py +0 -0
  123. {ok-script-0.0.96 → ok-script-0.0.97}/ok/interaction/__init__.py +0 -0
  124. {ok-script-0.0.96 → ok-script-0.0.97}/ok/logging/Logger.py +0 -0
  125. {ok-script-0.0.96 → ok-script-0.0.97}/ok/logging/__init__.py +0 -0
  126. {ok-script-0.0.96 → ok-script-0.0.97}/ok/ocr/__init__.py +0 -0
  127. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
  128. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
  129. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
  130. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
  131. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
  132. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
  133. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
  134. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
  135. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
  136. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Media/__init__.py +0 -0
  137. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
  138. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Security/__init__.py +0 -0
  139. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
  140. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/Storage/__init__.py +0 -0
  141. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/Windows/__init__.py +0 -0
  142. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/__init__.py +0 -0
  143. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/delegate.py +0 -0
  144. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/export.py +0 -0
  145. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/idldsl.py +0 -0
  146. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/inspectable.py +0 -0
  147. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/roapi.py +0 -0
  148. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/types.py +0 -0
  149. {ok-script-0.0.96 → ok-script-0.0.97}/ok/rotypes/winstring.py +0 -0
  150. {ok-script-0.0.96 → ok-script-0.0.97}/ok/save/BlackBarProcessor.py +0 -0
  151. {ok-script-0.0.96 → ok-script-0.0.97}/ok/save/PostProcessor.py +0 -0
  152. {ok-script-0.0.96 → ok-script-0.0.97}/ok/save/SaveByInterval.py +0 -0
  153. {ok-script-0.0.96 → ok-script-0.0.97}/ok/save/SaveByKeyPress.py +0 -0
  154. {ok-script-0.0.96 → ok-script-0.0.97}/ok/save/SaveMethodBase.py +0 -0
  155. {ok-script-0.0.96 → ok-script-0.0.97}/ok/save/__init__.py +0 -0
  156. {ok-script-0.0.96 → ok-script-0.0.97}/ok/scene/FeatureScene.py +0 -0
  157. {ok-script-0.0.96 → ok-script-0.0.97}/ok/scene/Scene.py +0 -0
  158. {ok-script-0.0.96 → ok-script-0.0.97}/ok/scene/__init__.py +0 -0
  159. {ok-script-0.0.96 → ok-script-0.0.97}/ok/stats/StreamStats.py +0 -0
  160. {ok-script-0.0.96 → ok-script-0.0.97}/ok/stats/__init__.py +0 -0
  161. {ok-script-0.0.96 → ok-script-0.0.97}/ok/task/BaseTask.py +0 -0
  162. {ok-script-0.0.96 → ok-script-0.0.97}/ok/task/TriggerTask.py +0 -0
  163. {ok-script-0.0.96 → ok-script-0.0.97}/ok/task/__init__.py +0 -0
  164. {ok-script-0.0.96 → ok-script-0.0.97}/ok/update/GithubMultiDownloader.py +0 -0
  165. {ok-script-0.0.96 → ok-script-0.0.97}/ok/update/Updater.py +0 -0
  166. {ok-script-0.0.96 → ok-script-0.0.97}/ok/update/__init__.py +0 -0
  167. {ok-script-0.0.96 → ok-script-0.0.97}/ok/update/gen_md5.py +0 -0
  168. {ok-script-0.0.96 → ok-script-0.0.97}/ok/util/Handler.py +0 -0
  169. {ok-script-0.0.96 → ok-script-0.0.97}/ok/util/__init__.py +0 -0
  170. {ok-script-0.0.96 → ok-script-0.0.97}/ok/util/exit_event.py +0 -0
  171. {ok-script-0.0.96 → ok-script-0.0.97}/ok/util/json.py +0 -0
  172. {ok-script-0.0.96 → ok-script-0.0.97}/ok/util/list.py +0 -0
  173. {ok-script-0.0.96 → ok-script-0.0.97}/ok/util/path.py +0 -0
  174. {ok-script-0.0.96 → ok-script-0.0.97}/ok/util/thread.py +0 -0
  175. {ok-script-0.0.96 → ok-script-0.0.97}/ok/util/win32_process.py +0 -0
  176. {ok-script-0.0.96 → ok-script-0.0.97}/ok/util/yaml.py +0 -0
  177. {ok-script-0.0.96 → ok-script-0.0.97}/ok_script.egg-info/SOURCES.txt +0 -0
  178. {ok-script-0.0.96 → ok-script-0.0.97}/ok_script.egg-info/dependency_links.txt +0 -0
  179. {ok-script-0.0.96 → ok-script-0.0.97}/ok_script.egg-info/requires.txt +0 -0
  180. {ok-script-0.0.96 → ok-script-0.0.97}/ok_script.egg-info/top_level.txt +0 -0
  181. {ok-script-0.0.96 → ok-script-0.0.97}/setup.cfg +0 -0
  182. {ok-script-0.0.96 → ok-script-0.0.97}/tests/__init__.py +0 -0
  183. {ok-script-0.0.96 → ok-script-0.0.97}/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.97
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
 
@@ -137,11 +137,12 @@ class DeviceManager:
137
137
  from ok.alas.emulator_windows import EmulatorManager
138
138
  manager = EmulatorManager()
139
139
  installed_emulators = manager.all_emulator_instances
140
+ logger.info(f'installed emulators {installed_emulators}')
140
141
  for emulator in installed_emulators:
141
142
  preferred = self.get_preferred_device()
142
143
  if current and preferred is not None and preferred['imei'] != emulator.name:
143
144
  logger.debug(f"refresh current only skip others {preferred['imei']} != {emulator.name}")
144
- break
145
+ continue
145
146
  adb_device = self.adb_connect(emulator.serial)
146
147
  width, height = self.get_resolution(adb_device) if adb_device is not None else 0, 0
147
148
  name, hwnd, full_path, x, y, width, height = find_hwnd(None,
@@ -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
@@ -18,10 +18,18 @@ class TaskDisabledException(Exception):
18
18
  pass
19
19
 
20
20
 
21
+ class CannotFindException(Exception):
22
+ pass
23
+
24
+
21
25
  class FinishedException(Exception):
22
26
  pass
23
27
 
24
28
 
29
+ class WaitFailedException(Exception):
30
+ pass
31
+
32
+
25
33
  class TaskExecutor:
26
34
  current_scene: Scene | None = None
27
35
  last_scene: Scene | None = None
@@ -34,7 +42,7 @@ class TaskExecutor:
34
42
  _last_frame_time = 0
35
43
 
36
44
  def __init__(self, device_manager: DeviceManager,
37
- wait_until_timeout=10, wait_until_before_delay=1, wait_until_check_delay=1,
45
+ wait_until_timeout=10, wait_until_before_delay=1, wait_until_check_delay=0,
38
46
  exit_event=None, trigger_tasks=[], onetime_tasks=[], scenes=[], feature_set=None,
39
47
  ocr=None,
40
48
  config_folder=None, debug=False):
@@ -45,7 +53,7 @@ class TaskExecutor:
45
53
  self.wait_scene_timeout = wait_until_timeout
46
54
  self.exit_event = exit_event
47
55
  self.debug_mode = False
48
- self.debug = False
56
+ self.debug = debug
49
57
  self.ocr = ocr
50
58
  self.current_task = None
51
59
  self.trigger_tasks = trigger_tasks
@@ -136,6 +144,11 @@ class TaskExecutor:
136
144
 
137
145
  @property
138
146
  def frame(self):
147
+ while self.paused:
148
+ time.sleep(1)
149
+ if self.exit_event.is_set():
150
+ logger.info("Exit event set. Exiting early.")
151
+ return
139
152
  if self._frame is None:
140
153
  return self.next_frame()
141
154
  else:
@@ -150,6 +163,7 @@ class TaskExecutor:
150
163
  if self.debug_mode:
151
164
  time.sleep(timeout)
152
165
  return
166
+ self.reset_scene()
153
167
  self.frame_stats.add_sleep(timeout)
154
168
  self.pause_end_time = time.time() + timeout
155
169
  while True:
@@ -185,8 +199,9 @@ class TaskExecutor:
185
199
  def wait_scene(self, scene_type, time_out, pre_action, post_action):
186
200
  return self.wait_condition(lambda: self.detect_scene(scene_type), time_out, pre_action, post_action)
187
201
 
188
- def wait_condition(self, condition, time_out=0, pre_action=None, post_action=None, wait_until_before_delay=0):
189
- if wait_until_before_delay == 0:
202
+ def wait_condition(self, condition, time_out=0, pre_action=None, post_action=None, wait_until_before_delay=-1,
203
+ raise_if_not_found=False):
204
+ if wait_until_before_delay == -1:
190
205
  wait_until_before_delay = self.wait_until_before_delay
191
206
  self.reset_scene()
192
207
  start = time.time()
@@ -201,15 +216,17 @@ class TaskExecutor:
201
216
  self.add_frame_stats()
202
217
  result_str = list_or_obj_to_str(result)
203
218
  if result:
204
- logger.debug(f"found result {result_str}")
205
- self.sleep(self.wait_until_check_delay)
219
+ logger.debug(
220
+ f"found result {result_str} {(time.time() - start):.3f} delay {wait_until_before_delay} {self.wait_until_check_delay}")
206
221
  return result
207
222
  if post_action is not None:
208
223
  post_action()
209
224
  if time.time() - start > time_out:
210
225
  logger.info(f"wait_until timeout {condition} {time_out} seconds")
211
226
  break
212
- self.sleep(0.01)
227
+ self.sleep(self.wait_until_check_delay)
228
+ if raise_if_not_found:
229
+ raise WaitFailedException()
213
230
  return None
214
231
 
215
232
  def reset_scene(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ok-script
3
- Version: 0.0.96
3
+ Version: 0.0.97
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
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="ok-script",
8
- version="0.0.96",
8
+ version="0.0.97",
9
9
  author="ok-oldking",
10
10
  author_email="firedcto@gmail.com",
11
11
  description="Automation with Computer Vision for Python",
File without changes
File without changes
File without changes
File without changes