lotus_script/
graphics.rs

1#[cfg(feature = "internal")]
2use lotus_script_sys::FfiObject;
3
4pub use lotus_shared::graphics::*;
5
6pub mod textures {
7    use lotus_script_sys::FfiObject;
8    use lotus_shared::{
9        content::ContentId,
10        graphics::Color,
11        math::{IVec2, Rectangle, UVec2},
12    };
13
14    pub use lotus_shared::graphics::textures::*;
15
16    /// A texture that can be manipulated and displayed on script texture slots.
17    #[derive(Debug)]
18    pub struct Texture(TextureHandle);
19
20    impl Texture {
21        /// Create a new texture.
22        #[must_use]
23        pub fn create<'a>(options: impl Into<TextureCreationOptions<'a>>) -> Self {
24            let options = options.into();
25            let options = FfiObject::new(&options);
26
27            unsafe {
28                Self(TextureHandle::new(lotus_script_sys::textures::create(
29                    options.packed(),
30                )))
31            }
32        }
33
34        /// Add an action to the texture. You may want to call the helper methods
35        /// instead of this.
36        pub fn add_action(&mut self, action: TextureAction) {
37            let action = FfiObject::new(&action);
38
39            unsafe { lotus_script_sys::textures::add_action(self.0.id(), action.packed()) }
40        }
41
42        /// Draw a rectangle on the texture.
43        pub fn draw_rect(&mut self, start: impl Into<UVec2>, end: impl Into<UVec2>, color: Color) {
44            self.add_action(TextureAction::DrawRect {
45                start: start.into(),
46                end: end.into(),
47                color,
48            });
49        }
50
51        /// Clear the texture with a color.
52        pub fn clear(&mut self, color: Color) {
53            self.add_action(TextureAction::Clear(color));
54        }
55
56        /// Read the color of a pixel on the texture.
57        #[inline]
58        pub fn read_pixel(&self, x: u32, y: u32) -> Color {
59            let packed = unsafe { lotus_script_sys::textures::get_pixel(self.0.id(), x, y) };
60            packed.into()
61        }
62
63        /// Draw multiple pixels on the texture.
64        pub fn draw_pixels<P>(&mut self, pixels: &[P])
65        where
66            P: Into<DrawPixel> + Copy,
67        {
68            let pixels = pixels.iter().map(|p| (*p).into()).collect();
69
70            self.add_action(TextureAction::DrawPixels(pixels));
71        }
72
73        /// Draws another texture on top of this one.
74        pub fn draw_texture(&mut self, other: &Texture, options: DrawTextureOpts) {
75            self.add_action(TextureAction::DrawScriptTexture {
76                handle: other.handle(),
77                options,
78            });
79        }
80
81        /// Call this once for every game-texture you want to apply this to. You can define the name in the content tool.
82        pub fn apply_to(&mut self, name: &str) {
83            let name = FfiObject::new(&name);
84            unsafe { lotus_script_sys::textures::apply_to(self.0.id(), name.packed()) }
85        }
86
87        /// Only call this if you need your actions to be applied immediately.
88        /// Cause of streaming assets, this method will return false if the actions are not yet applied.
89        /// Just call this method again until it returns true.
90        pub fn flush(&mut self) -> bool {
91            unsafe { lotus_script_sys::textures::flush_actions(self.0.id()) == 1 }
92        }
93
94        /// Draws another texture on top of this one.
95        pub fn draw_script_texture(&mut self, other: &Texture, options: DrawTextureOpts) {
96            self.add_action(TextureAction::DrawScriptTexture {
97                handle: other.handle(),
98                options,
99            });
100        }
101
102        /// Draws a text on the texture.
103        #[expect(clippy::too_many_arguments)]
104        pub fn draw_text(
105            &mut self,
106            font: ContentId,
107            text: impl Into<String>,
108            top_left: impl Into<IVec2>,
109            letter_spacing: u32,
110            full_color: impl Into<Option<Color>>,
111            alpha_mode: AlphaMode,
112            target_rect: impl Into<Option<Rectangle>>,
113        ) {
114            self.add_action(TextureAction::DrawText {
115                font,
116                text: text.into(),
117                top_left: top_left.into(),
118                letter_spacing,
119                full_color: full_color.into(),
120                alpha_mode,
121                target_rect: target_rect.into(),
122            });
123        }
124
125        /// Get the handle of the texture.
126        pub fn handle(&self) -> TextureHandle {
127            self.0
128        }
129
130        /// Forget the texture. This means it will not be disposed when the texture is dropped.
131        /// Use this only if you want to keep the texture alive without keeping a reference to it.
132        pub fn forget(mut self) {
133            self.0 = TextureHandle::new(u32::MAX);
134        }
135
136        /// Expose the texture to the plugin API under the given name.
137        pub fn expose(&self, name: &str) {
138            let name = FfiObject::new(&name);
139            unsafe { lotus_script_sys::textures::expose(self.0.id(), name.packed()) }
140        }
141    }
142
143    impl Drop for Texture {
144        fn drop(&mut self) {
145            if self.0.id() != u32::MAX {
146                unsafe { lotus_script_sys::textures::dispose(self.0.id()) }
147            }
148        }
149    }
150
151    pub enum DrawableTexture {
152        // TODO: Support content textures.
153        // Content(ContentId),
154        Script(TextureHandle),
155    }
156
157    impl From<&Texture> for DrawableTexture {
158        fn from(texture: &Texture) -> Self {
159            Self::Script(texture.handle())
160        }
161    }
162
163    impl From<TextureHandle> for DrawableTexture {
164        fn from(handle: TextureHandle) -> Self {
165            Self::Script(handle)
166        }
167    }
168}
169
170#[cfg(feature = "internal")]
171pub fn fetch_drawable_texture_properties() -> Vec<DrawableTextureProperties> {
172    let properties = unsafe { lotus_script_sys::textures::fetch_drawable_texture_properties() };
173    FfiObject::from_packed(properties).deserialize()
174}