ranim_items/vitem/geometry/
line.rs1use ranim_core::{
2 Extract,
3 color::{AlphaColor, Srgb},
4 core_item::{CoreItem, vitem::DEFAULT_STROKE_WIDTH},
5 glam::DVec3,
6 traits::{Aabb, ApplyTransform, Discard, Locate, Opacity, StrokeColor, StrokeWidth, With},
7};
8use ranim_macros::Interpolatable;
9
10use crate::vitem::VItem;
11
12#[derive(Debug, Clone, Interpolatable)]
14pub struct Line {
15 pub points: [DVec3; 2],
17 pub extrude: [f64; 2],
20 pub stroke_rgba: AlphaColor<Srgb>,
22 pub stroke_width: f32,
24}
25
26impl Line {
27 pub fn new(start: DVec3, end: DVec3) -> Self {
29 Self {
30 points: [start, end],
31 extrude: [0., 0.],
32 stroke_rgba: AlphaColor::WHITE,
33 stroke_width: DEFAULT_STROKE_WIDTH,
34 }
35 }
36
37 pub fn invert(&mut self) -> &mut Self {
39 self.points.reverse();
40 self.extrude.reverse();
41 self
42 }
43
44 pub fn points_with_extrude(&self) -> [DVec3; 2] {
46 let [p1, p2] = self.points;
47 let [ext1, ext2] = self.extrude;
48 let d = (p2 - p1).normalize();
49 [p1 - d * ext1, p2 + d * ext2]
50 }
51}
52
53impl Locate<Line> for f64 {
54 fn locate(&self, target: &Line) -> DVec3 {
55 let [p1, p2] = target.points;
56 p1.lerp(p2, *self)
57 }
58}
59
60impl Aabb for Line {
61 fn aabb(&self) -> [DVec3; 2] {
62 self.points_with_extrude().aabb()
63 }
64}
65
66impl<G: Into<ranim_core::glam::DAffine3>> ApplyTransform<G> for Line {
67 fn apply(&mut self, transform: G) -> &mut Self {
68 let transform = transform.into();
69 let direction = (self.points[1] - self.points[0]).try_normalize();
70 self.points.apply(transform);
71 if let Some(direction) = direction {
72 let length_scale = transform.transform_vector3(direction).length();
73 self.extrude.iter_mut().for_each(|e| *e *= length_scale);
74 }
75 self
76 }
77}
78
79impl StrokeColor for Line {
80 fn stroke_color(&self) -> AlphaColor<Srgb> {
81 self.stroke_rgba
82 }
83
84 fn set_stroke_opacity(&mut self, opacity: f32) -> &mut Self {
85 self.stroke_rgba = self.stroke_rgba.with_alpha(opacity);
86 self
87 }
88
89 fn set_stroke_color(&mut self, color: AlphaColor<Srgb>) -> &mut Self {
90 self.stroke_rgba = color;
91 self
92 }
93}
94
95impl From<Line> for VItem {
96 fn from(value: Line) -> Self {
97 let [p1, p2] = value.points_with_extrude();
98 VItem::from_vpoints(vec![p1, (p1 + p2) / 2., p2]).with(|item| {
99 item.set_stroke_color(value.stroke_rgba)
100 .set_stroke_width(value.stroke_width)
101 .discard()
102 })
103 }
104}
105
106impl Opacity for Line {
107 fn set_opacity(&mut self, opacity: f32) -> &mut Self {
108 self.set_stroke_opacity(opacity);
109 self
110 }
111}
112
113impl Extract for Line {
114 type Target = CoreItem;
115
116 fn extract_into(&self, buf: &mut Vec<Self::Target>) {
117 VItem::from(self.clone()).extract_into(buf);
118 }
119}