diff --git a/src/config.rs b/src/config.rs index 70aab49..4d899f3 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,37 +1,24 @@ /// Configs Module -/// -/// - -use serde::{Deserialize, Serialize}; use ron; +/// +/// +use serde::{Deserialize, Serialize}; #[derive(Deserialize, Serialize)] -pub struct Configs -{ - -} - +pub struct Configs {} #[derive(Deserialize, Serialize)] -pub struct DisplayConfigs -{ +pub struct DisplayConfigs { // TODO set Resolutions //Resolution: // i think thats it tbqh } +#[derive(Deserialize, Serialize)] +pub struct InputConfigs {} #[derive(Deserialize, Serialize)] -pub struct InputConfigs -{ - -} - - - -#[derive(Deserialize, Serialize)] -pub struct KeyboardConfig -{ +pub struct KeyboardConfig { // directionals Up: u32, Down: u32, @@ -50,13 +37,11 @@ pub struct KeyboardConfig // Macros PunchMacro: u32, - KickMacro: u32 + KickMacro: u32, } -impl Default for KeyboardConfig -{ - fn default() -> Self - { +impl Default for KeyboardConfig { + fn default() -> Self { KeyboardConfig { Up: ScanCodes::W, Down: ScanCodes::S, @@ -69,9 +54,8 @@ impl Default for KeyboardConfig MediumKick: ScanCodes::J, HeavyKick: ScanCodes::K, PunchMacro: ScanCodes::P, - KickMacro: ScanCodes::L + KickMacro: ScanCodes::L, } - } } @@ -80,68 +64,67 @@ impl Default for KeyboardConfig /// TODO finish this /// UNTESTED AND UNFINISHED #[repr(u32)] -pub enum ScanCodes -{ - Escape = 0x01, - Key1 = 0x02, - Key2 = 0x03, - Key3 = 0x04, - Key4 = 0x05, - Key5 = 0x06, - Key6 = 0x07, - Key7 = 0x08, - Key8 = 0x09, - Key9 = 0x0a, - Key0 = 0x0b, - Minus = 0x0c, - Equal = 0x0d, - BackSpace = 0x0e, - Tab = 0x0f, - Q = 0x10, - W = 0x11, - E = 0x12, - R = 0x13, - T = 0x14, - Y = 0x15, - U = 0x16, - I = 0x17, - O = 0x18, - P = 0x19, - OpenBracket = 0x1a, +pub enum ScanCodes { + Escape = 0x01, + Key1 = 0x02, + Key2 = 0x03, + Key3 = 0x04, + Key4 = 0x05, + Key5 = 0x06, + Key6 = 0x07, + Key7 = 0x08, + Key8 = 0x09, + Key9 = 0x0a, + Key0 = 0x0b, + Minus = 0x0c, + Equal = 0x0d, + BackSpace = 0x0e, + Tab = 0x0f, + Q = 0x10, + W = 0x11, + E = 0x12, + R = 0x13, + T = 0x14, + Y = 0x15, + U = 0x16, + I = 0x17, + O = 0x18, + P = 0x19, + OpenBracket = 0x1a, CloseBrack = 0x1b, - Enter = 0x1c, - LCtrl = 0x1d, - A = 0x1e, - S = 0x1f, - D = 0x20, - F = 0x21, - G = 0x22, - H = 0x23, - J = 0x24, - K = 0x25, - L = 0x26, + Enter = 0x1c, + LCtrl = 0x1d, + A = 0x1e, + S = 0x1f, + D = 0x20, + F = 0x21, + G = 0x22, + H = 0x23, + J = 0x24, + K = 0x25, + L = 0x26, SemiColon = 0x27, - Quote = 0x28, - Tilde = 0x29, - LShift = 0x2a, - Pipe = 0x2b, - Z = 0x2c, - X = 0x2d, - C = 0x2e, - V = 0x2f, - B = 0x30, - N = 0x31, - M = 0x32, + Quote = 0x28, + Tilde = 0x29, + LShift = 0x2a, + Pipe = 0x2b, + Z = 0x2c, + X = 0x2d, + C = 0x2e, + V = 0x2f, + B = 0x30, + N = 0x31, + M = 0x32, // TODO figure out what these are called lmao // "<" and ">" LeftTri = 0x33, RightTri = 0x34, - QMark = 0x35, - RShift = 0x36, - KeyPad = 0x37, - LAlt = 0x38, - Space = 0x39, - Caps = 0x3a, + QMark = 0x35, + RShift = 0x36, + KeyPad = 0x37, + LAlt = 0x38, + Space = 0x39, + Caps = 0x3a, // NOTE Skip the Function Keys, // Delusional // will have to do logic later to just ignore the call for that lmao @@ -154,16 +137,16 @@ pub enum ScanCodes KeyPad4 = 0x4b, KeyPad5 = 0x4c, KeyPad6 = 0x4d, - KeyPadPlus = 0x4e, + KeyPadPlus = 0x4e, KeyPad1 = 0x4f, KeyPad2 = 0x50, KeyPad3 = 0x51, KeyPad0 = 0x52, - KeyPadDot = 0x53, + KeyPadDot = 0x53, // NOTE don't bother with the ones after this, these are super important // (for some degenerates) - UpArrow = 0x67, - LeftArrow = 0x69, - RightArrow = 0x6a, - DownArrow = 0x6c + UpArrow = 0x67, + LeftArrow = 0x69, + RightArrow = 0x6a, + DownArrow = 0x6c, } diff --git a/src/gui.rs b/src/gui.rs index 46c8d9b..b39e274 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,81 +1,67 @@ use bevy_ecs::prelude::*; use egui::Key; -use winit::event; -use std::sync::Arc; use egui_glow::EguiGlow; use std::collections::HashMap; +use std::sync::Arc; +use winit::event; -pub struct Gui -{ +pub struct Gui { egui_ctx: EguiGlow, menus: MenuManager, window: Arc, } -impl Gui -{ - pub fn new(ctx: EguiGlow, window: Arc) -> Self - { +impl Gui { + pub fn new(ctx: EguiGlow, window: Arc) -> Self { let mut menus = MenuManager::new(); menus.add(Menu::Hello); - Self - { + Self { egui_ctx: ctx, menus, - window + window, } } - pub fn passEvent(&mut self, event: &event::WindowEvent) -> bool - { + pub fn passEvent(&mut self, event: &event::WindowEvent) -> bool { self.egui_ctx.on_event(event).consumed } - pub fn run(&mut self, world: &mut World) - { + pub fn run(&mut self, world: &mut World) { let mut to_be_removed = Vec::new(); - self.egui_ctx.run(&self.window, |ctx| - { - for (key, value) in &mut self.menus.0.iter_mut() - { - match value - { - Menu::Hello => if hellotest(ctx) - { - to_be_removed.push(*key); - }, - Menu::Second => () - - } - } - }); - for remove in to_be_removed - { + self.egui_ctx.run(&self.window, |ctx| { + for (key, value) in &mut self.menus.0.iter_mut() { + match value { + Menu::Hello => { + if hellotest(ctx) { + to_be_removed.push(*key); + } + } + Menu::Second => (), + } + } + }); + for remove in to_be_removed { self.menus.0.remove(&remove); } self.egui_ctx.paint(&self.window); } - } #[derive(PartialEq)] -pub enum Menu -{ +pub enum Menu { Hello, - Second + Second, } -fn hellotest(ctx: &egui::Context) -> bool -{ +fn hellotest(ctx: &egui::Context) -> bool { let mut open = true; egui::Window::new("hello there") .open(&mut open) .show(ctx, |ui| { - if ui.button("hello").clicked() - { + if ui.button("hello").clicked() { println!("hai"); } }); @@ -85,19 +71,15 @@ fn hellotest(ctx: &egui::Context) -> bool struct MenuManager(pub HashMap, u8); -impl MenuManager -{ - pub fn new() -> Self - { - Self - { +impl MenuManager { + pub fn new() -> Self { + Self { 0: HashMap::new(), - 1: 0 + 1: 0, } } - pub fn add(&mut self, new: Menu) - { + pub fn add(&mut self, new: Menu) { self.0.insert(self.1, new); self.1 = self.1.wrapping_add(1); } diff --git a/src/main.rs b/src/main.rs index de37e7d..a9d848d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,3 @@ - use std::rc::Rc; use std::sync::Arc; use std::thread; @@ -7,64 +6,56 @@ use std::time::{Duration, Instant}; use egui_glow::EguiGlow; use glow::HasContext; - use bevy_ecs::prelude::*; use gui::Gui; -use winit::{event_loop::EventLoopBuilder, window::WindowBuilder}; use winit::event::{Event, WindowEvent}; +use winit::{event_loop::EventLoopBuilder, window::WindowBuilder}; -use glutin::{config::ConfigTemplateBuilder, context::ContextAttributesBuilder}; -use glutin_winit::DisplayBuilder; -use glutin::{prelude::*, context::Version}; -use glutin_winit::{self, GlWindow}; use glutin::display::GetGlDisplay; +use glutin::{config::ConfigTemplateBuilder, context::ContextAttributesBuilder}; +use glutin::{context::Version, prelude::*}; +use glutin_winit::DisplayBuilder; +use glutin_winit::{self, GlWindow}; -pub mod renderer; pub mod gui; +pub mod renderer; fn main() { - // NOTE initialization code here - // create Event Loop let event_loop = EventLoopBuilder::new().build(); // set event loop to poll events every frame //event_loop.set_control_flow(winit::event_loop::ControlFlow::Poll); - - let window_builder = Some(WindowBuilder::new() - .with_transparent(false) - .with_title("MGQ Fighter Test") + let window_builder = Some( + WindowBuilder::new() + .with_transparent(false) + .with_title("MGQ Fighter Test"), ); - let template = ConfigTemplateBuilder::new() - .with_transparency(false); + let template = ConfigTemplateBuilder::new().with_transparency(false); - let display_builder = DisplayBuilder::new() - .with_window_builder(window_builder); + let display_builder = DisplayBuilder::new().with_window_builder(window_builder); let (window, gl_config) = display_builder .build(&event_loop, template, |configs| { - configs.reduce(|accum, config| { - let transparency_check = config.supports_transparency().unwrap_or(true) - & !accum.supports_transparency().unwrap_or(true); + configs + .reduce(|accum, config| { + let transparency_check = config.supports_transparency().unwrap_or(true) + & !accum.supports_transparency().unwrap_or(true); - if transparency_check || config.num_samples() > accum.num_samples() { - config - } - - else { - accum - } - }) - .unwrap() + if transparency_check || config.num_samples() > accum.num_samples() { + config + } else { + accum + } + }) + .unwrap() }) .unwrap(); - - // probably not needed here //let raw_window_handle = window.as_ref().map(|window| window.window_handle() // .unwrap() @@ -79,32 +70,38 @@ fn main() { .build(None); let compatibility_context_attributes = ContextAttributesBuilder::new() - .with_context_api(glutin::context::ContextApi::OpenGl(Some(Version::new(3, 3)))) + .with_context_api(glutin::context::ContextApi::OpenGl(Some(Version::new( + 3, 3, + )))) .build(None); // decide on the opengl Context to use, will use the newest one available // If the device does NOT at least support opengl 3.3 it will crash // opengl 3.3 is supported by most 64 bit computers let mut not_current_gl_context = Some(unsafe { - gl_display.create_context(&gl_config, &context_attributes).unwrap_or_else(|_| { - gl_display.create_context(&gl_config, &fallback_attributes).unwrap_or_else(|_| { + gl_display + .create_context(&gl_config, &context_attributes) + .unwrap_or_else(|_| { gl_display - .create_context(&gl_config, &compatibility_context_attributes) - .expect("get a newer Computer") - }, - ) - }) + .create_context(&gl_config, &fallback_attributes) + .unwrap_or_else(|_| { + gl_display + .create_context(&gl_config, &compatibility_context_attributes) + .expect("get a newer Computer") + }) + }) }); - // current Window Reference Counter let window = Arc::new(window.unwrap()); - let attrs = window.build_surface_attributes(<_>::default()); let gl_surface = unsafe { - gl_config.display().create_window_surface(&gl_config, &attrs).unwrap() + gl_config + .display() + .create_window_surface(&gl_config, &attrs) + .unwrap() }; let gl_context = not_current_gl_context @@ -123,7 +120,7 @@ fn main() { let mut gui = Gui::new( EguiGlow::new(&event_loop, Arc::clone(&gl), None), - window.clone() + window.clone(), ); unsafe { @@ -131,16 +128,12 @@ fn main() { gl.blend_func(glow::ONE, glow::ZERO); } - - // TODO write bevy Init code here let mut world = World::new(); let mut schedule = Schedule::default(); - schedule.add_systems(( - renderer::test_draw - )); + schedule.add_systems((renderer::test_draw)); let init_defaults = world.register_system(renderer::initialize_defaults); let initialize_test = world.register_system(renderer::test_init); @@ -149,43 +142,35 @@ fn main() { let _ = world.run_system(init_defaults); let _ = world.run_system(initialize_test); - let _ = event_loop.run(move |event, _ ,control_flow| { + let _ = event_loop.run(move |event, _, control_flow| { // new_frame for Framerate Locking - let new_frame = Instant::now() + Duration::from_secs_f32(1.0/60.0); - match event - { + let new_frame = Instant::now() + Duration::from_secs_f32(1.0 / 60.0); + match event { Event::WindowEvent { event, .. } => { - - if gui.passEvent(&event) == false - { - match event - { + if gui.passEvent(&event) == false { + match event { WindowEvent::CloseRequested => { println!("closing gracefully"); control_flow.set_exit(); - }, + } WindowEvent::Resized(size) => { - if size.width !=0 && size.height !=0 { + if size.width != 0 && size.height != 0 { gl_surface.resize( &gl_context, std::num::NonZeroU32::new(size.width).unwrap(), - std::num::NonZeroU32::new(size.height).unwrap() + std::num::NonZeroU32::new(size.height).unwrap(), ); } - }, + } // TODO to be implemented later - _ => () + _ => (), }; } - } - Event::Resumed => { - - }, + Event::Resumed => {} Event::MainEventsCleared => { unsafe { - gl.clear_color(0.0, 0.0, 0.0, 1.0); gl.clear(glow::COLOR_BUFFER_BIT); } @@ -194,11 +179,10 @@ fn main() { gui.run(&mut world); gl_surface.swap_buffers(&gl_context).unwrap(); - }, + } // TODO to be implemented - _ => () - + _ => (), } // will wait until it's time for the next frame diff --git a/src/renderer/animation.rs b/src/renderer/animation.rs index f770d77..0ddc524 100644 --- a/src/renderer/animation.rs +++ b/src/renderer/animation.rs @@ -9,15 +9,14 @@ use bevy_ecs::prelude::*; /// the spritesheet object is the only one of it's kind, so before it gets dropped make sure to delete /// the texture from vram #[derive(Clone)] -pub struct SpriteSheet -{ +pub struct SpriteSheet { pub texture_id: glow::NativeTexture, // NOTE where the spritesheet is saved // really only use here is just to stop saving copies - pub path: String, + pub path: String, // NOTE amount of Horizontal Cuts, a spritesheet with 5 frames of animation will have 5 horizontal cuts - pub cuts_x: u32, + pub cuts_x: u32, // NOTE possibly making it check vertically for saving multiple animations in one Texture? //cuts_y: u32, @@ -26,35 +25,30 @@ pub struct SpriteSheet // offsets: Vec> // NOTE Hold frames, if 0 it means it will be displayed for only 1 frame, 1 means it will be held for 2 etc - pub hold: Vec + pub hold: Vec, } -impl SpriteSheet -{ +impl SpriteSheet { /// creates a new Spritesheet - pub fn new(path: &str, gl: &glow::Context, cuts_x: u32, hold: Vec) -> Self - { + pub fn new(path: &str, gl: &glow::Context, cuts_x: u32, hold: Vec) -> Self { let texture_id = texture_from_file(path, gl); - SpriteSheet - { + SpriteSheet { texture_id, path: String::from(path), cuts_x, - hold + hold, } } } - /// Animation Component /// /// currently it's using a hashmap with String keys /// /// current also uses a String to identify the spritesheet #[derive(Component)] -pub struct Animator -{ +pub struct Animator { // NOTE sprite sheets in a hashmap pub spritesheets: HashMap, @@ -63,16 +57,11 @@ pub struct Animator // NOTE have a shader option to apply a different shader //pub shader: Option - - pub frame_time: f32 - - + pub frame_time: f32, } -impl Default for Animator -{ - fn default() -> Self - { +impl Default for Animator { + fn default() -> Self { Animator { spritesheets: HashMap::new(), current: AnimationType::Idle, @@ -84,13 +73,12 @@ impl Default for Animator // WIP all the animations that *could* show up, most of the air ones are expected to exist // However just because an AnimationType is in this list doesn't mean it has to exist or be loaded in #[derive(PartialEq, Eq, Hash)] -pub enum AnimationType -{ +pub enum AnimationType { // Basic Animations, universal Idle, StandUp, CrouchDown, // <- this is the animation of crouching down after standing - Crouch, // <- this is for the loop of being crouching + Crouch, // <- this is for the loop of being crouching WalkingForward, WalkingBackward, Guard, @@ -178,43 +166,53 @@ pub enum AnimationType Super05, } - - - /// load texture from a filepath and return the ID /// /// NOTE this function does not check if the texture has already loaded -fn texture_from_file(path: &str, gl: &glow::Context) -> glow::NativeTexture - { +fn texture_from_file(path: &str, gl: &glow::Context) -> glow::NativeTexture { + let texture_id; + unsafe { + texture_id = gl.create_texture().unwrap(); - let texture_id; - unsafe { - texture_id = gl.create_texture().unwrap(); + let img = image::open(&Path::new(&path)).expect("texture failed to load"); + let img = img.flipv(); - let img = image::open(&Path::new(&path)).expect("texture failed to load"); - let img = img.flipv(); + let format = match img { + image::DynamicImage::ImageLuma8(_) => glow::RED, + image::DynamicImage::ImageLumaA8(_) => glow::RG, + image::DynamicImage::ImageRgb8(_) => glow::RGB, + image::DynamicImage::ImageRgba8(_) => glow::RGBA, + _ => panic!("unknown image format at {path}"), + }; - let format = match img { - image::DynamicImage::ImageLuma8(_) => glow::RED, - image::DynamicImage::ImageLumaA8(_) => glow::RG, - image::DynamicImage::ImageRgb8(_) => glow::RGB, - image::DynamicImage::ImageRgba8(_) => glow::RGBA, - _ => panic!("unknown image format at {path}") - }; + let data = img.as_bytes(); - let data = img.as_bytes(); + gl.bind_texture(glow::TEXTURE_2D, Some(texture_id)); + gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + format as i32, + img.width() as i32, + img.height() as i32, + 0, + format, + glow::UNSIGNED_BYTE, + Some(&data), + ); + gl.generate_mipmap(glow::TEXTURE_2D); - gl.bind_texture(glow::TEXTURE_2D, Some(texture_id)); - gl.tex_image_2d(glow::TEXTURE_2D, 0, format as i32, img.width() as i32, img.height() as i32, - 0, format, glow::UNSIGNED_BYTE, Some(&data)); - gl.generate_mipmap(glow::TEXTURE_2D); + gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::REPEAT as i32); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MAG_FILTER, + glow::NEAREST as i32, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MAG_FILTER, + glow::NEAREST_MIPMAP_NEAREST as i32, + ); + } - - gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_WRAP_S, glow::REPEAT as i32); - gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32); - gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST_MIPMAP_NEAREST as i32); - - } - - texture_id + texture_id } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 6d0db11..ec17865 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1,12 +1,10 @@ /// Render Module +pub mod animation; /// /// all of the code pertaining to Rendering will be written here /// /// this also includes all Bevy Components and Resources relating to rendering - pub mod shader; -pub mod animation; - use core::slice; @@ -35,41 +33,31 @@ pub struct DefaultShader(pub shader::Shader); // // in a line const VERTICES: [f32; 20] = [ -// X Y Z xTex yTex - 0.5, 0.5, 0.0, 1.0, 1.0, - 0.5, -0.5, 0.0, 1.0, 0.0, - -0.5, -0.5, 0.0, 0.0, 0.0, - -0.5, 0.5, 0.0, 0.0, 1.0 + // X Y Z xTex yTex + 0.5, 0.5, 0.0, 1.0, 1.0, 0.5, -0.5, 0.0, 1.0, 0.0, -0.5, -0.5, 0.0, 0.0, 0.0, -0.5, 0.5, 0.0, + 0.0, 1.0, ]; // indices for the -const INDICES: [u32; 6] = [ - 0, 1, 3, - 1, 2, 3 -]; +const INDICES: [u32; 6] = [0, 1, 3, 1, 2, 3]; -pub fn initialize_defaults(mut commands: Commands, gl: Res) -{ +pub fn initialize_defaults(mut commands: Commands, gl: Res) { // create vertex array - let vao = unsafe { - Some(gl.0.create_vertex_array().unwrap()) - }; + let vao = unsafe { Some(gl.0.create_vertex_array().unwrap()) }; unsafe { // create buffers let vbo = Some(gl.0.create_buffer().unwrap()); let ebo = Some(gl.0.create_buffer().unwrap()); - gl.0.bind_vertex_array(vao); gl.0.bind_buffer(glow::ARRAY_BUFFER, vbo); - // pass buffers let data = core::slice::from_raw_parts( VERTICES.as_ptr() as *const u8, - VERTICES.len() * core::mem::size_of::() + VERTICES.len() * core::mem::size_of::(), ); gl.0.named_buffer_data_u8_slice(vbo.unwrap(), data, glow::STATIC_DRAW); @@ -87,11 +75,11 @@ pub fn initialize_defaults(mut commands: Commands, gl: Res) // Vertex Info gl.0.enable_vertex_attrib_array(0); - gl.0.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, size*5, 0); + gl.0.vertex_attrib_pointer_f32(0, 3, glow::FLOAT, false, size * 5, 0); // Texture Coordinates gl.0.enable_vertex_attrib_array(1); - gl.0.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, size*5, size*3); + gl.0.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, size * 5, size * 3); // unbind buffers and arrays gl.0.bind_buffer(glow::ARRAY_BUFFER, None); @@ -107,42 +95,44 @@ pub fn initialize_defaults(mut commands: Commands, gl: Res) commands.insert_resource(DefaultShader(shader)); } -pub fn test_init(mut commands: Commands, gl: Res) -{ +pub fn test_init(mut commands: Commands, gl: Res) { let mut animator = Animator::default(); let spritesheet = animation::SpriteSheet::new("data/sprite1.png", &gl.0, 4, Vec::new()); - animator.spritesheets.insert(animation::AnimationType::Idle, spritesheet); + animator + .spritesheets + .insert(animation::AnimationType::Idle, spritesheet); commands.spawn(animator); } -pub fn test_draw(mut query: Query<&mut Animator>, - gl: Res, - vao: Res, - shader: Res -) -{ - for mut animator in query.iter_mut() - { +pub fn test_draw( + mut query: Query<&mut Animator>, + gl: Res, + vao: Res, + shader: Res, +) { + for mut animator in query.iter_mut() { animator.frame_time += 0.1; let frame_time = animator.frame_time.clone(); - let sheet = &animator - .spritesheets - .get(&animator.current) - .unwrap(); - + let sheet = &animator.spritesheets.get(&animator.current).unwrap(); shader.0.Use(&gl.0); - shader.0.set_float(&gl.0, "frameCount", 1.0 / (sheet.cuts_x as f32)); - shader.0.set_float(&gl.0, "frameTime", frame_time.floor() + 1.0); + shader + .0 + .set_float(&gl.0, "frameCount", 1.0 / (sheet.cuts_x as f32)); + shader + .0 + .set_float(&gl.0, "frameTime", frame_time.floor() + 1.0); shader.0.set_float(&gl.0, "scale", 1.0); // NOTE this is where you would put the position - shader.0.set_vector2(&gl.0, "uniPos", cgmath::Vector2::new(0.0, 0.0)); + shader + .0 + .set_vector2(&gl.0, "uniPos", cgmath::Vector2::new(0.0, 0.0)); - unsafe{ + unsafe { gl.0.bind_vertex_array(Some(vao.0)); gl.0.bind_texture(glow::TEXTURE_2D, Some(sheet.texture_id)); diff --git a/src/renderer/shader.rs b/src/renderer/shader.rs index 0fef6ba..c0c4b36 100644 --- a/src/renderer/shader.rs +++ b/src/renderer/shader.rs @@ -3,135 +3,175 @@ use glow::*; use std::fs; use std::str; - - - /// Shader Struct for creating and using shaders in the Context of engine - /// +/// Shader Struct for creating and using shaders in the Context of engine +/// #[derive(Clone)] pub struct Shader { + pub ID: NativeProgram, - pub ID: NativeProgram, + pub path: String, +} - pub path: String +impl Shader { + /// Shader Constructor, will read, Compile and Create a GLSL Program for use + /// + /// currently panics if the files can't be found or the shader is wrong + /// + /// + /// # Example + /// `let shader = Shader::new("Example", &gl);` + /// + /// if the String given was "Example" the Program expects both shaders to be in the directory "data/shaders/Example/" + /// with the vertex shader being called "shader.vert" and fragment "shader.frag" + pub fn new(path: &str, gl: &glow::Context) -> Shader { + //read file contents + let VERT_SHADER = fs::read_to_string(format!("data/shaders/{path}/shader.vert")).unwrap(); + let FRAG_SHADER = fs::read_to_string(format!("data/shaders/{path}/shader.frag")).unwrap(); + + //create vertex shader + let vertex_shader = unsafe { gl.create_shader(glow::VERTEX_SHADER).unwrap() }; + unsafe { + gl.shader_source(vertex_shader, &VERT_SHADER); + gl.compile_shader(vertex_shader); + } + // create fragment shader + let fragment_shader = unsafe { gl.create_shader(glow::FRAGMENT_SHADER).unwrap() }; + unsafe { + gl.shader_source(fragment_shader, &FRAG_SHADER); + gl.compile_shader(fragment_shader); + if !gl.get_shader_compile_status(fragment_shader) { + panic!( + "Error, Compiling Fragment Shader: {}", + gl.get_shader_info_log(fragment_shader) + ); + } + + let shader_program = gl.create_program().unwrap(); + + gl.attach_shader(shader_program, vertex_shader); + gl.attach_shader(shader_program, fragment_shader); + gl.link_program(shader_program); + if !gl.get_program_link_status(shader_program) { + panic!( + "Error, Linking Shader Program {}", + gl.get_program_info_log(shader_program) + ); + } + gl.detach_shader(shader_program, vertex_shader); + gl.detach_shader(shader_program, fragment_shader); + gl.delete_shader(vertex_shader); + gl.delete_shader(fragment_shader); + + Shader { + ID: shader_program, + path: path.to_string(), + } + } } + // return program - -impl Shader - { - /// Shader Constructor, will read, Compile and Create a GLSL Program for use - /// - /// currently panics if the files can't be found or the shader is wrong - /// - /// - /// # Example - /// `let shader = Shader::new("Example", &gl);` - /// - /// if the String given was "Example" the Program expects both shaders to be in the directory "data/shaders/Example/" - /// with the vertex shader being called "shader.vert" and fragment "shader.frag" - pub fn new(path: &str, gl: &glow::Context) -> Shader - { - //read file contents - let VERT_SHADER = fs::read_to_string(format!("data/shaders/{path}/shader.vert")).unwrap(); - let FRAG_SHADER = fs::read_to_string(format!("data/shaders/{path}/shader.frag")).unwrap(); - - //create vertex shader - let vertex_shader = unsafe {gl.create_shader(glow::VERTEX_SHADER).unwrap() }; - unsafe { - gl.shader_source(vertex_shader, &VERT_SHADER); - gl.compile_shader(vertex_shader); - - } - // create fragment shader - let fragment_shader = unsafe{gl.create_shader(glow::FRAGMENT_SHADER).unwrap()}; - unsafe { - gl.shader_source(fragment_shader, &FRAG_SHADER); - gl.compile_shader(fragment_shader); - if !gl.get_shader_compile_status(fragment_shader) { - panic!("Error, Compiling Fragment Shader: {}", gl.get_shader_info_log(fragment_shader)); - } - - let shader_program = gl.create_program().unwrap(); - - gl.attach_shader(shader_program, vertex_shader); - gl.attach_shader(shader_program, fragment_shader); - gl.link_program(shader_program); - if !gl.get_program_link_status(shader_program) { - panic!("Error, Linking Shader Program {}", gl.get_program_info_log(shader_program)); - } - gl.detach_shader(shader_program, vertex_shader); - gl.detach_shader(shader_program, fragment_shader); - gl.delete_shader(vertex_shader); - gl.delete_shader(fragment_shader); - - Shader { - ID: shader_program, - path: path.to_string() - } - } - } - - - - // return program - - /// uses Shader - /// - pub fn Use(&self, gl: &glow::Context) - { - unsafe {gl.use_program(Some(self.ID));} - } - - // BOILERPLATE JUMPSCARE - //pub fn set_bool(&self, gl: &glow::Context name: &str, value: bool ) - //{unsafe {gl.uniform_1_bool(gl.get_uniform_location(self.ID, name).as_ref(), value);}} - - pub fn set_int(&self, gl: &glow::Context, name: &str, value: i32 ) - {unsafe {gl.uniform_1_i32(gl.get_uniform_location(self.ID, name).as_ref(), value);}} - - pub fn set_float(&self, gl: &glow::Context, name: &str, value: f32 ) - {unsafe {gl.uniform_1_f32(gl.get_uniform_location(self.ID, name).as_ref(), value);}} - - pub fn set_vector2(&self, gl: &glow::Context, name: &str, value: cgmath::Vector2 ) - {unsafe {gl.uniform_2_f32(gl.get_uniform_location(self.ID, name).as_ref(), value[0], value[1]);}} - - pub fn set_vector2d(&self, gl: &glow::Context, name: &str, x: f32, y: f32) - {unsafe {gl.uniform_2_f32(gl.get_uniform_location(self.ID, name).as_ref(), x, y);}} - - pub fn set_vector3(&self, gl: &glow::Context, name: &str, value: cgmath::Vector3 ) - {unsafe {gl.uniform_3_f32(gl.get_uniform_location(self.ID, name).as_ref(), value[0], value[1], value[2]);}} - - pub fn set_vector3d(&self, gl: &glow::Context, name: &str, x: f32, y: f32, z: f32 ) - {unsafe {gl.uniform_3_f32(gl.get_uniform_location(self.ID, name).as_ref(), x, y, z);}} - - pub fn set_vector4(&self, gl: &glow::Context, name: &str, value: &cgmath::Vector4 ) - {unsafe {gl.uniform_4_f32(gl.get_uniform_location(self.ID, name).as_ref(), value[0], value[1], value[2], value[3]);}} - - pub fn set_vector4d(&self, gl: &glow::Context, name: &str, x: f32, y: f32, z: f32, w: f32) - {unsafe {gl.uniform_4_f32(gl.get_uniform_location(self.ID, name).as_ref(), x, y, z, w);}} - //pub fn setMat2(&self, name: &str, value: cgmath::Matrix2) - - pub fn set_mat3(&self, gl: &glow::Context, name: &str, value: cgmath::Matrix3) - { - let nums = vec![value.x.x, value.x.y, value.x.z, - value.y.x, value.y.y, value.y.z, - value.z.x, value.z.y, value.z.z]; - unsafe - { - gl.uniform_matrix_3_f32_slice(gl.get_uniform_location(self.ID, name).as_ref(), false, nums.as_ref()); - } - } - - pub fn set_mat4(&self, gl: &glow::Context, name: &str, value: &cgmath::Matrix4) - { - let nums = vec![value.x.x, value.x.y, value.x.z, value.x.w, - value.y.x, value.y.y, value.y.z, value.y.w, - value.z.x, value.z.y, value.z.z, value.z.w, - value.w.x, value.w.y, value.w.z, value.w.w]; - unsafe - { - gl.uniform_matrix_4_f32_slice(gl.get_uniform_location(self.ID, name).as_ref(), false, nums.as_ref()); - } - } - + /// uses Shader + /// + pub fn Use(&self, gl: &glow::Context) { + unsafe { + gl.use_program(Some(self.ID)); } + } + + // BOILERPLATE JUMPSCARE + //pub fn set_bool(&self, gl: &glow::Context name: &str, value: bool ) + //{unsafe {gl.uniform_1_bool(gl.get_uniform_location(self.ID, name).as_ref(), value);}} + + pub fn set_int(&self, gl: &glow::Context, name: &str, value: i32) { + unsafe { + gl.uniform_1_i32(gl.get_uniform_location(self.ID, name).as_ref(), value); + } + } + + pub fn set_float(&self, gl: &glow::Context, name: &str, value: f32) { + unsafe { + gl.uniform_1_f32(gl.get_uniform_location(self.ID, name).as_ref(), value); + } + } + + pub fn set_vector2(&self, gl: &glow::Context, name: &str, value: cgmath::Vector2) { + unsafe { + gl.uniform_2_f32( + gl.get_uniform_location(self.ID, name).as_ref(), + value[0], + value[1], + ); + } + } + + pub fn set_vector2d(&self, gl: &glow::Context, name: &str, x: f32, y: f32) { + unsafe { + gl.uniform_2_f32(gl.get_uniform_location(self.ID, name).as_ref(), x, y); + } + } + + pub fn set_vector3(&self, gl: &glow::Context, name: &str, value: cgmath::Vector3) { + unsafe { + gl.uniform_3_f32( + gl.get_uniform_location(self.ID, name).as_ref(), + value[0], + value[1], + value[2], + ); + } + } + + pub fn set_vector3d(&self, gl: &glow::Context, name: &str, x: f32, y: f32, z: f32) { + unsafe { + gl.uniform_3_f32(gl.get_uniform_location(self.ID, name).as_ref(), x, y, z); + } + } + + pub fn set_vector4(&self, gl: &glow::Context, name: &str, value: &cgmath::Vector4) { + unsafe { + gl.uniform_4_f32( + gl.get_uniform_location(self.ID, name).as_ref(), + value[0], + value[1], + value[2], + value[3], + ); + } + } + + pub fn set_vector4d(&self, gl: &glow::Context, name: &str, x: f32, y: f32, z: f32, w: f32) { + unsafe { + gl.uniform_4_f32(gl.get_uniform_location(self.ID, name).as_ref(), x, y, z, w); + } + } + //pub fn setMat2(&self, name: &str, value: cgmath::Matrix2) + + pub fn set_mat3(&self, gl: &glow::Context, name: &str, value: cgmath::Matrix3) { + let nums = vec![ + value.x.x, value.x.y, value.x.z, value.y.x, value.y.y, value.y.z, value.z.x, value.z.y, + value.z.z, + ]; + unsafe { + gl.uniform_matrix_3_f32_slice( + gl.get_uniform_location(self.ID, name).as_ref(), + false, + nums.as_ref(), + ); + } + } + + pub fn set_mat4(&self, gl: &glow::Context, name: &str, value: &cgmath::Matrix4) { + let nums = vec![ + value.x.x, value.x.y, value.x.z, value.x.w, value.y.x, value.y.y, value.y.z, value.y.w, + value.z.x, value.z.y, value.z.z, value.z.w, value.w.x, value.w.y, value.w.z, value.w.w, + ]; + unsafe { + gl.uniform_matrix_4_f32_slice( + gl.get_uniform_location(self.ID, name).as_ref(), + false, + nums.as_ref(), + ); + } + } +}