ok-script 0.0.82__tar.gz → 0.0.83__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.82 → ok-script-0.0.83}/PKG-INFO +1 -1
  2. {ok-script-0.0.82 → ok-script-0.0.83}/ok/alas/emulator_windows.py +1 -1
  3. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/HwndWindow.py +9 -6
  4. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/adb/DeviceManager.py +18 -7
  5. ok-script-0.0.83/ok/color/Color.py +148 -0
  6. {ok-script-0.0.82 → ok-script-0.0.83}/ok/feature/Box.py +8 -8
  7. {ok-script-0.0.82 → ok-script-0.0.83}/ok/feature/FeatureSet.py +7 -2
  8. {ok-script-0.0.82 → ok-script-0.0.83}/ok/feature/FindFeature.py +4 -5
  9. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/StartController.py +2 -2
  10. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/debug/DebugTab.py +4 -2
  11. {ok-script-0.0.82 → ok-script-0.0.83}/ok/interaction/BaseInteraction.py +6 -0
  12. {ok-script-0.0.82 → ok-script-0.0.83}/ok/interaction/Win32Interaction.py +31 -2
  13. {ok-script-0.0.82 → ok-script-0.0.83}/ok/ocr/OCR.py +3 -6
  14. {ok-script-0.0.82 → ok-script-0.0.83}/ok/task/ExecutorOperation.py +26 -2
  15. {ok-script-0.0.82 → ok-script-0.0.83}/ok/task/TaskExecutor.py +1 -1
  16. {ok-script-0.0.82 → ok-script-0.0.83}/ok/task/TriggerTask.py +2 -1
  17. {ok-script-0.0.82 → ok-script-0.0.83}/ok_script.egg-info/PKG-INFO +1 -1
  18. {ok-script-0.0.82 → ok-script-0.0.83}/setup.py +1 -1
  19. ok-script-0.0.82/ok/color/Color.py +0 -42
  20. {ok-script-0.0.82 → ok-script-0.0.83}/README.md +0 -0
  21. {ok-script-0.0.82 → ok-script-0.0.83}/ok/OK.py +0 -0
  22. {ok-script-0.0.82 → ok-script-0.0.83}/ok/__init__.py +0 -0
  23. {ok-script-0.0.82 → ok-script-0.0.83}/ok/alas/__init__.py +0 -0
  24. {ok-script-0.0.82 → ok-script-0.0.83}/ok/alas/emulator_base.py +0 -0
  25. {ok-script-0.0.82 → ok-script-0.0.83}/ok/alas/platform_base.py +0 -0
  26. {ok-script-0.0.82 → ok-script-0.0.83}/ok/alas/platform_windows.py +0 -0
  27. {ok-script-0.0.82 → ok-script-0.0.83}/ok/alas/utils.py +0 -0
  28. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/BaseCaptureMethod.py +0 -0
  29. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/__init__.py +0 -0
  30. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/adb/ADBCaptureMethod.py +0 -0
  31. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/adb/WindowsCaptureFactory.py +0 -0
  32. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/adb/__init__.py +0 -0
  33. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/adb/bin/__init__.py +0 -0
  34. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/image/ImageCaptureMethod.py +0 -0
  35. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/image/__init__.py +0 -0
  36. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/windows/BaseWindowsCaptureMethod.py +0 -0
  37. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/windows/BitBltCaptureMethod.py +0 -0
  38. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/windows/DesktopDuplicationCaptureMethod.py +0 -0
  39. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +0 -0
  40. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/windows/__init__.py +0 -0
  41. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/windows/d3d11.py +0 -0
  42. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/windows/dump.py +0 -0
  43. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/windows/utils.py +0 -0
  44. {ok-script-0.0.82 → ok-script-0.0.83}/ok/capture/windows/window.py +0 -0
  45. {ok-script-0.0.82 → ok-script-0.0.83}/ok/color/__init__.py +0 -0
  46. {ok-script-0.0.82 → ok-script-0.0.83}/ok/config/Config.py +0 -0
  47. {ok-script-0.0.82 → ok-script-0.0.83}/ok/config/InfoDict.py +0 -0
  48. {ok-script-0.0.82 → ok-script-0.0.83}/ok/config/__init__.py +0 -0
  49. {ok-script-0.0.82 → ok-script-0.0.83}/ok/feature/Feature.py +0 -0
  50. {ok-script-0.0.82 → ok-script-0.0.83}/ok/feature/__init__.py +0 -0
  51. {ok-script-0.0.82 → ok-script-0.0.83}/ok/firebase/Analytics.py +0 -0
  52. {ok-script-0.0.82 → ok-script-0.0.83}/ok/firebase/__init__.py +0 -0
  53. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/App.py +0 -0
  54. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/Communicate.py +0 -0
  55. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/MainWindow.py +0 -0
  56. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/MessageWindow.py +0 -0
  57. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/TabTitles.py +0 -0
  58. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/__init__.py +0 -0
  59. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/about/AboutTab.py +0 -0
  60. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/about/HttpTextEdit.py +0 -0
  61. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/about/VersionCard.py +0 -0
  62. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/about/__init__.py +0 -0
  63. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/common/OKIcon.py +0 -0
  64. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/common/__init__.py +0 -0
  65. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/common/config.py +0 -0
  66. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/common/style_sheet.py +0 -0
  67. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/debug/AspectRatioWidget.py +0 -0
  68. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/debug/FrameWidget.py +0 -0
  69. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/debug/InfoWidget.py +0 -0
  70. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/debug/LoggerWidget.py +0 -0
  71. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/debug/Screenshot.py +0 -0
  72. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/debug/__init__.py +0 -0
  73. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/i18n/__init__.py +0 -0
  74. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/i18n/path.py +0 -0
  75. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/i18n/update.py +0 -0
  76. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/icon/__init__.py +0 -0
  77. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/icon/icon.py +0 -0
  78. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/overlay/OverlayWindow.py +0 -0
  79. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/overlay/__init__.py +0 -0
  80. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/qss/__init__.py +0 -0
  81. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/resources.py +0 -0
  82. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/settings/SettingTab.py +0 -0
  83. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/settings/__init__.py +0 -0
  84. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/start/SelectCaptureListView.py +0 -0
  85. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/start/StartCard.py +0 -0
  86. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/start/StartTab.py +0 -0
  87. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/start/__init__.py +0 -0
  88. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/ConfigItemFactory.py +0 -0
  89. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
  90. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
  91. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/LabelAndDropDown.py +0 -0
  92. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
  93. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/LabelAndList.py +0 -0
  94. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
  95. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
  96. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/LabelAndWidget.py +0 -0
  97. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/ModifyListDialog.py +0 -0
  98. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/ModifyListItem.py +0 -0
  99. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/OneTimeTaskTab.py +0 -0
  100. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/StartButton.py +0 -0
  101. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/TaskCard.py +0 -0
  102. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/TaskOpButton.py +0 -0
  103. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/TooltipTableWidget.py +0 -0
  104. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/TriggerTaskTab.py +0 -0
  105. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/tasks/__init__.py +0 -0
  106. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/util/Alert.py +0 -0
  107. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/util/InitWorker.py +0 -0
  108. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/util/__init__.py +0 -0
  109. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/Card.py +0 -0
  110. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/EmptyCard.py +0 -0
  111. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/FramelessDialog.py +0 -0
  112. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/ListTableWidgetItem.py +0 -0
  113. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
  114. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/StartLoadingDialog.py +0 -0
  115. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/StatusBar.py +0 -0
  116. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/Tab.py +0 -0
  117. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/TabWidget.py +0 -0
  118. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
  119. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/YesNonWidgetItem.py +0 -0
  120. {ok-script-0.0.82 → ok-script-0.0.83}/ok/gui/widget/__init__.py +0 -0
  121. {ok-script-0.0.82 → ok-script-0.0.83}/ok/interaction/ADBInteraction.py +0 -0
  122. {ok-script-0.0.82 → ok-script-0.0.83}/ok/interaction/DoNothingInteraction.py +0 -0
  123. {ok-script-0.0.82 → ok-script-0.0.83}/ok/interaction/__init__.py +0 -0
  124. {ok-script-0.0.82 → ok-script-0.0.83}/ok/logging/Logger.py +0 -0
  125. {ok-script-0.0.82 → ok-script-0.0.83}/ok/logging/__init__.py +0 -0
  126. {ok-script-0.0.82 → ok-script-0.0.83}/ok/ocr/__init__.py +0 -0
  127. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
  128. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
  129. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
  130. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
  131. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
  132. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
  133. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
  134. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
  135. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
  136. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Media/__init__.py +0 -0
  137. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
  138. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Security/__init__.py +0 -0
  139. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
  140. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/Storage/__init__.py +0 -0
  141. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/Windows/__init__.py +0 -0
  142. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/__init__.py +0 -0
  143. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/delegate.py +0 -0
  144. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/export.py +0 -0
  145. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/idldsl.py +0 -0
  146. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/inspectable.py +0 -0
  147. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/roapi.py +0 -0
  148. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/types.py +0 -0
  149. {ok-script-0.0.82 → ok-script-0.0.83}/ok/rotypes/winstring.py +0 -0
  150. {ok-script-0.0.82 → ok-script-0.0.83}/ok/save/BlackBarProcessor.py +0 -0
  151. {ok-script-0.0.82 → ok-script-0.0.83}/ok/save/PostProcessor.py +0 -0
  152. {ok-script-0.0.82 → ok-script-0.0.83}/ok/save/SaveByInterval.py +0 -0
  153. {ok-script-0.0.82 → ok-script-0.0.83}/ok/save/SaveByKeyPress.py +0 -0
  154. {ok-script-0.0.82 → ok-script-0.0.83}/ok/save/SaveMethodBase.py +0 -0
  155. {ok-script-0.0.82 → ok-script-0.0.83}/ok/save/__init__.py +0 -0
  156. {ok-script-0.0.82 → ok-script-0.0.83}/ok/scene/FeatureScene.py +0 -0
  157. {ok-script-0.0.82 → ok-script-0.0.83}/ok/scene/Scene.py +0 -0
  158. {ok-script-0.0.82 → ok-script-0.0.83}/ok/scene/__init__.py +0 -0
  159. {ok-script-0.0.82 → ok-script-0.0.83}/ok/stats/StreamStats.py +0 -0
  160. {ok-script-0.0.82 → ok-script-0.0.83}/ok/stats/__init__.py +0 -0
  161. {ok-script-0.0.82 → ok-script-0.0.83}/ok/task/BaseTask.py +0 -0
  162. {ok-script-0.0.82 → ok-script-0.0.83}/ok/task/OneTimeTask.py +0 -0
  163. {ok-script-0.0.82 → ok-script-0.0.83}/ok/task/__init__.py +0 -0
  164. {ok-script-0.0.82 → ok-script-0.0.83}/ok/update/GithubMultiDownloader.py +0 -0
  165. {ok-script-0.0.82 → ok-script-0.0.83}/ok/update/Updater.py +0 -0
  166. {ok-script-0.0.82 → ok-script-0.0.83}/ok/update/__init__.py +0 -0
  167. {ok-script-0.0.82 → ok-script-0.0.83}/ok/update/gen_md5.py +0 -0
  168. {ok-script-0.0.82 → ok-script-0.0.83}/ok/util/Handler.py +0 -0
  169. {ok-script-0.0.82 → ok-script-0.0.83}/ok/util/__init__.py +0 -0
  170. {ok-script-0.0.82 → ok-script-0.0.83}/ok/util/exit_event.py +0 -0
  171. {ok-script-0.0.82 → ok-script-0.0.83}/ok/util/json.py +0 -0
  172. {ok-script-0.0.82 → ok-script-0.0.83}/ok/util/list.py +0 -0
  173. {ok-script-0.0.82 → ok-script-0.0.83}/ok/util/path.py +0 -0
  174. {ok-script-0.0.82 → ok-script-0.0.83}/ok/util/thread.py +0 -0
  175. {ok-script-0.0.82 → ok-script-0.0.83}/ok/util/win32_process.py +0 -0
  176. {ok-script-0.0.82 → ok-script-0.0.83}/ok/util/yaml.py +0 -0
  177. {ok-script-0.0.82 → ok-script-0.0.83}/ok_script.egg-info/SOURCES.txt +0 -0
  178. {ok-script-0.0.82 → ok-script-0.0.83}/ok_script.egg-info/dependency_links.txt +0 -0
  179. {ok-script-0.0.82 → ok-script-0.0.83}/ok_script.egg-info/requires.txt +0 -0
  180. {ok-script-0.0.82 → ok-script-0.0.83}/ok_script.egg-info/top_level.txt +0 -0
  181. {ok-script-0.0.82 → ok-script-0.0.83}/setup.cfg +0 -0
  182. {ok-script-0.0.82 → ok-script-0.0.83}/tests/__init__.py +0 -0
  183. {ok-script-0.0.82 → ok-script-0.0.83}/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.82
3
+ Version: 0.0.83
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
@@ -467,7 +467,7 @@ class EmulatorManager(EmulatorManagerBase):
467
467
  try:
468
468
  exe = proc.cmdline()
469
469
  exe = exe[0]
470
- except (psutil.AccessDenied, IndexError):
470
+ except (psutil.AccessDenied, psutil.NoSuchProcess, IndexError):
471
471
  # psutil.AccessDenied
472
472
  continue
473
473
 
@@ -180,22 +180,25 @@ def find_hwnd(title, exe_name, frame_width, frame_height):
180
180
  win32gui.EnumWindows(callback, None)
181
181
  biggest = None
182
182
  if len(results) > 0:
183
+ biggest = results[0]
183
184
  for result in results:
184
185
  from ok.capture.windows.BitBltCaptureMethod import bit_blt_test_hwnd
185
186
  if (biggest is None or (result[2] * result[3]) > biggest[2] * biggest[3]) and bit_blt_test_hwnd(result[0]):
186
187
  biggest = result
187
188
  x_offset = 0
188
189
  y_offset = 0
189
- real_width, real_height = 0, 0
190
- if biggest is not None and frame_aspect_ratio != 0:
190
+ real_width = 0
191
+ real_height = 0
192
+ if frame_aspect_ratio != 0:
191
193
  real_width, real_height = biggest[2], biggest[3]
192
194
  matching_child = enum_child_windows(biggest, frame_aspect_ratio)
193
195
  if matching_child is not None:
194
196
  x_offset, y_offset, real_width, real_height = matching_child
195
- logger.info(f'find_hwnd {frame_width, frame_height} {biggest} {x_offset, y_offset, real_width, real_height}')
196
- return biggest[6], biggest[0], biggest[1], x_offset, y_offset, real_width, real_height,
197
- else:
198
- return None, None, None, 0, 0, 0, 0
197
+ logger.info(
198
+ f'find_hwnd {frame_width, frame_height} {biggest} {x_offset, y_offset, real_width, real_height}')
199
+ return biggest[6], biggest[0], biggest[1], x_offset, y_offset, real_width, real_height
200
+
201
+ return None, None, None, 0, 0, 0, 0
199
202
 
200
203
 
201
204
  def enum_child_windows(biggest, frame_aspect_ratio):
@@ -99,12 +99,12 @@ class DeviceManager:
99
99
  pc_device["resolution"] = f"{width}x{height}"
100
100
  self.device_dict['pc'] = pc_device
101
101
 
102
- def do_refresh(self, fast=False):
102
+ def do_refresh(self, current=False):
103
103
  self.update_pc_device()
104
104
 
105
- self.refresh_emulators()
105
+ self.refresh_emulators(current)
106
106
 
107
- self.refresh_phones()
107
+ self.refresh_phones(current)
108
108
 
109
109
  if self.exit_event.is_set():
110
110
  return
@@ -112,10 +112,16 @@ class DeviceManager:
112
112
 
113
113
  logger.debug(f'refresh {self.device_dict}')
114
114
 
115
- def refresh_phones(self):
115
+ def refresh_phones(self, current=False):
116
+ if self.adb_capture_config is None:
117
+ return
116
118
  for adb_device in self.adb.iter_device():
117
119
  imei = self.adb_get_imei(adb_device)
118
120
  if imei is not None:
121
+ preferred = self.get_preferred_device()
122
+ if current and preferred is not None and preferred['imei'] != imei:
123
+ logger.debug(f"refresh current only skip others {preferred['imei']} != imei")
124
+ break
119
125
  found = False
120
126
  for device in self.device_dict.values():
121
127
  if device.get('adb_imei') == imei:
@@ -129,13 +135,17 @@ class DeviceManager:
129
135
  "resolution": f'{width}x{height}'}
130
136
  self.device_dict[imei] = phone_device
131
137
 
132
- def refresh_emulators(self):
138
+ def refresh_emulators(self, current=False):
133
139
  if self.adb_capture_config is None:
134
140
  return
135
141
  from ok.alas.emulator_windows import EmulatorManager
136
142
  manager = EmulatorManager()
137
143
  installed_emulators = manager.all_emulator_instances
138
144
  for emulator in installed_emulators:
145
+ preferred = self.get_preferred_device()
146
+ if current and preferred is not None and preferred['imei'] != emulator.name:
147
+ logger.debug(f"refresh current only skip others {preferred['imei']} != {emulator.name}")
148
+ break
139
149
  adb_device = self.adb_connect(emulator.serial)
140
150
  width, height = self.get_resolution(adb_device)
141
151
  name, hwnd, full_path, x, y, width, height = find_hwnd(None,
@@ -192,12 +202,13 @@ class DeviceManager:
192
202
  self.start()
193
203
  logger.debug(f'preferred device: {preferred}')
194
204
 
195
- def adb_get_imei(self, device):
205
+ @staticmethod
206
+ def adb_get_imei(device):
196
207
  try:
197
208
  return device.shell("settings get secure android_id") or device.shell(
198
209
  "service call iphonesubinfo 4") or device.prop.model
199
210
  except Exception as e:
200
- logger.error(f"adb_get_imei error {device}", e)
211
+ logger.error(f"adb_get_imei error maybe offline {device}")
201
212
  return None
202
213
 
203
214
  def get_preferred_device(self):
@@ -0,0 +1,148 @@
1
+ import cv2
2
+ import numpy as np
3
+
4
+ from ok.feature.Box import Box
5
+
6
+ black_color = {
7
+ 'r': (0, 0), # Red range
8
+ 'g': (0, 0), # Green range
9
+ 'b': (0, 0) # Blue range
10
+ }
11
+
12
+ white_color = {
13
+ 'r': (255, 255), # Red range
14
+ 'g': (255, 255), # Green range
15
+ 'b': (255, 255) # Blue range
16
+ }
17
+
18
+
19
+ def calculate_colorfulness(image, box=None):
20
+ if box is not None:
21
+ image = image[box.y:box.y + box.height, box.x:box.x + box.width, :3]
22
+ # Split the image into its respective RGB components
23
+ (B, G, R) = cv2.split(image.astype("float"))
24
+
25
+ # Compute rg = R - G
26
+ rg = np.absolute(R - G)
27
+
28
+ # Compute yb = 0.5 * (R + G) - B
29
+ yb = np.absolute(0.5 * (R + G) - B)
30
+
31
+ # Compute the mean and standard deviation of both rg and yb
32
+ (rbMean, rbStd) = (np.mean(rg), np.std(rg))
33
+ (ybMean, ybStd) = (np.mean(yb), np.std(yb))
34
+
35
+ # Combine the mean and standard deviation
36
+ stdRoot = np.sqrt((rbStd ** 2) + (ybStd ** 2))
37
+ meanRoot = np.sqrt((rbMean ** 2) + (ybMean ** 2))
38
+
39
+ # Derive the "colorfulness" metric
40
+ colorfulness = stdRoot + (0.3 * meanRoot)
41
+
42
+ return colorfulness / 100
43
+
44
+
45
+ def get_saturation(image, box=None):
46
+ # Load the image
47
+
48
+ # Check if image loaded successfully
49
+ if image is None:
50
+ raise ValueError("Image not found or path is incorrect")
51
+
52
+ if box is not None:
53
+ if (box.x >= 0 and box.y >= 0 and
54
+ box.x + box.width <= image.shape[1] and # image.shape[1] is the width of the image
55
+ box.y + box.height <= image.shape[
56
+ 0]) and box.width > 0 and box.height > 0: # image.shape[0] is the height of the image
57
+
58
+ # Extract the region of interest (ROI) using slicing
59
+
60
+ image = image[box.y:box.y + box.height, box.x:box.x + box.width, :3]
61
+
62
+ # Convert image to HSV color space
63
+ hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
64
+
65
+ # Extract the saturation channel
66
+ saturation_channel = hsv_image[:, :, 1]
67
+
68
+ # Calculate the mean saturation
69
+ mean_saturation = saturation_channel.mean() / 255
70
+
71
+ # If the mean saturation is above the threshold, the image is colored; otherwise, it is grayscale
72
+ return mean_saturation
73
+
74
+
75
+ def find_color_rectangles(image, color_range, min_width, min_height, max_width=-1, max_height=-1, threshold=0.95,
76
+ box=None):
77
+ if image is None:
78
+ raise ValueError("Image not found or path is incorrect")
79
+ if box is not None:
80
+ image = image[box.y:box.y + box.height, box.x:box.x + box.width, :3]
81
+
82
+ # Convert color range to BGR format for OpenCV
83
+ lower_bound = np.array([color_range['b'][0], color_range['g'][0], color_range['r'][0]], dtype="uint8")
84
+ upper_bound = np.array([color_range['b'][1], color_range['g'][1], color_range['r'][1]], dtype="uint8")
85
+
86
+ # Create a mask for the color range
87
+ mask = cv2.inRange(image, lower_bound, upper_bound)
88
+
89
+ # Find contours in the mask
90
+ contours, _ = cv2.findContours(mask, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
91
+
92
+ results = []
93
+
94
+ for contour in contours:
95
+ # Get the bounding rectangle
96
+ x, y, w, h = cv2.boundingRect(contour)
97
+
98
+ # Check if the rectangle meets the size criteria
99
+ if w >= min_width and h >= min_height and (max_height == -1 or h <= max_height) and (
100
+ max_width == -1 or w <= max_width):
101
+
102
+ # Extract the region of interest (ROI) from the mask
103
+ roi_mask = mask[y:y + h, x:x + w]
104
+
105
+ # Calculate the total number of pixels in the ROI
106
+ total_pixels = roi_mask.size
107
+
108
+ # Calculate the number of matching pixels (value 255)
109
+ matching_pixels = np.sum(roi_mask == 255)
110
+
111
+ # Check if the percentage of matching pixels is greater than or equal to 90%\
112
+ percent = (matching_pixels / total_pixels)
113
+ if percent >= threshold:
114
+ # Store the result
115
+ results.append(
116
+ Box(x, y, w, h, confidence=percent)
117
+ )
118
+
119
+ return results
120
+
121
+
122
+ def calculate_color_percentage(image, color_ranges, box=None):
123
+ # Check if the ROI is within the image bounds
124
+ if box is not None:
125
+ if (box.x >= 0 and box.y >= 0 and
126
+ box.x + box.width <= image.shape[1] and # image.shape[1] is the width of the image
127
+ box.y + box.height <= image.shape[
128
+ 0]) and box.width > 0 and box.height > 0: # image.shape[0] is the height of the image
129
+
130
+ # Extract the region of interest (ROI) using slicing
131
+
132
+ image = image[box.y:box.y + box.height, box.x:box.x + box.width, :3]
133
+ else:
134
+ # Return some error value or raise an exception
135
+ # For example, return 0 or None
136
+ return 0 # or None, or raise an exception
137
+ else:
138
+ image = image[:, :, :3]
139
+ # Create a mask for the pixels within the desired color range
140
+ mask = cv2.inRange(image,
141
+ (color_ranges['b'][0], color_ranges['g'][0], color_ranges['r'][0]),
142
+ (color_ranges['b'][1], color_ranges['g'][1], color_ranges['r'][1]))
143
+
144
+ # Calculate the percentage of pixels within the color range
145
+ target_pixels = cv2.countNonZero(mask)
146
+ total_pixels = image.size / 3 # Divide by 3 for an RGB image
147
+ percentage = target_pixels / total_pixels
148
+ return percentage
@@ -10,14 +10,14 @@ class Box:
10
10
  confidence: float = 1,
11
11
  name=None, to_x: int | float = -1, to_y: int | float = -1) -> None:
12
12
  self.name = name
13
- self.x = int(x)
14
- self.y = int(y)
13
+ self.x = round(x)
14
+ self.y = round(y)
15
15
  if to_x != -1 and to_y != -1:
16
- self.width = int(to_x - x)
17
- self.height = int(to_y - y)
16
+ self.width = round(to_x - x)
17
+ self.height = round(to_y - y)
18
18
  else:
19
- self.width = int(width)
20
- self.height = int(height)
19
+ self.width = round(width)
20
+ self.height = round(height)
21
21
  if self.width <= 0 or self.height <= 0:
22
22
  raise ValueError(f'width and height must be greater than zero {x} {y} {width} {height} {to_x} {to_y}')
23
23
  self.confidence = confidence
@@ -265,6 +265,6 @@ def relative_box(frame_width, frame_height, x, y, to_x=1, to_y=1, width=0, heigh
265
265
  width = to_x - x
266
266
  if height == 0:
267
267
  height = to_y - y
268
- return Box(int(x * frame_width), int(y * frame_height),
269
- int(width * frame_width), int(height * frame_height),
268
+ return Box(round(x * frame_width), round(y * frame_height),
269
+ round(width * frame_width), round(height * frame_height),
270
270
  name=name)
@@ -145,7 +145,7 @@ class FeatureSet:
145
145
 
146
146
  def find_feature(self, mat: np.ndarray, category_name: str, horizontal_variance: float = 0,
147
147
  vertical_variance: float = 0, threshold: float = 0, use_gray_scale: bool = False, x=-1, y=-1,
148
- to_x=-1, to_y=-1, width=-1, height=-1) -> List[Box]:
148
+ to_x=-1, to_y=-1, width=-1, height=-1, box=None) -> List[Box]:
149
149
  """
150
150
  Find a feature within a given variance.
151
151
 
@@ -172,7 +172,12 @@ class FeatureSet:
172
172
  raise ValueError(f"FeatureSet: " + category_name + " not found in featureDict")
173
173
  feature = self.feature_dict[category_name]
174
174
  feature_width, feature_height = feature.width, feature.height
175
- if x != -1 and y != -1:
175
+ if box is not None:
176
+ search_x1 = box.x
177
+ search_y1 = box.y
178
+ search_x2 = box.x + box.width
179
+ search_y2 = box.y + box.height
180
+ elif x != -1 and y != -1:
176
181
  frame_height, frame_width, *_ = mat.shape
177
182
  if width == -1:
178
183
  width = to_x - x
@@ -11,11 +11,9 @@ 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, x=-1, y=-1, to_x=-1, to_y=-1, width=-1, height=-1) -> List[Box]:
15
- if self.executor.frame is None:
16
- return list()
14
+ use_gray_scale=False, x=-1, y=-1, to_x=-1, to_y=-1, width=-1, height=-1, box=None) -> List[Box]:
17
15
  return self.feature_set.find_feature(self.executor.frame, feature_name, horizontal_variance, vertical_variance,
18
- threshold, use_gray_scale, x, y, to_x, to_y, width, height)
16
+ threshold, use_gray_scale, x, y, to_x, to_y, width, height, box=box)
19
17
 
20
18
  def get_box_by_name(self, name):
21
19
  return self.feature_set.get_box_by_name(self.executor.frame, name)
@@ -47,7 +45,8 @@ class FindFeature:
47
45
 
48
46
  def find_one(self, feature_name, horizontal_variance=0, vertical_variance=0, threshold=0,
49
47
  use_gray_scale=False) -> Box:
50
- boxes = self.find_feature(feature_name, horizontal_variance, vertical_variance, threshold, use_gray_scale=False)
48
+ boxes = self.find_feature(feature_name, horizontal_variance, vertical_variance, threshold,
49
+ use_gray_scale=use_gray_scale)
51
50
  if len(boxes) > 0:
52
51
  if len(boxes) > 1:
53
52
  print(f"find_one:found {feature_name} too many {len(boxes)}", file=sys.stderr)
@@ -24,7 +24,7 @@ class StartController(QObject):
24
24
 
25
25
  def do_start(self, task=None):
26
26
  communicate.starting_emulator.emit(False, None, 30)
27
- ok.gui.device_manager.do_refresh()
27
+ ok.gui.device_manager.do_refresh(True)
28
28
 
29
29
  device = ok.gui.device_manager.get_preferred_device()
30
30
 
@@ -35,7 +35,7 @@ class StartController(QObject):
35
35
  execute(path)
36
36
  wait_until = time.time() + 30
37
37
  while not self.exit_event.is_set():
38
- ok.gui.device_manager.do_refresh()
38
+ ok.gui.device_manager.do_refresh(True)
39
39
  error = self.check_device_error()
40
40
  if error is None:
41
41
  break
@@ -88,6 +88,7 @@ class DebugTab(Tab):
88
88
  self.task_changed(self.config.get('target_task'))
89
89
  else:
90
90
  self.tasks_combo_box.setCurrentIndex(0)
91
+ self.config['target_task'] = class_names[0]
91
92
 
92
93
  self.call_button = PushButton(self.tr("Call"))
93
94
  self.call_button.clicked.connect(lambda: self.handler.post(self.call))
@@ -146,8 +147,9 @@ class DebugTab(Tab):
146
147
  old_interaction = ok.gui.device_manager.interaction
147
148
  try:
148
149
  images = self.config.get("target_images")
149
- ok.gui.device_manager.capture_method = ImageCaptureMethod(images)
150
- ok.gui.device_manager.interaction = DoNothingInteraction(ok.gui.device_manager.capture_method)
150
+ if images:
151
+ ok.gui.device_manager.capture_method = ImageCaptureMethod(images)
152
+ ok.gui.device_manager.interaction = DoNothingInteraction(ok.gui.device_manager.capture_method)
151
153
  ok.gui.executor.debug_mode = True
152
154
  attr = getattr(task, func_name)
153
155
  if callable(attr):
@@ -14,6 +14,12 @@ class BaseInteraction:
14
14
  def send_key(self, key, down_time=0.02):
15
15
  pass
16
16
 
17
+ def send_key_down(self, key):
18
+ pass
19
+
20
+ def send_key_up(self, key):
21
+ pass
22
+
17
23
  def move(self, x, y):
18
24
  pass
19
25
 
@@ -22,10 +22,23 @@ class Win32Interaction(BaseInteraction):
22
22
 
23
23
  def send_key(self, key, down_time=0.02):
24
24
  if not self.capture.clickable():
25
+ logger.error(f"can't click on {key}, because capture is not clickable")
25
26
  return
26
- pydirectinput.keyDown(key)
27
+ pydirectinput.keyDown(str(key))
27
28
  time.sleep(down_time)
28
- pydirectinput.keyUp(key)
29
+ pydirectinput.keyUp(str(key))
30
+
31
+ def send_key_down(self, key):
32
+ if not self.capture.clickable():
33
+ logger.error(f"can't click on {key}, because capture is not clickable")
34
+ return
35
+ pydirectinput.keyDown(str(key))
36
+
37
+ def send_key_up(self, key):
38
+ if not self.capture.clickable():
39
+ logger.error(f"can't click on {key}, because capture is not clickable")
40
+ return
41
+ pydirectinput.keyUp(str(key))
29
42
 
30
43
  def move(self, x, y):
31
44
  if not self.capture.clickable():
@@ -82,6 +95,22 @@ class Win32Interaction(BaseInteraction):
82
95
  if current_x != -1 and current_y != -1:
83
96
  pydirectinput.moveTo(current_x, current_y)
84
97
 
98
+ def mouse_down(self, x=-1, y=-1, name=None):
99
+ if not self.capture.clickable():
100
+ logger.info(f"window in background, not clickable")
101
+ return
102
+ if x != -1 and y != -1:
103
+ x, y = self.capture.get_abs_cords(x, y)
104
+ logger.info(f"left_click {x, y}")
105
+ pydirectinput.moveTo(x, y)
106
+ pydirectinput.mouseDown()
107
+
108
+ def mouse_up(self):
109
+ if not self.capture.clickable():
110
+ logger.info(f"window in background, not clickable")
111
+ return
112
+ pydirectinput.mouseUp()
113
+
85
114
  def should_capture(self):
86
115
  return self.capture.clickable()
87
116
 
@@ -44,12 +44,9 @@ class OCR:
44
44
  box.name = str(match)
45
45
 
46
46
  image, scale_factor = resize_image(image, original_height, target_height)
47
- try:
48
- result, _ = self.executor.ocr(image, use_det=True, use_cls=False, use_rec=True)
49
- except Exception as e:
50
- logger.error('ocr_error sleep and retry once', e)
51
- time.sleep(3)
52
- result, _ = self.executor.ocr(image, use_det=True, use_cls=False, use_rec=True)
47
+
48
+ result, _ = self.executor.ocr(image, use_det=True, use_cls=False, use_rec=True)
49
+
53
50
  detected_boxes = []
54
51
  ocr_boxes = None
55
52
  # Process the results and create Box objects
@@ -34,12 +34,27 @@ class ExecutorOperation:
34
34
  def is_scene(self, the_scene):
35
35
  return isinstance(self.executor.current_scene, the_scene)
36
36
 
37
- def click(self, x, y, move_back=False, name=None):
37
+ def click(self, x=-1, y=-1, move_back=False, name=None):
38
38
  frame = self.executor.nullable_frame()
39
39
  communicate.emit_draw_box("click", [Box(max(0, x - 10), max(0, y - 10), 20, 20, name="click")], "green", frame)
40
40
  self.executor.reset_scene()
41
41
  self.executor.interaction.click(x, y, move_back, name=name)
42
42
 
43
+ def mouse_down(self, x=-1, y=-1, name=None):
44
+ frame = self.executor.nullable_frame()
45
+ communicate.emit_draw_box("mouse_down", [Box(max(0, x - 10), max(0, y - 10), 20, 20, name="click")], "green",
46
+ frame)
47
+ self.executor.reset_scene()
48
+ self.executor.interaction.mouse_down(x, y, name=name)
49
+
50
+ def mouse_up(self, name=None):
51
+ frame = self.executor.nullable_frame()
52
+ communicate.emit_draw_box("mouse_up", self.box_of_screen(0.5, 0.5, width=0.01, height=0.01, name="click"),
53
+ "green",
54
+ frame)
55
+ self.executor.reset_scene()
56
+ self.executor.interaction.mouse_up()
57
+
43
58
  def swipe_relative(self, from_x, from_y, to_x, to_y, duration=0.5):
44
59
  self.swipe(int(self.width * from_x), int(self.height * from_y), int(self.width * to_x),
45
60
  int(self.height * to_y), duration)
@@ -83,7 +98,7 @@ class ExecutorOperation:
83
98
  self.click_box(to_click, relative_x, relative_y)
84
99
  return to_click
85
100
 
86
- def box_of_screen(self, x, y, to_x=1, to_y=1, width=0, height=0, name=None):
101
+ def box_of_screen(self, x, y, to_x: float = 1, to_y: float = 1, width: float = 0, height: float = 0, name=None):
87
102
  if name is None:
88
103
  name = f"{x} {y} {width} {height}"
89
104
  return relative_box(self.executor.method.width, self.executor.method.height, x, y,
@@ -138,8 +153,17 @@ class ExecutorOperation:
138
153
  self.executor.sleep(timeout)
139
154
 
140
155
  def send_key(self, key, down_time=0.02):
156
+ self.executor.reset_scene()
141
157
  self.executor.interaction.send_key(key, down_time)
142
158
 
159
+ def send_key_down(self, key):
160
+ self.executor.reset_scene()
161
+ self.executor.interaction.send_key_down(key)
162
+
163
+ def send_key_up(self, key):
164
+ self.executor.reset_scene()
165
+ self.executor.interaction.send_key_up(key)
166
+
143
167
  def wait_until(self, condition, time_out=0, pre_action=None, post_action=None, wait_until_before_delay=0):
144
168
  return self.executor.wait_condition(condition, time_out, pre_action, post_action, wait_until_before_delay)
145
169
 
@@ -279,7 +279,7 @@ class TaskExecutor:
279
279
  traceback.print_exc()
280
280
  stack_trace_str = traceback.format_exc()
281
281
  logger.error(f"{name} exception: {e}, traceback: {stack_trace_str}")
282
- if self._frame:
282
+ if self._frame is not None:
283
283
  communicate.screenshot.emit(self.frame, name)
284
284
  self.current_task = None
285
285
  if isinstance(self.current_task, OneTimeTask):
@@ -8,10 +8,11 @@ class TriggerTask(BaseTask):
8
8
 
9
9
  def __init__(self):
10
10
  super().__init__()
11
- self.default_config = {'_enabled': True}
11
+ self.default_config = {'_enabled': False}
12
12
  self.trigger_count = 0
13
13
 
14
14
  def on_create(self):
15
+ self._enabled = self.config.get('_enabled', False)
15
16
  pass
16
17
 
17
18
  def get_status(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ok-script
3
- Version: 0.0.82
3
+ Version: 0.0.83
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.82",
8
+ version="0.0.83",
9
9
  author="ok-oldking",
10
10
  author_email="firedcto@gmail.com",
11
11
  description="Automation with Computer Vision for Python",
@@ -1,42 +0,0 @@
1
- import cv2
2
-
3
- black_color = {
4
- 'r': (0, 0), # Red range
5
- 'g': (0, 0), # Green range
6
- 'b': (0, 0) # Blue range
7
- }
8
-
9
- white_color = {
10
- 'r': (255, 255), # Red range
11
- 'g': (255, 255), # Green range
12
- 'b': (255, 255) # Blue range
13
- }
14
-
15
-
16
- def calculate_color_percentage(image, color_ranges, box=None):
17
- # Check if the ROI is within the image bounds
18
- if box is not None:
19
- if (box.x >= 0 and box.y >= 0 and
20
- box.x + box.width <= image.shape[1] and # image.shape[1] is the width of the image
21
- box.y + box.height <= image.shape[
22
- 0]) and box.width > 0 and box.height > 0: # image.shape[0] is the height of the image
23
-
24
- # Extract the region of interest (ROI) using slicing
25
-
26
- image = image[box.y:box.y + box.height, box.x:box.x + box.width, :3]
27
- else:
28
- # Return some error value or raise an exception
29
- # For example, return 0 or None
30
- return 0 # or None, or raise an exception
31
- else:
32
- image = image[:, :, :3]
33
- # Create a mask for the pixels within the desired color range
34
- mask = cv2.inRange(image,
35
- (color_ranges['b'][0], color_ranges['g'][0], color_ranges['r'][0]),
36
- (color_ranges['b'][1], color_ranges['g'][1], color_ranges['r'][1]))
37
-
38
- # Calculate the percentage of pixels within the color range
39
- target_pixels = cv2.countNonZero(mask)
40
- total_pixels = image.size / 3 # Divide by 3 for an RGB image
41
- percentage = target_pixels / total_pixels
42
- return percentage
File without changes
File without changes
File without changes
File without changes