diff --git a/Cargo.toml b/Cargo.toml index 25cfc96..6f17147 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,18 +58,10 @@ path = "examples/shapes/cube.rs" name = "rotate_around" path = "examples/camera/rotate_around.rs" +# Utils [[example]] -name = "fly_camera" -path = "examples/camera/fly_camera.rs" - -# GUI -[[example]] -name = "hello_gui" -path = "examples/gui/hello_gui.rs" - -[[example]] -name = "styling_gui" -path = "examples/gui/styling.rs" +name = "resource_sharing" +path = "examples/utils/resource_sharing.rs" # Development ONLY [[example]] diff --git a/examples/dev/dev.rs b/examples/dev/dev.rs index 4d374bb..1a39d91 100644 --- a/examples/dev/dev.rs +++ b/examples/dev/dev.rs @@ -9,80 +9,121 @@ use blue_engine::{ fn main() { let mut engine = Engine::new().expect("win"); - // =============================== + let texture = engine + .renderer + .build_texture( + "background", + TextureData::Path("resources/BlueLogoDiscord.png"), + blue_engine::TextureMode::Clamp, + ) + .unwrap(); + + let first = square( + "main", + ObjectSettings::default(), + &mut engine.renderer, + &mut engine.objects, + ); - //let triangle_id = triangle(Some("Triangleee"), &mut engine, camera).unwrap(); - let window_size = engine.window.inner_size(); + engine.objects.get_mut("main").unwrap().set_texture(texture); + engine + .objects + .get_mut("main") + .unwrap() + .set_position(-1f32, 0f32, 0f32); - uv_sphere( - "cube", - (18, 36, 1f32), + let second = square( + "alt", + ObjectSettings::default(), &mut engine.renderer, &mut engine.objects, - ) - .unwrap(); - // engine.objects.get_mut("cube").unwrap().scale(0.6, 0.6, 0.6); + ); + engine .objects - .get_mut("cube") + .get_mut("alt") .unwrap() - .set_color(1f32, 0f32, 0f32, 1f32); - //cube.scale(0.3, 0.3, 0.3); - + .reference_texture("main"); engine .objects - .get_mut("monke") + .get_mut("alt") .unwrap() - .set_color(0.051f32, 0.533f32, 0.898f32, 1f32); - //engine.objects[test].rotate(90f32, RotateAxis::Y); - - /*let sphere_1 = uv_sphere(Some("SPHERE1"), &mut engine, (18, 36, 1f32)).unwrap(); - engine.objects[sphere_1].scale(2f32, 2f32, 2f32); - engine.objects[sphere_1].set_color(0.051f32, 0.533f32, 0.898f32, 1f32); - - let sphere_1 = uv_sphere(Some("SPHERE1"), &mut engine, (18, 36, 1f32)).unwrap(); - engine.objects[sphere_1].position(2f32, 1f32, 0f32); - engine.objects[sphere_1].set_color(1.0f32, 0.5f32, 0.31f32, 1f32); - let sphere_2 = uv_sphere(Some("SPHERE2"), &mut engine, (18, 36, 1f32)).unwrap(); - engine.objects[sphere_2].position(-2f32, 1f32, 0f32); - engine.objects[sphere_2].set_color(1.0f32, 0.5f32, 0.31f32, 1f32); - let sphere_3 = uv_sphere(Some("SPHERE3"), &mut engine, (18, 36, 1f32)).unwrap(); - engine.objects[sphere_3].position(2f32, -1f32, 0f32); - engine.objects[sphere_3].set_color(1.0f32, 0.5f32, 0.31f32, 1f32); - let sphere_4 = uv_sphere(Some("SPHERE4"), &mut engine, (18, 36, 1f32)).unwrap(); - engine.objects[sphere_4].position(-2f32, -1f32, 0f32); - engine.objects[sphere_4].set_color(1.0f32, 0.5f32, 0.31f32, 1f32); */ - - //let window_size = engine.window.inner_size(); - /*let change_texture = engine - .renderer - .build_and_append_texture( - "name", - TextureData::Bytes(include_bytes!("resource/BlueLogoDiscord.png").to_vec()), - blue_engine::header::TextureMode::Clamp, - //blue_engine::header::TextureFormat::PNG, - ) - .unwrap();*/ - - //let square = engine.get_object(square_id).unwrap(); - - //square.change_color(0.0, 0.0, 1.0, 0.7).unwrap(); - //square.change_texture(change_texture); - //square.resize(100.0, 100.0, 0.0, window_size); - - //let square = engine.objects.get_mut(square_id).unwrap(); - - //square.no_stretch_update(&mut engine.renderer, engine.window.inner_size()).unwrap(); - //font.draw("Hello_World", (-100, 50), &mut engine).unwrap(); - - let radius = 10f32; - let start = std::time::SystemTime::now(); - let mut rotation = 0f32; - let speed = -0.05; - - let mut has_border = false; - let mut val = 0f32; + .set_position(1f32, 0f32, 0f32); + // =============================== + /* + //let triangle_id = triangle(Some("Triangleee"), &mut engine, camera).unwrap(); + let window_size = engine.window.inner_size(); + + uv_sphere( + "cube", + (18, 36, 1f32), + &mut engine.renderer, + &mut engine.objects, + ) + .unwrap(); + // engine.objects.get_mut("cube").unwrap().scale(0.6, 0.6, 0.6); + engine + .objects + .get_mut("cube") + .unwrap() + .set_color(1f32, 0f32, 0f32, 1f32); + //cube.scale(0.3, 0.3, 0.3); + + engine + .objects + .get_mut("monke") + .unwrap() + .set_color(0.051f32, 0.533f32, 0.898f32, 1f32); + //engine.objects[test].rotate(90f32, RotateAxis::Y); + + /*let sphere_1 = uv_sphere(Some("SPHERE1"), &mut engine, (18, 36, 1f32)).unwrap(); + engine.objects[sphere_1].scale(2f32, 2f32, 2f32); + engine.objects[sphere_1].set_color(0.051f32, 0.533f32, 0.898f32, 1f32); + + let sphere_1 = uv_sphere(Some("SPHERE1"), &mut engine, (18, 36, 1f32)).unwrap(); + engine.objects[sphere_1].position(2f32, 1f32, 0f32); + engine.objects[sphere_1].set_color(1.0f32, 0.5f32, 0.31f32, 1f32); + let sphere_2 = uv_sphere(Some("SPHERE2"), &mut engine, (18, 36, 1f32)).unwrap(); + engine.objects[sphere_2].position(-2f32, 1f32, 0f32); + engine.objects[sphere_2].set_color(1.0f32, 0.5f32, 0.31f32, 1f32); + let sphere_3 = uv_sphere(Some("SPHERE3"), &mut engine, (18, 36, 1f32)).unwrap(); + engine.objects[sphere_3].position(2f32, -1f32, 0f32); + engine.objects[sphere_3].set_color(1.0f32, 0.5f32, 0.31f32, 1f32); + let sphere_4 = uv_sphere(Some("SPHERE4"), &mut engine, (18, 36, 1f32)).unwrap(); + engine.objects[sphere_4].position(-2f32, -1f32, 0f32); + engine.objects[sphere_4].set_color(1.0f32, 0.5f32, 0.31f32, 1f32); */ + + //let window_size = engine.window.inner_size(); + /*let change_texture = engine + .renderer + .build_and_append_texture( + "name", + TextureData::Bytes(include_bytes!("resource/BlueLogoDiscord.png").to_vec()), + blue_engine::header::TextureMode::Clamp, + //blue_engine::header::TextureFormat::PNG, + ) + .unwrap();*/ + + //let square = engine.get_object(square_id).unwrap(); + + //square.change_color(0.0, 0.0, 1.0, 0.7).unwrap(); + //square.change_texture(change_texture); + //square.resize(100.0, 100.0, 0.0, window_size); + + //let square = engine.objects.get_mut(square_id).unwrap(); + + //square.no_stretch_update(&mut engine.renderer, engine.window.inner_size()).unwrap(); + //font.draw("Hello_World", (-100, 50), &mut engine).unwrap(); + + let radius = 10f32; + let start = std::time::SystemTime::now(); + let mut rotation = 0f32; + let speed = -0.05; + + let mut has_border = false; + let mut val = 0f32; + */ engine .update_loop(move |renderer, _window, objects, input, camera, plugins| { /*let o = diff --git a/examples/utils/resource_sharing.rs b/examples/utils/resource_sharing.rs new file mode 100644 index 0000000..f036620 --- /dev/null +++ b/examples/utils/resource_sharing.rs @@ -0,0 +1,65 @@ +use blue_engine::{primitive_shapes::square, Engine, ObjectSettings, TextureData}; + +fn main() { + // Start the engine + let mut engine = Engine::new().expect("window not initialized"); + + // build a texture as an example of resource to be shared + let texture = engine + .renderer + .build_texture( + "background", + TextureData::Path("resources/BlueLogoDiscord.png"), + blue_engine::TextureMode::Clamp, + ) + .unwrap(); + + // build your main object with the texture + square( + "main", + ObjectSettings::default(), + &mut engine.renderer, + &mut engine.objects, + ) + .expect("Error during creation of main square"); + + // add the texture to the main object as normally would + engine + .objects + .get_mut("main") + .unwrap() + .set_texture(texture) + .expect("Error during inserting texture to the main square"); + // set position to make it visible + engine + .objects + .get_mut("main") + .expect("Error during setting the position of the main square") + .set_position(-1.5f32, 0f32, 0f32); + + // create another object where you want to get resources shared with + square( + "alt", + ObjectSettings::default(), + &mut engine.renderer, + &mut engine.objects, + ) + .expect("Error during creation of alt square"); + + // here you can use `reference_texture` to reference the texture from the main object + engine + .objects + .get_mut("alt") + .expect("Error during copying texture of the main square") + .reference_texture("main"); + // setting position again to make it visible + engine + .objects + .get_mut("alt") + .expect("Error during setting the position of the alt square") + .set_position(1.5f32, 0f32, 0f32); + + engine + .update_loop(move |_, _, _, _, _, _| {}) + .expect("Error during update loop"); +} diff --git a/src/header.rs b/src/header.rs index 04b9392..62323e1 100644 --- a/src/header.rs +++ b/src/header.rs @@ -197,7 +197,6 @@ pub enum PipelineData { Copy(String), Data(T), } -//? ADD IT TO ALL OF PIPELINE /// Container for vertex and index buffer #[derive(Debug)] diff --git a/src/objects.rs b/src/objects.rs index eaff66c..65ec7a5 100644 --- a/src/objects.rs +++ b/src/objects.rs @@ -435,6 +435,27 @@ impl Object { Ok(updated_buffer2.0) } + + // ============================= FOR COPY OF PIPELINES ============================= + /// References another object's vertices + pub fn reference_vertices(&mut self, object_id: impl StringBuffer) { + self.pipeline.vertex_buffer = PipelineData::Copy(object_id.as_string()); + } + + /// References another object's shader + pub fn reference_shader(&mut self, object_id: impl StringBuffer) { + self.pipeline.shader = PipelineData::Copy(object_id.as_string()); + } + + /// References another object's texture + pub fn reference_texture(&mut self, object_id: impl StringBuffer) { + self.pipeline.texture = PipelineData::Copy(object_id.as_string()); + } + + /// References another object's uniform buffer + pub fn reference_uniform_buffer(&mut self, object_id: impl StringBuffer) { + self.pipeline.uniform = PipelineData::Copy(object_id.as_string()); + } } #[derive(Debug)] diff --git a/src/render.rs b/src/render.rs index 95fe855..c73eeaa 100644 --- a/src/render.rs +++ b/src/render.rs @@ -7,7 +7,7 @@ use crate::{ header::{uniform_type, Camera, Renderer, ShaderSettings, TextureData}, utils::default_resources::{DEFAULT_COLOR, DEFAULT_MATRIX_4, DEFAULT_SHADER, DEFAULT_TEXTURE}, - ObjectStorage, + ObjectStorage, PipelineData, }; use anyhow::Result; use wgpu::Features; @@ -273,17 +273,38 @@ impl Renderer { for i in objects.iter() { if i.1.is_visible { let i = i.1; - render_pass.set_pipeline(&i.pipeline.shader); - render_pass.set_bind_group(0, &i.pipeline.texture, &[]); - if i.pipeline.uniform.is_some() { - render_pass.set_bind_group(2, &i.pipeline.uniform.as_ref().unwrap(), &[]); + + let vertex_buffer = get_pipeline_vertex_buffer(&i.pipeline.vertex_buffer, objects); + let shader = get_pipeline_shader(&i.pipeline.shader, objects); + let texture = get_pipeline_texture(&i.pipeline.texture, objects); + let uniform = get_pipeline_uniform_buffer(&i.pipeline.uniform, objects); + + // vertex + if vertex_buffer.is_some() { + let vertex_buffer = vertex_buffer.unwrap(); + render_pass.set_vertex_buffer(0, vertex_buffer.vertex_buffer.slice(..)); + render_pass.set_index_buffer( + vertex_buffer.index_buffer.slice(..), + wgpu::IndexFormat::Uint16, + ); + + // shader + if shader.is_some() { + render_pass.set_pipeline(&shader.unwrap()); + } + // texture + if texture.is_some() { + render_pass.set_bind_group(0, &texture.unwrap(), &[]); + } + // uniform + if uniform.is_some() { + let uniform = uniform.unwrap(); + if uniform.is_some() { + render_pass.set_bind_group(2, uniform.as_ref().unwrap(), &[]); + } + } + render_pass.draw_indexed(0..vertex_buffer.length, 0, 0..1); } - render_pass.set_vertex_buffer(0, i.pipeline.vertex_buffer.vertex_buffer.slice(..)); - render_pass.set_index_buffer( - i.pipeline.vertex_buffer.index_buffer.slice(..), - wgpu::IndexFormat::Uint16, - ); - render_pass.draw_indexed(0..i.pipeline.vertex_buffer.length, 0, 0..1); } } drop(render_pass); @@ -308,3 +329,78 @@ impl Renderer { Ok(()) } } + +// =========================== Extract Pipeline Data =========================== +// I couldn't make them into one function, so here they are, four of them + +/// Get the pipeline vertex buffer. +fn get_pipeline_vertex_buffer<'a>( + data: &'a PipelineData, + objects: &'a ObjectStorage, +) -> Option<&'a crate::VertexBuffers> { + match data { + PipelineData::Copy(object_id) => { + let data = objects.get(object_id.as_str()); + if data.is_some() { + get_pipeline_vertex_buffer(&data.unwrap().pipeline.vertex_buffer, objects) + } else { + None + } + } + PipelineData::Data(data) => Some(data), + } +} + +/// Get the pipeline shader. +fn get_pipeline_shader<'a>( + data: &'a PipelineData, + objects: &'a ObjectStorage, +) -> Option<&'a crate::Shaders> { + match data { + PipelineData::Copy(object_id) => { + let data = objects.get(object_id.as_str()); + if data.is_some() { + get_pipeline_shader(&data.unwrap().pipeline.shader, objects) + } else { + None + } + } + PipelineData::Data(data) => Some(data), + } +} + +/// Get the pipeline texture. +fn get_pipeline_texture<'a>( + data: &'a PipelineData, + objects: &'a ObjectStorage, +) -> Option<&'a crate::Textures> { + match data { + PipelineData::Copy(object_id) => { + let data = objects.get(object_id.as_str()); + if data.is_some() { + get_pipeline_texture(&data.unwrap().pipeline.texture, objects) + } else { + None + } + } + PipelineData::Data(data) => Some(data), + } +} + +/// Get the pipeline uniform_buffer. +fn get_pipeline_uniform_buffer<'a>( + data: &'a PipelineData>, + objects: &'a ObjectStorage, +) -> Option<&'a Option> { + match data { + PipelineData::Copy(object_id) => { + let data = objects.get(object_id.as_str()); + if data.is_some() { + get_pipeline_uniform_buffer(&data.unwrap().pipeline.uniform, objects) + } else { + None + } + } + PipelineData::Data(data) => Some(data), + } +}