diff --git a/inox2d/src/math.rs b/inox2d/src/math.rs index 952b312d..6d314b9d 100644 --- a/inox2d/src/math.rs +++ b/inox2d/src/math.rs @@ -2,4 +2,5 @@ pub mod camera; pub mod deform; pub mod interp; pub mod matrix; +pub mod rect; pub mod transform; diff --git a/inox2d/src/math/rect.rs b/inox2d/src/math/rect.rs new file mode 100644 index 00000000..aba72069 --- /dev/null +++ b/inox2d/src/math/rect.rs @@ -0,0 +1,50 @@ +use glam::Vec2; + +#[derive(Clone, Copy)] +pub struct RectBounds { + top_left: Vec2, + bottom_right: Vec2, +} + +impl RectBounds { + pub fn from_point(point: Vec2) -> Self { + RectBounds { + top_left: point, + bottom_right: point, + } + } + + pub fn with_union_point(&self, point: Vec2) -> Self { + let mut child = *self; + + if point.x < child.top_left.x { + child.top_left.x = point.x; + } else if point.x > child.bottom_right.x { + child.bottom_right.x = point.x; + } + + if point.y < child.top_left.y { + child.top_left.y = point.y; + } else if point.y > child.bottom_right.y { + child.bottom_right.y = point.y; + } + + child + } + + pub fn width(&self) -> f32 { + self.bottom_right.x - self.top_left.x + } + + pub fn height(&self) -> f32 { + self.bottom_right.y - self.top_left.y + } + + pub fn top_left_point(&self) -> Vec2 { + self.top_left + } + + pub fn bottom_right_point(&self) -> Vec2 { + self.bottom_right + } +} diff --git a/inox2d/src/puppet.rs b/inox2d/src/puppet.rs index 7cdcbfa1..0089e406 100644 --- a/inox2d/src/puppet.rs +++ b/inox2d/src/puppet.rs @@ -5,11 +5,14 @@ mod world; use std::collections::HashMap; +use crate::math::rect::RectBounds; +use crate::node::components::{Mesh, TransformStore}; use crate::node::{InoxNode, InoxNodeUuid}; use crate::params::{Param, ParamCtx}; use crate::physics::{PhysicsCtx, PuppetPhysics}; use crate::render::RenderCtx; +use glam::Vec4Swizzles; use meta::PuppetMeta; use transforms::TransformCtx; pub use tree::InoxNodeTree; @@ -167,4 +170,27 @@ impl Puppet { render_ctx.update(&self.nodes, &mut self.node_comps); } } + + /// Compute the bounds of the puppet's current state. + pub fn bounds(&self) -> Option { + let mut out = None; + for node in self.nodes.iter() { + if let (Some(transform), Some(mesh)) = ( + self.node_comps.get::(node.uuid), + self.node_comps.get::(node.uuid), + ) { + let mvp = transform.absolute; + + for vert in &mesh.vertices { + let vert = mvp.mul_vec4(glam::Vec4::new(vert.x, vert.y, 0.0, 1.0)).xy(); + out = match out { + None => Some(RectBounds::from_point(vert)), + Some(rect) => Some(rect.with_union_point(vert)), + }; + } + } + } + + out + } }