wrap.rs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2025 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::ops::Range;
  19. use crate::{
  20. error::{Error, Result},
  21. expr::{SExprMachine, SExprVal},
  22. gfx::{Dimension, Point, Rectangle},
  23. scene::SceneNode as SceneNode3,
  24. };
  25. use super::{PropertyAtomicGuard, PropertyPtr, Role};
  26. #[derive(Clone)]
  27. pub struct PropertyBool {
  28. prop: PropertyPtr,
  29. role: Role,
  30. idx: usize,
  31. }
  32. impl PropertyBool {
  33. pub fn wrap(node: &SceneNode3, role: Role, prop_name: &str, idx: usize) -> Result<Self> {
  34. let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
  35. // Test if it works
  36. let _ = prop.get_bool(idx)?;
  37. Ok(Self { prop, role, idx })
  38. }
  39. pub fn get(&self) -> bool {
  40. self.prop.get_bool(self.idx).unwrap()
  41. }
  42. pub fn set(&self, atom: &mut PropertyAtomicGuard, val: bool) {
  43. self.prop().set_bool(atom, self.role, self.idx, val).unwrap()
  44. }
  45. #[inline]
  46. pub fn prop(&self) -> PropertyPtr {
  47. self.prop.clone()
  48. }
  49. }
  50. #[derive(Clone)]
  51. pub struct PropertyUint32 {
  52. prop: PropertyPtr,
  53. role: Role,
  54. idx: usize,
  55. }
  56. impl PropertyUint32 {
  57. pub fn from(prop: PropertyPtr, role: Role, idx: usize) -> Result<Self> {
  58. // Test if it works
  59. let _ = prop.get_u32(idx)?;
  60. Ok(Self { prop, role, idx })
  61. }
  62. pub fn wrap(node: &SceneNode3, role: Role, prop_name: &str, idx: usize) -> Result<Self> {
  63. let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
  64. // Test if it works
  65. let _ = prop.get_u32(idx)?;
  66. Ok(Self { prop, role, idx })
  67. }
  68. pub fn get(&self) -> u32 {
  69. self.prop.get_u32(self.idx).unwrap()
  70. }
  71. pub fn set(&self, atom: &mut PropertyAtomicGuard, val: u32) {
  72. self.prop().set_u32(atom, self.role, self.idx, val).unwrap()
  73. }
  74. #[inline]
  75. pub fn prop(&self) -> PropertyPtr {
  76. self.prop.clone()
  77. }
  78. }
  79. #[derive(Clone)]
  80. pub struct PropertyFloat32 {
  81. prop: PropertyPtr,
  82. role: Role,
  83. idx: usize,
  84. }
  85. impl PropertyFloat32 {
  86. pub fn wrap(node: &SceneNode3, role: Role, prop_name: &str, idx: usize) -> Result<Self> {
  87. let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
  88. // Test if it works
  89. let _ = prop.get_f32(idx)?;
  90. Ok(Self { prop, role, idx })
  91. }
  92. pub fn get(&self) -> f32 {
  93. self.prop.get_f32(self.idx).unwrap()
  94. }
  95. pub fn set(&self, atom: &mut PropertyAtomicGuard, val: f32) {
  96. self.prop().set_f32(atom, self.role, self.idx, val).unwrap()
  97. }
  98. pub fn prop(&self) -> PropertyPtr {
  99. self.prop.clone()
  100. }
  101. }
  102. #[derive(Clone)]
  103. pub struct PropertyStr {
  104. prop: PropertyPtr,
  105. role: Role,
  106. idx: usize,
  107. }
  108. impl PropertyStr {
  109. pub fn wrap(node: &SceneNode3, role: Role, prop_name: &str, idx: usize) -> Result<Self> {
  110. let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
  111. // Test if it works
  112. let _ = prop.get_str(idx)?;
  113. Ok(Self { prop, role, idx })
  114. }
  115. pub fn get(&self) -> String {
  116. self.prop.get_str(self.idx).unwrap()
  117. }
  118. pub fn set<S: Into<String>>(&self, atom: &mut PropertyAtomicGuard, val: S) {
  119. self.prop().set_str(atom, self.role, self.idx, val.into()).unwrap()
  120. }
  121. #[inline]
  122. pub fn prop(&self) -> PropertyPtr {
  123. self.prop.clone()
  124. }
  125. }
  126. #[derive(Clone)]
  127. pub struct PropertyColor {
  128. prop: PropertyPtr,
  129. role: Role,
  130. }
  131. impl PropertyColor {
  132. pub fn wrap(node: &SceneNode3, role: Role, prop_name: &str) -> Result<Self> {
  133. let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
  134. if !prop.is_bounded() || prop.get_len() != 4 {
  135. return Err(Error::PropertyWrongLen)
  136. }
  137. // Test if it works
  138. let _ = prop.get_f32(0)?;
  139. Ok(Self { prop, role })
  140. }
  141. pub fn get(&self) -> [f32; 4] {
  142. [
  143. self.prop.get_f32(0).unwrap(),
  144. self.prop.get_f32(1).unwrap(),
  145. self.prop.get_f32(2).unwrap(),
  146. self.prop.get_f32(3).unwrap(),
  147. ]
  148. }
  149. pub fn set(&self, atom: &mut PropertyAtomicGuard, val: [f32; 4]) {
  150. self.prop().set_f32(atom, self.role, 0, val[0]).unwrap();
  151. self.prop().set_f32(atom, self.role, 1, val[1]).unwrap();
  152. self.prop().set_f32(atom, self.role, 2, val[2]).unwrap();
  153. self.prop().set_f32(atom, self.role, 3, val[3]).unwrap();
  154. }
  155. #[inline]
  156. pub fn prop(&self) -> PropertyPtr {
  157. self.prop.clone()
  158. }
  159. }
  160. #[derive(Clone)]
  161. pub struct PropertyDimension {
  162. prop: PropertyPtr,
  163. role: Role,
  164. }
  165. impl PropertyDimension {
  166. pub fn wrap(node: &SceneNode3, role: Role, prop_name: &str) -> Result<Self> {
  167. let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
  168. if !prop.is_bounded() || prop.get_len() != 2 {
  169. return Err(Error::PropertyWrongLen)
  170. }
  171. // Test if it works
  172. let _ = prop.get_f32(0)?;
  173. Ok(Self { prop, role })
  174. }
  175. pub fn get(&self) -> Dimension {
  176. [self.prop.get_f32(0).unwrap(), self.prop.get_f32(1).unwrap()].into()
  177. }
  178. pub fn set(&self, atom: &mut PropertyAtomicGuard, dim: Dimension) {
  179. self.prop().set_f32(atom, self.role, 0, dim.w).unwrap();
  180. self.prop().set_f32(atom, self.role, 1, dim.h).unwrap();
  181. }
  182. #[inline]
  183. pub fn prop(&self) -> PropertyPtr {
  184. self.prop.clone()
  185. }
  186. }
  187. #[derive(Clone)]
  188. pub struct PropertyPoint {
  189. prop: PropertyPtr,
  190. role: Role,
  191. }
  192. impl PropertyPoint {
  193. pub fn wrap(node: &SceneNode3, role: Role, prop_name: &str) -> Result<Self> {
  194. let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
  195. if !prop.is_bounded() || prop.get_len() != 2 {
  196. return Err(Error::PropertyWrongLen)
  197. }
  198. // Test if it works
  199. let _ = prop.get_f32(0)?;
  200. Ok(Self { prop, role })
  201. }
  202. pub fn get(&self) -> Point {
  203. [self.prop.get_f32(0).unwrap(), self.prop.get_f32(1).unwrap()].into()
  204. }
  205. pub fn set(&self, atom: &mut PropertyAtomicGuard, pos: Point) {
  206. self.prop().set_f32(atom, self.role, 0, pos.x).unwrap();
  207. self.prop().set_f32(atom, self.role, 1, pos.y).unwrap();
  208. }
  209. #[inline]
  210. pub fn prop(&self) -> PropertyPtr {
  211. self.prop.clone()
  212. }
  213. }
  214. #[derive(Clone)]
  215. pub struct PropertyRect {
  216. prop: PropertyPtr,
  217. role: Role,
  218. }
  219. impl PropertyRect {
  220. pub fn wrap(node: &SceneNode3, role: Role, prop_name: &str) -> Result<Self> {
  221. let prop = node.get_property(prop_name).ok_or(Error::PropertyNotFound)?;
  222. if !prop.is_bounded() || prop.get_len() != 4 {
  223. return Err(Error::PropertyWrongLen)
  224. }
  225. // Test if it works
  226. let _ = prop.get_f32(0)?;
  227. Ok(Self { prop, role })
  228. }
  229. pub fn eval(&self, parent_rect: &Rectangle) -> Result<()> {
  230. self.eval_with(
  231. (0..4).collect(),
  232. vec![("w".to_string(), parent_rect.w), ("h".to_string(), parent_rect.h)],
  233. )
  234. }
  235. pub fn eval_with(&self, range: Vec<usize>, extras: Vec<(String, f32)>) -> Result<()> {
  236. let mut globals = vec![];
  237. for dep in self.prop.get_depends() {
  238. let Some(prop) = dep.prop.upgrade() else { return Err(Error::PropertyNotFound) };
  239. let value = prop.get_f32(dep.i)?;
  240. globals.push((dep.local_name, SExprVal::Float32(value)));
  241. }
  242. for (name, val) in extras {
  243. globals.push((name, SExprVal::Float32(val)));
  244. }
  245. //debug!(target: "prop::wrap", "PropertyRect::eval() [globals = {globals:?}]");
  246. let mut changes = vec![];
  247. for i in range {
  248. if !self.prop.is_expr(i)? {
  249. continue
  250. }
  251. let expr = self.prop.get_expr(i).unwrap();
  252. let mut machine = SExprMachine { globals: globals.clone(), stmts: &expr };
  253. let v = machine.call()?.as_f32()?;
  254. changes.push((i, v));
  255. }
  256. self.prop.set_cache_f32_multi(self.role, changes).unwrap();
  257. Ok(())
  258. }
  259. pub fn get(&self) -> Rectangle {
  260. Rectangle::from_array([
  261. self.prop.get_f32(0).unwrap(),
  262. self.prop.get_f32(1).unwrap(),
  263. self.prop.get_f32(2).unwrap(),
  264. self.prop.get_f32(3).unwrap(),
  265. ])
  266. }
  267. pub fn get_opt(&self) -> Option<Rectangle> {
  268. Some(Rectangle::from_array([
  269. self.prop.get_f32(0).ok()?,
  270. self.prop.get_f32(1).ok()?,
  271. self.prop.get_f32(2).ok()?,
  272. self.prop.get_f32(3).ok()?,
  273. ]))
  274. }
  275. pub fn set(&self, atom: &mut PropertyAtomicGuard, rect: &Rectangle) {
  276. self.prop().set_f32(atom, self.role, 0, rect.x).unwrap();
  277. self.prop().set_f32(atom, self.role, 1, rect.y).unwrap();
  278. self.prop().set_f32(atom, self.role, 2, rect.y).unwrap();
  279. self.prop().set_f32(atom, self.role, 3, rect.y).unwrap();
  280. }
  281. #[inline]
  282. pub fn prop(&self) -> PropertyPtr {
  283. self.prop.clone()
  284. }
  285. fn is_f32_or_has_cached(&self, i: usize) -> bool {
  286. if self.prop.is_expr(i).unwrap() {
  287. if self.prop.get_cached(i).unwrap().is_null() {
  288. return false
  289. }
  290. }
  291. true
  292. }
  293. pub fn has_cached(&self) -> bool {
  294. self.is_f32_or_has_cached(0) &&
  295. self.is_f32_or_has_cached(1) &&
  296. self.is_f32_or_has_cached(2) &&
  297. self.is_f32_or_has_cached(3)
  298. }
  299. }