MaaFw 2.1.0__py3-none-manylinux2014_x86_64.whl → 5.4.0b1__py3-none-manylinux2014_x86_64.whl
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.
- maa/__init__.py +7 -5
- maa/agent/__init__.py +12 -0
- maa/agent/agent_server.py +350 -0
- maa/agent_client.py +291 -0
- maa/bin/libMaaAdbControlUnit.so +0 -0
- maa/bin/libMaaAgentClient.so +0 -0
- maa/bin/libMaaAgentServer.so +0 -0
- maa/bin/libMaaCustomControlUnit.so +0 -0
- maa/bin/libMaaFramework.so +0 -0
- maa/bin/libMaaToolkit.so +0 -0
- maa/bin/libMaaUtils.so +0 -0
- maa/bin/libc++.so.1 +0 -0
- maa/bin/libc++abi.so.1 +0 -0
- maa/bin/libfastdeploy_ppocr.so +0 -0
- maa/bin/{libopencv_world4.so.408 → libonnxruntime.so.1} +0 -0
- maa/bin/{libonnxruntime.so.1.18.0 → libopencv_world4.so.411} +0 -0
- maa/bin/libunwind.so.1 +0 -0
- maa/bin/plugins/libMaaPluginDemo.so +0 -0
- maa/buffer.py +297 -153
- maa/context.py +449 -34
- maa/controller.py +760 -113
- maa/custom_action.py +46 -3
- maa/custom_recognition.py +69 -11
- maa/define.py +539 -42
- maa/event_sink.py +103 -0
- maa/job.py +95 -36
- maa/library.py +182 -53
- maa/pipeline.py +509 -0
- maa/resource.py +598 -71
- maa/tasker.py +696 -156
- maa/toolkit.py +125 -165
- maafw-5.4.0b1.dist-info/METADATA +297 -0
- maafw-5.4.0b1.dist-info/RECORD +35 -0
- maafw-5.4.0b1.dist-info/WHEEL +4 -0
- MaaFw-2.1.0.dist-info/METADATA +0 -166
- MaaFw-2.1.0.dist-info/RECORD +0 -26
- MaaFw-2.1.0.dist-info/WHEEL +0 -4
- MaaFw-2.1.0.dist-info/top_level.txt +0 -1
- maa/bin/libMaaDbgControlUnit.so +0 -0
- maa/notification_handler.py +0 -191
- {MaaFw-2.1.0.dist-info → maafw-5.4.0b1.dist-info/licenses}/LICENSE.md +0 -0
maa/controller.py
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import os
|
|
3
|
+
import numpy
|
|
2
4
|
from abc import abstractmethod
|
|
3
5
|
from ctypes import c_int32
|
|
4
|
-
import os
|
|
5
6
|
from pathlib import Path
|
|
6
|
-
from typing import Any, Dict, Optional, Union
|
|
7
|
+
from typing import Any, Dict, Optional, Tuple, Union
|
|
7
8
|
|
|
8
9
|
from .buffer import ImageBuffer, StringBuffer
|
|
9
|
-
from .
|
|
10
|
+
from .event_sink import EventSink, NotificationType
|
|
10
11
|
from .define import *
|
|
11
12
|
from .job import Job, JobWithResult
|
|
12
13
|
from .library import Library
|
|
@@ -14,25 +15,21 @@ from .library import Library
|
|
|
14
15
|
__all__ = [
|
|
15
16
|
"AdbController",
|
|
16
17
|
"DbgController",
|
|
18
|
+
"PlayCoverController",
|
|
17
19
|
"Win32Controller",
|
|
20
|
+
"GamepadController",
|
|
18
21
|
"CustomController",
|
|
19
22
|
]
|
|
20
23
|
|
|
21
24
|
|
|
22
25
|
class Controller:
|
|
23
|
-
_notification_handler: Optional[NotificationHandler]
|
|
24
26
|
_handle: MaaControllerHandle
|
|
25
|
-
_own: bool
|
|
27
|
+
_own: bool
|
|
26
28
|
|
|
27
29
|
def __init__(
|
|
28
30
|
self,
|
|
29
31
|
handle: Optional[MaaControllerHandle] = None,
|
|
30
32
|
):
|
|
31
|
-
if not Library.initialized:
|
|
32
|
-
raise RuntimeError(
|
|
33
|
-
"Library not initialized, please call `library.open()` first."
|
|
34
|
-
)
|
|
35
|
-
|
|
36
33
|
self._set_api_properties()
|
|
37
34
|
|
|
38
35
|
if handle:
|
|
@@ -44,40 +41,149 @@ class Controller:
|
|
|
44
41
|
|
|
45
42
|
def __del__(self):
|
|
46
43
|
if self._handle and self._own:
|
|
47
|
-
Library.framework.MaaControllerDestroy(self._handle)
|
|
44
|
+
Library.framework().MaaControllerDestroy(self._handle)
|
|
48
45
|
|
|
49
46
|
def post_connection(self) -> Job:
|
|
50
|
-
|
|
47
|
+
"""异步连接设备 / Asynchronously connect device
|
|
48
|
+
|
|
49
|
+
这是一个异步操作,会立即返回一个 Job 对象
|
|
50
|
+
This is an asynchronous operation that immediately returns a Job object
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Job: 作业对象,可通过 status/wait 查询状态 / Job object, can query status via status/wait
|
|
54
|
+
"""
|
|
55
|
+
ctrl_id = Library.framework().MaaControllerPostConnection(self._handle)
|
|
51
56
|
return self._gen_ctrl_job(ctrl_id)
|
|
52
57
|
|
|
53
|
-
def post_click(self, x: int, y: int) -> Job:
|
|
54
|
-
|
|
58
|
+
def post_click(self, x: int, y: int, contact: int = 0, pressure: int = 1) -> Job:
|
|
59
|
+
"""异步点击 / Asynchronously click
|
|
60
|
+
|
|
61
|
+
这是一个异步操作,会立即返回一个 Job 对象
|
|
62
|
+
This is an asynchronous operation that immediately returns a Job object
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
x: x 坐标 / x coordinate
|
|
66
|
+
y: y 坐标 / y coordinate
|
|
67
|
+
contact: 触点编号 (Adb 控制器: 手指编号; Win32 控制器: 鼠标按键 0:左键, 1:右键, 2:中键) / Contact number (Adb controller: finger number; Win32 controller: mouse button 0:left, 1:right, 2:middle)
|
|
68
|
+
pressure: 触点力度 / Contact pressure
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Job: 作业对象,可通过 status/wait 查询状态 / Job object, can query status via status/wait
|
|
72
|
+
"""
|
|
73
|
+
ctrl_id = Library.framework().MaaControllerPostClickV2(
|
|
74
|
+
self._handle, x, y, contact, pressure
|
|
75
|
+
)
|
|
55
76
|
return self._gen_ctrl_job(ctrl_id)
|
|
56
77
|
|
|
57
|
-
def post_swipe(
|
|
58
|
-
|
|
59
|
-
|
|
78
|
+
def post_swipe(
|
|
79
|
+
self,
|
|
80
|
+
x1: int,
|
|
81
|
+
y1: int,
|
|
82
|
+
x2: int,
|
|
83
|
+
y2: int,
|
|
84
|
+
duration: int,
|
|
85
|
+
contact: int = 0,
|
|
86
|
+
pressure: int = 1,
|
|
87
|
+
) -> Job:
|
|
88
|
+
"""滑动 / Swipe
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
x1: 起点 x 坐标 / Start x coordinate
|
|
92
|
+
y1: 起点 y 坐标 / Start y coordinate
|
|
93
|
+
x2: 终点 x 坐标 / End x coordinate
|
|
94
|
+
y2: 终点 y 坐标 / End y coordinate
|
|
95
|
+
duration: 滑动时长(毫秒) / Swipe duration in milliseconds
|
|
96
|
+
contact: 触点编号 (Adb 控制器: 手指编号; Win32 控制器: 鼠标按键 0:左键, 1:右键, 2:中键) / Contact number (Adb controller: finger number; Win32 controller: mouse button 0:left, 1:right, 2:middle)
|
|
97
|
+
pressure: 触点力度 / Contact pressure
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
Job: 作业对象 / Job object
|
|
101
|
+
"""
|
|
102
|
+
ctrl_id = Library.framework().MaaControllerPostSwipeV2(
|
|
103
|
+
self._handle, x1, y1, x2, y2, duration, contact, pressure
|
|
60
104
|
)
|
|
61
105
|
return self._gen_ctrl_job(ctrl_id)
|
|
62
106
|
|
|
63
107
|
def post_press_key(self, key: int) -> Job:
|
|
64
|
-
|
|
108
|
+
"""
|
|
109
|
+
Deprecated: Use post_click_key instead.
|
|
110
|
+
"""
|
|
111
|
+
return self.post_click_key(key)
|
|
112
|
+
|
|
113
|
+
def post_click_key(self, key: int) -> Job:
|
|
114
|
+
"""单击按键 / Click key
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
key: 虚拟键码 / Virtual key code
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Job: 作业对象 / Job object
|
|
121
|
+
"""
|
|
122
|
+
ctrl_id = Library.framework().MaaControllerPostClickKey(self._handle, key)
|
|
123
|
+
return self._gen_ctrl_job(ctrl_id)
|
|
124
|
+
|
|
125
|
+
def post_key_down(self, key: int) -> Job:
|
|
126
|
+
"""按下键 / Key down
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
key: 虚拟键码 / Virtual key code
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
Job: 作业对象 / Job object
|
|
133
|
+
"""
|
|
134
|
+
ctrl_id = Library.framework().MaaControllerPostKeyDown(self._handle, key)
|
|
135
|
+
return self._gen_ctrl_job(ctrl_id)
|
|
136
|
+
|
|
137
|
+
def post_key_up(self, key: int) -> Job:
|
|
138
|
+
"""抬起键 / Key up
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
key: 虚拟键码 / Virtual key code
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
Job: 作业对象 / Job object
|
|
145
|
+
"""
|
|
146
|
+
ctrl_id = Library.framework().MaaControllerPostKeyUp(self._handle, key)
|
|
65
147
|
return self._gen_ctrl_job(ctrl_id)
|
|
66
148
|
|
|
67
149
|
def post_input_text(self, text: str) -> Job:
|
|
68
|
-
|
|
150
|
+
"""输入文本 / Input text
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
text: 要输入的文本 / Text to input
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Job: 作业对象 / Job object
|
|
157
|
+
"""
|
|
158
|
+
ctrl_id = Library.framework().MaaControllerPostInputText(
|
|
69
159
|
self._handle, text.encode()
|
|
70
160
|
)
|
|
71
161
|
return self._gen_ctrl_job(ctrl_id)
|
|
72
162
|
|
|
73
163
|
def post_start_app(self, intent: str) -> Job:
|
|
74
|
-
|
|
164
|
+
"""启动应用 / Start app
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
intent: 目标应用 (Adb 控制器: package name 或 activity) / Target app (Adb controller: package name or activity)
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
Job: 作业对象 / Job object
|
|
171
|
+
"""
|
|
172
|
+
ctrl_id = Library.framework().MaaControllerPostStartApp(
|
|
75
173
|
self._handle, intent.encode()
|
|
76
174
|
)
|
|
77
175
|
return self._gen_ctrl_job(ctrl_id)
|
|
78
176
|
|
|
79
177
|
def post_stop_app(self, intent: str) -> Job:
|
|
80
|
-
|
|
178
|
+
"""关闭应用 / Stop app
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
intent: 目标应用 (Adb 控制器: package name) / Target app (Adb controller: package name)
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
Job: 作业对象 / Job object
|
|
185
|
+
"""
|
|
186
|
+
ctrl_id = Library.framework().MaaControllerPostStopApp(
|
|
81
187
|
self._handle, intent.encode()
|
|
82
188
|
)
|
|
83
189
|
return self._gen_ctrl_job(ctrl_id)
|
|
@@ -85,7 +191,18 @@ class Controller:
|
|
|
85
191
|
def post_touch_down(
|
|
86
192
|
self, x: int, y: int, contact: int = 0, pressure: int = 1
|
|
87
193
|
) -> Job:
|
|
88
|
-
|
|
194
|
+
"""按下 / Touch down
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
x: x 坐标 / x coordinate
|
|
198
|
+
y: y 坐标 / y coordinate
|
|
199
|
+
contact: 触点编号 (Adb 控制器: 手指编号; Win32 控制器: 鼠标按键 0:左键, 1:右键, 2:中键) / Contact number (Adb controller: finger number; Win32 controller: mouse button 0:left, 1:right, 2:middle)
|
|
200
|
+
pressure: 触点力度 / Contact pressure
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
Job: 作业对象 / Job object
|
|
204
|
+
"""
|
|
205
|
+
ctrl_id = Library.framework().MaaControllerPostTouchDown(
|
|
89
206
|
self._handle, contact, x, y, pressure
|
|
90
207
|
)
|
|
91
208
|
return self._gen_ctrl_job(ctrl_id)
|
|
@@ -93,17 +210,58 @@ class Controller:
|
|
|
93
210
|
def post_touch_move(
|
|
94
211
|
self, x: int, y: int, contact: int = 0, pressure: int = 1
|
|
95
212
|
) -> Job:
|
|
96
|
-
|
|
213
|
+
"""移动 / Move
|
|
214
|
+
|
|
215
|
+
Args:
|
|
216
|
+
x: x 坐标 / x coordinate
|
|
217
|
+
y: y 坐标 / y coordinate
|
|
218
|
+
contact: 触点编号 (Adb 控制器: 手指编号; Win32 控制器: 鼠标按键 0:左键, 1:右键, 2:中键) / Contact number (Adb controller: finger number; Win32 controller: mouse button 0:left, 1:right, 2:middle)
|
|
219
|
+
pressure: 触点力度 / Contact pressure
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Job: 作业对象 / Job object
|
|
223
|
+
"""
|
|
224
|
+
ctrl_id = Library.framework().MaaControllerPostTouchMove(
|
|
97
225
|
self._handle, contact, x, y, pressure
|
|
98
226
|
)
|
|
99
227
|
return self._gen_ctrl_job(ctrl_id)
|
|
100
228
|
|
|
101
229
|
def post_touch_up(self, contact: int = 0) -> Job:
|
|
102
|
-
|
|
230
|
+
"""抬起 / Touch up
|
|
231
|
+
|
|
232
|
+
Args:
|
|
233
|
+
contact: 触点编号 (Adb 控制器: 手指编号; Win32 控制器: 鼠标按键 0:左键, 1:右键, 2:中键) / Contact number (Adb controller: finger number; Win32 controller: mouse button 0:left, 1:right, 2:middle)
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
Job: 作业对象 / Job object
|
|
237
|
+
"""
|
|
238
|
+
ctrl_id = Library.framework().MaaControllerPostTouchUp(self._handle, contact)
|
|
239
|
+
return self._gen_ctrl_job(ctrl_id)
|
|
240
|
+
|
|
241
|
+
def post_scroll(self, dx: int, dy: int) -> Job:
|
|
242
|
+
"""滚动 / Scroll
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
dx: 水平滚动距离,正值向右滚动,负值向左滚动 / Horizontal scroll distance, positive for right, negative for left
|
|
246
|
+
dy: 垂直滚动距离,正值向上滚动,负值向下滚动 / Vertical scroll distance, positive for up, negative for down
|
|
247
|
+
|
|
248
|
+
Returns:
|
|
249
|
+
Job: 作业对象 / Job object
|
|
250
|
+
|
|
251
|
+
Note:
|
|
252
|
+
不是所有控制器都支持滚动操作 / Not all controllers support scroll operation
|
|
253
|
+
建议使用 120 的整数倍(WHEEL_DELTA)以获得最佳兼容性 / Using multiples of 120 (WHEEL_DELTA) is recommended
|
|
254
|
+
"""
|
|
255
|
+
ctrl_id = Library.framework().MaaControllerPostScroll(self._handle, dx, dy)
|
|
103
256
|
return self._gen_ctrl_job(ctrl_id)
|
|
104
257
|
|
|
105
258
|
def post_screencap(self) -> JobWithResult:
|
|
106
|
-
|
|
259
|
+
"""截图 / Screenshot
|
|
260
|
+
|
|
261
|
+
Returns:
|
|
262
|
+
JobWithResult: 作业对象,可通过 result 获取截图 / Job object, can get screenshot via result
|
|
263
|
+
"""
|
|
264
|
+
ctrl_id = Library.framework().MaaControllerPostScreencap(self._handle)
|
|
107
265
|
return JobWithResult(
|
|
108
266
|
ctrl_id,
|
|
109
267
|
self._status,
|
|
@@ -113,28 +271,127 @@ class Controller:
|
|
|
113
271
|
|
|
114
272
|
@property
|
|
115
273
|
def cached_image(self) -> numpy.ndarray:
|
|
274
|
+
"""获取最新一次截图 / Get the latest screenshot
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
numpy.ndarray: 截图图像 / Screenshot image
|
|
278
|
+
|
|
279
|
+
Raises:
|
|
280
|
+
RuntimeError: 如果获取失败
|
|
281
|
+
|
|
282
|
+
Note:
|
|
283
|
+
返回的图像是经过缩放的,尺寸根据截图目标尺寸设置(长边/短边)而定,可能与设备原始分辨率不同。
|
|
284
|
+
使用 resolution 属性可获取设备的原始(未缩放)分辨率。
|
|
285
|
+
|
|
286
|
+
The returned image is scaled according to the screenshot target size settings (long side / short side).
|
|
287
|
+
The image dimensions may differ from the raw device resolution.
|
|
288
|
+
Use the resolution property to get the raw (unscaled) device resolution.
|
|
289
|
+
"""
|
|
116
290
|
image_buffer = ImageBuffer()
|
|
117
|
-
if not Library.framework.MaaControllerCachedImage(
|
|
291
|
+
if not Library.framework().MaaControllerCachedImage(
|
|
118
292
|
self._handle, image_buffer._handle
|
|
119
293
|
):
|
|
120
294
|
raise RuntimeError("Failed to get cached image.")
|
|
121
295
|
return image_buffer.get()
|
|
122
296
|
|
|
297
|
+
def post_shell(self, cmd: str, timeout: int = 20000) -> JobWithResult:
|
|
298
|
+
"""执行 shell 命令 (仅 ADB 控制器) / Execute shell command (ADB only)
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
cmd: shell 命令 / shell command
|
|
302
|
+
timeout: 超时时间(毫秒),默认 20000 / Timeout in milliseconds, default 20000
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
JobWithResult: 作业对象,可通过 result 获取命令输出 / Job object, can get output via result
|
|
306
|
+
"""
|
|
307
|
+
ctrl_id = Library.framework().MaaControllerPostShell(
|
|
308
|
+
self._handle, cmd.encode("utf-8"), timeout
|
|
309
|
+
)
|
|
310
|
+
return JobWithResult(
|
|
311
|
+
ctrl_id,
|
|
312
|
+
self._status,
|
|
313
|
+
self._wait,
|
|
314
|
+
self._get_shell_output,
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
@property
|
|
318
|
+
def shell_output(self) -> str:
|
|
319
|
+
"""获取最近一次 shell 命令输出 / Get the latest shell command output
|
|
320
|
+
|
|
321
|
+
Returns:
|
|
322
|
+
str: shell 命令输出 / shell command output
|
|
323
|
+
|
|
324
|
+
Raises:
|
|
325
|
+
RuntimeError: 如果获取失败
|
|
326
|
+
"""
|
|
327
|
+
string_buffer = StringBuffer()
|
|
328
|
+
if not Library.framework().MaaControllerGetShellOutput(
|
|
329
|
+
self._handle, string_buffer._handle
|
|
330
|
+
):
|
|
331
|
+
raise RuntimeError("Failed to get shell output.")
|
|
332
|
+
return string_buffer.get()
|
|
333
|
+
|
|
123
334
|
@property
|
|
124
335
|
def connected(self) -> bool:
|
|
125
|
-
|
|
336
|
+
"""判断是否已连接 / Check if connected
|
|
337
|
+
|
|
338
|
+
Returns:
|
|
339
|
+
bool: 是否已连接 / Whether connected
|
|
340
|
+
"""
|
|
341
|
+
return bool(Library.framework().MaaControllerConnected(self._handle))
|
|
126
342
|
|
|
127
343
|
@property
|
|
128
344
|
def uuid(self) -> str:
|
|
345
|
+
"""获取设备 uuid / Get device uuid
|
|
346
|
+
|
|
347
|
+
Returns:
|
|
348
|
+
str: 设备 uuid / Device uuid
|
|
349
|
+
|
|
350
|
+
Raises:
|
|
351
|
+
RuntimeError: 如果获取失败
|
|
352
|
+
"""
|
|
129
353
|
buffer = StringBuffer()
|
|
130
|
-
if not Library.framework.MaaControllerGetUuid(self._handle, buffer._handle):
|
|
354
|
+
if not Library.framework().MaaControllerGetUuid(self._handle, buffer._handle):
|
|
131
355
|
raise RuntimeError("Failed to get UUID.")
|
|
132
356
|
return buffer.get()
|
|
133
357
|
|
|
358
|
+
@property
|
|
359
|
+
def resolution(self) -> Tuple[int, int]:
|
|
360
|
+
"""获取设备原始(未缩放)分辨率 / Get the raw (unscaled) device resolution
|
|
361
|
+
|
|
362
|
+
Returns:
|
|
363
|
+
Tuple[int, int]: (宽度, 高度),获取失败时返回 (0, 0) / (width, height), returns (0, 0) on failure
|
|
364
|
+
|
|
365
|
+
Note:
|
|
366
|
+
返回的是设备屏幕的实际分辨率,未经任何缩放处理。
|
|
367
|
+
而通过 cached_image 获取的截图是经过缩放的,其尺寸可能与此原始分辨率不同。
|
|
368
|
+
需要在首次截图后才能获取到有效值,否则返回 (0, 0)。
|
|
369
|
+
|
|
370
|
+
This returns the actual device screen resolution before any scaling.
|
|
371
|
+
The screenshot obtained via cached_image is scaled according to the screenshot target size settings,
|
|
372
|
+
so its dimensions may differ from this raw resolution.
|
|
373
|
+
Valid values are only available after the first screenshot is taken, otherwise returns (0, 0).
|
|
374
|
+
"""
|
|
375
|
+
width = ctypes.c_int32()
|
|
376
|
+
height = ctypes.c_int32()
|
|
377
|
+
if not Library.framework().MaaControllerGetResolution(
|
|
378
|
+
self._handle, ctypes.byref(width), ctypes.byref(height)
|
|
379
|
+
):
|
|
380
|
+
return (0, 0)
|
|
381
|
+
return (width.value, height.value)
|
|
382
|
+
|
|
134
383
|
def set_screenshot_target_long_side(self, long_side: int) -> bool:
|
|
384
|
+
"""设置截图缩放长边到指定长度 / Set screenshot scaling long side to specified length
|
|
385
|
+
|
|
386
|
+
Args:
|
|
387
|
+
long_side: 长边长度 / Long side length
|
|
388
|
+
|
|
389
|
+
Returns:
|
|
390
|
+
bool: 是否成功 / Whether successful
|
|
391
|
+
"""
|
|
135
392
|
cint = ctypes.c_int32(long_side)
|
|
136
393
|
return bool(
|
|
137
|
-
Library.framework.MaaControllerSetOption(
|
|
394
|
+
Library.framework().MaaControllerSetOption(
|
|
138
395
|
self._handle,
|
|
139
396
|
MaaOption(MaaCtrlOptionEnum.ScreenshotTargetLongSide),
|
|
140
397
|
ctypes.pointer(cint),
|
|
@@ -143,9 +400,17 @@ class Controller:
|
|
|
143
400
|
)
|
|
144
401
|
|
|
145
402
|
def set_screenshot_target_short_side(self, short_side: int) -> bool:
|
|
403
|
+
"""设置截图缩放短边到指定长度 / Set screenshot scaling short side to specified length
|
|
404
|
+
|
|
405
|
+
Args:
|
|
406
|
+
short_side: 短边长度 / Short side length
|
|
407
|
+
|
|
408
|
+
Returns:
|
|
409
|
+
bool: 是否成功 / Whether successful
|
|
410
|
+
"""
|
|
146
411
|
cint = ctypes.c_int32(short_side)
|
|
147
412
|
return bool(
|
|
148
|
-
Library.framework.MaaControllerSetOption(
|
|
413
|
+
Library.framework().MaaControllerSetOption(
|
|
149
414
|
self._handle,
|
|
150
415
|
MaaOption(MaaCtrlOptionEnum.ScreenshotTargetShortSide),
|
|
151
416
|
ctypes.pointer(cint),
|
|
@@ -153,17 +418,77 @@ class Controller:
|
|
|
153
418
|
)
|
|
154
419
|
)
|
|
155
420
|
|
|
421
|
+
def set_screenshot_use_raw_size(self, enable: bool) -> bool:
|
|
422
|
+
"""设置截图不缩放 / Set screenshot use raw size without scaling
|
|
423
|
+
|
|
424
|
+
注意:此选项可能导致在不同分辨率的设备上坐标不正确
|
|
425
|
+
Note: This option may cause incorrect coordinates on devices with different resolutions
|
|
426
|
+
|
|
427
|
+
Args:
|
|
428
|
+
enable: 是否启用 / Whether to enable
|
|
429
|
+
|
|
430
|
+
Returns:
|
|
431
|
+
bool: 是否成功 / Whether successful
|
|
432
|
+
"""
|
|
433
|
+
cbool = MaaBool(enable)
|
|
434
|
+
return bool(
|
|
435
|
+
Library.framework().MaaControllerSetOption(
|
|
436
|
+
self._handle,
|
|
437
|
+
MaaOption(MaaCtrlOptionEnum.ScreenshotUseRawSize),
|
|
438
|
+
ctypes.pointer(cbool),
|
|
439
|
+
ctypes.sizeof(MaaBool),
|
|
440
|
+
)
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
_sink_holder: Dict[int, "ControllerEventSink"] = {}
|
|
444
|
+
|
|
445
|
+
def add_sink(self, sink: "ControllerEventSink") -> Optional[int]:
|
|
446
|
+
"""添加控制器事件监听器 / Add controller event listener
|
|
447
|
+
|
|
448
|
+
Args:
|
|
449
|
+
sink: 事件监听器 / Event sink
|
|
450
|
+
|
|
451
|
+
Returns:
|
|
452
|
+
Optional[int]: 监听器 id,失败返回 None / Listener id, or None if failed
|
|
453
|
+
"""
|
|
454
|
+
sink_id = int(
|
|
455
|
+
Library.framework().MaaControllerAddSink(
|
|
456
|
+
self._handle, *EventSink._gen_c_param(sink)
|
|
457
|
+
)
|
|
458
|
+
)
|
|
459
|
+
if sink_id == MaaInvalidId:
|
|
460
|
+
return None
|
|
461
|
+
|
|
462
|
+
self._sink_holder[sink_id] = sink
|
|
463
|
+
return sink_id
|
|
464
|
+
|
|
465
|
+
def remove_sink(self, sink_id: int) -> None:
|
|
466
|
+
"""移除控制器事件监听器 / Remove controller event listener
|
|
467
|
+
|
|
468
|
+
Args:
|
|
469
|
+
sink_id: 监听器 id / Listener id
|
|
470
|
+
"""
|
|
471
|
+
Library.framework().MaaControllerRemoveSink(self._handle, sink_id)
|
|
472
|
+
self._sink_holder.pop(sink_id)
|
|
473
|
+
|
|
474
|
+
def clear_sinks(self) -> None:
|
|
475
|
+
"""清除所有控制器事件监听器 / Clear all controller event listeners"""
|
|
476
|
+
Library.framework().MaaControllerClearSinks(self._handle)
|
|
477
|
+
|
|
156
478
|
### private ###
|
|
157
479
|
|
|
158
480
|
def _status(self, maaid: int) -> MaaStatus:
|
|
159
|
-
return Library.framework.MaaControllerStatus(self._handle, maaid)
|
|
481
|
+
return Library.framework().MaaControllerStatus(self._handle, maaid)
|
|
160
482
|
|
|
161
483
|
def _wait(self, maaid: int) -> MaaStatus:
|
|
162
|
-
return Library.framework.MaaControllerWait(self._handle, maaid)
|
|
484
|
+
return Library.framework().MaaControllerWait(self._handle, maaid)
|
|
163
485
|
|
|
164
486
|
def _get_screencap(self, _: int) -> numpy.ndarray:
|
|
165
487
|
return self.cached_image
|
|
166
488
|
|
|
489
|
+
def _get_shell_output(self, _: int) -> str:
|
|
490
|
+
return self.shell_output
|
|
491
|
+
|
|
167
492
|
def _gen_ctrl_job(self, ctrlid: MaaCtrlId) -> Job:
|
|
168
493
|
return Job(
|
|
169
494
|
ctrlid,
|
|
@@ -179,68 +504,99 @@ class Controller:
|
|
|
179
504
|
return
|
|
180
505
|
Controller._api_properties_initialized = True
|
|
181
506
|
|
|
182
|
-
Library.framework.MaaControllerDestroy.restype = None
|
|
183
|
-
Library.framework.MaaControllerDestroy.argtypes = [MaaControllerHandle]
|
|
507
|
+
Library.framework().MaaControllerDestroy.restype = None
|
|
508
|
+
Library.framework().MaaControllerDestroy.argtypes = [MaaControllerHandle]
|
|
184
509
|
|
|
185
|
-
Library.framework.MaaControllerSetOption.restype = MaaBool
|
|
186
|
-
Library.framework.MaaControllerSetOption.argtypes = [
|
|
510
|
+
Library.framework().MaaControllerSetOption.restype = MaaBool
|
|
511
|
+
Library.framework().MaaControllerSetOption.argtypes = [
|
|
187
512
|
MaaControllerHandle,
|
|
188
513
|
MaaCtrlOption,
|
|
189
514
|
MaaOptionValue,
|
|
190
515
|
MaaOptionValueSize,
|
|
191
516
|
]
|
|
192
517
|
|
|
193
|
-
Library.framework.MaaControllerPostConnection.restype = MaaCtrlId
|
|
194
|
-
Library.framework.MaaControllerPostConnection.argtypes = [MaaControllerHandle]
|
|
518
|
+
Library.framework().MaaControllerPostConnection.restype = MaaCtrlId
|
|
519
|
+
Library.framework().MaaControllerPostConnection.argtypes = [MaaControllerHandle]
|
|
195
520
|
|
|
196
|
-
Library.framework.MaaControllerPostClick.restype = MaaCtrlId
|
|
197
|
-
Library.framework.MaaControllerPostClick.argtypes = [
|
|
521
|
+
Library.framework().MaaControllerPostClick.restype = MaaCtrlId
|
|
522
|
+
Library.framework().MaaControllerPostClick.argtypes = [
|
|
198
523
|
MaaControllerHandle,
|
|
199
524
|
c_int32,
|
|
200
525
|
c_int32,
|
|
201
526
|
]
|
|
202
527
|
|
|
203
|
-
Library.framework.
|
|
204
|
-
Library.framework.
|
|
528
|
+
Library.framework().MaaControllerPostClickV2.restype = MaaCtrlId
|
|
529
|
+
Library.framework().MaaControllerPostClickV2.argtypes = [
|
|
205
530
|
MaaControllerHandle,
|
|
206
531
|
c_int32,
|
|
207
532
|
c_int32,
|
|
208
533
|
c_int32,
|
|
209
534
|
c_int32,
|
|
535
|
+
]
|
|
536
|
+
|
|
537
|
+
Library.framework().MaaControllerPostSwipe.restype = MaaCtrlId
|
|
538
|
+
Library.framework().MaaControllerPostSwipe.argtypes = [
|
|
539
|
+
MaaControllerHandle,
|
|
540
|
+
c_int32,
|
|
541
|
+
c_int32,
|
|
542
|
+
c_int32,
|
|
543
|
+
c_int32,
|
|
544
|
+
c_int32,
|
|
545
|
+
]
|
|
546
|
+
|
|
547
|
+
Library.framework().MaaControllerPostSwipeV2.restype = MaaCtrlId
|
|
548
|
+
Library.framework().MaaControllerPostSwipeV2.argtypes = [
|
|
549
|
+
MaaControllerHandle,
|
|
550
|
+
c_int32,
|
|
551
|
+
c_int32,
|
|
552
|
+
c_int32,
|
|
553
|
+
c_int32,
|
|
554
|
+
c_int32,
|
|
555
|
+
c_int32,
|
|
210
556
|
c_int32,
|
|
211
557
|
]
|
|
212
558
|
|
|
213
|
-
Library.framework.
|
|
214
|
-
Library.framework.
|
|
559
|
+
Library.framework().MaaControllerPostClickKey.restype = MaaCtrlId
|
|
560
|
+
Library.framework().MaaControllerPostClickKey.argtypes = [
|
|
215
561
|
MaaControllerHandle,
|
|
216
562
|
c_int32,
|
|
217
563
|
]
|
|
218
564
|
|
|
219
|
-
Library.framework.
|
|
220
|
-
Library.framework.
|
|
565
|
+
Library.framework().MaaControllerPostKeyDown.restype = MaaCtrlId
|
|
566
|
+
Library.framework().MaaControllerPostKeyDown.argtypes = [
|
|
567
|
+
MaaControllerHandle,
|
|
568
|
+
c_int32,
|
|
569
|
+
]
|
|
570
|
+
Library.framework().MaaControllerPostKeyUp.restype = MaaCtrlId
|
|
571
|
+
Library.framework().MaaControllerPostKeyUp.argtypes = [
|
|
572
|
+
MaaControllerHandle,
|
|
573
|
+
c_int32,
|
|
574
|
+
]
|
|
575
|
+
Library.framework().MaaControllerPostInputText.restype = MaaCtrlId
|
|
576
|
+
Library.framework().MaaControllerPostInputText.argtypes = [
|
|
221
577
|
MaaControllerHandle,
|
|
222
578
|
ctypes.c_char_p,
|
|
223
579
|
]
|
|
224
580
|
|
|
225
|
-
Library.framework.MaaControllerPostScreencap.restype = MaaCtrlId
|
|
226
|
-
Library.framework.MaaControllerPostScreencap.argtypes = [
|
|
581
|
+
Library.framework().MaaControllerPostScreencap.restype = MaaCtrlId
|
|
582
|
+
Library.framework().MaaControllerPostScreencap.argtypes = [
|
|
227
583
|
MaaControllerHandle,
|
|
228
584
|
]
|
|
229
585
|
|
|
230
|
-
Library.framework.MaaControllerPostStartApp.restype = MaaCtrlId
|
|
231
|
-
Library.framework.MaaControllerPostStartApp.argtypes = [
|
|
586
|
+
Library.framework().MaaControllerPostStartApp.restype = MaaCtrlId
|
|
587
|
+
Library.framework().MaaControllerPostStartApp.argtypes = [
|
|
232
588
|
MaaControllerHandle,
|
|
233
589
|
ctypes.c_char_p,
|
|
234
590
|
]
|
|
235
591
|
|
|
236
|
-
Library.framework.MaaControllerPostStopApp.restype = MaaCtrlId
|
|
237
|
-
Library.framework.MaaControllerPostStopApp.argtypes = [
|
|
592
|
+
Library.framework().MaaControllerPostStopApp.restype = MaaCtrlId
|
|
593
|
+
Library.framework().MaaControllerPostStopApp.argtypes = [
|
|
238
594
|
MaaControllerHandle,
|
|
239
595
|
ctypes.c_char_p,
|
|
240
596
|
]
|
|
241
597
|
|
|
242
|
-
Library.framework.MaaControllerPostTouchDown.restype = MaaCtrlId
|
|
243
|
-
Library.framework.MaaControllerPostTouchDown.argtypes = [
|
|
598
|
+
Library.framework().MaaControllerPostTouchDown.restype = MaaCtrlId
|
|
599
|
+
Library.framework().MaaControllerPostTouchDown.argtypes = [
|
|
244
600
|
MaaControllerHandle,
|
|
245
601
|
c_int32,
|
|
246
602
|
c_int32,
|
|
@@ -248,8 +604,8 @@ class Controller:
|
|
|
248
604
|
c_int32,
|
|
249
605
|
]
|
|
250
606
|
|
|
251
|
-
Library.framework.MaaControllerPostTouchMove.restype = MaaCtrlId
|
|
252
|
-
Library.framework.MaaControllerPostTouchMove.argtypes = [
|
|
607
|
+
Library.framework().MaaControllerPostTouchMove.restype = MaaCtrlId
|
|
608
|
+
Library.framework().MaaControllerPostTouchMove.argtypes = [
|
|
253
609
|
MaaControllerHandle,
|
|
254
610
|
c_int32,
|
|
255
611
|
c_int32,
|
|
@@ -257,40 +613,77 @@ class Controller:
|
|
|
257
613
|
c_int32,
|
|
258
614
|
]
|
|
259
615
|
|
|
260
|
-
Library.framework.MaaControllerPostTouchUp.restype = MaaCtrlId
|
|
261
|
-
Library.framework.MaaControllerPostTouchUp.argtypes = [
|
|
616
|
+
Library.framework().MaaControllerPostTouchUp.restype = MaaCtrlId
|
|
617
|
+
Library.framework().MaaControllerPostTouchUp.argtypes = [
|
|
262
618
|
MaaControllerHandle,
|
|
263
619
|
c_int32,
|
|
264
620
|
]
|
|
265
|
-
|
|
266
|
-
Library.framework.
|
|
621
|
+
|
|
622
|
+
Library.framework().MaaControllerPostScroll.restype = MaaCtrlId
|
|
623
|
+
Library.framework().MaaControllerPostScroll.argtypes = [
|
|
624
|
+
MaaControllerHandle,
|
|
625
|
+
c_int32,
|
|
626
|
+
c_int32,
|
|
627
|
+
]
|
|
628
|
+
|
|
629
|
+
Library.framework().MaaControllerStatus.restype = MaaStatus
|
|
630
|
+
Library.framework().MaaControllerStatus.argtypes = [
|
|
267
631
|
MaaControllerHandle,
|
|
268
632
|
MaaCtrlId,
|
|
269
633
|
]
|
|
270
634
|
|
|
271
|
-
Library.framework.MaaControllerWait.restype = MaaStatus
|
|
272
|
-
Library.framework.MaaControllerWait.argtypes = [
|
|
635
|
+
Library.framework().MaaControllerWait.restype = MaaStatus
|
|
636
|
+
Library.framework().MaaControllerWait.argtypes = [
|
|
273
637
|
MaaControllerHandle,
|
|
274
638
|
MaaCtrlId,
|
|
275
639
|
]
|
|
276
640
|
|
|
277
|
-
Library.framework.MaaControllerConnected.restype = MaaBool
|
|
278
|
-
Library.framework.MaaControllerConnected.argtypes = [MaaControllerHandle]
|
|
641
|
+
Library.framework().MaaControllerConnected.restype = MaaBool
|
|
642
|
+
Library.framework().MaaControllerConnected.argtypes = [MaaControllerHandle]
|
|
279
643
|
|
|
280
|
-
Library.framework.MaaControllerCachedImage.restype = MaaBool
|
|
281
|
-
Library.framework.MaaControllerCachedImage.argtypes = [
|
|
644
|
+
Library.framework().MaaControllerCachedImage.restype = MaaBool
|
|
645
|
+
Library.framework().MaaControllerCachedImage.argtypes = [
|
|
282
646
|
MaaControllerHandle,
|
|
283
647
|
MaaImageBufferHandle,
|
|
284
648
|
]
|
|
285
649
|
|
|
286
|
-
Library.framework.MaaControllerGetUuid.restype = MaaBool
|
|
287
|
-
Library.framework.MaaControllerGetUuid.argtypes = [
|
|
650
|
+
Library.framework().MaaControllerGetUuid.restype = MaaBool
|
|
651
|
+
Library.framework().MaaControllerGetUuid.argtypes = [
|
|
288
652
|
MaaControllerHandle,
|
|
289
653
|
MaaStringBufferHandle,
|
|
290
654
|
]
|
|
291
655
|
|
|
656
|
+
Library.framework().MaaControllerGetResolution.restype = MaaBool
|
|
657
|
+
Library.framework().MaaControllerGetResolution.argtypes = [
|
|
658
|
+
MaaControllerHandle,
|
|
659
|
+
ctypes.POINTER(ctypes.c_int32),
|
|
660
|
+
ctypes.POINTER(ctypes.c_int32),
|
|
661
|
+
]
|
|
662
|
+
|
|
663
|
+
Library.framework().MaaControllerAddSink.restype = MaaSinkId
|
|
664
|
+
Library.framework().MaaControllerAddSink.argtypes = [
|
|
665
|
+
MaaControllerHandle,
|
|
666
|
+
MaaEventCallback,
|
|
667
|
+
ctypes.c_void_p,
|
|
668
|
+
]
|
|
669
|
+
|
|
670
|
+
Library.framework().MaaControllerRemoveSink.restype = None
|
|
671
|
+
Library.framework().MaaControllerRemoveSink.argtypes = [
|
|
672
|
+
MaaControllerHandle,
|
|
673
|
+
MaaSinkId,
|
|
674
|
+
]
|
|
675
|
+
|
|
676
|
+
Library.framework().MaaControllerClearSinks.restype = None
|
|
677
|
+
Library.framework().MaaControllerClearSinks.argtypes = [MaaControllerHandle]
|
|
678
|
+
|
|
292
679
|
|
|
293
680
|
class AdbController(Controller):
|
|
681
|
+
"""Adb 控制器 / Adb controller
|
|
682
|
+
|
|
683
|
+
截图方式和输入方式会在启动时进行测速, 选择最快的方案
|
|
684
|
+
Screenshot and input methods will be speed tested at startup, selecting the fastest option
|
|
685
|
+
"""
|
|
686
|
+
|
|
294
687
|
AGENT_BINARY_PATH = os.path.join(
|
|
295
688
|
os.path.dirname(__file__),
|
|
296
689
|
"../MaaAgentBinary",
|
|
@@ -304,21 +697,30 @@ class AdbController(Controller):
|
|
|
304
697
|
input_methods: int = MaaAdbInputMethodEnum.Default,
|
|
305
698
|
config: Dict[str, Any] = {},
|
|
306
699
|
agent_path: Union[str, Path] = AGENT_BINARY_PATH,
|
|
307
|
-
notification_handler: Optional[NotificationHandler] = None,
|
|
308
700
|
):
|
|
701
|
+
"""创建 Adb 控制器 / Create Adb controller
|
|
702
|
+
|
|
703
|
+
Args:
|
|
704
|
+
adb_path: adb 路径 / adb path
|
|
705
|
+
address: 连接地址 / connection address
|
|
706
|
+
screencap_methods: 所有可使用的截图方式 / all available screenshot methods
|
|
707
|
+
input_methods: 所有可使用的输入方式 / all available input methods
|
|
708
|
+
config: 额外配置 / extra config
|
|
709
|
+
agent_path: MaaAgentBinary 路径 / MaaAgentBinary path
|
|
710
|
+
|
|
711
|
+
Raises:
|
|
712
|
+
RuntimeError: 如果创建失败
|
|
713
|
+
"""
|
|
309
714
|
super().__init__()
|
|
310
715
|
self._set_adb_api_properties()
|
|
311
716
|
|
|
312
|
-
self.
|
|
313
|
-
|
|
314
|
-
self._handle = Library.framework.MaaAdbControllerCreate(
|
|
717
|
+
self._handle = Library.framework().MaaAdbControllerCreate(
|
|
315
718
|
str(adb_path).encode(),
|
|
316
719
|
address.encode(),
|
|
317
720
|
MaaAdbScreencapMethod(screencap_methods),
|
|
318
721
|
MaaAdbInputMethod(input_methods),
|
|
319
722
|
json.dumps(config, ensure_ascii=False).encode(),
|
|
320
723
|
str(agent_path).encode(),
|
|
321
|
-
*NotificationHandler._gen_c_param(self._notification_handler)
|
|
322
724
|
)
|
|
323
725
|
|
|
324
726
|
if not self._handle:
|
|
@@ -326,54 +728,103 @@ class AdbController(Controller):
|
|
|
326
728
|
|
|
327
729
|
def _set_adb_api_properties(self):
|
|
328
730
|
|
|
329
|
-
Library.framework.MaaAdbControllerCreate.restype = MaaControllerHandle
|
|
330
|
-
Library.framework.MaaAdbControllerCreate.argtypes = [
|
|
731
|
+
Library.framework().MaaAdbControllerCreate.restype = MaaControllerHandle
|
|
732
|
+
Library.framework().MaaAdbControllerCreate.argtypes = [
|
|
331
733
|
ctypes.c_char_p,
|
|
332
734
|
ctypes.c_char_p,
|
|
333
735
|
MaaAdbScreencapMethod,
|
|
334
736
|
MaaAdbInputMethod,
|
|
335
737
|
ctypes.c_char_p,
|
|
336
738
|
ctypes.c_char_p,
|
|
337
|
-
MaaNotificationCallback,
|
|
338
|
-
ctypes.c_void_p,
|
|
339
739
|
]
|
|
340
740
|
|
|
341
741
|
|
|
342
742
|
class Win32Controller(Controller):
|
|
743
|
+
"""Win32 控制器 / Win32 controller"""
|
|
343
744
|
|
|
344
745
|
def __init__(
|
|
345
746
|
self,
|
|
346
|
-
hWnd: ctypes.c_void_p,
|
|
347
|
-
screencap_method: int = MaaWin32ScreencapMethodEnum.
|
|
348
|
-
|
|
349
|
-
|
|
747
|
+
hWnd: Union[ctypes.c_void_p, int, None],
|
|
748
|
+
screencap_method: int = MaaWin32ScreencapMethodEnum.PrintWindow,
|
|
749
|
+
mouse_method: int = MaaWin32InputMethodEnum.Seize,
|
|
750
|
+
keyboard_method: int = MaaWin32InputMethodEnum.Seize,
|
|
350
751
|
):
|
|
752
|
+
"""创建 Win32 控制器 / Create Win32 controller
|
|
753
|
+
|
|
754
|
+
Args:
|
|
755
|
+
hWnd: 窗口句柄 / window handle
|
|
756
|
+
screencap_method: 使用的截图方式 / screenshot method used
|
|
757
|
+
mouse_method: 使用的鼠标输入方式 / mouse input method used
|
|
758
|
+
keyboard_method: 使用的键盘输入方式 / keyboard input method used
|
|
759
|
+
|
|
760
|
+
Raises:
|
|
761
|
+
RuntimeError: 如果创建失败
|
|
762
|
+
"""
|
|
351
763
|
super().__init__()
|
|
352
764
|
self._set_win32_api_properties()
|
|
353
765
|
|
|
354
|
-
self.
|
|
355
|
-
self._handle = Library.framework.MaaWin32ControllerCreate(
|
|
766
|
+
self._handle = Library.framework().MaaWin32ControllerCreate(
|
|
356
767
|
hWnd,
|
|
357
768
|
MaaWin32ScreencapMethod(screencap_method),
|
|
358
|
-
MaaWin32InputMethod(
|
|
359
|
-
|
|
769
|
+
MaaWin32InputMethod(mouse_method),
|
|
770
|
+
MaaWin32InputMethod(keyboard_method),
|
|
360
771
|
)
|
|
361
772
|
|
|
362
773
|
if not self._handle:
|
|
363
774
|
raise RuntimeError("Failed to create Win32 controller.")
|
|
364
775
|
|
|
365
776
|
def _set_win32_api_properties(self):
|
|
366
|
-
Library.framework.MaaWin32ControllerCreate.restype = MaaControllerHandle
|
|
367
|
-
Library.framework.MaaWin32ControllerCreate.argtypes = [
|
|
777
|
+
Library.framework().MaaWin32ControllerCreate.restype = MaaControllerHandle
|
|
778
|
+
Library.framework().MaaWin32ControllerCreate.argtypes = [
|
|
368
779
|
ctypes.c_void_p,
|
|
369
780
|
MaaWin32ScreencapMethod,
|
|
370
781
|
MaaWin32InputMethod,
|
|
371
|
-
|
|
372
|
-
|
|
782
|
+
MaaWin32InputMethod,
|
|
783
|
+
]
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
class PlayCoverController(Controller):
|
|
787
|
+
"""PlayCover 控制器 / PlayCover controller
|
|
788
|
+
|
|
789
|
+
用于在 macOS 上控制通过 PlayCover 运行的 iOS 应用
|
|
790
|
+
For controlling iOS apps running via PlayCover on macOS
|
|
791
|
+
"""
|
|
792
|
+
|
|
793
|
+
def __init__(
|
|
794
|
+
self,
|
|
795
|
+
address: str,
|
|
796
|
+
uuid: str,
|
|
797
|
+
):
|
|
798
|
+
"""创建 PlayCover 控制器 / Create PlayCover controller
|
|
799
|
+
|
|
800
|
+
Args:
|
|
801
|
+
address: PlayTools 服务地址 (host:port) / PlayTools service endpoint (host:port)
|
|
802
|
+
uuid: 目标应用 bundle identifier / Target app bundle identifier
|
|
803
|
+
|
|
804
|
+
Raises:
|
|
805
|
+
RuntimeError: 如果创建失败
|
|
806
|
+
"""
|
|
807
|
+
super().__init__()
|
|
808
|
+
self._set_playcover_api_properties()
|
|
809
|
+
|
|
810
|
+
self._handle = Library.framework().MaaPlayCoverControllerCreate(
|
|
811
|
+
address.encode(),
|
|
812
|
+
uuid.encode(),
|
|
813
|
+
)
|
|
814
|
+
|
|
815
|
+
if not self._handle:
|
|
816
|
+
raise RuntimeError("Failed to create PlayCover controller.")
|
|
817
|
+
|
|
818
|
+
def _set_playcover_api_properties(self):
|
|
819
|
+
Library.framework().MaaPlayCoverControllerCreate.restype = MaaControllerHandle
|
|
820
|
+
Library.framework().MaaPlayCoverControllerCreate.argtypes = [
|
|
821
|
+
ctypes.c_char_p,
|
|
822
|
+
ctypes.c_char_p,
|
|
373
823
|
]
|
|
374
824
|
|
|
375
825
|
|
|
376
826
|
class DbgController(Controller):
|
|
827
|
+
"""调试控制器 / Debug controller"""
|
|
377
828
|
|
|
378
829
|
def __init__(
|
|
379
830
|
self,
|
|
@@ -381,51 +832,109 @@ class DbgController(Controller):
|
|
|
381
832
|
write_path: Union[str, Path],
|
|
382
833
|
dbg_type: int,
|
|
383
834
|
config: Dict[str, Any] = {},
|
|
384
|
-
notification_handler: Optional[NotificationHandler] = None,
|
|
385
835
|
):
|
|
836
|
+
"""创建调试控制器 / Create debug controller
|
|
837
|
+
|
|
838
|
+
Args:
|
|
839
|
+
read_path: 输入路径, 包含通过 Recording 选项记录的操作 / Input path, includes operations recorded via Recording option
|
|
840
|
+
write_path: 输出路径, 包含执行结果 / Output path, includes execution results
|
|
841
|
+
dbg_type: 控制器模式 / Controller mode
|
|
842
|
+
config: 额外配置 / Extra config
|
|
843
|
+
|
|
844
|
+
Raises:
|
|
845
|
+
RuntimeError: 如果创建失败
|
|
846
|
+
"""
|
|
386
847
|
super().__init__()
|
|
387
848
|
self._set_dbg_api_properties()
|
|
388
849
|
|
|
389
|
-
self.
|
|
390
|
-
self._handle = Library.framework.MaaDbgControllerCreate(
|
|
850
|
+
self._handle = Library.framework().MaaDbgControllerCreate(
|
|
391
851
|
str(read_path).encode(),
|
|
392
852
|
str(write_path).encode(),
|
|
393
853
|
MaaDbgControllerType(dbg_type),
|
|
394
854
|
json.dumps(config, ensure_ascii=False).encode(),
|
|
395
|
-
*NotificationHandler._gen_c_param(self._notification_handler)
|
|
396
855
|
)
|
|
397
856
|
|
|
398
857
|
if not self._handle:
|
|
399
858
|
raise RuntimeError("Failed to create DBG controller.")
|
|
400
859
|
|
|
401
860
|
def _set_dbg_api_properties(self):
|
|
402
|
-
Library.framework.MaaDbgControllerCreate.restype = MaaControllerHandle
|
|
403
|
-
Library.framework.MaaDbgControllerCreate.argtypes = [
|
|
861
|
+
Library.framework().MaaDbgControllerCreate.restype = MaaControllerHandle
|
|
862
|
+
Library.framework().MaaDbgControllerCreate.argtypes = [
|
|
404
863
|
ctypes.c_char_p,
|
|
405
864
|
ctypes.c_char_p,
|
|
406
865
|
MaaDbgControllerType,
|
|
407
866
|
ctypes.c_char_p,
|
|
408
|
-
MaaNotificationCallback,
|
|
409
|
-
ctypes.c_void_p,
|
|
410
867
|
]
|
|
411
868
|
|
|
412
869
|
|
|
413
|
-
class
|
|
870
|
+
class GamepadController(Controller):
|
|
871
|
+
"""虚拟手柄控制器 (仅 Windows) / Virtual gamepad controller (Windows only)
|
|
414
872
|
|
|
415
|
-
|
|
873
|
+
通过 ViGEm 模拟 Xbox 360 或 DualShock 4 手柄,用于控制需要手柄输入的游戏。
|
|
874
|
+
Emulates Xbox 360 or DualShock 4 gamepad via ViGEm for controlling games that require gamepad input.
|
|
875
|
+
|
|
876
|
+
需要安装 ViGEm Bus Driver: https://github.com/ViGEm/ViGEmBus/releases
|
|
877
|
+
Requires ViGEm Bus Driver: https://github.com/ViGEm/ViGEmBus/releases
|
|
878
|
+
|
|
879
|
+
手柄操作映射:
|
|
880
|
+
- click_key/key_down/key_up: 数字按键 (使用 MaaGamepadButtonEnum)
|
|
881
|
+
- touch_down/touch_move/touch_up: 摇杆和扳机 (contact 使用 MaaGamepadContactEnum)
|
|
882
|
+
- contact 0: 左摇杆 (x, y: -32768~32767)
|
|
883
|
+
- contact 1: 右摇杆 (x, y: -32768~32767)
|
|
884
|
+
- contact 2: 左扳机 (pressure: 0~255)
|
|
885
|
+
- contact 3: 右扳机 (pressure: 0~255)
|
|
886
|
+
"""
|
|
416
887
|
|
|
417
888
|
def __init__(
|
|
418
889
|
self,
|
|
419
|
-
|
|
890
|
+
hWnd: Union[ctypes.c_void_p, int, None],
|
|
891
|
+
gamepad_type: int = MaaGamepadTypeEnum.Xbox360,
|
|
892
|
+
screencap_method: int = MaaWin32ScreencapMethodEnum.PrintWindow,
|
|
420
893
|
):
|
|
894
|
+
"""创建虚拟手柄控制器 / Create virtual gamepad controller
|
|
895
|
+
|
|
896
|
+
Args:
|
|
897
|
+
hWnd: 窗口句柄,用于截图 (可为 None,不需要截图时) / Window handle for screencap (can be None if screencap not needed)
|
|
898
|
+
gamepad_type: 手柄类型 (MaaGamepadTypeEnum.Xbox360 或 MaaGamepadTypeEnum.DualShock4) / Gamepad type
|
|
899
|
+
screencap_method: 截图方式 (当 hWnd 不为 None 时使用) / Screencap method (used when hWnd is not None)
|
|
900
|
+
|
|
901
|
+
Raises:
|
|
902
|
+
RuntimeError: 如果创建失败
|
|
903
|
+
"""
|
|
421
904
|
super().__init__()
|
|
422
|
-
self.
|
|
905
|
+
self._set_gamepad_api_properties()
|
|
906
|
+
|
|
907
|
+
self._handle = Library.framework().MaaGamepadControllerCreate(
|
|
908
|
+
hWnd,
|
|
909
|
+
MaaGamepadType(gamepad_type),
|
|
910
|
+
MaaWin32ScreencapMethod(screencap_method),
|
|
911
|
+
)
|
|
912
|
+
|
|
913
|
+
if not self._handle:
|
|
914
|
+
raise RuntimeError("Failed to create Gamepad controller.")
|
|
915
|
+
|
|
916
|
+
def _set_gamepad_api_properties(self):
|
|
917
|
+
Library.framework().MaaGamepadControllerCreate.restype = MaaControllerHandle
|
|
918
|
+
Library.framework().MaaGamepadControllerCreate.argtypes = [
|
|
919
|
+
ctypes.c_void_p,
|
|
920
|
+
MaaGamepadType,
|
|
921
|
+
MaaWin32ScreencapMethod,
|
|
922
|
+
]
|
|
423
923
|
|
|
424
|
-
|
|
924
|
+
|
|
925
|
+
class CustomController(Controller):
|
|
926
|
+
|
|
927
|
+
_callbacks: MaaCustomControllerCallbacks
|
|
928
|
+
|
|
929
|
+
def __init__(self):
|
|
930
|
+
super().__init__()
|
|
931
|
+
self._set_custom_api_properties()
|
|
425
932
|
|
|
426
933
|
self._callbacks = MaaCustomControllerCallbacks(
|
|
427
934
|
CustomController._c_connect_agent,
|
|
935
|
+
CustomController._c_connected_agent,
|
|
428
936
|
CustomController._c_request_uuid_agent,
|
|
937
|
+
CustomController._c_get_features_agent,
|
|
429
938
|
CustomController._c_start_app_agent,
|
|
430
939
|
CustomController._c_stop_app_agent,
|
|
431
940
|
CustomController._c_screencap_agent,
|
|
@@ -434,14 +943,16 @@ class CustomController(Controller):
|
|
|
434
943
|
CustomController._c_touch_down_agent,
|
|
435
944
|
CustomController._c_touch_move_agent,
|
|
436
945
|
CustomController._c_touch_up_agent,
|
|
437
|
-
CustomController.
|
|
946
|
+
CustomController._c_click_key_agent,
|
|
438
947
|
CustomController._c_input_text_agent,
|
|
948
|
+
CustomController._c_key_down_agent,
|
|
949
|
+
CustomController._c_key_up_agent,
|
|
950
|
+
CustomController._c_scroll_agent,
|
|
439
951
|
)
|
|
440
952
|
|
|
441
|
-
self._handle = Library.framework.MaaCustomControllerCreate(
|
|
953
|
+
self._handle = Library.framework().MaaCustomControllerCreate(
|
|
442
954
|
self.c_handle,
|
|
443
955
|
self.c_arg,
|
|
444
|
-
*NotificationHandler._gen_c_param(self._notification_handler)
|
|
445
956
|
)
|
|
446
957
|
|
|
447
958
|
if not self._handle:
|
|
@@ -459,10 +970,20 @@ class CustomController(Controller):
|
|
|
459
970
|
def connect(self) -> bool:
|
|
460
971
|
raise NotImplementedError
|
|
461
972
|
|
|
973
|
+
def connected(self) -> bool:
|
|
974
|
+
"""检查是否已连接(可选实现,默认返回 True)"""
|
|
975
|
+
return True
|
|
976
|
+
|
|
462
977
|
@abstractmethod
|
|
463
978
|
def request_uuid(self) -> str:
|
|
464
979
|
raise NotImplementedError
|
|
465
980
|
|
|
981
|
+
def get_features(self) -> int:
|
|
982
|
+
return (
|
|
983
|
+
MaaControllerFeatureEnum.UseMouseDownAndUpInsteadOfClick
|
|
984
|
+
| MaaControllerFeatureEnum.UseKeyboardDownAndUpInsteadOfClick
|
|
985
|
+
)
|
|
986
|
+
|
|
466
987
|
@abstractmethod
|
|
467
988
|
def start_app(self, intent: str) -> bool:
|
|
468
989
|
raise NotImplementedError
|
|
@@ -508,13 +1029,25 @@ class CustomController(Controller):
|
|
|
508
1029
|
raise NotImplementedError
|
|
509
1030
|
|
|
510
1031
|
@abstractmethod
|
|
511
|
-
def
|
|
1032
|
+
def click_key(self, keycode: int) -> bool:
|
|
512
1033
|
raise NotImplementedError
|
|
513
1034
|
|
|
514
1035
|
@abstractmethod
|
|
515
1036
|
def input_text(self, text: str) -> bool:
|
|
516
1037
|
raise NotImplementedError
|
|
517
1038
|
|
|
1039
|
+
@abstractmethod
|
|
1040
|
+
def key_down(self, keycode: int) -> bool:
|
|
1041
|
+
raise NotImplementedError
|
|
1042
|
+
|
|
1043
|
+
@abstractmethod
|
|
1044
|
+
def key_up(self, keycode: int) -> bool:
|
|
1045
|
+
raise NotImplementedError
|
|
1046
|
+
|
|
1047
|
+
@abstractmethod
|
|
1048
|
+
def scroll(self, dx: int, dy: int) -> bool:
|
|
1049
|
+
raise NotImplementedError
|
|
1050
|
+
|
|
518
1051
|
@staticmethod
|
|
519
1052
|
@MaaCustomControllerCallbacks.ConnectFunc
|
|
520
1053
|
def _c_connect_agent(
|
|
@@ -530,6 +1063,21 @@ class CustomController(Controller):
|
|
|
530
1063
|
|
|
531
1064
|
return int(self.connect())
|
|
532
1065
|
|
|
1066
|
+
@staticmethod
|
|
1067
|
+
@MaaCustomControllerCallbacks.ConnectedFunc
|
|
1068
|
+
def _c_connected_agent(
|
|
1069
|
+
trans_arg: ctypes.c_void_p,
|
|
1070
|
+
) -> int:
|
|
1071
|
+
if not trans_arg:
|
|
1072
|
+
return int(False)
|
|
1073
|
+
|
|
1074
|
+
self: CustomController = ctypes.cast(
|
|
1075
|
+
trans_arg,
|
|
1076
|
+
ctypes.py_object,
|
|
1077
|
+
).value
|
|
1078
|
+
|
|
1079
|
+
return int(self.connected())
|
|
1080
|
+
|
|
533
1081
|
@staticmethod
|
|
534
1082
|
@MaaCustomControllerCallbacks.RequestUuidFunc
|
|
535
1083
|
def _c_request_uuid_agent(
|
|
@@ -550,6 +1098,19 @@ class CustomController(Controller):
|
|
|
550
1098
|
uuid_buffer.set(uuid)
|
|
551
1099
|
return int(True)
|
|
552
1100
|
|
|
1101
|
+
@staticmethod
|
|
1102
|
+
@MaaCustomControllerCallbacks.GetFeaturesFunc
|
|
1103
|
+
def _c_get_features_agent(trans_arg: ctypes.c_void_p) -> int:
|
|
1104
|
+
if not trans_arg:
|
|
1105
|
+
return int(MaaControllerFeatureEnum.Null)
|
|
1106
|
+
|
|
1107
|
+
self: CustomController = ctypes.cast(
|
|
1108
|
+
trans_arg,
|
|
1109
|
+
ctypes.py_object,
|
|
1110
|
+
).value
|
|
1111
|
+
|
|
1112
|
+
return int(self.get_features())
|
|
1113
|
+
|
|
553
1114
|
@staticmethod
|
|
554
1115
|
@MaaCustomControllerCallbacks.StartAppFunc
|
|
555
1116
|
def _c_start_app_agent(
|
|
@@ -697,8 +1258,8 @@ class CustomController(Controller):
|
|
|
697
1258
|
return int(self.touch_up(int(c_contact)))
|
|
698
1259
|
|
|
699
1260
|
@staticmethod
|
|
700
|
-
@MaaCustomControllerCallbacks.
|
|
701
|
-
def
|
|
1261
|
+
@MaaCustomControllerCallbacks.ClickKeyFunc
|
|
1262
|
+
def _c_click_key_agent(
|
|
702
1263
|
c_keycode: ctypes.c_int32,
|
|
703
1264
|
trans_arg: ctypes.c_void_p,
|
|
704
1265
|
) -> int:
|
|
@@ -710,7 +1271,39 @@ class CustomController(Controller):
|
|
|
710
1271
|
ctypes.py_object,
|
|
711
1272
|
).value
|
|
712
1273
|
|
|
713
|
-
return int(self.
|
|
1274
|
+
return int(self.click_key(int(c_keycode)))
|
|
1275
|
+
|
|
1276
|
+
@staticmethod
|
|
1277
|
+
@MaaCustomControllerCallbacks.KeyDownFunc
|
|
1278
|
+
def _c_key_down_agent(
|
|
1279
|
+
c_keycode: ctypes.c_int32,
|
|
1280
|
+
trans_arg: ctypes.c_void_p,
|
|
1281
|
+
) -> int:
|
|
1282
|
+
if not trans_arg:
|
|
1283
|
+
return int(False)
|
|
1284
|
+
|
|
1285
|
+
self: CustomController = ctypes.cast(
|
|
1286
|
+
trans_arg,
|
|
1287
|
+
ctypes.py_object,
|
|
1288
|
+
).value
|
|
1289
|
+
|
|
1290
|
+
return int(self.key_down(int(c_keycode)))
|
|
1291
|
+
|
|
1292
|
+
@staticmethod
|
|
1293
|
+
@MaaCustomControllerCallbacks.KeyUpFunc
|
|
1294
|
+
def _c_key_up_agent(
|
|
1295
|
+
c_keycode: ctypes.c_int32,
|
|
1296
|
+
trans_arg: ctypes.c_void_p,
|
|
1297
|
+
) -> int:
|
|
1298
|
+
if not trans_arg:
|
|
1299
|
+
return int(False)
|
|
1300
|
+
|
|
1301
|
+
self: CustomController = ctypes.cast(
|
|
1302
|
+
trans_arg,
|
|
1303
|
+
ctypes.py_object,
|
|
1304
|
+
).value
|
|
1305
|
+
|
|
1306
|
+
return int(self.key_up(int(c_keycode)))
|
|
714
1307
|
|
|
715
1308
|
@staticmethod
|
|
716
1309
|
@MaaCustomControllerCallbacks.InputTextFunc
|
|
@@ -728,11 +1321,65 @@ class CustomController(Controller):
|
|
|
728
1321
|
|
|
729
1322
|
return int(self.input_text(c_text.decode()))
|
|
730
1323
|
|
|
1324
|
+
@staticmethod
|
|
1325
|
+
@MaaCustomControllerCallbacks.ScrollFunc
|
|
1326
|
+
def _c_scroll_agent(
|
|
1327
|
+
c_dx: ctypes.c_int32,
|
|
1328
|
+
c_dy: ctypes.c_int32,
|
|
1329
|
+
trans_arg: ctypes.c_void_p,
|
|
1330
|
+
) -> int:
|
|
1331
|
+
if not trans_arg:
|
|
1332
|
+
return int(False)
|
|
1333
|
+
|
|
1334
|
+
self: CustomController = ctypes.cast(
|
|
1335
|
+
trans_arg,
|
|
1336
|
+
ctypes.py_object,
|
|
1337
|
+
).value
|
|
1338
|
+
|
|
1339
|
+
return int(self.scroll(int(c_dx), int(c_dy)))
|
|
1340
|
+
|
|
731
1341
|
def _set_custom_api_properties(self):
|
|
732
|
-
Library.framework.MaaCustomControllerCreate.restype = MaaControllerHandle
|
|
733
|
-
Library.framework.MaaCustomControllerCreate.argtypes = [
|
|
1342
|
+
Library.framework().MaaCustomControllerCreate.restype = MaaControllerHandle
|
|
1343
|
+
Library.framework().MaaCustomControllerCreate.argtypes = [
|
|
734
1344
|
ctypes.POINTER(MaaCustomControllerCallbacks),
|
|
735
1345
|
ctypes.c_void_p,
|
|
736
|
-
MaaNotificationCallback,
|
|
737
|
-
ctypes.c_void_p,
|
|
738
1346
|
]
|
|
1347
|
+
|
|
1348
|
+
|
|
1349
|
+
class ControllerEventSink(EventSink):
|
|
1350
|
+
|
|
1351
|
+
@dataclass
|
|
1352
|
+
class ControllerActionDetail:
|
|
1353
|
+
ctrl_id: int
|
|
1354
|
+
uuid: str
|
|
1355
|
+
action: str
|
|
1356
|
+
param: dict
|
|
1357
|
+
|
|
1358
|
+
def on_controller_action(
|
|
1359
|
+
self,
|
|
1360
|
+
controller: Controller,
|
|
1361
|
+
noti_type: NotificationType,
|
|
1362
|
+
detail: ControllerActionDetail,
|
|
1363
|
+
):
|
|
1364
|
+
pass
|
|
1365
|
+
|
|
1366
|
+
def on_raw_notification(self, controller: Controller, msg: str, details: dict):
|
|
1367
|
+
pass
|
|
1368
|
+
|
|
1369
|
+
def _on_raw_notification(self, handle: ctypes.c_void_p, msg: str, details: dict):
|
|
1370
|
+
|
|
1371
|
+
controller = Controller(handle=handle)
|
|
1372
|
+
self.on_raw_notification(controller, msg, details)
|
|
1373
|
+
|
|
1374
|
+
noti_type = EventSink._notification_type(msg)
|
|
1375
|
+
if msg.startswith("Controller.Action"):
|
|
1376
|
+
detail = self.ControllerActionDetail(
|
|
1377
|
+
ctrl_id=details["ctrl_id"],
|
|
1378
|
+
uuid=details["uuid"],
|
|
1379
|
+
action=details["action"],
|
|
1380
|
+
param=details["param"],
|
|
1381
|
+
)
|
|
1382
|
+
self.on_controller_action(controller, noti_type, detail)
|
|
1383
|
+
|
|
1384
|
+
else:
|
|
1385
|
+
self.on_unknown_notification(controller, msg, details)
|