libobs_wrapper\scenes/
transform_info.rs1use std::fmt::Debug;
2
3use libobs::obs_transform_info;
4
5use crate::{
6 enums::{ObsBoundsType, OsEnumType},
7 graphics::Vec2,
8 macros::enum_from_number,
9 scenes::scene_item::SceneItemTrait,
10 utils::ObsError,
11};
12
13pub struct ObsTransformInfo(pub(crate) obs_transform_info);
15impl Debug for ObsTransformInfo {
16 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17 f.debug_struct("ObsTransformInfo")
18 .field("pos", &Vec2::from(self.0.pos))
19 .field("scale", &Vec2::from(self.0.scale))
20 .field("alignment", &self.0.alignment)
21 .field("rot", &self.0.rot)
22 .field("bounds", &Vec2::from(self.0.bounds))
23 .field("bounds_type", &self.0.bounds_type)
24 .field("bounds_alignment", &self.0.bounds_alignment)
25 .field("crop_to_bounds", &self.0.crop_to_bounds)
26 .finish()
27 }
28}
29
30impl Clone for ObsTransformInfo {
31 fn clone(&self) -> Self {
32 ObsTransformInfo(obs_transform_info {
33 pos: self.0.pos,
34 scale: self.0.scale,
35 alignment: self.0.alignment,
36 rot: self.0.rot,
37 bounds: self.0.bounds,
38 bounds_type: self.0.bounds_type,
39 bounds_alignment: self.0.bounds_alignment,
40 crop_to_bounds: self.0.crop_to_bounds,
41 })
42 }
43}
44
45impl ObsTransformInfo {
46 pub fn get_pos(&self) -> Vec2 {
47 Vec2::from(self.0.pos)
48 }
49
50 pub fn get_scale(&self) -> Vec2 {
51 Vec2::from(self.0.scale)
52 }
53
54 pub fn get_alignment(&self) -> u32 {
55 self.0.alignment
56 }
57
58 pub fn get_rot(&self) -> f32 {
59 self.0.rot
60 }
61
62 pub fn get_bounds(&self) -> Vec2 {
63 Vec2::from(self.0.bounds)
64 }
65
66 pub fn get_bounds_type(&self) -> ObsBoundsType {
67 enum_from_number!(ObsBoundsType, self.0.bounds_type).unwrap()
68 }
69
70 pub fn get_bounds_alignment(&self) -> u32 {
71 self.0.bounds_alignment
72 }
73
74 pub fn get_crop_to_bounds(&self) -> bool {
75 self.0.crop_to_bounds
76 }
77}
78
79pub struct ObsTransformInfoBuilder {
80 pos: Option<Vec2>,
81 scale: Option<Vec2>,
82 alignment: Option<u32>,
83 rot: Option<f32>,
84 bounds: Option<Vec2>,
85 bounds_type: Option<ObsBoundsType>,
86 bounds_alignment: Option<u32>,
87 crop_to_bounds: Option<bool>,
88}
89
90impl Default for ObsTransformInfoBuilder {
91 fn default() -> Self {
92 Self::new()
93 }
94}
95
96impl ObsTransformInfoBuilder {
97 pub fn new() -> Self {
98 Self {
99 pos: None,
100 scale: None,
101 alignment: None,
102 rot: None,
103 bounds: None,
104 bounds_type: None,
105 bounds_alignment: None,
106 crop_to_bounds: None,
107 }
108 }
109
110 pub fn set_pos(mut self, pos: Vec2) -> Self {
111 self.pos = Some(pos);
112 self
113 }
114
115 pub fn set_scale(mut self, scale: Vec2) -> Self {
116 self.scale = Some(scale);
117 self
118 }
119
120 pub fn set_alignment(mut self, alignment: u32) -> Self {
122 self.alignment = Some(alignment);
123 self
124 }
125
126 pub fn set_rot(mut self, rot: f32) -> Self {
127 self.rot = Some(rot);
128 self
129 }
130
131 pub fn set_bounds(mut self, bounds: Vec2) -> Self {
132 self.bounds = Some(bounds);
133 self
134 }
135
136 pub fn set_bounds_type(mut self, bounds_type: ObsBoundsType) -> Self {
137 self.bounds_type = Some(bounds_type);
138 self
139 }
140
141 pub fn set_bounds_alignment(mut self, bounds_alignment: u32) -> Self {
143 self.bounds_alignment = Some(bounds_alignment);
144 self
145 }
146
147 pub fn set_crop_to_bounds(mut self, crop_to_bounds: bool) -> Self {
148 self.crop_to_bounds = Some(crop_to_bounds);
149 self
150 }
151
152 pub fn build_with_fallback<T: SceneItemTrait>(
154 self,
155 scene_item: &T,
156 ) -> Result<ObsTransformInfo, ObsError> {
157 let current = scene_item.get_transform_info()?;
158 let bounds_type = self
159 .bounds_type
160 .unwrap_or_else(|| current.get_bounds_type());
161
162 let bounds_type = bounds_type as OsEnumType;
163 Ok(ObsTransformInfo(obs_transform_info {
164 pos: self.pos.unwrap_or_else(|| current.get_pos()).into(),
165 scale: self.scale.unwrap_or_else(|| current.get_scale()).into(),
166 alignment: self.alignment.unwrap_or_else(|| current.get_alignment()),
167 rot: self.rot.unwrap_or_else(|| current.get_rot()),
168 bounds: self.bounds.unwrap_or_else(|| current.get_bounds()).into(),
169 bounds_type,
170 bounds_alignment: self
171 .bounds_alignment
172 .unwrap_or_else(|| current.get_bounds_alignment()),
173 crop_to_bounds: self
174 .crop_to_bounds
175 .unwrap_or_else(|| current.get_crop_to_bounds()),
176 }))
177 }
178
179 pub fn build(self, base_width: u32, base_height: u32) -> ObsTransformInfo {
181 let bounds_type = self.bounds_type.unwrap_or(ObsBoundsType::ScaleInner) as OsEnumType;
182
183 ObsTransformInfo(obs_transform_info {
184 pos: self.pos.unwrap_or_else(|| Vec2::new(0.0, 0.0)).into(),
185 scale: self.scale.unwrap_or_else(|| Vec2::new(1.0, 1.0)).into(),
186 alignment: self
187 .alignment
188 .unwrap_or(libobs::OBS_ALIGN_LEFT | libobs::OBS_ALIGN_TOP),
189 rot: self.rot.unwrap_or(0.0),
190 bounds: self
191 .bounds
192 .unwrap_or_else(|| Vec2::new(base_width as f32, base_height as f32))
193 .into(),
194 bounds_type,
195 bounds_alignment: self.bounds_alignment.unwrap_or(libobs::OBS_ALIGN_CENTER),
196 crop_to_bounds: self.crop_to_bounds.unwrap_or(false),
197 })
198 }
199}