ok-script 0.0.82__tar.gz → 0.0.84__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {ok-script-0.0.82 → ok-script-0.0.84}/PKG-INFO +1 -1
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/alas/emulator_base.py +8 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/alas/emulator_windows.py +1 -1
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/HwndWindow.py +25 -10
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/adb/DeviceManager.py +19 -8
- ok-script-0.0.84/ok/color/Color.py +148 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/feature/Box.py +8 -8
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/feature/FeatureSet.py +7 -2
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/feature/FindFeature.py +4 -5
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/StartController.py +2 -2
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/debug/DebugTab.py +4 -2
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/interaction/BaseInteraction.py +6 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/interaction/Win32Interaction.py +31 -2
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/ocr/OCR.py +3 -6
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/task/ExecutorOperation.py +26 -2
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/task/TaskExecutor.py +1 -1
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/task/TriggerTask.py +2 -1
- {ok-script-0.0.82 → ok-script-0.0.84}/ok_script.egg-info/PKG-INFO +1 -1
- {ok-script-0.0.82 → ok-script-0.0.84}/setup.py +1 -1
- ok-script-0.0.82/ok/color/Color.py +0 -42
- {ok-script-0.0.82 → ok-script-0.0.84}/README.md +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/OK.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/alas/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/alas/platform_base.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/alas/platform_windows.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/alas/utils.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/BaseCaptureMethod.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/adb/ADBCaptureMethod.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/adb/WindowsCaptureFactory.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/adb/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/adb/bin/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/image/ImageCaptureMethod.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/image/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/windows/BaseWindowsCaptureMethod.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/windows/BitBltCaptureMethod.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/windows/DesktopDuplicationCaptureMethod.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/windows/WindowsGraphicsCaptureMethod.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/windows/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/windows/d3d11.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/windows/dump.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/windows/utils.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/capture/windows/window.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/color/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/config/Config.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/config/InfoDict.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/config/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/feature/Feature.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/feature/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/firebase/Analytics.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/firebase/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/App.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/Communicate.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/MainWindow.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/MessageWindow.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/TabTitles.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/about/AboutTab.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/about/HttpTextEdit.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/about/VersionCard.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/about/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/common/OKIcon.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/common/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/common/config.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/common/style_sheet.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/debug/AspectRatioWidget.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/debug/FrameWidget.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/debug/InfoWidget.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/debug/LoggerWidget.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/debug/Screenshot.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/debug/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/i18n/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/i18n/path.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/i18n/update.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/icon/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/icon/icon.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/overlay/OverlayWindow.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/overlay/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/qss/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/resources.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/settings/SettingTab.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/settings/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/start/SelectCaptureListView.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/start/StartCard.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/start/StartTab.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/start/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/ConfigItemFactory.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/ConfigLabelAndWidget.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/LabelAndDoubleSpinBox.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/LabelAndDropDown.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/LabelAndLineEdit.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/LabelAndList.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/LabelAndSpinBox.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/LabelAndSwitchButton.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/LabelAndWidget.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/ModifyListDialog.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/ModifyListItem.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/OneTimeTaskTab.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/StartButton.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/TaskCard.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/TaskOpButton.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/TooltipTableWidget.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/TriggerTaskTab.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/tasks/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/util/Alert.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/util/InitWorker.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/util/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/Card.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/EmptyCard.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/FramelessDialog.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/ListTableWidgetItem.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/NumericTableWidgetItem.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/StartLoadingDialog.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/StatusBar.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/Tab.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/TabWidget.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/UpdateConfigWidgetItem.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/YesNonWidgetItem.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/gui/widget/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/interaction/ADBInteraction.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/interaction/DoNothingInteraction.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/interaction/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/logging/Logger.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/logging/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/ocr/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Foundation/Collections.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Foundation/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Globalization/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Graphics/Capture/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Graphics/DirectX/Direct3D11/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Graphics/DirectX/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Graphics/Imaging/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Graphics/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Media/Ocr/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Media/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Security/Cryptography/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Security/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Storage/Streams/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/Storage/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/Windows/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/delegate.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/export.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/idldsl.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/inspectable.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/roapi.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/types.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/rotypes/winstring.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/save/BlackBarProcessor.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/save/PostProcessor.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/save/SaveByInterval.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/save/SaveByKeyPress.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/save/SaveMethodBase.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/save/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/scene/FeatureScene.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/scene/Scene.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/scene/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/stats/StreamStats.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/stats/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/task/BaseTask.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/task/OneTimeTask.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/task/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/update/GithubMultiDownloader.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/update/Updater.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/update/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/update/gen_md5.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/util/Handler.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/util/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/util/exit_event.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/util/json.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/util/list.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/util/path.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/util/thread.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/util/win32_process.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok/util/yaml.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok_script.egg-info/SOURCES.txt +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok_script.egg-info/dependency_links.txt +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok_script.egg-info/requires.txt +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/ok_script.egg-info/top_level.txt +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/setup.cfg +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/tests/__init__.py +0 -0
- {ok-script-0.0.82 → ok-script-0.0.84}/tests/test_updater.py +0 -0
|
@@ -114,6 +114,14 @@ class EmulatorInstanceBase:
|
|
|
114
114
|
|
|
115
115
|
return None
|
|
116
116
|
|
|
117
|
+
@property
|
|
118
|
+
def player_id(self):
|
|
119
|
+
|
|
120
|
+
# Find all integer groups in the string that are at the end of the string
|
|
121
|
+
integers = re.findall(r'\d+$', self.name)
|
|
122
|
+
# Return the last integer if it exists, otherwise return 0
|
|
123
|
+
return int(integers[0]) if integers else 0
|
|
124
|
+
|
|
117
125
|
|
|
118
126
|
class EmulatorBase:
|
|
119
127
|
# Values here must match those in argument.yaml EmulatorInfo.Emulator.option
|
|
@@ -152,7 +152,7 @@ class HwndWindow:
|
|
|
152
152
|
return f"title:{self.title}_{self.exe_name}_{self.width}x{self.height}_{self.hwnd}_{self.exists}_{self.visible}"
|
|
153
153
|
|
|
154
154
|
|
|
155
|
-
def find_hwnd(title, exe_name, frame_width, frame_height):
|
|
155
|
+
def find_hwnd(title, exe_name, frame_width, frame_height, player_id=-1):
|
|
156
156
|
results = []
|
|
157
157
|
if exe_name is None and title is None:
|
|
158
158
|
return None, None, None, 0, 0, 0, 0
|
|
@@ -167,35 +167,50 @@ def find_hwnd(title, exe_name, frame_width, frame_height):
|
|
|
167
167
|
return True
|
|
168
168
|
elif not re.search(title, text):
|
|
169
169
|
return True
|
|
170
|
-
name, full_path = get_exe_by_hwnd(hwnd)
|
|
170
|
+
name, full_path, cmdline = get_exe_by_hwnd(hwnd)
|
|
171
171
|
x, y, border, title_height, width, height, scaling, ext_left_bounds, ext_top_bounds = get_window_bounds(
|
|
172
172
|
hwnd)
|
|
173
173
|
ret = (hwnd, full_path, width, height, x, y, text)
|
|
174
174
|
if exe_name:
|
|
175
175
|
if name != exe_name and exe_name != full_path:
|
|
176
176
|
return True
|
|
177
|
+
if player_id != -1:
|
|
178
|
+
if player_id != get_player_id_from_cmdline(cmdline):
|
|
179
|
+
logger.debug(
|
|
180
|
+
f'player id check failed,cmdline {cmdline} {get_player_id_from_cmdline(cmdline)} != {player_id}')
|
|
181
|
+
return True
|
|
177
182
|
results.append(ret)
|
|
178
183
|
return True
|
|
179
184
|
|
|
180
185
|
win32gui.EnumWindows(callback, None)
|
|
181
|
-
biggest = None
|
|
182
186
|
if len(results) > 0:
|
|
187
|
+
biggest = results[0]
|
|
183
188
|
for result in results:
|
|
184
189
|
from ok.capture.windows.BitBltCaptureMethod import bit_blt_test_hwnd
|
|
185
190
|
if (biggest is None or (result[2] * result[3]) > biggest[2] * biggest[3]) and bit_blt_test_hwnd(result[0]):
|
|
186
191
|
biggest = result
|
|
187
192
|
x_offset = 0
|
|
188
193
|
y_offset = 0
|
|
189
|
-
real_width
|
|
190
|
-
|
|
194
|
+
real_width = 0
|
|
195
|
+
real_height = 0
|
|
196
|
+
if frame_aspect_ratio != 0:
|
|
191
197
|
real_width, real_height = biggest[2], biggest[3]
|
|
192
198
|
matching_child = enum_child_windows(biggest, frame_aspect_ratio)
|
|
193
199
|
if matching_child is not None:
|
|
194
200
|
x_offset, y_offset, real_width, real_height = matching_child
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
201
|
+
logger.info(
|
|
202
|
+
f'find_hwnd {frame_width, frame_height} {biggest} {x_offset, y_offset, real_width, real_height}')
|
|
203
|
+
return biggest[6], biggest[0], biggest[1], x_offset, y_offset, real_width, real_height
|
|
204
|
+
|
|
205
|
+
return None, None, None, 0, 0, 0, 0
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def get_player_id_from_cmdline(cmdline):
|
|
209
|
+
for i in range(len(cmdline)):
|
|
210
|
+
if i != 0:
|
|
211
|
+
if cmdline[i].isdigit():
|
|
212
|
+
return int(cmdline[i])
|
|
213
|
+
return 0
|
|
199
214
|
|
|
200
215
|
|
|
201
216
|
def enum_child_windows(biggest, frame_aspect_ratio):
|
|
@@ -234,7 +249,7 @@ def get_exe_by_hwnd(hwnd):
|
|
|
234
249
|
|
|
235
250
|
# Get the process name and executable path
|
|
236
251
|
process = psutil.Process(pid)
|
|
237
|
-
return process.name(), process.exe()
|
|
252
|
+
return process.name(), process.exe(), process.cmdline()
|
|
238
253
|
|
|
239
254
|
|
|
240
255
|
if __name__ == '__main__':
|
|
@@ -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,
|
|
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,17 +135,21 @@ 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,
|
|
142
|
-
emulator.path, width, height)
|
|
152
|
+
emulator.path, width, height, emulator.player_id)
|
|
143
153
|
connected = adb_device is not None and name is not None
|
|
144
154
|
emulator_device = {"address": emulator.serial, "device": "adb",
|
|
145
155
|
"full_path": emulator.path, "connected": connected,
|
|
@@ -192,12 +202,13 @@ class DeviceManager:
|
|
|
192
202
|
self.start()
|
|
193
203
|
logger.debug(f'preferred device: {preferred}')
|
|
194
204
|
|
|
195
|
-
|
|
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}"
|
|
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 =
|
|
14
|
-
self.y =
|
|
13
|
+
self.x = round(x)
|
|
14
|
+
self.y = round(y)
|
|
15
15
|
if to_x != -1 and to_y != -1:
|
|
16
|
-
self.width =
|
|
17
|
-
self.height =
|
|
16
|
+
self.width = round(to_x - x)
|
|
17
|
+
self.height = round(to_y - y)
|
|
18
18
|
else:
|
|
19
|
-
self.width =
|
|
20
|
-
self.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(
|
|
269
|
-
|
|
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
|
|
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,
|
|
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
|
-
|
|
150
|
-
|
|
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):
|
|
@@ -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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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':
|
|
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):
|