blue_engine_core/prelude/mod.rs
1use downcast::{Any, downcast};
2/// re-exports from dependencies that are useful
3pub mod imports;
4pub use imports::*;
5/// contains definition for some 2D and 3D shapes. They are basic shapes and
6/// can be used as examples of how to create your own content.
7pub mod primitive_shapes;
8pub use crate::camera::{Camera, CameraContainer, Projection};
9pub use crate::definition::{
10 Pipeline, PipelineData, ShaderSettings, TextureData, TextureMode, VertexBuffers,
11 pixel_to_cartesian,
12};
13pub use crate::objects::{
14 Instance, InstanceRaw, Object, ObjectSettings, ObjectStorage, RotateAmount, RotateAxis,
15};
16pub use crate::render::Renderer;
17pub use crate::window::{Window, WindowDescriptor};
18
19/// The uint type used for indices and more
20#[cfg(not(feature = "u32"))]
21pub type UnsignedIntType = u16;
22#[cfg(feature = "u32")]
23pub type UnsignedIntType = u32;
24
25///
26pub mod macros {
27 macro_rules! impl_deref {
28 ($struct:ty,$type:ty) => {
29 impl std::ops::Deref for $struct {
30 type Target = $type;
31
32 fn deref(&self) -> &Self::Target {
33 &self.0
34 }
35 }
36 impl std::ops::DerefMut for $struct {
37 fn deref_mut(&mut self) -> &mut Self::Target {
38 &mut self.0
39 }
40 }
41 };
42 }
43
44 macro_rules! impl_deref_field {
45 ($struct:ty,$type:ty,$field:ident) => {
46 impl std::ops::Deref for $struct {
47 type Target = $type;
48
49 fn deref(&self) -> &Self::Target {
50 &self.$field
51 }
52 }
53 impl std::ops::DerefMut for $struct {
54 fn deref_mut(&mut self) -> &mut Self::Target {
55 &mut self.$field
56 }
57 }
58 };
59 }
60
61 pub(crate) use impl_deref;
62 pub(crate) use impl_deref_field;
63}
64
65/// Will contain all details about a vertex and will be sent to GPU
66// Will be turned to C code and sent to GPU
67#[repr(C)]
68#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
69pub struct Vertex {
70 /// Contains position data for the vertex in 3D space
71 pub position: [f32; 3],
72 /// Contains uv position data for the vertex
73 pub uv: [f32; 2],
74 /// Contains the normal face of the vertex
75 pub normal: [f32; 3],
76}
77impl Vertex {
78 pub(crate) fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
79 wgpu::VertexBufferLayout {
80 array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
81 step_mode: wgpu::VertexStepMode::Vertex,
82 attributes: &[
83 wgpu::VertexAttribute {
84 offset: 0,
85 shader_location: 0,
86 format: wgpu::VertexFormat::Float32x3,
87 },
88 wgpu::VertexAttribute {
89 // This should be replaced with `std::mem::size_of::<Vector3>() as wgpu::BufferAddress`
90 offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
91 shader_location: 1,
92 format: wgpu::VertexFormat::Float32x2,
93 },
94 wgpu::VertexAttribute {
95 offset: std::mem::size_of::<[f32; 5]>() as wgpu::BufferAddress,
96 shader_location: 2,
97 format: wgpu::VertexFormat::Float32x3,
98 },
99 ],
100 }
101 }
102}
103unsafe impl Send for Vertex {}
104unsafe impl Sync for Vertex {}
105
106/// The engine is the main starting point of using the Blue Engine.
107/// Everything that runs on Blue Engine will be under this struct.
108/// The structure of engine is monolithic, but the underlying data and the way it works is not.
109/// It gives a set of default data to work with,
110/// but also allow you to go beyond that and work as low level as you wish to.
111///
112/// You can also use the Engine to build you own custom structure the way you wish for it to be.
113/// Possibilities are endless!
114///
115/// To start using the Blue Engine, you can start by creating a new Engine like follows:
116/// ```
117/// use blue_engine::prelude::{Engine, WindowDescriptor};
118///
119/// fn main() {
120/// let engine = Engine::new().expect("Couldn't create the engine");
121/// }
122/// ```
123/// The WindowDescriptor simply holds what features you would like for your window.
124/// If you are reading this on later version of
125/// the engine, you might be able to even run the engine in headless mode
126/// meaning there would not be a need for a window and the
127/// renders would come as image files.
128///
129/// If you so wish to have a window, you would need to start a window update loop.
130/// The update loop of window runs a frame every few millisecond,
131/// and gives you details of what is happening during this time, like input events.
132/// You can also modify existing parts of the engine during
133/// this update loop, such as changing camera to look differently,
134/// or creating a new object on the scene, or even changing window details!
135///
136/// The update loop is just a method of the Engine struct
137/// that have one argument which is a callback function.
138/// ```
139///
140/// ```
141/// [THE DATA HERE IS WORK IN PROGRESS!]
142pub struct Engine {
143 /// The renderer does exactly what it is called.
144 /// It works with the GPU to render frames according to the data you gave it.
145 pub renderer: Renderer,
146 /// The event_loop handles the events of the window and inputs.
147 ///
148 /// #### USED INTERNALLY
149 pub event_loop_control_flow: crate::winit::event_loop::ControlFlow,
150 /// The window handles everything about window and inputs.
151 /// This includes ability to modify window and listen toinput devices for changes.
152 ///
153 /// ### The window is not available before update_loop.
154 pub window: Window,
155 /// The object system is a way to make it easier to work with the engine.
156 /// Obviously you can work without it, but it's for those who
157 /// do not have the know-how, or wish to handle all the work of rendering data manually.
158 pub objects: ObjectStorage,
159 /// The camera handles the way the scene looks when rendered.
160 /// You can modify everything there is to camera through this.
161 pub camera: CameraContainer,
162 /// Handles all engine plugins
163 pub signals: SignalStorage,
164
165 /// holds the update_loop function
166 ///
167 /// #### USED INTERNALLY
168 #[allow(clippy::type_complexity)]
169 pub update_loop: Option<
170 Box<
171 dyn 'static
172 + FnMut(
173 // Core
174 &mut Renderer,
175 &mut Window,
176 &mut ObjectStorage,
177 &crate::utils::winit_input_helper::WinitInputHelper,
178 &mut CameraContainer,
179 &mut crate::SignalStorage,
180 ),
181 >,
182 >,
183
184 /// input events
185 ///
186 /// #### USED INTERNALLY
187 pub input_events: crate::utils::winit_input_helper::WinitInputHelper,
188}
189unsafe impl Send for Engine {}
190unsafe impl Sync for Engine {}
191
192/// Allows all events to be fetched directly, making it easier to add custom additions to the engine.
193pub trait Signal: Any {
194 /// This is ran as soon as the engine is properly initialized and all components are ready
195 #[allow(clippy::too_many_arguments)]
196 fn init(
197 &mut self,
198 _renderer: &mut crate::Renderer,
199 _window: &crate::Window,
200 _objects: &mut ObjectStorage,
201 _camera: &mut crate::CameraContainer,
202 ) {
203 }
204
205 /// This is ran at the device events when available
206 #[allow(clippy::too_many_arguments)]
207 fn device_events(
208 &mut self,
209 _renderer: &mut crate::Renderer,
210 _window: &crate::Window,
211 _objects: &mut ObjectStorage,
212 _events: &crate::DeviceEvent,
213 _input: &crate::InputHelper,
214 _camera: &mut crate::CameraContainer,
215 ) {
216 }
217
218 /// This is ran at the window events when available
219 #[allow(clippy::too_many_arguments)]
220 fn window_events(
221 &mut self,
222 _renderer: &mut crate::Renderer,
223 _window: &crate::Window,
224 _objects: &mut ObjectStorage,
225 _events: &crate::WindowEvent,
226 _input: &crate::InputHelper,
227 _camera: &mut crate::CameraContainer,
228 ) {
229 }
230
231 /// ran before the frame is rendered
232 #[allow(clippy::too_many_arguments)]
233 fn frame(
234 &mut self,
235 _renderer: &mut crate::Renderer,
236 _window: &crate::Window,
237 _objects: &mut ObjectStorage,
238 _camera: &mut crate::CameraContainer,
239 _input: &crate::InputHelper,
240 _encoder: &mut crate::CommandEncoder,
241 _view: &crate::TextureView,
242 ) {
243 }
244}
245// The engine needs to know the functions of Signal to do things internally,
246// so we use downcast and not the std::any::Any
247downcast!(dyn Signal);
248
249/// Handles the live events in the engine
250pub struct SignalStorage {
251 /// list of events with key and the event
252 pub events: Vec<(String, Box<dyn Signal>)>,
253}
254
255/// A unified way to handle strings
256pub trait StringBuffer: StringBufferTrait + Clone {}
257/// A trait for [StringBuffer]
258pub trait StringBufferTrait {
259 /// Returns the string as &[`str`]
260 fn as_str(&self) -> &str;
261 /// Returns the string as [`String`]
262 fn as_string(&self) -> String;
263 /// Returns Arc<str> for ease of computation
264 fn as_arc(&self) -> std::sync::Arc<str>;
265}
266
267impl StringBufferTrait for String {
268 fn as_str(&self) -> &str {
269 self.as_ref()
270 }
271 fn as_string(&self) -> String {
272 self.clone()
273 }
274 fn as_arc(&self) -> std::sync::Arc<str> {
275 self.as_str().into()
276 }
277}
278impl StringBuffer for String {}
279impl StringBufferTrait for &str {
280 fn as_str(&self) -> &str {
281 self
282 }
283 fn as_string(&self) -> String {
284 self.to_string()
285 }
286 fn as_arc(&self) -> std::sync::Arc<str> {
287 self.as_str().into()
288 }
289}
290impl StringBuffer for &str {}