add bounds/crop/rotation flags to sceneitem transform

upd readme
upd changelog

upd tests

minor bump
This commit is contained in:
onyx-and-iris 2025-04-27 13:50:40 +01:00
parent 8465944f30
commit 87eb7752bd
7 changed files with 112 additions and 7 deletions

View File

@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
# [0.10.0] - 2025-04-27
### Added
- sceneitem transform, see *transform* under [Scene Item](https://github.com/onyx-and-iris/obsws-cli?tab=readme-ov-file#scene-item)
# [0.9.2] - 2025-04-26
### Added

View File

@ -148,15 +148,30 @@ obsws-cli sceneitem visible --parent=test_group START "Colour Source 4"
- transform: Set the transform of an item in a scene.
- flags:
*optional*
- --parent: Parent group name.
- --alignment: Alignment of the item in the scene
- --bounds-alignment: Bounds alignment of the item in the scene
- --bounds-height: Height of the item in the scene
- --bounds-type: Type of bounds for the item in the scene
- --bounds-width: Width of the item in the scene
- --crop-to-bounds: Crop the item to the bounds
- --crop-bottom: Bottom crop of the item in the scene
- --crop-left: Left crop of the item in the scene
- --crop-right: Right crop of the item in the scene
- --crop-top: Top crop of the item in the scene
- --position-x: X position of the item in the scene
- --position-y: Y position of the item in the scene
- --scale-x: X scale of the item in the scene
- --scale-y: Y scale of the item in the scene
- args: <scene_name> <item_name>
```console
obsws-cli sceneitem transform --position-x=556.0 --scale-x=0.7946954965591431 --scale-y=0.7948529124259949 LIVE "Window Capture"
obsws-cli sceneitem transform \
--rotation=5 \
--position-x=250.8 \
Scene "Colour Source 3"
```
#### Scene Collections

View File

@ -1,4 +1,4 @@
# SPDX-FileCopyrightText: 2025-present onyx-and-iris <code@onyxandiris.online>
#
# SPDX-License-Identifier: MIT
__version__ = "0.9.2"
__version__ = "0.10.0"

View File

@ -212,12 +212,45 @@ def transform(
scene_name: str,
item_name: str,
parent: Annotated[str, typer.Option(help='Parent group name')] = None,
alignment: Annotated[
int, typer.Option(help='Alignment of the item in the scene')
] = None,
bounds_alignment: Annotated[
int, typer.Option(help='Bounds alignment of the item in the scene')
] = None,
bounds_height: Annotated[
float, typer.Option(help='Height of the item in the scene')
] = None,
bounds_type: Annotated[
str, typer.Option(help='Type of bounds for the item in the scene')
] = None,
bounds_width: Annotated[
float, typer.Option(help='Width of the item in the scene')
] = None,
crop_to_bounds: Annotated[
bool, typer.Option(help='Crop the item to the bounds')
] = None,
crop_bottom: Annotated[
float, typer.Option(help='Bottom crop of the item in the scene')
] = None,
crop_left: Annotated[
float, typer.Option(help='Left crop of the item in the scene')
] = None,
crop_right: Annotated[
float, typer.Option(help='Right crop of the item in the scene')
] = None,
crop_top: Annotated[
float, typer.Option(help='Top crop of the item in the scene')
] = None,
position_x: Annotated[
float, typer.Option(help='X position of the item in the scene')
] = None,
position_y: Annotated[
float, typer.Option(help='Y position of the item in the scene')
] = None,
rotation: Annotated[
float, typer.Option(help='Rotation of the item in the scene')
] = None,
scale_x: Annotated[
float, typer.Option(help='X scale of the item in the scene')
] = None,
@ -241,10 +274,32 @@ def transform(
)
transform = {}
if alignment is not None:
transform['alignment'] = alignment
if bounds_alignment is not None:
transform['boundsAlignment'] = bounds_alignment
if bounds_height is not None:
transform['boundsHeight'] = bounds_height
if bounds_type is not None:
transform['boundsType'] = bounds_type
if bounds_width is not None:
transform['boundsWidth'] = bounds_width
if crop_to_bounds is not None:
transform['cropToBounds'] = crop_to_bounds
if crop_bottom is not None:
transform['cropBottom'] = crop_bottom
if crop_left is not None:
transform['cropLeft'] = crop_left
if crop_right is not None:
transform['cropRight'] = crop_right
if crop_top is not None:
transform['cropTop'] = crop_top
if position_x is not None:
transform['positionX'] = position_x
if position_y is not None:
transform['positionY'] = position_y
if rotation is not None:
transform['rotation'] = rotation
if scale_x is not None:
transform['scaleX'] = scale_x
if scale_y is not None:

View File

@ -71,6 +71,17 @@ def pytest_sessionstart(session):
},
sceneItemEnabled=True,
)
resp = session.obsws.get_scene_item_list('pytest')
for item in resp.scene_items:
if item['sourceName'] == 'pytest_input_2':
session.obsws.set_scene_item_transform(
'pytest',
item['sceneItemId'],
{
'rotation': 0,
},
)
break
def pytest_sessionfinish(session, exitstatus):

View File

@ -7,9 +7,27 @@ from obsws_cli.app import app
runner = CliRunner()
def test_item_list():
"""Test the item list command."""
def test_sceneitem_list():
"""Test the sceneitem list command."""
result = runner.invoke(app, ['sceneitem', 'list', 'pytest'])
assert result.exit_code == 0
assert 'pytest_input' in result.stdout
assert 'pytest_input_2' in result.stdout
def test_sceneitem_transform():
"""Test the sceneitem transform command."""
result = runner.invoke(
app,
[
'sceneitem',
'transform',
'--rotation=60',
'pytest',
'pytest_input_2',
],
)
assert result.exit_code == 0
assert (
"Item 'pytest_input_2' in scene 'pytest' has been transformed" in result.stdout
)

View File

@ -18,7 +18,7 @@ def test_stream_start():
result = runner.invoke(app, ['stream', 'start'])
assert result.exit_code == 0
time.sleep(1) # Wait for the stream to start
time.sleep(2) # Wait for the stream to start
if active:
assert 'Streaming is already in progress, cannot start.' in result.stdout
@ -35,7 +35,7 @@ def test_stream_stop():
result = runner.invoke(app, ['stream', 'stop'])
assert result.exit_code == 0
time.sleep(1) # Wait for the stream to stop
time.sleep(2) # Wait for the stream to stop
if active:
assert 'Streaming stopped successfully.' in result.stdout