outleap 0.6.1__tar.gz → 0.7.0__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.
- {outleap-0.6.1 → outleap-0.7.0}/PKG-INFO +3 -2
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/api_wrappers.py +275 -36
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/scripts/agent.py +1 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/scripts/inspector.py +1 -2
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/scripts/repl.py +1 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/version.py +2 -2
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap.egg-info/PKG-INFO +3 -2
- {outleap-0.6.1 → outleap-0.7.0}/.coveragerc +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/.github/workflows/cis.yml +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/.github/workflows/pypi_publish.yml +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/.gitignore +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/COPYING +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/MANIFEST.in +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/README.md +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/codecov.yml +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/examples/README.md +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/examples/complex_leap_script.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/examples/simple_leap_script.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/pyproject.toml +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/setup.cfg +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/setup.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/__init__.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/bridge.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/client.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/protocol.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/qt_helpers.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/scripts/__init__.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/scripts/ui/inspector.ui +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/ui_elems.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap/utils.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap.egg-info/SOURCES.txt +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap.egg-info/dependency_links.txt +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap.egg-info/entry_points.txt +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap.egg-info/requires.txt +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/src/outleap.egg-info/top_level.txt +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/static/inspector_screenshot.png +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/tests/__init__.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/tests/test_client.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/tests/test_protocol.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/tests/test_stdio.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/tests/test_ui_elems.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/tests/test_wrappers.py +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/tests/ui_paths.txt +0 -0
- {outleap-0.6.1 → outleap-0.7.0}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: outleap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Tools for using asyncio to control a Second Life viewer over the LEAP protocol
|
|
5
5
|
Author-email: Salad Dais <83434023+SaladDais@users.noreply.github.com>
|
|
6
6
|
License: MIT License
|
|
@@ -26,6 +26,7 @@ Provides-Extra: tools
|
|
|
26
26
|
Requires-Dist: ptpython<4,>=3; extra == "tools"
|
|
27
27
|
Requires-Dist: qasync; extra == "tools"
|
|
28
28
|
Requires-Dist: pyside6-essentials; extra == "tools"
|
|
29
|
+
Dynamic: license-file
|
|
29
30
|
|
|
30
31
|
# outleap
|
|
31
32
|
|
|
@@ -97,11 +97,11 @@ class LLWindowAPI(LEAPAPIWrapper):
|
|
|
97
97
|
path: UI_PATH_TYPE,
|
|
98
98
|
) -> Dict:
|
|
99
99
|
if keycode is not None:
|
|
100
|
-
payload = {"keycode": keycode}
|
|
100
|
+
payload: Dict = {"keycode": keycode}
|
|
101
101
|
elif keysym is not None:
|
|
102
|
-
payload = {"keysym": keysym}
|
|
102
|
+
payload: Dict = {"keysym": keysym}
|
|
103
103
|
elif char is not None:
|
|
104
|
-
payload = {"char": char}
|
|
104
|
+
payload: Dict = {"char": char}
|
|
105
105
|
else:
|
|
106
106
|
raise ValueError("Didn't have one of keycode, keysym or char")
|
|
107
107
|
|
|
@@ -163,9 +163,7 @@ class LLWindowAPI(LEAPAPIWrapper):
|
|
|
163
163
|
|
|
164
164
|
async def get_paths(self, under: Optional[UI_PATH_TYPE] = None) -> List[UIPath]:
|
|
165
165
|
"""Get all UI paths under the root, or under a path if specified"""
|
|
166
|
-
|
|
167
|
-
under = ""
|
|
168
|
-
resp = await self._client.command(self._pump_name, "getPaths", {"under": str(under)})
|
|
166
|
+
resp = await self._client.command(self._pump_name, "getPaths", {"under": str(under or "")})
|
|
169
167
|
if error := resp.get("error"):
|
|
170
168
|
raise ValueError(error)
|
|
171
169
|
return [UIPath(path) for path in resp.get("paths", [])]
|
|
@@ -185,9 +183,9 @@ class LLWindowAPI(LEAPAPIWrapper):
|
|
|
185
183
|
button: str = None,
|
|
186
184
|
) -> Dict:
|
|
187
185
|
if path is not None:
|
|
188
|
-
payload = {"path": str(path)}
|
|
186
|
+
payload: Dict = {"path": str(path)}
|
|
189
187
|
elif x is not None and y is not None:
|
|
190
|
-
payload = {"x": x, "y": y}
|
|
188
|
+
payload: Dict = {"x": x, "y": y}
|
|
191
189
|
else:
|
|
192
190
|
raise ValueError("Didn't have one of x + y or path")
|
|
193
191
|
|
|
@@ -381,7 +379,7 @@ class LLAgentAPI(LEAPAPIWrapper):
|
|
|
381
379
|
lookat_type: int = 8,
|
|
382
380
|
):
|
|
383
381
|
"""Look at either a specific `obj_uuid` or the closest object to `position`"""
|
|
384
|
-
payload = {"type": lookat_type}
|
|
382
|
+
payload: Dict = {"type": lookat_type}
|
|
385
383
|
if obj_uuid:
|
|
386
384
|
payload["obj_uuid"] = obj_uuid
|
|
387
385
|
elif position:
|
|
@@ -391,9 +389,124 @@ class LLAgentAPI(LEAPAPIWrapper):
|
|
|
391
389
|
self._client.void_command(self._pump_name, "lookAt", payload)
|
|
392
390
|
|
|
393
391
|
def get_auto_pilot(self) -> Awaitable[Dict]:
|
|
394
|
-
"""Get information about current state of the autopilot system"""
|
|
392
|
+
"""Get information about the current state of the autopilot system"""
|
|
395
393
|
return self._client.command(self._pump_name, "getAutoPilot", {})
|
|
396
394
|
|
|
395
|
+
def get_agent_screen_pos(self, avatar_id: Optional[uuid.UUID] = None) -> Awaitable[Dict]:
|
|
396
|
+
"""Get where the specified agent is on the screen, uses current agent's ID if none provided"""
|
|
397
|
+
payload = {}
|
|
398
|
+
if avatar_id:
|
|
399
|
+
payload["avatar_id"] = avatar_id
|
|
400
|
+
return self._client.command(self._pump_name, "getAgentScreenPos", payload)
|
|
401
|
+
|
|
402
|
+
def get_nearby_avatars(self, dist: Optional[float] = None) -> Awaitable[List[Dict]]:
|
|
403
|
+
payload = {}
|
|
404
|
+
if dist is not None:
|
|
405
|
+
payload["dist"] = dist
|
|
406
|
+
fut = self._client.command(self._pump_name, "getNearbyAvatarsList", payload)
|
|
407
|
+
return _data_unwrapper(fut, "result")
|
|
408
|
+
|
|
409
|
+
def get_nearby_objects(self, dist: Optional[float] = None) -> Awaitable[List[Dict]]:
|
|
410
|
+
payload = {}
|
|
411
|
+
if dist is not None:
|
|
412
|
+
payload["dist"] = dist
|
|
413
|
+
fut = self._client.command(self._pump_name, "getNearbyObjectsList", payload)
|
|
414
|
+
return _data_unwrapper(fut, "result")
|
|
415
|
+
|
|
416
|
+
def get_position(self) -> Awaitable[Dict]:
|
|
417
|
+
"""Get details about the agent's position"""
|
|
418
|
+
return self._client.command(self._pump_name, "getPosition", {})
|
|
419
|
+
|
|
420
|
+
def request_sit(
|
|
421
|
+
self,
|
|
422
|
+
obj_uuid: Optional[uuid.UUID] = None,
|
|
423
|
+
position: Optional[Sequence[float]] = None,
|
|
424
|
+
) -> Awaitable:
|
|
425
|
+
"""Request to sit on obj_id, or object closest to position. Sits on ground if no args provided"""
|
|
426
|
+
if position and obj_uuid is not None:
|
|
427
|
+
raise ValueError("obj_uuid and position are mutually exclusive")
|
|
428
|
+
|
|
429
|
+
params = {}
|
|
430
|
+
if obj_uuid:
|
|
431
|
+
params["obj_uuid"] = obj_uuid
|
|
432
|
+
if position:
|
|
433
|
+
params["position"] = list(position)
|
|
434
|
+
return self._client.command(self._pump_name, "requestSit", params)
|
|
435
|
+
|
|
436
|
+
def request_stand(self) -> None:
|
|
437
|
+
self._client.void_command(self._pump_name, "requestStand", {})
|
|
438
|
+
|
|
439
|
+
def request_teleport(
|
|
440
|
+
self,
|
|
441
|
+
region_name: Optional[str] = None,
|
|
442
|
+
x: Optional[int] = None,
|
|
443
|
+
y: Optional[int] = None,
|
|
444
|
+
z: Optional[int] = None,
|
|
445
|
+
skip_confirmation: bool = True,
|
|
446
|
+
) -> None:
|
|
447
|
+
"""Request a teleport from the system, (x,y,z) are global if region_name unspecified"""
|
|
448
|
+
have_coords = all(_ is not None for _ in (x, y, z))
|
|
449
|
+
if not region_name and not have_coords:
|
|
450
|
+
raise ValueError("region_name or (x,y,z) is required")
|
|
451
|
+
|
|
452
|
+
params: Dict = {"skip_confirmation": skip_confirmation}
|
|
453
|
+
if region_name:
|
|
454
|
+
params["regionname"] = region_name
|
|
455
|
+
if have_coords:
|
|
456
|
+
params["x"] = x
|
|
457
|
+
params["y"] = y
|
|
458
|
+
params["z"] = z
|
|
459
|
+
|
|
460
|
+
self._client.void_command(self._pump_name, "requestTeleport", params)
|
|
461
|
+
|
|
462
|
+
def get_id(self) -> Awaitable[uuid.UUID]:
|
|
463
|
+
"""Get the current agent's ID"""
|
|
464
|
+
return _data_unwrapper(self._client.command(self._pump_name, "getId", {}), "id")
|
|
465
|
+
|
|
466
|
+
def get_groups(self) -> Awaitable[List[Dict]]:
|
|
467
|
+
return _data_unwrapper(self._client.command(self._pump_name, "getGroups", {}), "groups")
|
|
468
|
+
|
|
469
|
+
def play_animation(self, item_id: uuid.UUID, inworld: bool = True) -> Awaitable:
|
|
470
|
+
"""Play an animation by item id"""
|
|
471
|
+
return self._client.command(
|
|
472
|
+
self._pump_name, "playAnimation", {"item_id": item_id, "inworld": inworld}
|
|
473
|
+
)
|
|
474
|
+
|
|
475
|
+
def stop_animation(self, item_id: uuid.UUID) -> Awaitable:
|
|
476
|
+
"""Stop an animation by item id"""
|
|
477
|
+
return self._client.command(self._pump_name, "stopAnimation", {"item_id": item_id})
|
|
478
|
+
|
|
479
|
+
def get_animation_info(self, item_id: uuid.UUID) -> Awaitable[Dict]:
|
|
480
|
+
"""Get information about an animation by item id"""
|
|
481
|
+
return _data_unwrapper(
|
|
482
|
+
self._client.command(self._pump_name, "getAnimationInfo", {"item_id": item_id}), "anim_info"
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
def set_camera_params(self, params: Dict) -> None:
|
|
486
|
+
"""Set camera parameters using LSL-like semantics"""
|
|
487
|
+
self._client.void_command(self._pump_name, "setCameraParams", params)
|
|
488
|
+
|
|
489
|
+
def set_follow_cam_active(self, active: bool) -> None:
|
|
490
|
+
self._client.void_command(self._pump_name, "setFollowCamActive", {"active": active})
|
|
491
|
+
|
|
492
|
+
def remove_camera_params(self) -> None:
|
|
493
|
+
self._client.void_command(self._pump_name, "removeCameraParams", {})
|
|
494
|
+
|
|
495
|
+
def request_touch(
|
|
496
|
+
self,
|
|
497
|
+
obj_uuid: Optional[uuid.UUID] = None,
|
|
498
|
+
position: Optional[Sequence[float]] = None,
|
|
499
|
+
face: int = 0,
|
|
500
|
+
) -> None:
|
|
501
|
+
if not obj_uuid and not position:
|
|
502
|
+
raise ValueError("Must specify either obj_uuid or position")
|
|
503
|
+
params: Dict = {"face": face}
|
|
504
|
+
if obj_uuid:
|
|
505
|
+
params["obj_uuid"] = obj_uuid
|
|
506
|
+
if position:
|
|
507
|
+
params["position"] = list(position)
|
|
508
|
+
self._client.void_command(self._pump_name, "requestTouch", params)
|
|
509
|
+
|
|
397
510
|
|
|
398
511
|
class LLFloaterRegAPI(LEAPAPIWrapper):
|
|
399
512
|
PUMP_NAME = "LLFloaterReg"
|
|
@@ -466,40 +579,159 @@ class LLFloaterRegAPI(LEAPAPIWrapper):
|
|
|
466
579
|
)
|
|
467
580
|
|
|
468
581
|
|
|
469
|
-
class
|
|
470
|
-
PUMP_NAME = "
|
|
471
|
-
|
|
582
|
+
class LLURLDispatcherAPI(LEAPAPIWrapper):
|
|
583
|
+
PUMP_NAME = "LLUrlDispatcher"
|
|
584
|
+
|
|
585
|
+
def dispatch(self, url: str, trusted: bool = True):
|
|
586
|
+
"""At startup time or on clicks in internal web browsers, teleport, open map, or run requested command."""
|
|
587
|
+
self._client.void_command(self._pump_name, "dispatch", {"url": url, "trusted": trusted})
|
|
588
|
+
|
|
589
|
+
def dispatch_right_click(self, url: str):
|
|
590
|
+
"""Dispatch ["url"] as if from a right-click on a hot link."""
|
|
591
|
+
self._client.void_command(self._pump_name, "dispatchRightClick", {"url": url})
|
|
472
592
|
|
|
473
|
-
def
|
|
474
|
-
"""
|
|
475
|
-
|
|
476
|
-
return _data_unwrapper(fut, "camera_id")
|
|
593
|
+
def dispatch_from_text_editor(self, url: str):
|
|
594
|
+
"""Dispatch ["url"] as if from an edit field"""
|
|
595
|
+
self._client.void_command(self._pump_name, "dispatchFromTextEditor", {"url": url})
|
|
477
596
|
|
|
478
|
-
def set_camera(self, camera_id: int) -> None:
|
|
479
|
-
"""Request camera number: returns ["camera_id"]"""
|
|
480
|
-
payload = {"camera_id": camera_id}
|
|
481
|
-
self._client.void_command(self._pump_name, "set_camera", payload, op_key=self.OP_KEY)
|
|
482
597
|
|
|
483
|
-
|
|
598
|
+
class LLFloaterAboutAPI(LEAPAPIWrapper):
|
|
599
|
+
PUMP_NAME = "LLFloaterAbout"
|
|
600
|
+
|
|
601
|
+
def get_info(self) -> Awaitable[dict]:
|
|
602
|
+
"""Request an LLSD::Map containing information used to populate About box"""
|
|
603
|
+
return self._client.command(self._pump_name, "getInfo")
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
class LLGestureAPI(LEAPAPIWrapper):
|
|
607
|
+
PUMP_NAME = "LLGesture"
|
|
608
|
+
|
|
609
|
+
def get_active_gestures(self) -> Awaitable[list]:
|
|
484
610
|
"""
|
|
485
|
-
|
|
611
|
+
Return information about the agent's available gestures
|
|
486
612
|
|
|
487
|
-
|
|
613
|
+
Returns a list of dicts with the following dict values for each entry:
|
|
614
|
+
["name"]: name of the gesture, may be empty
|
|
615
|
+
["trigger"]: trigger string used to invoke via user chat, may be empty
|
|
616
|
+
["playing"]: true or false indicating the playing state
|
|
488
617
|
"""
|
|
489
|
-
self._client.
|
|
618
|
+
fut = self._client.command(self._pump_name, "getActiveGestures")
|
|
619
|
+
return _data_unwrapper(fut, "gestures")
|
|
620
|
+
|
|
621
|
+
def is_gesture_playing(self, gesture_id: uuid.UUID) -> Awaitable[bool]:
|
|
622
|
+
fut = self._client.command(self._pump_name, "isGesturePlaying", {"id": gesture_id})
|
|
623
|
+
return _data_unwrapper(fut, "playing")
|
|
624
|
+
|
|
625
|
+
def start_gesture(self, gesture_id: uuid):
|
|
626
|
+
self._client.void_command(self._pump_name, "startGesture", {"id": gesture_id})
|
|
627
|
+
|
|
628
|
+
def stop_gesture(self, gesture_id: uuid):
|
|
629
|
+
self._client.void_command(self._pump_name, "stopGesture", {"id": gesture_id})
|
|
630
|
+
|
|
490
631
|
|
|
491
|
-
|
|
632
|
+
class GroupChatAPI(LEAPAPIWrapper):
|
|
633
|
+
PUMP_NAME = "GroupChat"
|
|
634
|
+
|
|
635
|
+
def start_im(self, group_id: uuid.UUID) -> Awaitable:
|
|
636
|
+
"""Start an IM session for the specified group"""
|
|
637
|
+
return self._client.command(self._pump_name, "startGroupChat", {"group_id": group_id})
|
|
638
|
+
|
|
639
|
+
def end_im(self, group_id: uuid.UUID):
|
|
640
|
+
"""End an IM session with the specified group"""
|
|
641
|
+
return self._client.command(self._pump_name, "leaveGroupChat", {"group_id": group_id})
|
|
642
|
+
|
|
643
|
+
def send_im(self, group_id: uuid.UUID, message: str) -> Awaitable:
|
|
644
|
+
"""Send an IM to the specified group"""
|
|
645
|
+
return self._client.command(
|
|
646
|
+
self._pump_name, "sendGroupIM", {"group_id": group_id, "message": message}
|
|
647
|
+
)
|
|
648
|
+
|
|
649
|
+
|
|
650
|
+
class LLChatBarAPI(LEAPAPIWrapper):
|
|
651
|
+
PUMP_NAME = "LLChatBar"
|
|
652
|
+
|
|
653
|
+
def send_chat(self, message: str, channel: int = 0, chat_type: str = "normal"):
|
|
492
654
|
"""
|
|
493
|
-
Send
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
joint_name = e.g. mWristLeft
|
|
499
|
-
param_name = rot | pos | scale | eff
|
|
500
|
-
param value = array of 3 floats [x,y,z]
|
|
655
|
+
Send chat to the simulator
|
|
656
|
+
|
|
657
|
+
:param message: chat message text [required]
|
|
658
|
+
:param channel: chat channel number [default = 0]
|
|
659
|
+
:param chat_type: "whisper", "normal", "shout" [default = "normal"]
|
|
501
660
|
"""
|
|
502
|
-
self._client.void_command(
|
|
661
|
+
self._client.void_command(
|
|
662
|
+
self._pump_name, "sendChat", {"message": message, "channel": channel, "chat_type": chat_type}
|
|
663
|
+
)
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
class LLAppViewerAPI(LEAPAPIWrapper):
|
|
667
|
+
PUMP_NAME = "LLAppViewer"
|
|
668
|
+
|
|
669
|
+
def request_quit(self):
|
|
670
|
+
self._client.void_command(self._pump_name, "requestQuit")
|
|
671
|
+
|
|
672
|
+
def force_quit(self):
|
|
673
|
+
self._client.void_command(self._pump_name, "forceQuit")
|
|
674
|
+
|
|
675
|
+
|
|
676
|
+
class LLTeleportHandlerAPI(LEAPAPIWrapper):
|
|
677
|
+
PUMP_NAME = "LLTeleportHandler"
|
|
678
|
+
|
|
679
|
+
def teleport(
|
|
680
|
+
self,
|
|
681
|
+
region_name: Optional[str] = None,
|
|
682
|
+
x: Optional[int] = None,
|
|
683
|
+
y: Optional[int] = None,
|
|
684
|
+
z: Optional[int] = None,
|
|
685
|
+
) -> None:
|
|
686
|
+
have_coords = all(_ is not None for _ in (x, y, z))
|
|
687
|
+
if not region_name and not have_coords:
|
|
688
|
+
raise ValueError("region_name or (x,y,z) is required")
|
|
689
|
+
|
|
690
|
+
params = {}
|
|
691
|
+
if region_name:
|
|
692
|
+
params["regionname"] = region_name
|
|
693
|
+
if have_coords:
|
|
694
|
+
params["x"] = x
|
|
695
|
+
params["y"] = y
|
|
696
|
+
params["z"] = z
|
|
697
|
+
|
|
698
|
+
self._client.void_command(self._pump_name, "teleport", params)
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
class LLAppearanceAPI(LEAPAPIWrapper):
|
|
702
|
+
PUMP_NAME = "LLAppearance"
|
|
703
|
+
|
|
704
|
+
def wear_outfit(
|
|
705
|
+
self,
|
|
706
|
+
folder_id: Optional[uuid.UUID] = None,
|
|
707
|
+
folder_name: Optional[str] = None,
|
|
708
|
+
append: bool = False,
|
|
709
|
+
) -> Awaitable:
|
|
710
|
+
params: Dict = {"append": append}
|
|
711
|
+
if folder_id:
|
|
712
|
+
params["folder_id"] = folder_id
|
|
713
|
+
if folder_name:
|
|
714
|
+
params["folder_name"] = folder_name
|
|
715
|
+
return self._client.command(self._pump_name, "wearOutfit", params)
|
|
716
|
+
|
|
717
|
+
def wear_items(self, item_ids: Sequence[uuid.UUID], replace: bool = False) -> None:
|
|
718
|
+
self._client.void_command(
|
|
719
|
+
self._pump_name, "wearItems", {"items_id": list(item_ids), "replace": replace}
|
|
720
|
+
)
|
|
721
|
+
|
|
722
|
+
def detach_items(self, item_ids: Sequence[uuid.UUID], replace: bool = False) -> None:
|
|
723
|
+
self._client.void_command(
|
|
724
|
+
self._pump_name, "detachItems", {"items_id": list(item_ids), "replace": replace}
|
|
725
|
+
)
|
|
726
|
+
|
|
727
|
+
def get_outfits_list(self) -> Awaitable[Dict[str, str]]:
|
|
728
|
+
return _data_unwrapper(self._client.command(self._pump_name, "getOutfitsList", {}), "outfits")
|
|
729
|
+
|
|
730
|
+
def get_outfit_items(self, outfit_id: uuid.UUID) -> Awaitable[Dict[str, dict]]:
|
|
731
|
+
return _data_unwrapper(
|
|
732
|
+
self._client.command(self._pump_name, "getOutfitItems", {"outfit_id": outfit_id}),
|
|
733
|
+
"items",
|
|
734
|
+
)
|
|
503
735
|
|
|
504
736
|
|
|
505
737
|
__all__ = [
|
|
@@ -511,6 +743,13 @@ __all__ = [
|
|
|
511
743
|
"LLViewerWindowAPI",
|
|
512
744
|
"LLCommandDispatcherAPI",
|
|
513
745
|
"LLFloaterRegAPI",
|
|
514
|
-
"
|
|
746
|
+
"LLURLDispatcherAPI",
|
|
747
|
+
"LLFloaterAboutAPI",
|
|
748
|
+
"LLGestureAPI",
|
|
749
|
+
"GroupChatAPI",
|
|
750
|
+
"LLChatBarAPI",
|
|
751
|
+
"LLAppViewerAPI",
|
|
752
|
+
"LLTeleportHandlerAPI",
|
|
753
|
+
"LLAppearanceAPI",
|
|
515
754
|
"LEAPAPIWrapper",
|
|
516
755
|
]
|
|
@@ -285,8 +285,7 @@ def inspector_main():
|
|
|
285
285
|
print(
|
|
286
286
|
"Running in direct LEAP execution mode.\n"
|
|
287
287
|
"If you're seeing this anywhere other than the viewer logs, "
|
|
288
|
-
"you probably messed up, the viewer should be executing this!\n"
|
|
289
|
-
"Try adding a '--tcp' argument!",
|
|
288
|
+
"you probably messed up, the viewer should be executing this!\n",
|
|
290
289
|
file=sys.stderr,
|
|
291
290
|
)
|
|
292
291
|
|
|
@@ -5,7 +5,7 @@ from collections import namedtuple
|
|
|
5
5
|
#: A namedtuple of the version info for the current release.
|
|
6
6
|
_version_info = namedtuple("_version_info", "major minor micro status")
|
|
7
7
|
|
|
8
|
-
parts = "0.
|
|
8
|
+
parts = "0.7.0".split(".", 3)
|
|
9
9
|
version_info = _version_info(
|
|
10
10
|
int(parts[0]),
|
|
11
11
|
int(parts[1]),
|
|
@@ -16,4 +16,4 @@ version_info = _version_info(
|
|
|
16
16
|
# Remove everything but the 'version_info' from this module.
|
|
17
17
|
del namedtuple, _version_info, parts
|
|
18
18
|
|
|
19
|
-
__version__ = "0.
|
|
19
|
+
__version__ = "0.7.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: outleap
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.0
|
|
4
4
|
Summary: Tools for using asyncio to control a Second Life viewer over the LEAP protocol
|
|
5
5
|
Author-email: Salad Dais <83434023+SaladDais@users.noreply.github.com>
|
|
6
6
|
License: MIT License
|
|
@@ -26,6 +26,7 @@ Provides-Extra: tools
|
|
|
26
26
|
Requires-Dist: ptpython<4,>=3; extra == "tools"
|
|
27
27
|
Requires-Dist: qasync; extra == "tools"
|
|
28
28
|
Requires-Dist: pyside6-essentials; extra == "tools"
|
|
29
|
+
Dynamic: license-file
|
|
29
30
|
|
|
30
31
|
# outleap
|
|
31
32
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|