mirror of
https://github.com/onyx-and-iris/obsws-cli.git
synced 2025-05-15 22:10:23 +01:00
add bounds/crop/rotation flags to sceneitem transform
upd readme upd changelog upd tests minor bump
This commit is contained in:
parent
8465944f30
commit
87eb7752bd
@ -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/),
|
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).
|
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
|
# [0.9.2] - 2025-04-26
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
19
README.md
19
README.md
@ -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.
|
- transform: Set the transform of an item in a scene.
|
||||||
- flags:
|
- flags:
|
||||||
|
|
||||||
*optional*
|
*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-x: X position of the item in the scene
|
||||||
- --position-y: Y 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-x: X scale of the item in the scene
|
||||||
- --scale-y: Y scale of the item in the scene
|
- --scale-y: Y scale of the item in the scene
|
||||||
|
- args: <scene_name> <item_name>
|
||||||
|
|
||||||
```console
|
```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
|
#### Scene Collections
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# SPDX-FileCopyrightText: 2025-present onyx-and-iris <code@onyxandiris.online>
|
# SPDX-FileCopyrightText: 2025-present onyx-and-iris <code@onyxandiris.online>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
__version__ = "0.9.2"
|
__version__ = "0.10.0"
|
||||||
|
@ -212,12 +212,45 @@ def transform(
|
|||||||
scene_name: str,
|
scene_name: str,
|
||||||
item_name: str,
|
item_name: str,
|
||||||
parent: Annotated[str, typer.Option(help='Parent group name')] = None,
|
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[
|
position_x: Annotated[
|
||||||
float, typer.Option(help='X position of the item in the scene')
|
float, typer.Option(help='X position of the item in the scene')
|
||||||
] = None,
|
] = None,
|
||||||
position_y: Annotated[
|
position_y: Annotated[
|
||||||
float, typer.Option(help='Y position of the item in the scene')
|
float, typer.Option(help='Y position of the item in the scene')
|
||||||
] = None,
|
] = None,
|
||||||
|
rotation: Annotated[
|
||||||
|
float, typer.Option(help='Rotation of the item in the scene')
|
||||||
|
] = None,
|
||||||
scale_x: Annotated[
|
scale_x: Annotated[
|
||||||
float, typer.Option(help='X scale of the item in the scene')
|
float, typer.Option(help='X scale of the item in the scene')
|
||||||
] = None,
|
] = None,
|
||||||
@ -241,10 +274,32 @@ def transform(
|
|||||||
)
|
)
|
||||||
|
|
||||||
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:
|
if position_x is not None:
|
||||||
transform['positionX'] = position_x
|
transform['positionX'] = position_x
|
||||||
if position_y is not None:
|
if position_y is not None:
|
||||||
transform['positionY'] = position_y
|
transform['positionY'] = position_y
|
||||||
|
if rotation is not None:
|
||||||
|
transform['rotation'] = rotation
|
||||||
if scale_x is not None:
|
if scale_x is not None:
|
||||||
transform['scaleX'] = scale_x
|
transform['scaleX'] = scale_x
|
||||||
if scale_y is not None:
|
if scale_y is not None:
|
||||||
|
@ -71,6 +71,17 @@ def pytest_sessionstart(session):
|
|||||||
},
|
},
|
||||||
sceneItemEnabled=True,
|
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):
|
def pytest_sessionfinish(session, exitstatus):
|
||||||
|
@ -7,9 +7,27 @@ from obsws_cli.app import app
|
|||||||
runner = CliRunner()
|
runner = CliRunner()
|
||||||
|
|
||||||
|
|
||||||
def test_item_list():
|
def test_sceneitem_list():
|
||||||
"""Test the item list command."""
|
"""Test the sceneitem list command."""
|
||||||
result = runner.invoke(app, ['sceneitem', 'list', 'pytest'])
|
result = runner.invoke(app, ['sceneitem', 'list', 'pytest'])
|
||||||
assert result.exit_code == 0
|
assert result.exit_code == 0
|
||||||
assert 'pytest_input' in result.stdout
|
assert 'pytest_input' in result.stdout
|
||||||
assert 'pytest_input_2' 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
|
||||||
|
)
|
||||||
|
@ -18,7 +18,7 @@ def test_stream_start():
|
|||||||
result = runner.invoke(app, ['stream', 'start'])
|
result = runner.invoke(app, ['stream', 'start'])
|
||||||
assert result.exit_code == 0
|
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:
|
if active:
|
||||||
assert 'Streaming is already in progress, cannot start.' in result.stdout
|
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'])
|
result = runner.invoke(app, ['stream', 'stop'])
|
||||||
assert result.exit_code == 0
|
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:
|
if active:
|
||||||
assert 'Streaming stopped successfully.' in result.stdout
|
assert 'Streaming stopped successfully.' in result.stdout
|
||||||
|
Loading…
x
Reference in New Issue
Block a user