diff --git a/src/debug.rs b/src/debug.rs new file mode 100644 index 0000000..ac29990 --- /dev/null +++ b/src/debug.rs @@ -0,0 +1,231 @@ + +use imgui_glow_renderer::AutoRenderer; +use imgui_sdl2_support::SdlPlatform; +use std::collections::HashMap; +use sdl2::event::Event; +const MODELS: [&str; 3]= ["resources/models/TestCarModel/CarW4.obj", "resources/models/TestCarModel/CarW1.obj", +"resources/models/TestCarModel/CarW0.obj"]; + +mod info; + + +pub enum dEvent + { + loadModel(i32), + setTest(f32, i32), + addWindow(OpenWindows), + removeWindow(OpenWindows), + exit, + } + + +pub enum Callback + { + ModelInfo(info::ModelI), + TestWind(info::testI), + MainMenu, + } + +#[derive(Clone, PartialEq)] +pub enum OpenWindows { + ModelInfo, + TestWind, + MainMenu, +} + +pub struct Debug { + imgui: imgui::Context, + renderer: AutoRenderer, + platform: SdlPlatform, + pub windows: HashMap, + next_id: u16, + free_ids:Vec +} + + + +impl Debug { + pub fn new(gl: std::sync::Arc) -> Debug + { + let mut imgui = imgui::Context::create(); + + imgui + .fonts() + .add_font(&[imgui::FontSource::DefaultFontData {config: None}]); + + let mut platform = SdlPlatform::init(&mut imgui); + let mut renderer = match AutoRenderer::initialize(gl.clone(), &mut imgui) + { + Ok(ret) => ret, + Err(s) => panic!("Failed to initialize Imgui Platform Renderer: {}", s), + }; + + let mut windows = HashMap::new(); + windows.insert(0,OpenWindows::MainMenu,); + Debug { + imgui, + renderer, + platform, + windows, + next_id: 1, + free_ids: Vec::new(), + } + } + + pub fn handle(&mut self, event: &sdl2::event::Event) + { + self.platform.handle_event(&mut self.imgui, event); + } + + pub fn drawImgui(&mut self, events_loop: &sdl2::EventPump, window: &sdl2::video::Window, + callback: Vec) -> Vec + { + self.platform.prepare_frame(&mut self.imgui, &window, &events_loop); + let ui = self.imgui.new_frame(); + let mut ret = Vec::new(); + for call in callback + { + match call { + Callback::ModelInfo(a) => + ret.append(&mut Debug::displayModel(ui, &a)), + Callback::TestWind(mut a) => + ret.append(&mut Debug::displayTest(ui, &mut a)), + Callback::MainMenu => + ret.append(&mut Debug::displayMain(ui)), + } + + } + + + + let draw_data = self.imgui.render(); + + self.renderer.render(draw_data).unwrap(); + + ret + } + pub fn addWindow(&mut self, window: OpenWindows) + { + if (self.free_ids.is_empty()) + { + self.windows.insert(self.next_id, window); + self.next_id += 1; + } + else { + self.windows.insert(self.free_ids.pop().unwrap(), window); + } + } + pub fn removeWindow(&mut self, window: OpenWindows) + { + println!("searching for a match..."); + let mut id = 0; + for (hashId, windowType) in &self.windows + { + if *windowType == window { + id = *hashId; + break; + } + + } + if id !=0 + { + self.windows.remove(&id); + self.free_ids.push(id); + } + } + + fn displayTest(ui: &mut imgui::Ui, testI: &mut info::testI) -> Vec + { + let mut ret = Vec::new(); + let mut selectedModel = testI.selectedModel; + let mut spinSpeed = testI.spinSpeed; + ui.window("POLY I WILL FUCKING") + .size([500.0, 100.0], imgui::Condition::FirstUseEver) + .build(|| { + ui.text("you serve no purpose in life"); + ui.text("Your Purpose in life is to suck my dick"); + ui.slider("The Spin Speed", 0.1, 10.0, &mut spinSpeed); + if ui + .button("Close") { + ret.push(dEvent::removeWindow(OpenWindows::TestWind)); + } + if ui.list_box("Select Model to Load", &mut selectedModel, &MODELS, 5) { + ret.push(dEvent::loadModel(selectedModel)); + } + }); + ret.push(dEvent::setTest(spinSpeed, selectedModel + )); + ret + } + + fn displayModel(ui: &mut imgui::Ui ,model: &info::ModelI) -> Vec + { + let mut ret = Vec::new(); + ui.window("Stats") + .size([300.0, 500.0], imgui::Condition::Always) + .build(|| { + ui.text("Model Information"); + ui.text(format!("count meshes: {}", model.meshesCount)); + ui.separator(); + for i in 0..model.meshesCount + { + ui.text(format!("Mesh Number {}", i)); + ui.text(format!("count Vertices: {}", model.vertCount[i])); + ui.separator(); + } + if ui.button("close") { + ret.push(dEvent::removeWindow(OpenWindows::ModelInfo)) + } + }); + ret + } + + fn displayMain(ui: &mut imgui::Ui) -> Vec + { + let mut ret = Vec::new(); + ui.window("Welcome to the main Menu") + .size([500.0, 500.0], imgui::Condition::Always) + .build(|| { + ui.text("this is the main Debugger Menu, it's used to Debug the game"); + ui.text("although it isn't done yet"); + ui.separator(); + if ui.button("Open the Model Info") { + ret.push(dEvent::addWindow(OpenWindows::ModelInfo)) + } + if ui.button("Open the Test Modifier"){ + ret.push(dEvent::addWindow(OpenWindows::TestWind)) + } + if ui.button("Quit") { + ret.push(dEvent::exit) + } + + }); + ret + } + + + } + + + +use crate::model; +pub fn ModelInfo(model: &model::Model) -> Callback + { + let mut vertCount = Vec::new(); + let meshesCount = model.meshes.len(); + for i in 0..model.meshes.len() { + vertCount.push(model.meshes[i].vertices.len()); + } + Callback::ModelInfo(info::ModelI { + meshesCount, + vertCount + }) + } + +pub fn TestWind(spinSpeed: f32, selectedModel: i32) -> Callback + { + Callback::TestWind(info::testI { + spinSpeed, + selectedModel, + }) + } diff --git a/src/debug/info.rs b/src/debug/info.rs new file mode 100644 index 0000000..b4386b1 --- /dev/null +++ b/src/debug/info.rs @@ -0,0 +1,12 @@ + +pub struct ModelI +{ + pub meshesCount: usize, + pub vertCount: Vec +} + +pub struct testI + { + pub spinSpeed: f32, + pub selectedModel: i32, + } diff --git a/src/main.rs b/src/main.rs index aa00574..85a9ced 100644 --- a/src/main.rs +++ b/src/main.rs @@ -13,6 +13,10 @@ enum gameState { Playing } +enum SceneEnum { + Exit, + Resume +} use imgui_glow_renderer::AutoRenderer; use imgui_sdl2_support::SdlPlatform; @@ -24,8 +28,6 @@ use sdl2::pixels::Color; use sdl2::keyboard::Keycode; use sdl2::event::Event; -use std::sync::mpsc::Receiver; -use std::ptr; use std::mem; use std::os::raw::c_void; use std::path::Path; @@ -34,8 +36,14 @@ use std::ffi::{CString, CStr}; mod shader; mod model; mod camera; +mod scene; +mod debug; + +use scene::Scene; + fn main() { + // initialize SDL and gl let (gl, shader_version, window, mut events_loop, _context) = { let sdl = match sdl2::init() { @@ -76,58 +84,12 @@ fn main() { - let mut imgui = imgui::Context::create(); - - imgui - .fonts() - .add_font(&[imgui::FontSource::DefaultFontData {config: None}]); - - - let mut platform = SdlPlatform::init(&mut imgui); - let mut renderer = match AutoRenderer::initialize(gl.clone(), &mut imgui) - { - Ok(ret) => ret, - Err(s) => panic!("Failed to initialize Imgui Platform Renderer: {}", s), - }; // NOTE intiialize Camera - let mut camera = camera::Camera { - Position: Point3::new(0.0, 0.40, 1.0), - Pitch: -20.0, - ..camera::Camera::default() - }; - - let mut firstMouse = true; - let mut lastX: f32 = SCR_WIDTH as f32 / 2.0; - let mut lastY: f32 = SCR_HEIGHT as f32 / 2.0; - - // timing - let mut deltaTime: f32; // time between current frame and last frame - let mut lastFrame: f32 = 0.0; - - //gl::load_with(|ptr| window.get_proc_address(ptr) as *const _); - let (ourshader, ourModel) = unsafe { - gl.enable(glow::DEPTH_TEST); - - let ourShader = shader::shader::new("model", Arc::clone(&gl)); - - let ourModel = model::Model::new("resources/models/TestCarModel/CarW4.obj", Arc::clone(&gl)); - - (ourShader, ourModel) - }; - - let mut State = gameState::Playing; - - - let time = std::time::Instant::now(); - let mut spinSpeed = 1.0; - let mut current_rad = 1.0; - let projection: Matrix4 = perspective(Deg(45.0), SCR_WIDTH as f32/ SCR_HEIGHT as f32, 0.1, 100.0); - - + let mut scene = Scene::new(gl); println!("entering main loop"); @@ -140,83 +102,20 @@ fn main() { 'main: loop { match &State { gameState::Playing => { - let currentFrame = time.elapsed().as_secs_f32(); - deltaTime = currentFrame - lastFrame; - lastFrame = currentFrame; - current_rad += spinSpeed/15.0; - - unsafe{ - gl.enable(glow::DEPTH_TEST); - gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT); - - ourshader.Use(); - let Projection: Matrix4 = perspective(Deg(camera.Zoom), SCR_WIDTH as f32 / SCR_HEIGHT as f32, 0.1, 100.0); - - let view = camera.GetViewMatrix(); - ourshader.setMat4("projection", &projection); - ourshader.setMat4("view", &view); - - - - let mut model: Matrix4 = Matrix4::from_axis_angle(vec3(0.0, -1.0, 0.0).normalize(), - cgmath::Rad(current_rad)); - model = model * Matrix4::from_scale(0.2); - ourshader.setMat4("model", &model); - - + match scene.update(&mut events_loop, &window) + { + scene::SceneEnum::Exit => { + break 'main; + }, + _ => (), } - ourModel.Draw(&ourshader); - - platform.prepare_frame(&mut imgui, &window, &events_loop); - let ui = imgui.new_frame(); - - ui.window("POLY I WILL FUCKING") - .size([500.0, 100.0], imgui::Condition::FirstUseEver) - .build(|| { - ui.text("you serve no purpose in life"); - ui.text("Your Purpose in life is to suck my dick"); - ui.slider("The Spin Speed", 0.1, 10.0, &mut spinSpeed); - }); - - drawDebugUI(ui, &ourModel); - let draw_data = imgui.render(); - - - renderer.render(draw_data).unwrap(); - - window.gl_swap_window(); - for event in events_loop.poll_iter() { - platform.handle_event(&mut imgui, &event); - - match event { - Event::Quit {..} | - Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { - break 'main - }, - Event::KeyDown {keycode: Some(Keycode::P), ..} => { - State = gameState::Paused; - } - _ => {} - } - } } gameState::Paused => { - - for event in events_loop.poll_iter() { - platform.handle_event(&mut imgui, &event); - - match event { - Event::KeyDown {keycode: Some(Keycode::P), ..} => { - State = gameState::Playing; - } - _ => {} - } - } } } } diff --git a/src/scene.rs b/src/scene.rs new file mode 100644 index 0000000..1313a5f --- /dev/null +++ b/src/scene.rs @@ -0,0 +1,177 @@ + +use crate::model::Model; +use crate::camera::Camera; +use crate::shader::shader; +use std::sync::Arc; +use std::rc::Rc; +use glow::*; + +use imgui_glow_renderer::AutoRenderer; +use imgui_sdl2_support::SdlPlatform; +use crate::debug; +use cgmath::{Matrix4, vec3, Point3, Deg, perspective}; +use cgmath::prelude::*; + +use sdl2::keyboard::Keycode; +use sdl2::event::Event; + +const SCR_WIDTH: u32 = 1600; +const SCR_HEIGHT: u32 = 900; + +const MODELS: [&str; 3]= ["resources/models/TestCarModel/CarW4.obj", "resources/models/TestCarModel/CarW1.obj", +"resources/models/TestCarModel/CarW0.obj"]; + + +/// XXX this is temporary, thus the name +pub struct tempData { + pub projection: Matrix4, + pub spinSpeed: f32, + pub current_rad: f32, + pub currentFrame: f32, + pub deltaTime: f32, + pub lastFrame: f32, + DebugMode: bool, + selectedModel: i32 +} +use crate::debug::Debug; + +pub enum SceneEnum { + Exit, + Pause, + Resume, +} + + +pub struct Scene { + gl: Arc, + pub Car: Model, + camera: Camera, + debug: Debug, + shaders: Vec>, + time: std::time::Instant, + tempData: tempData, +} + +impl Scene{ + pub fn new(gl: Arc) -> Scene + { + let Car = Model::new(MODELS[0], Arc::clone(&gl)); + + let shader = Rc::new(shader::new("model", Arc::clone(&gl))); + + let time = std::time::Instant::now(); + + let camera = Camera { + Position: Point3::new(0.0, 0.40, 1.0), + Pitch: -20.0, + ..Camera::default() + }; + + let tempData = tempData { + projection: perspective(Deg(45.0), 1600.0/ 900.0, 0.1, 100.0), + spinSpeed: 1.0, + current_rad: 1.0, + currentFrame: 0.0, + deltaTime: 0.0, + lastFrame: 0.0, + DebugMode: false, + selectedModel: 0, + + }; + + let debug = Debug::new(gl.clone()); + Scene{ + gl, + Car, + camera, + debug, + shaders: vec![shader], + time, + tempData, + } + } + + pub fn update(&mut self ,events_loop: &mut sdl2::EventPump, window: &sdl2::video::Window) -> SceneEnum + { + self.tempData.currentFrame = self.time.elapsed().as_secs_f32(); + self.tempData.deltaTime = self.tempData.currentFrame - self.tempData.lastFrame; + self.tempData.lastFrame = self.tempData.currentFrame; + self.tempData.current_rad += self.tempData.spinSpeed/15.0; + let mut ret = SceneEnum::Resume; + + unsafe { + self.gl.enable(glow::DEPTH_TEST); + self.gl.clear(glow::COLOR_BUFFER_BIT | glow::DEPTH_BUFFER_BIT); + + self.shaders[0].Use(); + self.tempData.projection = perspective(Deg(self.camera.Zoom), SCR_WIDTH as f32 /SCR_HEIGHT as f32, 0.1, 100.0); + let view = self.camera.GetViewMatrix(); + self.shaders[0].setMat4("projection", &self.tempData.projection); + self.shaders[0].setMat4("view", &view); + + let mut model: Matrix4 = Matrix4::from_axis_angle(vec3(0.0, -1.0, 0.0).normalize(), + cgmath::Rad(self.tempData.current_rad)); + + model = model * Matrix4::from_scale(0.2); + self.shaders[0].setMat4("model", &model); + } + self.Car.Draw(&self.shaders[0]); + + if self.tempData.DebugMode{ + let mut Callbacks = Vec::new(); + let windows = self.debug.windows.clone(); + for (id, window) in windows + { + match window { + debug::OpenWindows::ModelInfo => Callbacks.push(debug::ModelInfo(&self.Car)), + debug::OpenWindows::TestWind => Callbacks.push(debug::TestWind(self.tempData.spinSpeed, self.tempData.selectedModel)), + debug::OpenWindows::MainMenu => Callbacks.push(debug::Callback::MainMenu), + + } + } + + + for command in self.debug.drawImgui(&events_loop, &window, Callbacks) + { + use crate::debug::dEvent; + match command + { + dEvent::exit => ret = SceneEnum::Exit, + dEvent::loadModel(i) => self.Car = Model::new(MODELS[i as usize], Arc::clone(&self.gl)), + dEvent::setTest(a, b) => { + self.tempData.spinSpeed = a; + self.tempData.selectedModel = b; + }, + dEvent::addWindow(a) => self.debug.addWindow(a), + dEvent::removeWindow(a) => self.debug.removeWindow(a), + } + } + } + + for event in events_loop.poll_iter() { + if self.tempData.DebugMode { + self.debug.handle(&event); + } + match event { + Event::Quit {..} | + Event::KeyDown { keycode: Some(Keycode::Escape), .. } => { + ret = SceneEnum::Exit; + }, + Event::KeyDown {keycode: Some(Keycode::P), ..} => { + }, + Event::KeyDown {keycode: Some(Keycode::D), ..} => { + self.tempData.DebugMode = !self.tempData.DebugMode + } + Event::KeyDown {keycode: Some(Keycode::M), ..} => { + self.debug.addWindow(debug::OpenWindows::ModelInfo) + } + _ => {} + } + + } + + ret + } + + +}