rusty_spine/
region_attachment.rs

1use crate::{
2    c::{
3        c_float, spAttachment, spRegionAttachment, spRegionAttachment_computeWorldVertices,
4        spRegionAttachment_updateRegion, spTextureRegion,
5    },
6    c_interface::SyncPtr,
7    slot::Slot,
8    texture_region::TextureRegion,
9    Color,
10};
11
12#[cfg(feature = "mint")]
13use mint::Vector2;
14
15/// Properties for updating [`RegionAttachment`].
16#[derive(Debug)]
17pub struct RegionProps {
18    pub x: f32,
19    pub y: f32,
20    pub scale_x: f32,
21    pub scale_y: f32,
22    pub rotation: f32,
23    pub width: f32,
24    pub height: f32,
25    pub color: Color,
26}
27
28/// An attachment which draws a texture.
29///
30/// [Spine API Reference](http://esotericsoftware.com/spine-api-reference#RegionAttachment)
31#[derive(Debug)]
32pub struct RegionAttachment {
33    c_region_attachment: SyncPtr<spRegionAttachment>,
34}
35
36impl RegionAttachment {
37    #[must_use]
38    pub const fn new_from_ptr(c_region_attachment: *mut spRegionAttachment) -> Self {
39        Self {
40            c_region_attachment: SyncPtr(c_region_attachment),
41        }
42    }
43
44    #[must_use]
45    fn attachment(&self) -> &spAttachment {
46        unsafe { &self.c_ptr_ref().super_0 }
47    }
48
49    /// # Safety
50    ///
51    /// The slot passed in must be the same slot this attachment originated from.
52    pub unsafe fn compute_world_vertices(
53        &self,
54        slot: &Slot,
55        vertices: &mut [f32],
56        offset: i32,
57        stride: i32,
58    ) {
59        spRegionAttachment_computeWorldVertices(
60            self.c_ptr(),
61            slot.c_ptr(),
62            vertices.as_mut_ptr(),
63            offset,
64            stride,
65        );
66    }
67
68    pub fn update_region(&mut self) {
69        unsafe {
70            spRegionAttachment_updateRegion(self.c_ptr());
71        }
72    }
73
74    pub fn update_from_props(&mut self, props: &RegionProps) {
75        self.set_x(props.x);
76        self.set_y(props.y);
77        self.set_scale_x(props.scale_x);
78        self.set_scale_y(props.scale_y);
79        self.set_rotation(props.rotation);
80        self.set_width(props.width);
81        self.set_height(props.height);
82        *self.color_mut() = props.color;
83        self.update_region();
84    }
85
86    c_attachment_accessors!();
87    c_accessor_string_mut!(path, set_path, path);
88    c_accessor_mut!(
89        /// The local x translation.
90        x,
91        set_x,
92        x,
93        f32
94    );
95    c_accessor_mut!(
96        /// The local y translation.
97        y,
98        set_y,
99        y,
100        f32
101    );
102    c_accessor_mut!(
103        /// The local scaleX.
104        scale_x,
105        set_scale_x,
106        scaleX,
107        f32
108    );
109    c_accessor_mut!(
110        /// The local scaleY.
111        scale_y,
112        set_scale_y,
113        scaleY,
114        f32
115    );
116    // TODO: docs: in degrees? counter-clockwise?
117    c_accessor_mut!(
118        /// The local rotation.
119        rotation,
120        set_rotation,
121        rotation,
122        f32
123    );
124    c_accessor_mut!(
125        /// The width of the region attachment in Spine.
126        width,
127        set_width,
128        width,
129        f32
130    );
131    c_accessor_mut!(
132        /// The height of the region attachment in Spine.
133        height,
134        set_height,
135        height,
136        f32
137    );
138    c_accessor_color_mut!(color, color_mut, color);
139    c_accessor_passthrough!(uvs, uvs, [c_float; 8]);
140    c_accessor_passthrough!(offset, offset, [c_float; 8]);
141    c_accessor_renderer_object!();
142    c_accessor_tmp_ptr_optional_mut!(region, region_mut, region, TextureRegion, spTextureRegion);
143    c_ptr!(c_region_attachment, spRegionAttachment);
144
145    // TODO: sequence accessor
146}
147
148/// Functions available if using the `mint` feature.
149#[cfg(feature = "mint")]
150impl RegionAttachment {
151    #[must_use]
152    pub fn translation(&self) -> Vector2<f32> {
153        Vector2 {
154            x: self.x(),
155            y: self.y(),
156        }
157    }
158
159    #[must_use]
160    pub fn scale(&self) -> Vector2<f32> {
161        Vector2 {
162            x: self.scale_x(),
163            y: self.scale_y(),
164        }
165    }
166
167    #[must_use]
168    pub fn size(&self) -> Vector2<f32> {
169        Vector2 {
170            x: self.width(),
171            y: self.height(),
172        }
173    }
174}