From 55d46b8a012ad115ca0c09c329c438eb7345104b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Thulliez?= <43185161+grzi@users.noreply.github.com> Date: Thu, 25 Mar 2021 23:03:58 +0100 Subject: [PATCH] feat: UiImage and layer rendering (#60) FIXES #51 --- examples/taquin/main.rs | 60 +++---- examples/tetris/main.rs | 18 +- src/rendering/bidimensional/components/mod.rs | 1 + .../bidimensional/components/square.rs | 23 +-- .../bidimensional/components/triangle.rs | 8 +- .../bidimensional/components/ui/mod.rs | 1 + .../bidimensional/components/ui/ui_image.rs | 134 ++++++++++++++ .../bidimensional/gl_representations.rs | 32 ++-- src/rendering/bidimensional/mod.rs | 2 +- src/rendering/bidimensional/scion2d.rs | 167 ++++++++++++++---- src/rendering/bidimensional/transform.rs | 73 ++++++-- 11 files changed, 395 insertions(+), 124 deletions(-) create mode 100644 src/rendering/bidimensional/components/ui/mod.rs create mode 100644 src/rendering/bidimensional/components/ui/ui_image.rs diff --git a/examples/taquin/main.rs b/examples/taquin/main.rs index fd84209..c07f992 100644 --- a/examples/taquin/main.rs +++ b/examples/taquin/main.rs @@ -8,13 +8,13 @@ use scion::{ Camera2D, components::Square, Material2D, - Position2D, Transform2D, + Coordinates, Transform2D, }, utils::file::app_base_path, }; #[derive(Debug)] -struct Case(Position2D); +struct Case(Coordinates); enum MoveDirection { Left, @@ -65,25 +65,13 @@ fn square(x: usize, y: usize) -> Square { let x_offset = x as f32 * 0.25; let y_offset = y as f32 * 0.25; Square::new( - Position2D { x: 0., y: 0. }, + Coordinates::new(0., 0.), 192., Some([ - Position2D { - x: x_offset, - y: y_offset, - }, - Position2D { - x: x_offset, - y: 0.25 + y_offset, - }, - Position2D { - x: 0.25 + x_offset, - y: 0.25 + y_offset, - }, - Position2D { - x: 0.25 + x_offset, - y: y_offset, - }, + Coordinates::new(x_offset, y_offset), + Coordinates::new(x_offset, 0.25 + y_offset), + Coordinates::new(0.25 + x_offset, 0.25 + y_offset), + Coordinates::new(0.25 + x_offset, y_offset), ]), ) } @@ -98,26 +86,26 @@ fn taquin( if inputs.mouse().click_event() { let mouse_x = inputs.mouse().x(); let mouse_y = inputs.mouse().y(); - if mouse_x > (case.0.x * 192.) as f64 - && mouse_y > (case.0.y * 192.) as f64 - && mouse_x < (case.0.x * 192. + 192.) as f64 - && mouse_y < (case.0.y * 192. + 192.) as f64 + if mouse_x > (case.0.x() * 192.) as f64 + && mouse_y > (case.0.y() * 192.) as f64 + && mouse_x < (case.0.x() * 192. + 192.) as f64 + && mouse_y < (case.0.y() * 192. + 192.) as f64 { - match taquin.try_move(case.0.x as usize, case.0.y as usize) { + match taquin.try_move(case.0.x() as usize, case.0.y() as usize) { MoveDirection::Left => { - case.0.x -= 1.; + case.0.set_x(case.0.x() -1.); transform.append_translation(-192., 0.); } MoveDirection::Top => { - case.0.y -= 1.; + case.0.set_y(case.0.y() -1.); transform.append_translation(0., -192.); } MoveDirection::Right => { - case.0.x += 1.; + case.0.set_x(case.0.x() + 1.); transform.append_translation(192., 0.); } MoveDirection::Bottom => { - case.0.y += 1.; + case.0.set_y(case.0.y() + 1.); transform.append_translation(0., 192.); } MoveDirection::None => {} @@ -137,17 +125,11 @@ impl SimpleGameLayer for Layer { for y in 0..4 { if !(x == 3 && y == 3) { let square = ( - Case(Position2D { - x: x as f32, - y: y as f32, - }), + Case(Coordinates::new(x as f32, y as f32)), square(x, y), Material2D::Texture(p.as_path().to_str().unwrap().to_string()), Transform2D::new( - Position2D { - x: x as f32 * 192., - y: y as f32 * 192., - }, + Coordinates::new(x as f32 * 192., y as f32 * 192.), 1., 0., ), @@ -167,7 +149,7 @@ fn main() { .with_window_config(WindowConfigBuilder::new().with_dimensions((768, 768)).get()) .get(), ) - .with_system(taquin_system()) - .with_game_layer(GameLayer::weak::()) - .run(); + .with_system(taquin_system()) + .with_game_layer(GameLayer::weak::()) + .run(); } diff --git a/examples/tetris/main.rs b/examples/tetris/main.rs index 191c264..659ccd5 100644 --- a/examples/tetris/main.rs +++ b/examples/tetris/main.rs @@ -1,8 +1,10 @@ use scion::game_layer::{GameLayer, GameLayerController, SimpleGameLayer}; use scion::legion::{Resources, system, World}; -use scion::rendering::bidimensional::{Camera2D, Material2D, Position2D, Transform2D}; +use scion::rendering::bidimensional::{Camera2D, Material2D, Coordinates, Transform2D}; use scion::rendering::bidimensional::components::Square; use scion::Scion; +use scion::utils::file::app_base_path; +use scion::rendering::bidimensional::components::ui::ui_image::UiImage; #[system] fn test() { @@ -14,6 +16,20 @@ struct LayerA; impl SimpleGameLayer for LayerA { fn on_start(&mut self, world: &mut World, resource: &mut Resources) { + let path = app_base_path().expect("").join("assets").join("tetris").join("ui.png").to_str().expect("").to_string(); + let mut t = Transform2D::default(); + t.set_layer(0); + let image = UiImage::new(544., 704., path); + + world.push((image, t,)); + resource.insert(Camera2D::new(544., 704., 10.)); + + let path = app_base_path().expect("").join("assets").join("taquin.png").to_str().expect("").to_string(); + let mut t = Transform2D::default(); + t.set_layer(1); + let image = UiImage::new(300., 300., path); + + world.push((image, t,)); } } diff --git a/src/rendering/bidimensional/components/mod.rs b/src/rendering/bidimensional/components/mod.rs index 70d89af..6b9554a 100644 --- a/src/rendering/bidimensional/components/mod.rs +++ b/src/rendering/bidimensional/components/mod.rs @@ -2,6 +2,7 @@ pub use square::Square; pub use triangle::Triangle; +pub mod ui; mod square; mod triangle; diff --git a/src/rendering/bidimensional/components/square.rs b/src/rendering/bidimensional/components/square.rs index 362534c..bc8da75 100644 --- a/src/rendering/bidimensional/components/square.rs +++ b/src/rendering/bidimensional/components/square.rs @@ -3,33 +3,24 @@ use std::ops::Range; use wgpu::{util::BufferInitDescriptor, BindGroupLayout, Device, RenderPipeline, SwapChainDescriptor, BlendFactor, BlendOperation}; use crate::rendering::bidimensional::{ - gl_representations::TexturedGlVertex, scion2d::Renderable2D, transform::Position2D, + gl_representations::TexturedGlVertex, scion2d::Renderable2D, transform::Coordinates, }; const INDICES: &[u16] = &[0, 1, 3, 3, 1, 2]; /// Renderable 2D Square. pub struct Square { - pub vertices: [Position2D; 4], - pub uvs: Option<[Position2D; 4]>, + pub vertices: [Coordinates; 4], + pub uvs: Option<[Coordinates; 4]>, contents: [TexturedGlVertex; 4], } impl Square { - pub fn new(origin: Position2D, length: f32, uvs: Option<[Position2D; 4]>) -> Self { + pub fn new(origin: Coordinates, length: f32, uvs: Option<[Coordinates; 4]>) -> Self { let a = origin; - let b = Position2D { - x: a.x, - y: a.y + length, - }; - let c = Position2D { - x: a.x + length, - y: a.y + length, - }; - let d = Position2D { - x: a.x + length, - y: a.y, - }; + let b = Coordinates::new (a.x(), a.y() + length); + let c = Coordinates::new ( a.x() + length, a.y() + length); + let d = Coordinates::new (a.x() + length, a.y()); let uvs_ref = uvs .as_ref() .expect("Uvs are currently mandatory, this need to be fixed"); diff --git a/src/rendering/bidimensional/components/triangle.rs b/src/rendering/bidimensional/components/triangle.rs index 65ef53e..ec7b399 100644 --- a/src/rendering/bidimensional/components/triangle.rs +++ b/src/rendering/bidimensional/components/triangle.rs @@ -3,20 +3,20 @@ use std::ops::Range; use wgpu::{util::BufferInitDescriptor, BindGroupLayout, Device, RenderPipeline, SwapChainDescriptor, BlendFactor, BlendOperation}; use crate::rendering::bidimensional::{ - gl_representations::TexturedGlVertex, scion2d::Renderable2D, transform::Position2D, + gl_representations::TexturedGlVertex, scion2d::Renderable2D, transform::Coordinates, }; const INDICES: &[u16] = &[1, 0, 2]; /// Renderable 2D Triangle. pub struct Triangle { - pub vertices: [Position2D; 3], - pub uvs: Option<[Position2D; 3]>, + pub vertices: [Coordinates; 3], + pub uvs: Option<[Coordinates; 3]>, contents: [TexturedGlVertex; 3], } impl Triangle { - pub fn new(vertices: [Position2D; 3], uvs: Option<[Position2D; 3]>) -> Self { + pub fn new(vertices: [Coordinates; 3], uvs: Option<[Coordinates; 3]>) -> Self { let uvs_ref = uvs .as_ref() .expect("Uvs are currently mandatory, this need to be fixed"); diff --git a/src/rendering/bidimensional/components/ui/mod.rs b/src/rendering/bidimensional/components/ui/mod.rs new file mode 100644 index 0000000..3ad4e6f --- /dev/null +++ b/src/rendering/bidimensional/components/ui/mod.rs @@ -0,0 +1 @@ +pub mod ui_image; \ No newline at end of file diff --git a/src/rendering/bidimensional/components/ui/ui_image.rs b/src/rendering/bidimensional/components/ui/ui_image.rs new file mode 100644 index 0000000..938b585 --- /dev/null +++ b/src/rendering/bidimensional/components/ui/ui_image.rs @@ -0,0 +1,134 @@ +use std::ops::Range; + +use wgpu::{util::BufferInitDescriptor, BindGroupLayout, Device, RenderPipeline, SwapChainDescriptor, BlendFactor, BlendOperation}; + +use crate::rendering::bidimensional::{ + gl_representations::TexturedGlVertex, scion2d::Renderable2D, transform::Coordinates, +}; +use crate::rendering::bidimensional::scion2d::RenderableUi; + +/// Renderable 2D Square. +pub struct UiImage { + image_path: String, + vertices: [Coordinates; 4], + uvs: [Coordinates; 4], + contents: [TexturedGlVertex; 4], +} + +const INDICES: &[u16] = &[0, 1, 3, 3, 1, 2]; + +impl UiImage { + pub fn new(width: f32, height:f32, image_path: String) -> Self { + let a = Coordinates::new(0., 0.); + let b = Coordinates::new (a.x(), a.y() + height); + let c = Coordinates::new ( a.x() + width, a.y() + height); + let d = Coordinates::new (a.x() + width, a.y()); + + let uvs = [ + Coordinates::new(0., 0.), + Coordinates::new(0., 1.), + Coordinates::new(1., 1.), + Coordinates::new(1., 0.), + ]; + let contents = [ + TexturedGlVertex::from((&a, &uvs[0])), + TexturedGlVertex::from((&b, &uvs[1])), + TexturedGlVertex::from((&c, &uvs[2])), + TexturedGlVertex::from((&d, &uvs[3])), + ]; + Self { + image_path, + vertices: [a, b, c, d], + uvs, + contents, + } + } +} + +impl Renderable2D for UiImage { + fn vertex_buffer_descriptor(&self) -> BufferInitDescriptor { + wgpu::util::BufferInitDescriptor { + label: Some("Square Vertex Buffer"), + contents: bytemuck::cast_slice(&self.contents), + usage: wgpu::BufferUsage::VERTEX, + } + } + + fn indexes_buffer_descriptor(&self) -> BufferInitDescriptor { + wgpu::util::BufferInitDescriptor { + label: Some("Square Index Buffer"), + contents: bytemuck::cast_slice(&INDICES), + usage: wgpu::BufferUsage::INDEX, + } + } + + fn pipeline( + &self, + device: &Device, + sc_desc: &SwapChainDescriptor, + texture_bind_group_layout: &BindGroupLayout, + transform_bind_group_layout: &BindGroupLayout, + ) -> RenderPipeline { + let vs_module = + device.create_shader_module(&wgpu::include_spirv!("../shaders/shader.vert.spv")); + let fs_module = + device.create_shader_module(&wgpu::include_spirv!("../shaders/shader.frag.spv")); + + let render_pipeline_layout = + device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + label: Some("Basic square pipeline layout"), + bind_group_layouts: &[texture_bind_group_layout, transform_bind_group_layout], + push_constant_ranges: &[], + }); + + let render_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor { + label: Some("Square render pipeline"), + layout: Some(&render_pipeline_layout), + vertex: wgpu::VertexState { + module: &vs_module, + entry_point: "main", + buffers: &[TexturedGlVertex::desc()], + }, + fragment: Some(wgpu::FragmentState { + module: &fs_module, + entry_point: "main", + targets: &[wgpu::ColorTargetState { + format: sc_desc.format, + alpha_blend: wgpu::BlendState { + src_factor: BlendFactor::One, + dst_factor: BlendFactor::One, + operation: BlendOperation::Add, + }, + color_blend: wgpu::BlendState { + src_factor: BlendFactor::SrcAlpha, + dst_factor: BlendFactor::OneMinusSrcAlpha, + operation: BlendOperation::Add, + }, + write_mask: wgpu::ColorWrite::ALL, + }], + }), + primitive: wgpu::PrimitiveState { + topology: wgpu::PrimitiveTopology::TriangleList, + strip_index_format: None, + front_face: wgpu::FrontFace::Ccw, + cull_mode: wgpu::CullMode::Back, + polygon_mode: wgpu::PolygonMode::Fill, + }, + depth_stencil: None, + multisample: wgpu::MultisampleState { + count: 1, + mask: !0, + alpha_to_coverage_enabled: false, + }, + }); + render_pipeline + } + + fn range(&self) -> Range { + 0..INDICES.len() as u32 + } +} + +impl RenderableUi for UiImage { + fn get_texture_path(&self) -> Option{Some(self.image_path.clone())} +} diff --git a/src/rendering/bidimensional/gl_representations.rs b/src/rendering/bidimensional/gl_representations.rs index e19e4a7..b6a603b 100644 --- a/src/rendering/bidimensional/gl_representations.rs +++ b/src/rendering/bidimensional/gl_representations.rs @@ -1,6 +1,6 @@ use ultraviolet::{Mat4, Rotor3, Similarity3, Vec3, Vec4}; -use crate::rendering::bidimensional::{Camera2D, Position2D, Transform2D}; +use crate::rendering::bidimensional::{Camera2D, Coordinates, Transform2D}; #[repr(C)] #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)] @@ -17,11 +17,11 @@ pub(crate) struct GlVec3 { pub z: f32, } -impl From<&Position2D> for GlVec3 { - fn from(position: &Position2D) -> Self { +impl From<&Coordinates> for GlVec3 { + fn from(position: &Coordinates) -> Self { Self { - x: position.x, - y: position.y, + x: position.x(), + y: position.y(), z: 0., } } @@ -113,17 +113,17 @@ impl TexturedGlVertex { } } -impl From<(&Position2D, &Position2D)> for TexturedGlVertex { - fn from(positions: (&Position2D, &Position2D)) -> Self { +impl From<(&Coordinates, &Coordinates)> for TexturedGlVertex { + fn from(positions: (&Coordinates, &Coordinates)) -> Self { TexturedGlVertex { position: GlVec3 { - x: positions.0.x, - y: positions.0.y, + x: positions.0.x(), + y: positions.0.y(), z: 0.0, }, tex_coords: GlVec2 { - x: positions.1.x, - y: positions.1.y, + x: positions.1.x(), + y: positions.1.y(), }, } } @@ -162,15 +162,11 @@ impl From<(&Transform2D, &Camera2D)> for GlUniform { let mut model_trans = Similarity3::identity(); model_trans.prepend_scaling(transform.scale); model_trans.append_translation(Vec3 { - x: transform.position.x, - y: transform.position.y, - z: 1.0, + x: transform.coords.x(), + y: transform.coords.y(), + z: transform.coords.layer() as f32, }); model_trans.prepend_rotation(Rotor3::from_rotation_xy(transform.angle).normalized()); - - let mut test = Similarity3::identity(); - test.append_translation(Vec3::new(-384., 384., 0.)); - let mut model_trans = model_trans.into_homogeneous_matrix(); let mut camera_view = ultraviolet::projection::lh_ydown::orthographic_wgpu_dx( camera.left, diff --git a/src/rendering/bidimensional/mod.rs b/src/rendering/bidimensional/mod.rs index 172833e..fc111e2 100644 --- a/src/rendering/bidimensional/mod.rs +++ b/src/rendering/bidimensional/mod.rs @@ -2,7 +2,7 @@ pub use camera::Camera2D; pub use material::Material2D; -pub use transform::{Position2D, Transform2D}; +pub use transform::{Coordinates, Transform2D}; mod camera; pub mod components; diff --git a/src/rendering/bidimensional/scion2d.rs b/src/rendering/bidimensional/scion2d.rs index 9a60e60..6307af0 100644 --- a/src/rendering/bidimensional/scion2d.rs +++ b/src/rendering/bidimensional/scion2d.rs @@ -1,22 +1,24 @@ use std::{collections::HashMap, ops::Range, path::Path}; +use std::collections::VecDeque; -use legion::{storage::Component, Entity, IntoQuery, Resources, World}; +use legion::{Entity, IntoQuery, Resources, storage::Component, World}; use wgpu::{ - util::{BufferInitDescriptor, DeviceExt}, - BindGroup, BindGroupLayout, Buffer, CommandEncoder, Device, Queue, - RenderPassColorAttachmentDescriptor, RenderPipeline, SwapChainDescriptor, SwapChainTexture, + BindGroup, + BindGroupLayout, Buffer, CommandEncoder, Device, Queue, RenderPassColorAttachmentDescriptor, + RenderPipeline, SwapChainDescriptor, SwapChainTexture, util::{BufferInitDescriptor, DeviceExt}, }; use crate::rendering::{ bidimensional::{ + Camera2D, components::{Square, Triangle}, gl_representations::GlUniform, material::{Material2D, Texture}, transform::Transform2D, - Camera2D, }, ScionRenderer, }; +use crate::rendering::bidimensional::components::ui::ui_image::UiImage; pub(crate) trait Renderable2D { fn vertex_buffer_descriptor(&self) -> BufferInitDescriptor; @@ -31,6 +33,10 @@ pub(crate) trait Renderable2D { fn range(&self) -> Range; } +pub(crate) trait RenderableUi: Renderable2D { + fn get_texture_path(&self) -> Option { None } +} + #[derive(Default)] pub(crate) struct Scion2D { vertex_buffers: HashMap, @@ -40,6 +46,13 @@ pub(crate) struct Scion2D { transform_uniform_bind_groups: HashMap, } +struct RenderingInfos{ + layer: usize, + range: Range, + entity: Entity, + texture_path: Option +} + impl ScionRenderer for Scion2D { fn update( &mut self, @@ -54,6 +67,7 @@ impl ScionRenderer for Scion2D { self.update_transforms(world, resources, &device, queue); self.upsert_component_pipeline::(world, &device, &sc_desc); self.upsert_component_pipeline::(world, &device, &sc_desc); + self.upsert_ui_component_pipeline::(world, &device, &sc_desc, queue); } } @@ -73,8 +87,15 @@ impl ScionRenderer for Scion2D { } if resource.contains::() { - self.render_component::(world, &frame, encoder); - self.render_component::(world, &frame, encoder); + let mut rendering_infos = Vec::new(); + rendering_infos.append(&mut self.pre_render_component::(world)); + rendering_infos.append(&mut self.pre_render_component::(world)); + rendering_infos.append(&mut self.pre_render_ui_component::(world)); + + rendering_infos.sort_by(|a,b| b.layer.cmp(&a.layer)); + while let Some(info) = rendering_infos.pop() { + self.render_component(&frame, encoder, info); + } } } } @@ -245,7 +266,7 @@ impl Scion2D { sc_desc: &&SwapChainDescriptor, ) { for (entity, component, material, _) in - <(Entity, &mut T, &Material2D, &Transform2D)>::query().iter_mut(world) + <(Entity, &mut T, &Material2D, &Transform2D)>::query().iter_mut(world) { if !self.vertex_buffers.contains_key(entity) { let vertex_buffer = @@ -278,48 +299,128 @@ impl Scion2D { } } - fn render_component( + fn upsert_ui_component_pipeline( &mut self, world: &mut World, - frame: &&SwapChainTexture, - encoder: &mut CommandEncoder, + device: &&Device, + sc_desc: &&SwapChainDescriptor, + queue: &mut Queue, ) { + for (entity, component, _) in + <(Entity, &mut T, &Transform2D)>::query().iter_mut(world) + { + if !self.vertex_buffers.contains_key(entity) { + let vertex_buffer = + device.create_buffer_init(&component.vertex_buffer_descriptor()); + self.vertex_buffers.insert(*entity, vertex_buffer); + } + + if !self.index_buffers.contains_key(entity) { + let index_buffer = + device.create_buffer_init(&component.indexes_buffer_descriptor()); + self.index_buffers.insert(*entity, index_buffer); + } + if let Some(path) = component.get_texture_path() { + if !self.diffuse_bind_groups.contains_key(path.as_str()) { + let loaded_texture = Texture::from_png(Path::new(path.as_str())); + self.diffuse_bind_groups.insert( + path.clone(), + load_texture_to_queue(&loaded_texture, queue, device), + ); + } + + if !self.render_pipelines.contains_key(path.as_str()) { + self.render_pipelines.insert( + path.clone(), + component.pipeline( + &device, + &sc_desc, + &self.diffuse_bind_groups.get(path.as_str()).unwrap().0, + &self.transform_uniform_bind_groups.get(entity).unwrap().2, + ), + ); + } + } + } + } + + fn render_component(&mut self, + frame: &&SwapChainTexture, + encoder: &mut CommandEncoder, + rendering_infos: RenderingInfos) { let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { label: Some("Scion 2D Render Pass"), color_attachments: &[get_no_color_attachment(frame)], depth_stencil_attachment: None, }); - for (entity, component, material, _transform) in - <(Entity, &mut T, &Material2D, &Transform2D)>::query().iter_mut(world) - { + render_pass.set_bind_group( + 1, + &self.transform_uniform_bind_groups.get(&rendering_infos.entity).unwrap().3, + &[], + ); + render_pass.set_vertex_buffer( + 0, + self.vertex_buffers.get(&rendering_infos.entity).as_ref().unwrap().slice(..), + ); + render_pass.set_index_buffer( + self.index_buffers.get(&rendering_infos.entity).as_ref().unwrap().slice(..), + wgpu::IndexFormat::Uint16, + ); + + if let Some(path) = rendering_infos.texture_path { + render_pass + .set_pipeline(self.render_pipelines.get(path.as_str()).as_ref().unwrap()); render_pass.set_bind_group( - 1, - &self.transform_uniform_bind_groups.get(entity).unwrap().3, - &[], - ); - render_pass.set_vertex_buffer( 0, - self.vertex_buffers.get(entity).as_ref().unwrap().slice(..), - ); - render_pass.set_index_buffer( - self.index_buffers.get(entity).as_ref().unwrap().slice(..), - wgpu::IndexFormat::Uint16, + &self.diffuse_bind_groups.get(path.as_str()).unwrap().1, + &[], ); + } + render_pass.draw_indexed(rendering_infos.range, 0, 0..1); + } + + fn pre_render_component( + &mut self, + world: &mut World + ) -> Vec { + let mut render_infos = Vec::new(); + for (entity, component, material, transform) in + <(Entity, &mut T, &Material2D, &Transform2D)>::query().iter_mut(world) + { + let mut path = None; match material { Material2D::Color(_) => {} - Material2D::Texture(path) => { - render_pass - .set_pipeline(self.render_pipelines.get(path.as_str()).as_ref().unwrap()); - render_pass.set_bind_group( - 0, - &self.diffuse_bind_groups.get(path.as_str()).unwrap().1, - &[], - ); + Material2D::Texture(p) => { + path = Some(p.clone()); } }; - render_pass.draw_indexed(component.range(), 0, 0..1); + render_infos.push(RenderingInfos{ + layer: transform.coords().layer(), + range: component.range(), + entity: *entity, + texture_path: path + }); + } + render_infos + } + + fn pre_render_ui_component( + &mut self, + world: &mut World, + ) -> Vec { + let mut render_infos = Vec::new(); + for (entity, component, transform) in + <(Entity, &mut T, &Transform2D)>::query().iter_mut(world) { + + render_infos.push(RenderingInfos{ + layer: transform.coords().layer(), + range: component.range(), + entity: *entity, + texture_path: component.get_texture_path() + }); } + render_infos } fn update_transforms( diff --git a/src/rendering/bidimensional/transform.rs b/src/rendering/bidimensional/transform.rs index 9087f6c..d28ffa8 100644 --- a/src/rendering/bidimensional/transform.rs +++ b/src/rendering/bidimensional/transform.rs @@ -1,15 +1,59 @@ /// Convenience struct used in all `Scion` to specify any 2D position. #[derive(Default, Debug, Copy, Clone)] -pub struct Position2D { - pub x: f32, - pub y: f32, +pub struct Coordinates { + x: f32, + y: f32, + layer: usize, +} + +impl Coordinates { + pub fn new(x: f32, y: f32) -> Self { + Self { + x, + y, + layer: 0, + } + } + + pub fn new_with_layer(x: f32, y: f32, layer: usize) -> Self { + Self { + x, + y, + layer, + } + } + + pub fn x(&self) -> f32 { + self.x + } + + pub fn y(&self) -> f32 { + self.y + } + + pub fn layer(&self) -> usize { + self.layer + } + + pub fn set_x(&mut self, x: f32) { + self.x = x + } + + pub fn set_y(&mut self, y: f32) { + self.y = y; + } + + pub fn set_layer(&mut self, layer: usize) { + self.layer = layer; + } + } /// Component used by the renderer to know where and how to represent an object. /// Default is position 0;0 with a scale of 1.0 and no angle. #[derive(Debug)] pub struct Transform2D { - pub(crate) position: Position2D, + pub(crate) coords: Coordinates, pub(crate) scale: f32, pub(crate) angle: f32, } @@ -17,7 +61,7 @@ pub struct Transform2D { impl Default for Transform2D { fn default() -> Self { Self { - position: Default::default(), + coords: Default::default(), scale: 1.0, angle: 0.0, } @@ -26,9 +70,9 @@ impl Default for Transform2D { impl Transform2D { /// Creates a new transform using provided values. - pub fn new(position: Position2D, scale: f32, angle: f32) -> Self { + pub fn new(coords: Coordinates, scale: f32, angle: f32) -> Self { Self { - position, + coords, scale, angle, } @@ -36,8 +80,8 @@ impl Transform2D { /// Append a translation to this transform's position pub fn append_translation(&mut self, x: f32, y: f32) { - self.position.x += x; - self.position.y += y; + self.coords.x += x; + self.coords.y += y; } /// Append an angle to this transform's angle @@ -45,13 +89,18 @@ impl Transform2D { self.angle += angle; } - /// Get the transform's position - pub fn position(&self) -> &Position2D { - &self.position + /// Get the transform's coordinates + pub fn coords(&self) -> &Coordinates { + &self.coords } /// Change the scale value to a new one. pub fn set_scale(&mut self, scale: f32) { self.scale = scale } + + /// Change the layer value in the coordinates. + pub fn set_layer(&mut self, layer: usize) { + self.coords.layer = layer + } }