1#[macro_use]
2mod macros;
3
4pub mod audio;
5pub mod automation;
6pub mod callbacks;
7pub mod camera;
8pub mod collision;
9pub mod color;
10pub mod data;
11pub mod drawing;
12pub mod error;
13pub mod file;
14
15pub mod input;
16pub mod logging;
17pub mod math;
18pub mod misc;
19pub mod models;
20pub mod shaders;
21pub mod text;
22pub mod texture;
23pub mod vr;
24pub mod window;
25
26use raylib_sys::TraceLogLevel;
27
28use crate::ffi;
29use std::ffi::CString;
30use std::marker::PhantomData;
31
32#[macro_export]
34macro_rules! rstr {
35 ($e:tt) => ({
36 #[allow(unused_unsafe)]
37 unsafe {
38 std::ffi::CStr::from_bytes_with_nul_unchecked(concat!($e, "\0").as_bytes())
39 }
40 });
41 ($e:tt, $($arg:tt)*) => ({
42 #[allow(unused_unsafe)]
43 unsafe {
44 std::ffi::CString::new(format!($e, $($arg)*)).unwrap()
45 }
46 })
47}
48
49#[derive(Clone, Debug)]
53pub struct RaylibThread(PhantomData<*const ()>);
54
55#[derive(Debug)]
63pub struct RaylibHandle(()); impl Drop for RaylibHandle {
66 fn drop(&mut self) {
67 unsafe {
68 if ffi::IsWindowReady() {
69 ffi::CloseWindow();
70 }
73 }
74 }
75}
76
77#[derive(Debug, Default)]
79pub struct RaylibBuilder {
80 fullscreen_mode: bool,
81 window_resizable: bool,
82 window_undecorated: bool,
83 window_transparent: bool,
84 msaa_4x_hint: bool,
85 vsync_hint: bool,
86 log_level: TraceLogLevel,
87 width: i32,
88 height: i32,
89 title: String,
90 #[cfg(feature = "imgui")]
91 imgui_theme: crate::imgui::ImGuiTheme,
92}
93
94pub fn init() -> RaylibBuilder {
96 RaylibBuilder {
97 width: 640,
98 height: 480,
99 title: "raylib-rs".to_string(),
100 ..Default::default()
101 }
102}
103
104impl RaylibBuilder {
105 pub fn fullscreen(&mut self) -> &mut Self {
107 self.fullscreen_mode = true;
108 self
109 }
110
111 pub fn log_level(&mut self, level: TraceLogLevel) -> &mut Self {
113 self.log_level = level;
114 self
115 }
116 pub fn resizable(&mut self) -> &mut Self {
118 self.window_resizable = true;
119 self
120 }
121
122 pub fn undecorated(&mut self) -> &mut Self {
124 self.window_undecorated = true;
125 self
126 }
127
128 pub fn transparent(&mut self) -> &mut Self {
130 self.window_transparent = true;
131 self
132 }
133
134 pub fn msaa_4x(&mut self) -> &mut Self {
136 self.msaa_4x_hint = true;
137 self
138 }
139
140 pub fn vsync(&mut self) -> &mut Self {
142 self.vsync_hint = true;
143 self
144 }
145
146 pub fn width(&mut self, w: i32) -> &mut Self {
148 self.width = w;
149 self
150 }
151
152 pub fn height(&mut self, h: i32) -> &mut Self {
154 self.height = h;
155 self
156 }
157
158 pub fn size(&mut self, w: i32, h: i32) -> &mut Self {
160 self.width = w;
161 self.height = h;
162 self
163 }
164
165 pub fn title(&mut self, text: &str) -> &mut Self {
167 self.title = text.to_string();
168 self
169 }
170
171 #[cfg(feature = "imgui")]
172 pub fn imgui_theme(&mut self, theme: crate::imgui::ImGuiTheme) -> &mut Self {
174 self.imgui_theme = theme;
175 self
176 }
177
178 pub fn build(&self) -> (RaylibHandle, RaylibThread) {
184 use crate::consts::ConfigFlags::*;
185 let mut flags = 0u32;
186 if self.fullscreen_mode {
187 flags |= FLAG_FULLSCREEN_MODE as u32;
188 }
189 if self.window_resizable {
190 flags |= FLAG_WINDOW_RESIZABLE as u32;
191 }
192 if self.window_undecorated {
193 flags |= FLAG_WINDOW_UNDECORATED as u32;
194 }
195 if self.window_transparent {
196 flags |= FLAG_WINDOW_TRANSPARENT as u32;
197 }
198 if self.msaa_4x_hint {
199 flags |= FLAG_MSAA_4X_HINT as u32;
200 }
201 if self.vsync_hint {
202 flags |= FLAG_VSYNC_HINT as u32;
203 }
204
205 unsafe {
206 ffi::SetConfigFlags(flags as u32);
207 }
208
209 unsafe {
210 ffi::SetTraceLogLevel(self.log_level as i32);
211 }
212
213 let rl = init_window(self.width, self.height, &self.title);
214
215 #[cfg(feature = "imgui")]
216 unsafe {
217 crate::imgui::init_imgui_context(self.imgui_theme == crate::imgui::ImGuiTheme::Dark);
218 }
219
220 (rl, RaylibThread(PhantomData))
221 }
222}
223
224fn init_window(width: i32, height: i32, title: &str) -> RaylibHandle {
230 if unsafe { ffi::IsWindowReady() } {
231 panic!("Attempted to initialize raylib-rs more than once!");
232 } else {
233 unsafe {
234 let c_title = CString::new(title).unwrap();
235 ffi::InitWindow(width, height, c_title.as_ptr());
236 }
237 if !unsafe { ffi::IsWindowReady() } {
238 panic!("Attempting to create window failed!");
239 }
240
241 RaylibHandle(())
242 }
243}