library

Online co-op book organization video game
git clone https://git.bradleygannon.com/library.git
Log | Files | Refs

commit 2e3361408c34945f3a8b0a3be9854f7716f87d52
parent 19f210b2ade5aa6bb0b39655dd6a7702c80bb57b
Author: Bradley Gannon <bradley@bradleygannon.com>
Date:   Wed,  9 Sep 2026 17:27:08 -0400

Highlight moused-over book slot and show popup for that book if present

Diffstat:
Mclient/src/input.rs | 2+-
Mclient/src/render.rs | 142++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
Mcommon/src/game/book.rs | 6++++++
3 files changed, 100 insertions(+), 50 deletions(-)

diff --git a/client/src/input.rs b/client/src/input.rs @@ -70,7 +70,7 @@ pub(crate) fn handle_drop_book_input( } } -fn get_bookshelf_mouse_address( +pub(crate) fn get_bookshelf_mouse_address( camera: &Camera, bookshelves: &HashMap<BookshelfId, Bookshelf>, ) -> Option<SlotAddress> { diff --git a/client/src/render.rs b/client/src/render.rs @@ -1,8 +1,8 @@ -use common::game::book::{BOOKS, Bookshelf, Slot}; +use common::game::book::{BOOKS, BookId, Bookshelf, Slot}; use lazy_static::lazy_static; use macroquad::prelude::*; -use crate::ClientState; +use crate::{ClientState, input::get_bookshelf_mouse_address}; lazy_static! { pub(crate) static ref SPRITESHEET: Spritesheet = Spritesheet::load(); @@ -87,8 +87,9 @@ impl ClientState { if let Some(local_player_id) = self.local_player_id && let Some(local_player) = self.interpolated_game.get_player(&local_player_id) { + let mouse_slot = get_bookshelf_mouse_address(&self.camera, self.game.bookshelves()); // Render bookshelves - for bookshelf in self.interpolated_game.bookshelves().values() { + for (bookshelf_id, bookshelf) in self.interpolated_game.bookshelves() { const BOOKSHELF_BACKGROUND: Color = BROWN; const BOOKSHELF_FRAME: Color = DARKBROWN; let bounds: Rect = bookshelf.rect().offset(-self.camera.position); @@ -127,26 +128,63 @@ impl ClientState { * (Bookshelf::BOOK_HEIGHT + Bookshelf::SHELF_THICKNESS) - Bookshelf::FRAME_THICKNESS; for (slot_index, slot) in shelf.iter().enumerate() { - if let Slot::Book { .. } = slot { - let x = bounds.x - + Bookshelf::FRAME_THICKNESS - + slot_index as f32 * Bookshelf::BOOK_WIDTH; - draw_line(x, y, x, y + Bookshelf::BOOK_HEIGHT, 2., BLACK); - draw_rectangle( - x, - y, - Bookshelf::BOOK_WIDTH, - Bookshelf::BOOK_HEIGHT, - BLUE, - ); - draw_line( - x + Bookshelf::BOOK_WIDTH, - y, - x + Bookshelf::BOOK_WIDTH, - y + Bookshelf::BOOK_HEIGHT, - 1., - BLACK, - ); + let x = bounds.x + + Bookshelf::FRAME_THICKNESS + + slot_index as f32 * Bookshelf::BOOK_WIDTH; + match slot { + Slot::Book { book_id } => { + draw_line(x, y, x, y + Bookshelf::BOOK_HEIGHT, 2., BLACK); + draw_rectangle( + x, + y, + Bookshelf::BOOK_WIDTH, + Bookshelf::BOOK_HEIGHT, + BLUE, + ); + draw_line( + x + Bookshelf::BOOK_WIDTH, + y, + x + Bookshelf::BOOK_WIDTH, + y + Bookshelf::BOOK_HEIGHT, + 1., + BLACK, + ); + if let Some(ms) = mouse_slot + && ms.bookshelf_id() == *bookshelf_id + && ms.shelf_index() == shelf_index + && ms.position() == slot_index + { + draw_rectangle( + x, + y, + Bookshelf::BOOK_WIDTH, + Bookshelf::BOOK_HEIGHT, + GOLD.with_alpha(0.5), + ); + self.draw_book_metadata_popup( + Vec2::new( + x - Bookshelf::BOOK_WIDTH / 2. + self.camera.position.x, + y + self.camera.position.y, + ), + book_id, + ); + } + } + Slot::Empty => { + if let Some(ms) = mouse_slot + && ms.bookshelf_id() == *bookshelf_id + && ms.shelf_index() == shelf_index + && ms.position() == slot_index + { + draw_rectangle( + x, + y, + Bookshelf::BOOK_WIDTH, + Bookshelf::BOOK_HEIGHT, + GOLD.with_alpha(0.5), + ); + } + } } } } @@ -193,31 +231,9 @@ impl ClientState { ) }) { - let text = if let Some(metadata) = BOOKS.get(&nearby_floor_book.id()) { - metadata.to_string() - } else { - "Unknown book".to_string() - }; - let font_size = 24.; - let text_dimensions = measure_text(&text, None, font_size as u16, 1.); - let padding = 4.; - let x = nearby_floor_book.position().x - self.camera.position.x; - let y = nearby_floor_book.position().y - self.camera.position.y - 16.; - let w = text_dimensions.width; - let h = text_dimensions.height; - draw_rectangle( - x - padding, - y - text_dimensions.offset_y - padding, - w + padding, - h + padding, - WHITE.with_alpha(0.5), - ); - draw_text(text, x, y, font_size, BLACK.with_alpha(0.5)); - draw_triangle( - Vec2::new(x + 4., y + 5.), - Vec2::new(x + 12., y + 13.), - Vec2::new(x + 20., y + 5.), - WHITE.with_alpha(0.5), + self.draw_book_metadata_popup( + nearby_floor_book.position(), + &nearby_floor_book.id(), ); } @@ -238,7 +254,7 @@ impl ClientState { // Render debug view if enabled if self.debug_view { draw_rectangle(0., 0., 284., 56., BLACK); - draw_text("Library Tech Demo 2026-09-07", 4., 16., 16., WHITE); + draw_text("Library Tech Demo 2026-09-09", 4., 16., 16., WHITE); draw_text(format!("fps {}", get_fps()), 4., 32., 16., WHITE); draw_text(format!("id {}", local_player_id), 4., 48., 16., WHITE); draw_text( @@ -265,4 +281,32 @@ impl ClientState { local_player.position() - screen_center + player_sprite.size / 2.; } } + fn draw_book_metadata_popup(&self, position: Vec2, book_id: &BookId) { + let text = if let Some(metadata) = BOOKS.get(book_id) { + metadata.to_string() + } else { + "Unknown book".to_string() + }; + let font_size = 24.; + let text_dimensions = measure_text(&text, None, font_size as u16, 1.); + let padding = 4.; + let x = position.x - self.camera.position.x; + let y = position.y - self.camera.position.y - 16.; + let w = text_dimensions.width; + let h = text_dimensions.height; + draw_rectangle( + x - padding, + y - text_dimensions.offset_y - padding, + w + padding, + h + padding, + WHITE.with_alpha(0.5), + ); + draw_text(text, x, y, font_size, BLACK.with_alpha(0.5)); + draw_triangle( + Vec2::new(x + 4., y + 5.), + Vec2::new(x + 12., y + 13.), + Vec2::new(x + 20., y + 5.), + WHITE.with_alpha(0.5), + ); + } } diff --git a/common/src/game/book.rs b/common/src/game/book.rs @@ -41,6 +41,12 @@ impl SlotAddress { pub fn bookshelf_id(&self) -> BookshelfId { self.bookshelf_id } + pub fn shelf_index(&self) -> usize { + self.shelf_index + } + pub fn position(&self) -> usize { + self.position + } } #[derive(