diff --git a/samples/setup.py b/samples/setup.py index b5193268..dd7daa60 100644 --- a/samples/setup.py +++ b/samples/setup.py @@ -65,10 +65,12 @@ def get_exec(engine: Literal['blender', 'unreal'], exec_from_config: Optional[Pa return path.as_posix() -def ask_unreal_project() -> str: +def ask_unreal_project(unreal_project: Optional[str] = None) -> str: """Ask for unreal project path.""" - txt = 'Please input the path to the unreal project, or press [bold]enter[/bold] to download a sample project\n\[Enter]' - unreal_project = Prompt.ask(txt, default=None) + txt = 'Please input the path to the unreal project' + if unreal_project is None: + txt += ', or press [bold]enter[/bold] to download a sample project\n' '\[Enter]' + unreal_project = Prompt.ask(txt, default=unreal_project) return get_unreal_project(unreal_project) diff --git a/src/XRFeitoriaUnreal/Content/Python/sequence.py b/src/XRFeitoriaUnreal/Content/Python/sequence.py index c1d2d8e9..07d1e5ed 100644 --- a/src/XRFeitoriaUnreal/Content/Python/sequence.py +++ b/src/XRFeitoriaUnreal/Content/Python/sequence.py @@ -601,6 +601,7 @@ def add_camera_to_sequence( camera: unreal.CameraActor, camera_transform_keys: Optional[Union[SequenceTransformKey, List[SequenceTransformKey]]] = None, camera_fov: float = 90.0, + camera_aspect_ratio: float = 16.0 / 9.0, seq_length: Optional[int] = None, ) -> unreal.CameraActor: if seq_length is None: @@ -618,6 +619,11 @@ def add_camera_to_sequence( # set the camera FOV fov_track, fov_section = add_property_float_track_to_binding(camera_component_binding, 'FieldOfView', camera_fov) + # set the camera aspect ratio + aspect_ratio_track, aspect_ratio_section = add_property_float_track_to_binding( + camera_component_binding, 'AspectRatio', camera_aspect_ratio + ) + # ------- add master track ------- # camera_cut_track: unreal.MovieSceneCameraCutTrack = sequence.add_master_track(unreal.MovieSceneCameraCutTrack) # type: ignore @@ -647,6 +653,7 @@ def add_camera_to_sequence( 'self': camera.camera_component, }, 'fov': {'track': fov_track, 'section': fov_section}, + 'aspect_ratio': {'track': aspect_ratio_track, 'section': aspect_ratio_section}, 'transform': {'track': transform_track, 'section': transform_section}, } @@ -657,6 +664,7 @@ def add_spawnable_camera_to_sequence( camera_transform_keys: Optional[Union[SequenceTransformKey, List[SequenceTransformKey]]] = None, camera_class: Type[unreal.CameraActor] = unreal.CameraActor, camera_fov: float = 90.0, + camera_aspect_ratio: float = 16.0 / 9.0, seq_length: Optional[int] = None, ) -> unreal.CameraActor: """Add a camera actor to the sequence. @@ -667,6 +675,7 @@ def add_spawnable_camera_to_sequence( camera_transform_keys (Optional[Union[SequenceTransformKey, List[SequenceTransformKey]]], optional): transform keys of the camera actor. Defaults to None. camera_class (Type[unreal.CameraActor], optional): the camera actor class to spawn. Defaults to unreal.CameraActor. camera_fov (float, optional): Filed of view of the camera. Defaults to 90.0. + camera_aspect_ratio (float, optional): Aspect ratio of the camera. Defaults to 16.0 / 9.0. seq_length (Optional[int], optional): Sequence length. Defaults to None. Returns: @@ -688,6 +697,11 @@ def add_spawnable_camera_to_sequence( # set the camera FOV fov_track, fov_section = add_property_float_track_to_binding(camera_component_binding, 'FieldOfView', camera_fov) + # set the camera aspect ratio + aspect_ratio_track, aspect_ratio_section = add_property_float_track_to_binding( + camera_component_binding, 'AspectRatio', camera_aspect_ratio + ) + # ------- add master track ------- # # add master track (camera) to sequence # camera_cut_track = sequence.add_track(unreal.MovieSceneCameraCutTrack) @@ -726,6 +740,7 @@ def add_spawnable_camera_to_sequence( 'self': camera_actor.camera_component, }, 'fov': {'track': fov_track, 'section': fov_section}, + 'aspect_ratio': {'track': aspect_ratio_track, 'section': aspect_ratio_section}, 'transform': {'track': transform_track, 'section': transform_section}, } @@ -1174,6 +1189,7 @@ def add_camera( camera_name: str, transform_keys: 'Optional[TransformKeys]' = None, fov: float = 90.0, + aspect_ratio: float = 16.0 / 9.0, spawnable: bool = False, ): """Spawn a camera in sequence. @@ -1190,6 +1206,7 @@ def add_camera( camera_name=camera_name, camera_transform_keys=transform_keys, camera_fov=fov, + camera_aspect_ratio=aspect_ratio, ) cls.bindings[camera_name] = bindings else: @@ -1199,6 +1216,7 @@ def add_camera( camera=camera, camera_transform_keys=transform_keys, camera_fov=fov, + camera_aspect_ratio=aspect_ratio, ) cls.bindings[camera_name] = bindings diff --git a/xrfeitoria/camera/camera_unreal.py b/xrfeitoria/camera/camera_unreal.py index b336b67f..0d95ee26 100644 --- a/xrfeitoria/camera/camera_unreal.py +++ b/xrfeitoria/camera/camera_unreal.py @@ -1,6 +1,7 @@ from ..data_structure.constants import Vector from ..object.object_utils import ObjectUtilsUnreal from ..rpc import remote_unreal +from ..utils import Validator from .camera_base import CameraBase try: @@ -16,6 +17,16 @@ class CameraUnreal(CameraBase): _object_utils = ObjectUtilsUnreal + @property + def aspect_ratio(self) -> float: + """Aspect of ratio, Width / Height.""" + return self._get_aspect_ratio_in_engine(self._name) + + @aspect_ratio.setter + def aspect_ratio(self, value: float): + Validator.validate_argument_type(value, [float, int]) + self._set_aspect_ratio_in_engine(self._name, value) + def look_at(self, target: Vector) -> None: """Set the camera to look at the target. @@ -36,6 +47,11 @@ def _get_fov_in_engine(name): camera: unreal.CameraActor = XRFeitoriaUnrealFactory.utils_actor.get_actor_by_name(name) return camera.camera_component.field_of_view + @staticmethod + def _get_aspect_ratio_in_engine(name: str) -> float: + camera: unreal.CameraActor = XRFeitoriaUnrealFactory.utils_actor.get_actor_by_name(name) + return camera.camera_component.aspect_ratio + # ----- Setter ----- # @staticmethod @@ -47,6 +63,11 @@ def _set_camera_fov_in_engine(name, fov): camera: unreal.CameraActor = XRFeitoriaUnrealFactory.utils_actor.get_actor_by_name(name) camera.camera_component.field_of_view = fov + @staticmethod + def _set_aspect_ratio_in_engine(name: str, ratio: float): + camera: unreal.CameraActor = XRFeitoriaUnrealFactory.utils_actor.get_actor_by_name(name) + camera.camera_component.aspect_ratio = ratio + @staticmethod def _spawn_in_engine( camera_name, diff --git a/xrfeitoria/sequence/sequence_base.py b/xrfeitoria/sequence/sequence_base.py index 0e6b523e..82e6f5d8 100644 --- a/xrfeitoria/sequence/sequence_base.py +++ b/xrfeitoria/sequence/sequence_base.py @@ -132,6 +132,7 @@ def spawn_camera( location: 'Vector' = None, rotation: 'Vector' = None, fov: float = 90.0, + aspect_ratio: float = 16.0 / 9.0, camera_name: Optional[str] = None, ) -> CameraBase: """Spawn a new camera in the sequence. @@ -140,6 +141,7 @@ def spawn_camera( location (Vector): Location of the camera. rotation (Vector): Rotation of the camera. fov (float in (0.0, 180.0), optional): Field of view of the camera len. Defaults to 90.0. (unit: degrees) + aspect_ratio (float, optional): Aspect ratio of the camera. Defaults to 16.0 / 9.0. camera_name (str, optional): Name of the camera. Defaults to None. """ if camera_name is None: @@ -148,6 +150,7 @@ def spawn_camera( cls._spawn_camera_in_engine( transform_keys=transform_keys.model_dump(), fov=fov, + aspect_ratio=aspect_ratio, camera_name=camera_name, ) logger.info(f'[cyan]Spawned[/cyan] camera "{camera_name}" in sequence "{cls.name}"') @@ -158,6 +161,7 @@ def spawn_camera_with_keys( cls, transform_keys: 'TransformKeys', fov: float = 90.0, + aspect_ratio: float = 16.0 / 9.0, camera_name: str = None, ) -> CameraBase: """Spawn a new camera with keyframes in the sequence. @@ -165,6 +169,7 @@ def spawn_camera_with_keys( Args: transform_keys (TransformKeys): Keyframes of transform (location, rotation, and scale). fov (float in (0.0, 180.0), optional): Field of view of the camera len. Defaults to 90.0. (unit: degrees) + aspect_ratio (float, optional): Aspect ratio of the camera. Defaults to 16.0 / 9.0. camera_name (str, optional): Name of the camera. Defaults to 'Camera'. """ if not isinstance(transform_keys, list): @@ -175,6 +180,7 @@ def spawn_camera_with_keys( cls._spawn_camera_in_engine( transform_keys=transform_keys, fov=fov, + aspect_ratio=aspect_ratio, camera_name=camera_name, ) logger.info( @@ -269,6 +275,7 @@ def use_camera( location: 'Optional[Vector]' = None, rotation: 'Optional[Vector]' = None, fov: float = None, + aspect_ratio: float = None, ) -> None: """Use the specified level camera in the sequence. The location, rotation and fov set in this method are only used in the sequence. The location, rotation and @@ -279,6 +286,7 @@ def use_camera( location (Optional[Vector], optional): The location of the camera. Defaults to None. unit: meter. rotation (Optional[Vector], optional): The rotation of the camera. Defaults to None. unit: degree. fov (float, optional): The field of view of the camera. Defaults to None. unit: degree. + aspect_ratio (float, optional): The aspect ratio of the camera. Defaults to None. """ camera_name = camera.name location = camera.location if location is None else location @@ -289,6 +297,7 @@ def use_camera( cls._use_camera_in_engine( transform_keys=transform_keys.model_dump(), fov=fov, + aspect_ratio=aspect_ratio, camera_name=camera_name, ) logger.info(f'[cyan]Used[/cyan] camera "{camera_name}" in sequence "{cls.name}"') @@ -299,6 +308,7 @@ def use_camera_with_keys( camera: _camera, transform_keys: 'TransformKeys', fov: float = None, + aspect_ratio: float = None, ) -> None: """Use the specified level camera in the sequence. The transform_keys and fov set in this method are only used in the sequence. The location, rotation and fov @@ -308,6 +318,7 @@ def use_camera_with_keys( camera (CameraUnreal or CameraBlender): The camera to use. transform_keys (TransformKeys): The transform keys to use. fov (float, optional): The field of view to use. Defaults to None. unit: degree. + aspect_ratio (float, optional): The aspect ratio of the camera. Defaults to None. """ camera_name = camera.name if not isinstance(transform_keys, list): @@ -317,6 +328,7 @@ def use_camera_with_keys( cls._use_camera_in_engine( transform_keys=transform_keys, fov=fov, + aspect_ratio=aspect_ratio, camera_name=camera_name, ) logger.info( @@ -453,6 +465,7 @@ def _import_actor_in_engine( def _spawn_camera_in_engine( transform_keys: 'Union[List[Dict], Dict]', fov: float = 90.0, + aspect_ratio: float = 16.0 / 9.0, camera_name: str = 'Camera', ) -> None: pass diff --git a/xrfeitoria/sequence/sequence_blender.py b/xrfeitoria/sequence/sequence_blender.py index 10d3853f..a22cd3f1 100644 --- a/xrfeitoria/sequence/sequence_blender.py +++ b/xrfeitoria/sequence/sequence_blender.py @@ -194,6 +194,7 @@ def _import_actor_in_engine( def _spawn_camera_in_engine( transform_keys: 'Union[List[Dict], Dict]', fov: float = 90.0, + aspect_ratio: float = 16.0 / 9.0, camera_name: str = 'Camera', ) -> None: """Spawn a camera in the engine. @@ -270,6 +271,7 @@ def _spawn_shape_in_engine( def _use_camera_in_engine( transform_keys: 'Union[List[Dict], Dict]', fov: float = 90.0, + aspect_ratio: float = 16.0 / 9.0, camera_name: str = 'Camera', ) -> None: """Use level camera to render in the sequence in the engine. diff --git a/xrfeitoria/sequence/sequence_unreal.py b/xrfeitoria/sequence/sequence_unreal.py index 3d509322..5fba1654 100644 --- a/xrfeitoria/sequence/sequence_unreal.py +++ b/xrfeitoria/sequence/sequence_unreal.py @@ -460,6 +460,7 @@ def _set_camera_cut_player_in_engine( def _use_camera_in_engine( transform_keys: 'Union[List[Dict], Dict]', fov: float = 90.0, + aspect_ratio: float = 16.0 / 9.0, camera_name: str = 'Camera', ) -> None: if not isinstance(transform_keys, list): @@ -470,6 +471,7 @@ def _use_camera_in_engine( XRFeitoriaUnrealFactory.Sequence.add_camera( transform_keys=transform_keys, fov=fov, + aspect_ratio=aspect_ratio, camera_name=camera_name, ) @@ -522,6 +524,7 @@ def _import_actor_in_engine( def _spawn_camera_in_engine( transform_keys: 'Union[List[Dict], Dict]', fov: float = 90.0, + aspect_ratio: float = 16.0 / 9.0, camera_name: str = 'Camera', ) -> None: if not isinstance(transform_keys, list): @@ -532,6 +535,7 @@ def _spawn_camera_in_engine( XRFeitoriaUnrealFactory.Sequence.add_camera( transform_keys=transform_keys, fov=fov, + aspect_ratio=aspect_ratio, camera_name=camera_name, spawnable=True, )