blue_engine_core/
header.rs

1/*
2 * Blue Engine by Elham Aryanpur
3 *
4 * The license is Apache-2.0
5*/
6
7/// re-exports from dependencies that are useful
8pub mod imports;
9/// few commonly used uniform buffer structures
10pub mod uniform_buffer;
11pub use imports::*;
12pub use uniform_buffer::*;
13
14use downcast::{downcast, Any};
15
16/// The uint type used for indices and more
17#[cfg(feature = "u16")]
18pub type UnsignedIntType = u16;
19#[cfg(feature = "u32")]
20pub type UnsignedIntType = u32;
21
22macro_rules! impl_deref {
23    ($struct:ty,$type:ty) => {
24        impl std::ops::Deref for $struct {
25            type Target = $type;
26
27            fn deref(&self) -> &Self::Target {
28                &self.0
29            }
30        }
31        impl std::ops::DerefMut for $struct {
32            fn deref_mut(&mut self) -> &mut Self::Target {
33                &mut self.0
34            }
35        }
36    };
37}
38
39macro_rules! impl_deref_field {
40    ($struct:ty,$type:ty,$field:ident) => {
41        impl std::ops::Deref for $struct {
42            type Target = $type;
43
44            fn deref(&self) -> &Self::Target {
45                &self.$field
46            }
47        }
48        impl std::ops::DerefMut for $struct {
49            fn deref_mut(&mut self) -> &mut Self::Target {
50                &mut self.$field
51            }
52        }
53    };
54}
55
56/// Will contain all details about a vertex and will be sent to GPU
57// Will be turned to C code and sent to GPU
58#[repr(C)]
59#[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
60pub struct Vertex {
61    /// Contains position data for the vertex in 3D space
62    pub position: Vector3,
63    /// Contains uv position data for the vertex
64    pub uv: Vector2,
65    /// Contains the normal face of the vertex
66    pub normal: Vector3,
67}
68impl Vertex {
69    pub(crate) fn desc<'a>() -> wgpu::VertexBufferLayout<'a> {
70        wgpu::VertexBufferLayout {
71            array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
72            step_mode: wgpu::VertexStepMode::Vertex,
73            attributes: &[
74                wgpu::VertexAttribute {
75                    offset: 0,
76                    shader_location: 0,
77                    format: wgpu::VertexFormat::Float32x3,
78                },
79                wgpu::VertexAttribute {
80                    // This should be replaced with `std::mem::size_of::<Vector3>() as wgpu::BufferAddress`
81                    offset: std::mem::size_of::<[f32; 3]>() as wgpu::BufferAddress,
82                    shader_location: 1,
83                    format: wgpu::VertexFormat::Float32x2,
84                },
85                wgpu::VertexAttribute {
86                    offset: std::mem::size_of::<[f32; 5]>() as wgpu::BufferAddress,
87                    shader_location: 2,
88                    format: wgpu::VertexFormat::Float32x3,
89                },
90            ],
91        }
92    }
93}
94unsafe impl Send for Vertex {}
95unsafe impl Sync for Vertex {}
96
97/// Objects make it easier to work with Blue Engine, it automates most of work needed for
98/// creating 3D objects and showing them on screen. A range of default objects are available
99/// as well as ability to customize each of them and even create your own! You can also
100/// customize almost everything there is about them!
101pub struct Object {
102    /// Give your object a name, which can help later on for debugging.
103    pub name: std::sync::Arc<str>,
104    /// A list of Vertex
105    pub vertices: Vec<Vertex>,
106    /// A list of indices that dictates the order that vertices appear
107    pub indices: Vec<UnsignedIntType>,
108    /// Describes how to uniform buffer is structures
109    pub uniform_layout: wgpu::BindGroupLayout,
110    /// Pipeline holds all the data that is sent to GPU, including shaders and textures
111    pub pipeline: Pipeline,
112    /// List of instances of this object
113    pub instances: Vec<Instance>,
114    /// instance buffer
115    pub instance_buffer: wgpu::Buffer,
116    /// Dictates the size of your object in relation to the world
117    pub size: Vector3,
118    /// Dictates the position of your object in pixels
119    pub position: Vector3,
120    /// Dictates the rotation of your object
121    pub rotation: Vector3,
122    // flags the object to be updated until next frame
123    pub(crate) changed: bool,
124    /// Transformation matrices helps to apply changes to your object, including position, orientation, ...
125    /// Best choice is to let the Object system handle it
126    pub position_matrix: nalgebra_glm::Mat4,
127    /// Transformation matrices helps to apply changes to your object, including position, orientation, ...
128    /// Best choice is to let the Object system handle it
129    pub scale_matrix: nalgebra_glm::Mat4,
130    /// Transformation matrices helps to apply changes to your object, including position, orientation, ...
131    /// Best choice is to let the Object system handle it
132    pub rotation_matrix: nalgebra_glm::Mat4,
133    /// Transformation matrix, but inversed
134    pub inverse_transformation_matrix: crate::uniform_type::Matrix,
135    /// The main color of your object
136    pub color: crate::uniform_type::Array4,
137    /// A struct making it easier to manipulate specific parts of shader
138    pub shader_builder: crate::objects::ShaderBuilder,
139    /// Shader settings
140    pub shader_settings: ShaderSettings,
141    /// Camera have any effect on the object?
142    pub camera_effect: Option<std::sync::Arc<str>>,
143    /// Uniform Buffers to be sent to GPU. These are raw and not compiled for GPU yet
144    pub uniform_buffers: Vec<wgpu::Buffer>,
145    /// Should be rendered or not
146    pub is_visible: bool,
147    /// Objects with higher number get rendered later and appear "on top" when occupying the same space
148    pub render_order: usize,
149}
150unsafe impl Send for Object {}
151unsafe impl Sync for Object {}
152
153/// Extra settings to customize objects on time of creation
154#[derive(Debug, Clone)]
155pub struct ObjectSettings {
156    /// Should it be affected by camera?
157    pub camera_effect: Option<std::sync::Arc<str>>,
158    /// Shader Settings
159    pub shader_settings: ShaderSettings,
160}
161impl Default for ObjectSettings {
162    fn default() -> Self {
163        Self {
164            camera_effect: Some("main".into()),
165            shader_settings: ShaderSettings::default(),
166        }
167    }
168}
169unsafe impl Send for ObjectSettings {}
170unsafe impl Sync for ObjectSettings {}
171
172/// The engine is the main starting point of using the Blue Engine.
173/// Everything that runs on Blue Engine will be under this struct.
174/// The structure of engine is monolithic, but the underlying data and the way it works is not.
175/// It gives a set of default data to work with,
176/// but also allow you to go beyond that and work as low level as you wish to.
177///
178/// You can also use the Engine to build you own custom structure the way you wish for it to be.
179/// Possibilities are endless!
180///
181/// To start using the Blue Engine, you can start by creating a new Engine like follows:
182/// ```
183/// use blue_engine::header::{Engine, WindowDescriptor};
184///
185/// fn main() {
186///     let engine = Engine::new().expect("Couldn't create the engine");
187/// }
188/// ```
189/// The WindowDescriptor simply holds what features you would like for your window.
190/// If you are reading this on later version of
191/// the engine, you might be able to even run the engine in headless mode
192/// meaning there would not be a need for a window and the
193/// renders would come as image files.
194///
195/// If you so wish to have a window, you would need to start a window update loop.
196/// The update loop of window runs a frame every few millisecond,
197/// and gives you details of what is happening during this time, like input events.
198/// You can also modify existing parts of the engine during
199/// this update loop, such as changing camera to look differently,
200/// or creating a new object on the scene, or even changing window details!
201///
202/// The update loop is just a method of the Engine struct
203/// that have one argument which is a callback function.
204/// ```
205///
206/// ```
207/// [THE DATA HERE IS WORK IN PROGRESS!]
208pub struct Engine {
209    /// The renderer does exactly what it is called.
210    /// It works with the GPU to render frames according to the data you gave it.
211    pub renderer: Renderer,
212    /// The event_loop handles the events of the window and inputs.
213    ///
214    /// #### USED INTERNALLY
215    pub event_loop_control_flow: crate::winit::event_loop::ControlFlow,
216    /// The window handles everything about window and inputs.
217    /// This includes ability to modify window and listen toinput devices for changes.
218    ///
219    /// ### The window is not available before update_loop.
220    pub window: Window,
221    /// The object system is a way to make it easier to work with the engine.
222    /// Obviously you can work without it, but it's for those who
223    /// do not have the know-how, or wish to handle all the work of rendering data manually.
224    pub objects: ObjectStorage,
225    /// The camera handles the way the scene looks when rendered.
226    /// You can modify everything there is to camera through this.
227    pub camera: CameraContainer,
228    /// Handles all engine plugins
229    pub signals: SignalStorage,
230
231    /// holds the update_loop function
232    ///
233    /// #### USED INTERNALLY
234    #[allow(clippy::type_complexity)]
235    pub update_loop: Option<
236        Box<
237            dyn 'static
238                + FnMut(
239                    // Core
240                    &mut Renderer,
241                    &mut Window,
242                    &mut ObjectStorage,
243                    &crate::utils::winit_input_helper::WinitInputHelper,
244                    &mut CameraContainer,
245                    &mut crate::SignalStorage,
246                ),
247        >,
248    >,
249
250    /// input events
251    ///
252    /// #### USED INTERNALLY
253    pub input_events: crate::utils::winit_input_helper::WinitInputHelper,
254}
255unsafe impl Send for Engine {}
256unsafe impl Sync for Engine {}
257
258/// Container for pipeline values. Each pipeline takes only 1 vertex shader,
259/// 1 fragment shader, 1 texture data, and optionally a vector of uniform data.
260#[derive(Debug)]
261pub struct Pipeline {
262    /// the shader buffer that's sent to the gpu
263    pub shader: PipelineData<crate::Shaders>,
264    /// The vertex buffer that's sent to the gpu. This includes indices as well
265    pub vertex_buffer: PipelineData<VertexBuffers>,
266    /// The texture that's sent to the gpu.
267    pub texture: PipelineData<crate::Textures>,
268    /// the Uniform buffers that are sent to the gpu
269    pub uniform: PipelineData<Option<crate::UniformBuffers>>,
270}
271unsafe impl Send for Pipeline {}
272unsafe impl Sync for Pipeline {}
273
274/// Container for pipeline data. Allows for sharing resources with other objects
275#[derive(Debug)]
276pub enum PipelineData<T> {
277    /// No data, just a reference to a buffer
278    Copy(String),
279    /// The actual data
280    Data(T),
281}
282
283/// Container for vertex and index buffer
284#[derive(Debug)]
285pub struct VertexBuffers {
286    /// An array of vertices. A vertex is a point in 3D space containing
287    /// an X, Y, and a Z coordinate between -1 and +1
288    pub vertex_buffer: wgpu::Buffer,
289    /// An array of indices. Indices are a way to reuse vertices,
290    /// this in turn helps greatly in reduction of amount of vertices needed to be sent to the GPU
291    pub index_buffer: wgpu::Buffer,
292    /// The length of the vertex buffer
293    pub length: u32,
294}
295unsafe impl Send for VertexBuffers {}
296unsafe impl Sync for VertexBuffers {}
297
298/// Main renderer class. this will contain all methods and data related to the renderer
299#[derive(Debug)]
300pub struct Renderer {
301    /// A [`wgpu::Surface`] represents a platform-specific surface
302    /// (e.g. a window) onto which rendered images may be presented.
303    pub surface: Option<wgpu::Surface<'static>>,
304    /// Context for all of the gpu objects
305    pub instance: wgpu::Instance,
306    /// Handle to a physical graphics and/or compute device.
307    #[allow(unused)]
308    pub adapter: wgpu::Adapter,
309    /// Open connection to a graphics and/or compute device.
310    pub device: wgpu::Device,
311    /// Handle to a command queue on a device.
312    pub queue: wgpu::Queue,
313    /// Describes a [`wgpu::Surface`]
314    pub config: wgpu::SurfaceConfiguration,
315    /// The size of the window
316    pub size: winit::dpi::PhysicalSize<u32>,
317    /// The texture bind group layout
318    pub texture_bind_group_layout: wgpu::BindGroupLayout,
319    /// The uniform bind group layout
320    pub default_uniform_bind_group_layout: wgpu::BindGroupLayout,
321    /// The depth buffer, used to render object depth
322    pub depth_buffer: (wgpu::Texture, wgpu::TextureView, wgpu::Sampler),
323    /// The default data used within the renderer
324    pub default_data: Option<(crate::Textures, crate::Shaders, crate::UniformBuffers)>,
325    /// The camera used in the engine
326    pub camera: Option<crate::UniformBuffers>,
327    /// Background clear color
328    pub clear_color: wgpu::Color,
329    /// Scissor cut section of the screen to render to
330    /// (x, y, width, height)
331    pub scissor_rect: Option<(u32, u32, u32, u32)>,
332}
333unsafe impl Sync for Renderer {}
334unsafe impl Send for Renderer {}
335
336/// Descriptor and settings for a window.
337#[derive(Debug, Clone)]
338pub struct WindowDescriptor {
339    /// The width of the window
340    pub width: u32,
341    /// The height of the window
342    pub height: u32,
343    /// The title of the window
344    pub title: &'static str,
345    /// Should the window contain the keys like minimize, maximize, or resize?
346    pub decorations: bool,
347    /// Should the window be resizable
348    pub resizable: bool,
349    /// Define how much power should the app ask for
350    pub power_preference: crate::PowerPreference,
351    /// The backend to use for the draw
352    pub backends: crate::Backends,
353    /// The features to be enabled on a backend
354    ///
355    /// read more at [wgpu::Features]
356    pub features: crate::wgpu::Features,
357    /// Controls how the events are processed
358    ///
359    /// read more at [winit::event_loop::ControlFlow]
360    pub control_flow: crate::winit::event_loop::ControlFlow,
361    /// The presentation mode of renderer for things like VSync
362    ///
363    /// read more at [wgpu::PresentMode]
364    pub present_mode: crate::wgpu::PresentMode,
365    /// Limits to be required based on the generation of the GPU and the API.
366    ///
367    /// read more at [wgpu::Limits]
368    pub limits: crate::wgpu::Limits,
369    /// The alpha mode which specifies how the alpha channel of
370    /// the textures should be handled during compositing.
371    pub alpha_mode: crate::wgpu::CompositeAlphaMode,
372    /// The desired frame latency.
373    ///
374    /// read more at [wgpu::SurfaceConfiguration::desired_maximum_frame_latency]
375    pub desired_maximum_frame_latency: u32,
376    /// How the memory should be utilized
377    ///
378    /// read more at [wgpu::MemoryHints]
379    pub memory_hints: crate::wgpu::MemoryHints,
380}
381impl std::default::Default for WindowDescriptor {
382    /// Will quickly create a window with default settings
383    fn default() -> Self {
384        let backends = crate::Backends::all();
385        Self {
386            width: 800,
387            height: 600,
388            title: "Blue Engine",
389            decorations: true,
390            resizable: true,
391            power_preference: crate::PowerPreference::LowPower,
392            backends,
393            features: if backends == wgpu::Backends::VULKAN {
394                wgpu::Features::POLYGON_MODE_LINE | wgpu::Features::POLYGON_MODE_POINT
395            } else if backends
396                .contains(wgpu::Backends::VULKAN | wgpu::Backends::METAL | wgpu::Backends::DX12)
397            {
398                wgpu::Features::POLYGON_MODE_LINE
399            } else {
400                wgpu::Features::empty()
401            },
402            control_flow: crate::winit::event_loop::ControlFlow::Poll,
403            present_mode: crate::wgpu::PresentMode::AutoNoVsync,
404            limits: crate::wgpu::Limits::default(),
405            alpha_mode: crate::wgpu::CompositeAlphaMode::Auto,
406            desired_maximum_frame_latency: 2,
407            memory_hints: crate::MemoryHints::Performance,
408        }
409    }
410}
411unsafe impl Send for WindowDescriptor {}
412unsafe impl Sync for WindowDescriptor {}
413
414/// Container for the projection used by the camera
415#[derive(Debug, Clone, PartialEq, PartialOrd)]
416pub enum Projection {
417    /// Perspective projection
418    ///
419    /// This is the default project used by the video games and majority of graphics
420    Perspective {
421        /// The field of view
422        fov: f32,
423    },
424    /// Orthographic projection
425    ///
426    /// This projection gives you a 2D view of the scene
427    Orthographic {
428        /// The size of the view
429        zoom: f32,
430    },
431}
432
433/// Container for the camera feature. The settings here are needed for
434/// algebra equations needed for camera vision and movement. Please leave it to the renderer to handle
435#[derive(Debug)]
436pub struct Camera {
437    /// The position of the camera in 3D space
438    pub position: Vector3,
439    /// The target at which the camera should be looking
440    pub target: Vector3,
441    /// The up vector of the camera. This defines the elevation of the camera
442    pub up: Vector3,
443    /// The resolution of the camera view
444    pub resolution: (f32, f32), //maybe this should be a Vector2i
445    /// The projection of the camera
446    pub projection: Projection,
447    /// The closest view of camera
448    pub near: f32,
449    /// The furthest view of camera
450    pub far: f32,
451    /// The final data that will be sent to GPU
452    pub view_data: nalgebra_glm::Mat4,
453    // For checking and rebuilding it's uniform buffer
454    pub(crate) changed: bool,
455    /// The uniform data of the camera to be sent to the gpu
456    pub uniform_data: UniformBuffers,
457    /// The position and target of the camera
458    pub(crate) add_position_and_target: bool,
459}
460unsafe impl Send for Camera {}
461unsafe impl Sync for Camera {}
462
463/// Container for Cameras
464///
465/// This allows for different objects have a different camera perspective.
466#[derive(Debug)]
467pub struct CameraContainer {
468    /// The list of cameras
469    // Arc<str> is used instead of String for performance
470    pub cameras: std::collections::HashMap<std::sync::Arc<str>, Camera>,
471}
472impl_deref_field!(
473    CameraContainer,
474    std::collections::HashMap<std::sync::Arc<str>, Camera>,
475    cameras
476);
477
478/// These definitions are taken from wgpu API docs
479#[derive(Debug, Clone, Copy)]
480pub struct ShaderSettings {
481    // ===== PRIMITIVE ===== //
482    /// The primitive topology used to interpret vertices
483    pub topology: crate::ShaderPrimitive,
484    /// When drawing strip topologies with indices, this is the
485    /// required format for the index buffer. This has no effect
486    /// on non-indexed or non-strip draws.
487    pub strip_index_format: Option<crate::IndexFormat>,
488    /// The face to consider the front for the purpose of
489    /// culling and stencil operations.
490    pub front_face: crate::FrontFace,
491    /// The face culling mode
492    pub cull_mode: Option<crate::CullMode>,
493    /// Controls the way each polygon is rasterized. Can be
494    /// either `Fill` (default), `Line` or `Point`
495    ///
496    /// Setting this to something other than `Fill` requires
497    /// `NON_FILL_POLYGON_MODE` feature to be enabled
498    pub polygon_mode: crate::PolygonMode,
499    /// If set to true, the polygon depth is clamped to 0-1
500    /// range instead of being clipped.
501    ///
502    /// Enabling this requires the `DEPTH_CLAMPING` feature
503    /// to be enabled
504    pub clamp_depth: bool,
505    /// If set to true, the primitives are rendered with
506    /// conservative overestimation. I.e. any rastered
507    /// pixel touched by it is filled. Only valid for PolygonMode::Fill!
508    ///
509    /// Enabling this requires `CONSERVATIVE_RASTERIZATION`
510    /// features to be enabled.
511    pub conservative: bool,
512
513    // ===== Multisample ===== //
514    /// The number of samples calculated per pixel (for MSAA).
515    /// For non-multisampled textures, this should be `1`
516    pub count: u32,
517    /// Bitmask that restricts the samples of a pixel modified
518    /// by this pipeline. All samples can be enabled using the
519    /// value `!0`
520    pub mask: u64,
521    /// When enabled, produces another sample mask per pixel
522    /// based on the alpha output value, that is ANDead with the
523    /// sample_mask and the primitive coverage to restrict the
524    /// set of samples affected by a primitive.
525
526    /// The implicit mask produced for alpha of zero is guaranteed
527    /// to be zero, and for alpha of one is guaranteed to be all
528    /// 1-s.
529    pub alpha_to_coverage_enabled: bool,
530}
531impl Default for ShaderSettings {
532    fn default() -> Self {
533        Self {
534            topology: wgpu::PrimitiveTopology::TriangleList,
535            strip_index_format: None,
536            front_face: wgpu::FrontFace::Ccw,
537            cull_mode: Some(wgpu::Face::Back),
538            polygon_mode: wgpu::PolygonMode::Fill,
539            clamp_depth: false,
540            conservative: false,
541            count: 1,
542            mask: !0,
543            alpha_to_coverage_enabled: true,
544        }
545    }
546}
547unsafe impl Send for ShaderSettings {}
548unsafe impl Sync for ShaderSettings {}
549
550/// Instance buffer data that is sent to GPU
551#[repr(C)]
552#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)]
553pub struct InstanceRaw {
554    /// The transformation matrix of the instance
555    pub model: uniform_type::Matrix,
556}
557
558/// Instance buffer data storage
559#[derive(Debug, Clone, Copy)]
560pub struct Instance {
561    /// The position of the instance
562    pub position: Vector3,
563    /// The rotation of the instance
564    pub rotation: Vector3,
565    /// The scale of the instance
566    pub scale: Vector3,
567}
568
569/// Allows all events to be fetched directly, making it easier to add custom additions to the engine.
570pub trait Signal: Any {
571    /// This is ran as soon as the engine is properly initialized and all components are ready
572    #[allow(clippy::too_many_arguments)]
573    fn init(
574        &mut self,
575        _renderer: &mut crate::Renderer,
576        _window: &crate::Window,
577        _objects: &mut ObjectStorage,
578        _camera: &mut crate::CameraContainer,
579    ) {
580    }
581
582    /// This is ran at the device events when available
583    #[allow(clippy::too_many_arguments)]
584    fn device_events(
585        &mut self,
586        _renderer: &mut crate::Renderer,
587        _window: &crate::Window,
588        _objects: &mut ObjectStorage,
589        _events: &crate::DeviceEvent,
590        _input: &crate::InputHelper,
591        _camera: &mut crate::CameraContainer,
592    ) {
593    }
594
595    /// This is ran at the window events when available
596    #[allow(clippy::too_many_arguments)]
597    fn window_events(
598        &mut self,
599        _renderer: &mut crate::Renderer,
600        _window: &crate::Window,
601        _objects: &mut ObjectStorage,
602        _events: &crate::WindowEvent,
603        _input: &crate::InputHelper,
604        _camera: &mut crate::CameraContainer,
605    ) {
606    }
607
608    /// ran before the frame is rendered
609    #[allow(clippy::too_many_arguments)]
610    fn frame(
611        &mut self,
612        _renderer: &mut crate::Renderer,
613        _window: &crate::Window,
614        _objects: &mut ObjectStorage,
615        _camera: &mut crate::CameraContainer,
616        _input: &crate::InputHelper,
617        _encoder: &mut crate::CommandEncoder,
618        _view: &crate::TextureView,
619    ) {
620    }
621}
622// The engine needs to know the functions of Signal to do things internally,
623// so we use downcast and not the std::any::Any
624downcast!(dyn Signal);
625
626/// Defines how the rotation axis is
627#[derive(Debug, Clone, Copy, PartialEq, Eq)]
628pub enum RotateAxis {
629    #[doc(hidden)]
630    X,
631    #[doc(hidden)]
632    Y,
633    #[doc(hidden)]
634    Z,
635}
636unsafe impl Send for RotateAxis {}
637unsafe impl Sync for RotateAxis {}
638
639/// Defines how the rotation amount is
640#[derive(Debug, Clone, Copy, PartialEq)]
641pub enum RotateAmount {
642    #[doc(hidden)]
643    Radians(f32),
644    #[doc(hidden)]
645    Degrees(f32),
646}
647unsafe impl Send for RotateAmount {}
648unsafe impl Sync for RotateAmount {}
649
650/// Defines how the texture data is
651#[derive(Debug, Clone)]
652pub enum TextureData {
653    /// the texture file bytes directly
654    Bytes(Vec<u8>),
655    /// the texture as a [`image::DynamicImage`]
656    Image(image::DynamicImage),
657    /// path to a texture file to load
658    Path(String),
659}
660unsafe impl Send for TextureData {}
661unsafe impl Sync for TextureData {}
662
663/// Defines how the borders of texture would look like
664#[derive(Debug, Clone, Copy, PartialEq, Eq)]
665pub enum TextureMode {
666    /// Expands the texture to fit the object
667    Clamp,
668    /// Repeats the texture instead of stretching
669    Repeat,
670    /// Repeats the texture, but mirrors it on edges
671    MirrorRepeat,
672}
673unsafe impl Send for TextureMode {}
674unsafe impl Sync for TextureMode {}
675
676/// This function helps in converting pixel value to the value that is between -1 and +1
677pub fn pixel_to_cartesian(value: f32, max: u32) -> f32 {
678    let mut result = value / max as f32;
679
680    if value == max as f32 {
681        result = 0.0;
682    } else if result < max as f32 / 2.0 {
683    }
684
685    if result > -1.0 {
686        result
687    } else {
688        -1.0
689    }
690}
691
692/// A unified way to handle strings
693pub trait StringBuffer: StringBufferTrait + Clone {}
694/// A trait for [StringBuffer]
695pub trait StringBufferTrait {
696    /// Returns the string as &[`str`]
697    fn as_str(&self) -> &str;
698    /// Returns the string as [`String`]
699    fn as_string(&self) -> String;
700    /// Returns Arc<str> for ease of computation
701    fn as_arc(&self) -> std::sync::Arc<str>;
702}
703
704impl StringBufferTrait for String {
705    fn as_str(&self) -> &str {
706        self.as_ref()
707    }
708    fn as_string(&self) -> String {
709        self.clone()
710    }
711    fn as_arc(&self) -> std::sync::Arc<str> {
712        self.as_str().into()
713    }
714}
715impl StringBuffer for String {}
716impl StringBufferTrait for &str {
717    fn as_str(&self) -> &str {
718        self
719    }
720    fn as_string(&self) -> String {
721        self.to_string()
722    }
723    fn as_arc(&self) -> std::sync::Arc<str> {
724        self.as_str().into()
725    }
726}
727impl StringBuffer for &str {}
728
729/// A unified way to handle objects
730///
731/// This is a container for objects that is used to apply different operations on the objects at the same time.
732/// It can deref to the object hashmap itself when needed.
733pub struct ObjectStorage(std::collections::HashMap<String, Object>);
734impl ObjectStorage {
735    /// Creates a new object storage
736    pub fn new() -> Self {
737        ObjectStorage(std::collections::HashMap::new())
738    }
739}
740impl Default for ObjectStorage {
741    fn default() -> Self {
742        Self::new()
743    }
744}
745unsafe impl Send for ObjectStorage {}
746unsafe impl Sync for ObjectStorage {}
747
748impl_deref!(ObjectStorage, std::collections::HashMap<String, Object>);
749
750/// Depth format
751pub const DEPTH_FORMAT: wgpu::TextureFormat = wgpu::TextureFormat::Depth32Float;
752
753/// Handles the live events in the engine
754pub struct SignalStorage {
755    /// list of events with key and the event
756    pub events: Vec<(String, Box<dyn Signal>)>,
757}
758
759/// Handles the order in which a functionality in the engine should be executed
760pub enum ExecuteOrder {
761    /// The main function that is the update_loop
762    UpdateLoopFunction,
763}
764
765/// A wrapper for winit window to make it easier to use and more ergonomic.
766#[derive(Debug)]
767pub struct Window {
768    /// The winit window itself.
769    pub window: Option<std::sync::Arc<crate::winit::window::Window>>,
770    /// Default attributes of the window
771    pub default_attributes: winit::window::WindowAttributes,
772    /// Whether the engine should close.
773    pub should_close: bool,
774}
775impl_deref_field!(
776    Window,
777    Option<std::sync::Arc<crate::winit::window::Window>>,
778    window
779);
780
781#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default, Zeroable)]
782#[repr(C)]
783/// General purposes 3D vector
784pub struct Vector3 {
785    /// X coordinate in 3D space
786    pub x: f32,
787    /// Y coordinate in 3D space
788    pub y: f32,
789    /// Z coordinate in 3D space
790    pub z: f32,
791}
792
793#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Default, Zeroable)]
794#[repr(C)]
795/// General purposes 2D vector
796pub struct Vector2 {
797    /// X coordinate in 2D space
798    pub x: f32,
799    /// Y coordinate in 2D space
800    pub y: f32,
801}