mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-07-08 00:05:00 +00:00
131 lines
3.4 KiB
Rust
131 lines
3.4 KiB
Rust
use glam::{DAffine2, DMat2, DVec2};
|
|
|
|
pub trait Transform {
|
|
fn transform(&self) -> DAffine2;
|
|
fn local_pivot(&self, pivot: DVec2) -> DVec2 {
|
|
pivot
|
|
}
|
|
fn decompose_scale(&self) -> DVec2 {
|
|
DVec2::new(
|
|
self.transform().transform_vector2((1., 0.).into()).length(),
|
|
self.transform().transform_vector2((0., 1.).into()).length(),
|
|
)
|
|
}
|
|
}
|
|
|
|
pub trait TransformMut: Transform {
|
|
fn transform_mut(&mut self) -> &mut DAffine2;
|
|
fn translate(&mut self, offset: DVec2) {
|
|
*self.transform_mut() = DAffine2::from_translation(offset) * self.transform();
|
|
}
|
|
}
|
|
|
|
// Implementation for references to anything that implements Transform
|
|
impl<T: Transform> Transform for &T {
|
|
fn transform(&self) -> DAffine2 {
|
|
(*self).transform()
|
|
}
|
|
}
|
|
|
|
// Implementations for DAffine2
|
|
impl Transform for DAffine2 {
|
|
fn transform(&self) -> DAffine2 {
|
|
*self
|
|
}
|
|
}
|
|
impl TransformMut for DAffine2 {
|
|
fn transform_mut(&mut self) -> &mut DAffine2 {
|
|
self
|
|
}
|
|
}
|
|
|
|
// Implementations for Footprint
|
|
impl Transform for Footprint {
|
|
fn transform(&self) -> DAffine2 {
|
|
self.transform
|
|
}
|
|
}
|
|
impl TransformMut for Footprint {
|
|
fn transform_mut(&mut self) -> &mut DAffine2 {
|
|
&mut self.transform
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone, Copy, dyn_any::DynAny, PartialEq, serde::Serialize, serde::Deserialize)]
|
|
pub enum RenderQuality {
|
|
/// Low quality, fast rendering
|
|
Preview,
|
|
/// Ensure that the render is available with at least the specified quality
|
|
/// A value of 0.5 means that the render is available with at least 50% of the final image resolution
|
|
Scale(f32),
|
|
/// Flip a coin to decide if the render should be available with the current quality or done at full quality
|
|
/// This should be used to gradually update the render quality of a cached node
|
|
Probability(f32),
|
|
/// Render at full quality
|
|
Full,
|
|
}
|
|
#[derive(Debug, Clone, Copy, dyn_any::DynAny, PartialEq, serde::Serialize, serde::Deserialize)]
|
|
pub struct Footprint {
|
|
/// Inverse of the transform which will be applied to the node output during the rendering process
|
|
pub transform: DAffine2,
|
|
/// Resolution of the target output area in pixels
|
|
pub resolution: glam::UVec2,
|
|
/// Quality of the render, this may be used by caching nodes to decide if the cached render is sufficient
|
|
pub quality: RenderQuality,
|
|
}
|
|
|
|
impl Default for Footprint {
|
|
fn default() -> Self {
|
|
Self::DEFAULT
|
|
}
|
|
}
|
|
|
|
impl Footprint {
|
|
pub const DEFAULT: Self = Self {
|
|
transform: DAffine2::IDENTITY,
|
|
resolution: glam::UVec2::new(1920, 1080),
|
|
quality: RenderQuality::Full,
|
|
};
|
|
|
|
pub const BOUNDLESS: Self = Self {
|
|
transform: DAffine2 {
|
|
matrix2: DMat2::from_diagonal(DVec2::splat(f64::INFINITY)),
|
|
translation: DVec2::ZERO,
|
|
},
|
|
resolution: glam::UVec2::new(0, 0),
|
|
quality: RenderQuality::Full,
|
|
};
|
|
|
|
pub fn scale(&self) -> DVec2 {
|
|
self.transform.decompose_scale()
|
|
}
|
|
|
|
pub fn offset(&self) -> DVec2 {
|
|
self.transform.transform_point2(DVec2::ZERO)
|
|
}
|
|
}
|
|
|
|
impl From<()> for Footprint {
|
|
fn from(_: ()) -> Self {
|
|
Footprint::default()
|
|
}
|
|
}
|
|
|
|
impl std::hash::Hash for Footprint {
|
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
|
self.transform.to_cols_array().iter().for_each(|x| x.to_le_bytes().hash(state));
|
|
self.resolution.hash(state)
|
|
}
|
|
}
|
|
|
|
pub trait ApplyTransform {
|
|
fn apply_transform(&mut self, modification: &DAffine2);
|
|
}
|
|
impl<T: TransformMut> ApplyTransform for T {
|
|
fn apply_transform(&mut self, &modification: &DAffine2) {
|
|
*self.transform_mut() = self.transform() * modification
|
|
}
|
|
}
|
|
impl ApplyTransform for () {
|
|
fn apply_transform(&mut self, &_modification: &DAffine2) {}
|
|
}
|