From 449a36dbd32cc2edd2629268faa75f90cd3e39a2 Mon Sep 17 00:00:00 2001 From: Alula <6276139+alula@users.noreply.github.com> Date: Sat, 13 Feb 2021 00:03:38 +0100 Subject: [PATCH] add procedures for rectangle drawing --- src/framework/backend.rs | 4 + src/framework/backend_sdl2.rs | 173 ++++++++++++++++++---------------- src/framework/graphics.rs | 18 +++- src/texture_set.rs | 8 -- 4 files changed, 114 insertions(+), 89 deletions(-) diff --git a/src/framework/backend.rs b/src/framework/backend.rs index 13975fd..e86e837 100644 --- a/src/framework/backend.rs +++ b/src/framework/backend.rs @@ -29,6 +29,10 @@ pub trait BackendRenderer { fn set_render_target(&mut self, texture: Option<&Box>) -> GameResult; + fn draw_rect(&mut self, rect: Rect, color: Color) -> GameResult; + + fn draw_outline_rect(&mut self, rect: Rect, line_width: usize, color: Color) -> GameResult; + fn imgui(&self) -> GameResult<&mut imgui::Context>; fn render_imgui(&mut self, draw_data: &DrawData) -> GameResult; diff --git a/src/framework/backend_sdl2.rs b/src/framework/backend_sdl2.rs index e96aa48..4ec5f71 100644 --- a/src/framework/backend_sdl2.rs +++ b/src/framework/backend_sdl2.rs @@ -13,10 +13,8 @@ use sdl2::render::{Texture, TextureCreator, WindowCanvas}; use sdl2::video::WindowContext; use sdl2::{keyboard, pixels, EventPump, Sdl}; -use crate::common::Color; -use crate::framework::backend::{ - Backend, BackendEventLoop, BackendRenderer, BackendTexture, SpriteBatchCommand, -}; +use crate::common::{Color, Rect}; +use crate::framework::backend::{Backend, BackendEventLoop, BackendRenderer, BackendTexture, SpriteBatchCommand}; use crate::framework::context::Context; use crate::framework::error::{GameError, GameResult}; use crate::framework::graphics::{imgui_context, BlendMode}; @@ -97,10 +95,7 @@ impl BackendEventLoop for SDL2EventLoop { let (imgui, imgui_sdl2) = unsafe { let renderer: &Box = std::mem::transmute(ctx.renderer.as_ref().unwrap()); - ( - &mut *renderer.imgui.as_ptr(), - &mut *renderer.imgui_event.as_ptr(), - ) + (&mut *renderer.imgui.as_ptr(), &mut *renderer.imgui_event.as_ptr()) }; { @@ -127,17 +122,14 @@ impl BackendEventLoop for SDL2EventLoop { if let Some(renderer) = ctx.renderer.as_ref() { if let Ok(imgui) = renderer.imgui() { - imgui.io_mut().display_size = - [ctx.screen_size.0, ctx.screen_size.1]; + imgui.io_mut().display_size = [ctx.screen_size.0, ctx.screen_size.1]; } } state.handle_resize(ctx); } _ => {} }, - Event::KeyDown { - scancode, repeat, .. - } => { + Event::KeyDown { scancode, repeat, .. } => { if let Some(scancode) = scancode { if let Some(drs_scan) = conv_scancode(scancode) { if !repeat { @@ -309,11 +301,7 @@ impl BackendRenderer for SDL2Renderer { Ok(()) } - fn create_texture_mutable( - &mut self, - width: u16, - height: u16, - ) -> GameResult> { + fn create_texture_mutable(&mut self, width: u16, height: u16) -> GameResult> { let refs = self.refs.borrow_mut(); let texture = refs @@ -321,21 +309,10 @@ impl BackendRenderer for SDL2Renderer { .create_texture_target(PixelFormatEnum::RGBA32, width as u32, height as u32) .map_err(|e| GameError::RenderError(e.to_string()))?; - Ok(Box::new(SDL2Texture { - refs: self.refs.clone(), - texture: Some(texture), - width, - height, - commands: vec![], - })) + Ok(Box::new(SDL2Texture { refs: self.refs.clone(), texture: Some(texture), width, height, commands: vec![] })) } - fn create_texture( - &mut self, - width: u16, - height: u16, - data: &[u8], - ) -> GameResult> { + fn create_texture(&mut self, width: u16, height: u16, data: &[u8]) -> GameResult> { let refs = self.refs.borrow_mut(); let mut texture = refs @@ -360,13 +337,7 @@ impl BackendRenderer for SDL2Renderer { }) .map_err(|e| GameError::RenderError(e.to_string()))?; - Ok(Box::new(SDL2Texture { - refs: self.refs.clone(), - texture: Some(texture), - width, - height, - commands: vec![], - })) + Ok(Box::new(SDL2Texture { refs: self.refs.clone(), texture: Some(texture), width, height, commands: vec![] })) } fn set_blend_mode(&mut self, blend: BlendMode) -> GameResult { @@ -403,6 +374,68 @@ impl BackendRenderer for SDL2Renderer { Ok(()) } + fn draw_rect(&mut self, rect: Rect, color: Color) -> GameResult<()> { + let mut refs = self.refs.borrow_mut(); + + let (r, g, b, a) = color.to_rgba(); + + refs.canvas.set_draw_color(pixels::Color::RGBA(r, g, b, a)); + refs.canvas + .fill_rect(sdl2::rect::Rect::new( + rect.left as i32, + rect.top as i32, + rect.width() as u32, + rect.height() as u32, + )) + .map_err(|e| GameError::RenderError(e.to_string()))?; + + Ok(()) + } + + fn draw_outline_rect(&mut self, rect: Rect, line_width: usize, color: Color) -> GameResult<()> { + let mut refs = self.refs.borrow_mut(); + + let (r, g, b, a) = color.to_rgba(); + + refs.canvas.set_draw_color(pixels::Color::RGBA(r, g, b, a)); + + match line_width { + 0 => {} // no-op + 1 => { + refs.canvas + .draw_rect(sdl2::rect::Rect::new( + rect.left as i32, + rect.top as i32, + rect.width() as u32, + rect.height() as u32, + )) + .map_err(|e| GameError::RenderError(e.to_string()))?; + } + _ => { + let rects = [ + sdl2::rect::Rect::new(rect.left as i32, rect.top as i32, rect.width() as u32, line_width as u32), + sdl2::rect::Rect::new( + rect.left as i32, + rect.bottom as i32 - line_width as i32, + rect.width() as u32, + line_width as u32, + ), + sdl2::rect::Rect::new(rect.left as i32, rect.top as i32, line_width as u32, rect.height() as u32), + sdl2::rect::Rect::new( + rect.right as i32 - line_width as i32, + rect.top as i32, + line_width as u32, + rect.height() as u32, + ), + ]; + + refs.canvas.fill_rects(&rects).map_err(|e| GameError::RenderError(e.to_string()))?; + } + } + + Ok(()) + } + fn imgui(&self) -> GameResult<&mut imgui::Context> { unsafe { Ok(&mut *self.imgui.as_ptr()) } } @@ -435,12 +468,12 @@ impl BackendRenderer for SDL2Renderer { continue; } - let v1 = draw_list.vtx_buffer()[cmd_params.vtx_offset - + idx_buffer[cmd_params.idx_offset + i] as usize]; - let v2 = draw_list.vtx_buffer()[cmd_params.vtx_offset - + idx_buffer[cmd_params.idx_offset + i + 1] as usize]; - let v3 = draw_list.vtx_buffer()[cmd_params.vtx_offset - + idx_buffer[cmd_params.idx_offset + i + 2] as usize]; + let v1 = draw_list.vtx_buffer() + [cmd_params.vtx_offset + idx_buffer[cmd_params.idx_offset + i] as usize]; + let v2 = draw_list.vtx_buffer() + [cmd_params.vtx_offset + idx_buffer[cmd_params.idx_offset + i + 1] as usize]; + let v3 = draw_list.vtx_buffer() + [cmd_params.vtx_offset + idx_buffer[cmd_params.idx_offset + i + 2] as usize]; vert_x[0] = (v1.pos[0] - 0.5) as i16; vert_y[0] = (v1.pos[1] - 0.5) as i16; @@ -451,12 +484,12 @@ impl BackendRenderer for SDL2Renderer { #[allow(clippy::float_cmp)] if i < count - 3 { - let v4 = draw_list.vtx_buffer()[cmd_params.vtx_offset - + idx_buffer[cmd_params.idx_offset + i + 3] as usize]; - let v5 = draw_list.vtx_buffer()[cmd_params.vtx_offset - + idx_buffer[cmd_params.idx_offset + i + 4] as usize]; - let v6 = draw_list.vtx_buffer()[cmd_params.vtx_offset - + idx_buffer[cmd_params.idx_offset + i + 5] as usize]; + let v4 = draw_list.vtx_buffer() + [cmd_params.vtx_offset + idx_buffer[cmd_params.idx_offset + i + 3] as usize]; + let v5 = draw_list.vtx_buffer() + [cmd_params.vtx_offset + idx_buffer[cmd_params.idx_offset + i + 4] as usize]; + let v6 = draw_list.vtx_buffer() + [cmd_params.vtx_offset + idx_buffer[cmd_params.idx_offset + i + 5] as usize]; min[0] = min3(v1.pos[0], v2.pos[0], v3.pos[0]); min[1] = min3(v1.pos[1], v2.pos[1], v3.pos[1]); @@ -484,8 +517,7 @@ impl BackendRenderer for SDL2Renderer { } } - if let Some(surf) = self.imgui_textures.get_mut(&cmd_params.texture_id) - { + if let Some(surf) = self.imgui_textures.get_mut(&cmd_params.texture_id) { if is_rect { let src = sdl2::rect::Rect::new( (tex_pos[0] * surf.width as f32) as i32, @@ -525,9 +557,7 @@ impl BackendRenderer for SDL2Renderer { refs.canvas.set_clip_rect(None); } DrawCmd::ResetRenderState => {} - DrawCmd::RawCallback { callback, raw_cmd } => unsafe { - callback(draw_list.raw(), raw_cmd) - }, + DrawCmd::RawCallback { callback, raw_cmd } => unsafe { callback(draw_list.raw(), raw_cmd) }, } } } @@ -861,21 +891,14 @@ impl ImguiSdl2 { imgui.io_mut().key_map[Key::Y as usize] = Scancode::Y as u32; imgui.io_mut().key_map[Key::Z as usize] = Scancode::Z as u32; - Self { - mouse_press: [false; 5], - ignore_keyboard: false, - ignore_mouse: false, - cursor: None, - sdl_cursor: None, - } + Self { mouse_press: [false; 5], ignore_keyboard: false, ignore_mouse: false, cursor: None, sdl_cursor: None } } pub fn ignore_event(&self, event: &Event) -> bool { match *event { - Event::KeyDown { .. } - | Event::KeyUp { .. } - | Event::TextEditing { .. } - | Event::TextInput { .. } => self.ignore_keyboard, + Event::KeyDown { .. } | Event::KeyUp { .. } | Event::TextEditing { .. } | Event::TextInput { .. } => { + self.ignore_keyboard + } Event::MouseMotion { .. } | Event::MouseButtonDown { .. } | Event::MouseButtonUp { .. } @@ -928,17 +951,13 @@ impl ImguiSdl2 { imgui.io_mut().add_input_character(chr); } } - Event::KeyDown { - scancode, keymod, .. - } => { + Event::KeyDown { scancode, keymod, .. } => { set_mod(imgui, keymod); if let Some(scancode) = scancode { imgui.io_mut().keys_down[scancode as usize] = true; } } - Event::KeyUp { - scancode, keymod, .. - } => { + Event::KeyUp { scancode, keymod, .. } => { set_mod(imgui, keymod); if let Some(scancode) = scancode { imgui.io_mut().keys_down[scancode as usize] = false; @@ -960,10 +979,7 @@ impl ImguiSdl2 { let (draw_w, draw_h) = window.drawable_size(); io.display_size = [win_w as f32, win_h as f32]; - io.display_framebuffer_scale = [ - (draw_w as f32) / (win_w as f32), - (draw_h as f32) / (win_h as f32), - ]; + io.display_framebuffer_scale = [(draw_w as f32) / (win_w as f32), (draw_h as f32) / (win_h as f32)]; // Merging the mousedown events we received into the current state prevents us from missing // clicks that happen faster than a frame @@ -987,10 +1003,7 @@ impl ImguiSdl2 { pub fn prepare_render(&mut self, ui: &imgui::Ui, window: &sdl2::video::Window) { let io = ui.io(); - if !io - .config_flags - .contains(ConfigFlags::NO_MOUSE_CURSOR_CHANGE) - { + if !io.config_flags.contains(ConfigFlags::NO_MOUSE_CURSOR_CHANGE) { let mouse_util = window.subsystem().sdl().mouse(); match ui.mouse_cursor() { diff --git a/src/framework/graphics.rs b/src/framework/graphics.rs index 57f3070..9dbd845 100644 --- a/src/framework/graphics.rs +++ b/src/framework/graphics.rs @@ -1,4 +1,4 @@ -use crate::common::Color; +use crate::common::{Color, Rect}; use crate::framework::context::Context; use crate::framework::error::{GameResult, GameError}; use crate::framework::backend::BackendTexture; @@ -76,6 +76,22 @@ pub fn set_blend_mode(ctx: &mut Context, blend: BlendMode) -> GameResult { Err(GameError::RenderError("Rendering backend hasn't been initialized yet.".to_string())) } +pub fn draw_rect(ctx: &mut Context, rect: Rect, color: Color) -> GameResult { + if let Some(renderer) = ctx.renderer.as_mut() { + return renderer.draw_rect(rect, color); + } + + Err(GameError::RenderError("Rendering backend hasn't been initialized yet.".to_string())) +} + +pub fn draw_outline_rect(ctx: &mut Context, rect: Rect, line_width: usize, color: Color) -> GameResult { + if let Some(renderer) = ctx.renderer.as_mut() { + return renderer.draw_outline_rect(rect, line_width, color); + } + + Ok(()) +} + pub fn imgui_context(ctx: &Context) -> GameResult<&mut imgui::Context> { if let Some(renderer) = ctx.renderer.as_ref() { return renderer.imgui(); diff --git a/src/texture_set.rs b/src/texture_set.rs index 4149838..9b9976a 100644 --- a/src/texture_set.rs +++ b/src/texture_set.rs @@ -289,12 +289,4 @@ impl TextureSet { Ok(self.tex_map.get_mut(name).unwrap()) } - - pub fn draw_rect(&self, rect: common::Rect, color: [f32; 4], ctx: &mut Context) -> GameResult { - Ok(()) - } - - pub fn draw_outline_rect(&self, rect: common::Rect, width: f32, color: [f32; 4], ctx: &mut Context) -> GameResult { - Ok(()) - } }