Skip to main content

ranim_items/vitem/geometry/
ellipse.rs

1#[cfg(feature = "render")]
2use ranim_render::extract::{Extract, ExtractContext};
3
4use ranim_core::{
5    color::{AlphaColor, Srgb},
6    glam::{DVec2, DVec3},
7    traits::{Aabb, Discard, FillColor, Opacity, StrokeColor, With},
8};
9
10use crate::vitem::{
11    DEFAULT_STROKE_WIDTH, VItem,
12    geometry::{Circle, EllipticArc},
13};
14
15/// An ellipse centered at the origin in the XY plane.
16#[derive(Clone, Debug, ranim_macros::Interpolatable)]
17pub struct Ellipse {
18    /// Semi-axes in the x and y directions.
19    pub radius: DVec2,
20    /// Stroke rgba.
21    pub stroke_rgba: AlphaColor<Srgb>,
22    /// Stroke width.
23    pub stroke_width: f32,
24    /// Fill rgba.
25    pub fill_rgba: AlphaColor<Srgb>,
26}
27
28impl Ellipse {
29    /// Creates a new ellipse.
30    pub fn new(radius: DVec2) -> Self {
31        Self {
32            radius,
33            stroke_rgba: AlphaColor::WHITE,
34            stroke_width: DEFAULT_STROKE_WIDTH,
35            fill_rgba: AlphaColor::TRANSPARENT,
36        }
37    }
38}
39
40impl From<Circle> for Ellipse {
41    fn from(value: Circle) -> Self {
42        let Circle {
43            radius,
44            stroke_rgba,
45            stroke_width,
46            fill_rgba,
47        } = value;
48        Self {
49            radius: DVec2::splat(radius),
50            stroke_rgba,
51            stroke_width,
52            fill_rgba,
53        }
54    }
55}
56
57impl From<Ellipse> for VItem {
58    fn from(value: Ellipse) -> Self {
59        let fill_rgba = value.fill_rgba;
60        VItem::from(EllipticArc::from(value)).with(|item| item.set_fill_color(fill_rgba).discard())
61    }
62}
63
64impl Aabb for Ellipse {
65    fn aabb(&self) -> [DVec3; 2] {
66        let r = self.radius.extend(0.0);
67        [-r, r].aabb()
68    }
69}
70
71impl StrokeColor for Ellipse {
72    fn stroke_color(&self) -> AlphaColor<Srgb> {
73        self.stroke_rgba
74    }
75
76    fn set_stroke_opacity(&mut self, opacity: f32) -> &mut Self {
77        self.stroke_rgba = self.stroke_rgba.with_alpha(opacity);
78        self
79    }
80
81    fn set_stroke_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
82        self.stroke_rgba = color;
83        self
84    }
85}
86
87impl FillColor for Ellipse {
88    fn fill_color(&self) -> AlphaColor<Srgb> {
89        self.fill_rgba
90    }
91
92    fn set_fill_opacity(&mut self, opacity: f32) -> &mut Self {
93        self.fill_rgba = self.fill_rgba.with_alpha(opacity);
94        self
95    }
96
97    fn set_fill_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
98        self.fill_rgba = color;
99        self
100    }
101}
102
103impl Opacity for Ellipse {
104    fn set_opacity(&mut self, opacity: f32) -> &mut Self {
105        self.set_fill_opacity(opacity).set_stroke_opacity(opacity);
106        self
107    }
108}
109
110#[cfg(feature = "render")]
111impl Extract for Ellipse {
112    fn extract(&self, ctx: &mut ExtractContext<'_>) {
113        VItem::from(self.clone()).extract(ctx);
114    }
115}