pybevy_camera/
viewport.rs1use bevy::camera::Viewport;
2use pybevy_core::{FromBorrowedStorage, field_storage::FieldStorage};
3use pybevy_macros::native_field;
4use pybevy_math::PyUVec2;
5use pyo3::{basic::CompareOp, exceptions::PyTypeError, prelude::*};
6
7#[native_field]
8#[pyclass(name = "Viewport")]
9#[derive(Debug)]
10pub struct PyViewport {
11 storage: FieldStorage<Viewport>,
12}
13
14#[pymethods]
15impl PyViewport {
16 #[new]
17 #[pyo3(signature = (physical_position = PyUVec2::ZERO, physical_size = PyUVec2::ONE, depth=(0.0, 1.0)))]
18 pub fn new(physical_position: PyUVec2, physical_size: PyUVec2, depth: (f32, f32)) -> Self {
19 Self::from_owned(Viewport {
20 physical_position: physical_position.into(),
21 physical_size: physical_size.into(),
22 depth: depth.0..depth.1,
23 })
24 }
25
26 #[getter]
27 pub fn physical_position(&self) -> PyResult<PyUVec2> {
28 Ok(self.storage.borrow_field_as(|v| &v.physical_position)?)
29 }
30
31 #[setter]
32 pub fn set_physical_position(&mut self, value: PyUVec2) -> PyResult<()> {
33 self.as_mut()?.physical_position = value.into();
34 Ok(())
35 }
36
37 #[getter]
38 pub fn physical_size(&self) -> PyResult<PyUVec2> {
39 Ok(self.storage.borrow_field_as(|v| &v.physical_size)?)
40 }
41
42 #[setter]
43 pub fn set_physical_size(&mut self, value: PyUVec2) -> PyResult<()> {
44 self.as_mut()?.physical_size = value.into();
45 Ok(())
46 }
47
48 #[getter]
49 pub fn depth(&self) -> PyResult<(f32, f32)> {
50 let viewport = self.as_ref()?;
51 Ok((viewport.depth.start, viewport.depth.end))
52 }
53
54 #[setter]
55 pub fn set_depth(&mut self, value: (f32, f32)) -> PyResult<()> {
56 self.as_mut()?.depth = value.0..value.1;
57 Ok(())
58 }
59
60 pub fn __repr__(&self) -> PyResult<String> {
61 let viewport = self.as_ref()?;
62 Ok(format!(
63 "Viewport(physical_position=UVec2({}, {}), physical_size=UVec2({}, {}), depth=({}, {}))",
64 viewport.physical_position.x,
65 viewport.physical_position.y,
66 viewport.physical_size.x,
67 viewport.physical_size.y,
68 viewport.depth.start,
69 viewport.depth.end
70 ))
71 }
72
73 pub fn __richcmp__(&self, other: &PyViewport, op: CompareOp) -> PyResult<bool> {
74 let self_viewport = self.as_ref()?;
75 let other_viewport = other.as_ref()?;
76 match op {
77 CompareOp::Eq => Ok(self_viewport.physical_position
78 == other_viewport.physical_position
79 && self_viewport.physical_size == other_viewport.physical_size
80 && self_viewport.depth == other_viewport.depth),
81 CompareOp::Ne => Ok(self_viewport.physical_position
82 != other_viewport.physical_position
83 || self_viewport.physical_size != other_viewport.physical_size
84 || self_viewport.depth != other_viewport.depth),
85 _ => Err(PyTypeError::new_err("Unsupported comparison operation")),
86 }
87 }
88
89 pub fn __copy__(&self) -> PyResult<Self> {
90 Ok(Self::from_owned(self.storage.get()?))
91 }
92
93 pub fn clamp_to_size(&mut self, size: PyUVec2) -> PyResult<()> {
94 self.as_mut()?.clamp_to_size(size.into());
95 Ok(())
96 }
97
98 #[staticmethod]
99 pub fn from_viewport_and_override(
100 viewport: Option<&PyViewport>,
101 main_pass_resolution_override: Option<PyUVec2>,
102 ) -> PyResult<Option<PyViewport>> {
103 let mut result_viewport = viewport.map(|v| v.storage.get()).transpose()?;
104
105 if let Some(override_size) = main_pass_resolution_override {
106 if result_viewport.is_none() {
107 result_viewport = Some(Viewport::default());
108 }
109 if let Some(ref mut vp) = result_viewport {
110 vp.physical_size = override_size.into();
111 }
112 }
113
114 Ok(result_viewport.map(PyViewport::from_owned))
115 }
116}