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        // SAFETY: Pointer checked non-null above; allocated by builder_new via Box::into_raw.
52        let s = unsafe { &mut (*builder).sprite };
53        s.color_r = r;
54        s.color_g = g;
55        s.color_b = b;
56        s.color_a = a;
57        builder
58    }
59
60    /// Sets the alpha on the builder.
61    pub fn builder_with_alpha(builder: *mut FfiSpriteBuilder, alpha: f32) -> *mut FfiSpriteBuilder {
62        if builder.is_null() {
63            return builder;
64        }
65        // SAFETY: Pointer checked non-null above; allocated by builder_new via Box::into_raw.
66        unsafe { (*builder).sprite.color_a = alpha };
67        builder
68    }
69
70    /// Sets the source rectangle on the builder.
71    pub fn builder_with_source_rect(
72        builder: *mut FfiSpriteBuilder,
73        x: f32,
74        y: f32,
75        width: f32,
76        height: f32,
77    ) -> *mut FfiSpriteBuilder {
78        if builder.is_null() {
79            return builder;
80        }
81        // SAFETY: Pointer checked non-null above; allocated by builder_new via Box::into_raw.
82        let s = unsafe { &mut (*builder).sprite };
83        s.source_rect_x = x;
84        s.source_rect_y = y;
85        s.source_rect_width = width;
86        s.source_rect_height = height;
87        s.has_source_rect = true;
88        builder
89    }
90
91    /// Sets the horizontal flip on the builder.
92    pub fn builder_with_flip_x(
93        builder: *mut FfiSpriteBuilder,
94        flip: bool,
95    ) -> *mut FfiSpriteBuilder {
96        if builder.is_null() {
97            return builder;
98        }
99        // SAFETY: Pointer checked non-null above; allocated by builder_new via Box::into_raw.
100        unsafe { (*builder).sprite.flip_x = flip };
101        builder
102    }
103
104    /// Sets the vertical flip on the builder.
105    pub fn builder_with_flip_y(
106        builder: *mut FfiSpriteBuilder,
107        flip: bool,
108    ) -> *mut FfiSpriteBuilder {
109        if builder.is_null() {
110            return builder;
111        }
112        // SAFETY: Pointer checked non-null above; allocated by builder_new via Box::into_raw.
113        unsafe { (*builder).sprite.flip_y = flip };
114        builder
115    }
116
117    /// Sets both flip flags on the builder.
118    pub fn builder_with_flip(
119        builder: *mut FfiSpriteBuilder,
120        flip_x: bool,
121        flip_y: bool,
122    ) -> *mut FfiSpriteBuilder {
123        if builder.is_null() {
124            return builder;
125        }
126        // SAFETY: Pointer checked non-null above; allocated by builder_new via Box::into_raw.
127        let s = unsafe { &mut (*builder).sprite };
128        s.flip_x = flip_x;
129        s.flip_y = flip_y;
130        builder
131    }
132
133    /// Sets the anchor point on the builder.
134    pub fn builder_with_anchor(
135        builder: *mut FfiSpriteBuilder,
136        x: f32,
137        y: f32,
138    ) -> *mut FfiSpriteBuilder {
139        if builder.is_null() {
140            return builder;
141        }
142        // SAFETY: Pointer checked non-null above; allocated by builder_new via Box::into_raw.
143        let s = unsafe { &mut (*builder).sprite };
144        s.anchor_x = x;
145        s.anchor_y = y;
146        builder
147    }
148
149    /// Sets the custom size on the builder.
150    pub fn builder_with_custom_size(
151        builder: *mut FfiSpriteBuilder,
152        width: f32,
153        height: f32,
154    ) -> *mut FfiSpriteBuilder {
155        if builder.is_null() {
156            return builder;
157        }
158        // SAFETY: Pointer checked non-null above; allocated by builder_new via Box::into_raw.
159        let s = unsafe { &mut (*builder).sprite };
160        s.custom_size_x = width;
161        s.custom_size_y = height;
162        s.has_custom_size = true;
163        builder
164    }
165
166    /// Builds the sprite, consuming and freeing the builder.
167    pub fn builder_build(builder: *mut FfiSpriteBuilder) -> FfiSprite {
168        if builder.is_null() {
169            return super::factory::SpriteOps::new_default();
170        }
171        // SAFETY: Takes ownership from builder_new allocation.
172        let boxed = unsafe { Box::from_raw(builder) };
173        boxed.sprite
174    }
175
176    /// Frees a sprite builder without building.
177    pub fn builder_free(builder: *mut FfiSpriteBuilder) {
178        if !builder.is_null() {
179            // SAFETY: Takes ownership and drops.
180            drop(unsafe { Box::from_raw(builder) });
181        }
182    }
183}