Skip to main content

goud_engine/sdk/components_sprite/
builder.rs

1//! Heap-allocated sprite builder operations.
2
3use crate::core::types::{FfiSprite, FfiSpriteBuilder};
4
5/// Zero-sized type for Sprite builder operations.
6pub struct SpriteBuilderOps;
7
8// NOTE: FFI wrappers are hand-written in ffi/component_sprite.rs. The `#[goud_api]`
9// attribute is omitted here to avoid duplicate `#[no_mangle]` symbol conflicts.
10impl SpriteBuilderOps {
11    /// Creates a new sprite builder with a texture handle.
12    pub fn builder_new(texture_handle: u64) -> *mut FfiSpriteBuilder {
13        let builder = FfiSpriteBuilder {
14            sprite: super::factory::SpriteOps::new_sprite(texture_handle),
15        };
16        Box::into_raw(Box::new(builder))
17    }
18
19    /// Creates a new sprite builder with default values.
20    pub fn builder_default() -> *mut FfiSpriteBuilder {
21        let builder = FfiSpriteBuilder {
22            sprite: super::factory::SpriteOps::new_default(),
23        };
24        Box::into_raw(Box::new(builder))
25    }
26
27    /// Sets the texture handle on the builder.
28    pub fn builder_with_texture(
29        builder: *mut FfiSpriteBuilder,
30        texture_handle: u64,
31    ) -> *mut FfiSpriteBuilder {
32        if builder.is_null() {
33            return builder;
34        }
35        // SAFETY: Caller guarantees pointer from builder_new.
36        unsafe { (*builder).sprite.texture_handle = texture_handle };
37        builder
38    }
39
40    /// Sets the color tint on the builder.
41    pub fn builder_with_color(
42        builder: *mut FfiSpriteBuilder,
43        r: f32,
44        g: f32,
45        b: f32,
46        a: f32,
47    ) -> *mut FfiSpriteBuilder {
48        if builder.is_null() {
49            return builder;
50        }
51        let s = unsafe { &mut (*builder).sprite };
52        s.color_r = r;
53        s.color_g = g;
54        s.color_b = b;
55        s.color_a = a;
56        builder
57    }
58
59    /// Sets the alpha on the builder.
60    pub fn builder_with_alpha(builder: *mut FfiSpriteBuilder, alpha: f32) -> *mut FfiSpriteBuilder {
61        if builder.is_null() {
62            return builder;
63        }
64        unsafe { (*builder).sprite.color_a = alpha };
65        builder
66    }
67
68    /// Sets the source rectangle on the builder.
69    pub fn builder_with_source_rect(
70        builder: *mut FfiSpriteBuilder,
71        x: f32,
72        y: f32,
73        width: f32,
74        height: f32,
75    ) -> *mut FfiSpriteBuilder {
76        if builder.is_null() {
77            return builder;
78        }
79        let s = unsafe { &mut (*builder).sprite };
80        s.source_rect_x = x;
81        s.source_rect_y = y;
82        s.source_rect_width = width;
83        s.source_rect_height = height;
84        s.has_source_rect = true;
85        builder
86    }
87
88    /// Sets the horizontal flip on the builder.
89    pub fn builder_with_flip_x(
90        builder: *mut FfiSpriteBuilder,
91        flip: bool,
92    ) -> *mut FfiSpriteBuilder {
93        if builder.is_null() {
94            return builder;
95        }
96        unsafe { (*builder).sprite.flip_x = flip };
97        builder
98    }
99
100    /// Sets the vertical flip on the builder.
101    pub fn builder_with_flip_y(
102        builder: *mut FfiSpriteBuilder,
103        flip: bool,
104    ) -> *mut FfiSpriteBuilder {
105        if builder.is_null() {
106            return builder;
107        }
108        unsafe { (*builder).sprite.flip_y = flip };
109        builder
110    }
111
112    /// Sets both flip flags on the builder.
113    pub fn builder_with_flip(
114        builder: *mut FfiSpriteBuilder,
115        flip_x: bool,
116        flip_y: bool,
117    ) -> *mut FfiSpriteBuilder {
118        if builder.is_null() {
119            return builder;
120        }
121        let s = unsafe { &mut (*builder).sprite };
122        s.flip_x = flip_x;
123        s.flip_y = flip_y;
124        builder
125    }
126
127    /// Sets the anchor point on the builder.
128    pub fn builder_with_anchor(
129        builder: *mut FfiSpriteBuilder,
130        x: f32,
131        y: f32,
132    ) -> *mut FfiSpriteBuilder {
133        if builder.is_null() {
134            return builder;
135        }
136        let s = unsafe { &mut (*builder).sprite };
137        s.anchor_x = x;
138        s.anchor_y = y;
139        builder
140    }
141
142    /// Sets the custom size on the builder.
143    pub fn builder_with_custom_size(
144        builder: *mut FfiSpriteBuilder,
145        width: f32,
146        height: f32,
147    ) -> *mut FfiSpriteBuilder {
148        if builder.is_null() {
149            return builder;
150        }
151        let s = unsafe { &mut (*builder).sprite };
152        s.custom_size_x = width;
153        s.custom_size_y = height;
154        s.has_custom_size = true;
155        builder
156    }
157
158    /// Builds the sprite, consuming and freeing the builder.
159    pub fn builder_build(builder: *mut FfiSpriteBuilder) -> FfiSprite {
160        if builder.is_null() {
161            return super::factory::SpriteOps::new_default();
162        }
163        // SAFETY: Takes ownership from builder_new allocation.
164        let boxed = unsafe { Box::from_raw(builder) };
165        boxed.sprite
166    }
167
168    /// Frees a sprite builder without building.
169    pub fn builder_free(builder: *mut FfiSpriteBuilder) {
170        if !builder.is_null() {
171            // SAFETY: Takes ownership and drops.
172            drop(unsafe { Box::from_raw(builder) });
173        }
174    }
175}