//! The sidebar showing all tools available to the user. This toolbar handles changing the active tool //! based on the mouse input and (TODO!) keyboard inputs. // TODO: Currently, the keyboard shortcuts for tools are handled by the editor, but a lot speaks for // them being handled by the ToolSidebar instead. use crate::client::input::Input; use crate::client::tool::ToolType; use crate::client::Editor; use crate::math::Rect; use raylib::core::texture::Texture2D; use raylib::rgui::RaylibDrawGui; use raylib::{RaylibHandle, RaylibThread}; use std::mem; /// The file containing textures for all buttons describing the tools. pub const BUTTON_FILE: &str = "assets/button/tool_buttons.png"; /// Sidebar that renders and handles input for the tool activation buttons. pub struct ToolSidebar { button_texture: Texture2D, bindings_id: usize, panel_rect: Rect, } impl ToolSidebar { /// Create a new tool sidebar. There should be only one sidebar per program instance. pub fn new(rl: &mut RaylibHandle, rlt: &RaylibThread, input: &mut Input) -> Self { let button_texture = rl .load_texture(rlt, BUTTON_FILE) .expect("Could not read file containing tool icons."); let panel_rect = Self::panel_rect(rl.get_screen_height() as u16); let bindings_id = input.add_local_handler(panel_rect.clone()); Self { button_texture, bindings_id, panel_rect, } } fn panel_rect(screen_height: u16) -> Rect { /* The width is currently hardcoded as 104, which is * 64 (button-size) + 20 left gap + 20 right gap */ Rect::new(0, 0, 104, screen_height) } /// Update the state of the tool sidebar. Due to raylib limitations, this is not where the tools /// are selected for the editor, which happens in draw. pub fn update(&mut self, screen_height: u16, input: &mut Input) { let new_panel_rect = Self::panel_rect(screen_height); if new_panel_rect != self.panel_rect { self.panel_rect = new_panel_rect; input.set_binding_rect(self.bindings_id, self.panel_rect); } } /// Draw the tool buttons and encasing panel. Because of the way raylib works, this also handles /// clicking on tool buttons, which may be changed in the future, should a different gui be /// chosen. pub fn draw(&self, rld: &mut impl RaylibDrawGui, editor: &mut Editor) { rld.gui_panel(Rect::new( self.panel_rect.x as f32, self.panel_rect.y as f32, self.panel_rect.w as f32, self.panel_rect.h as f32, )); // TODO: Update to new input system. Create buttons that integrate. let mut active = editor.active(); for i in 0..ToolType::NumTools as usize { let is_current_active = active as usize == i; if rld.gui_image_button_ex( Rect::new(20., i as f32 * 100. + 20., 64., 64.), None, &self.button_texture, Rect::new( is_current_active as u8 as f32 * 64., i as f32 * 64., 64., 64., ), ) { active = unsafe { mem::transmute(i as u8) }; } } editor.set_active(active); } }