From f5ac8a9a4f845317a2cdfed81efee32a2ae9ff42 Mon Sep 17 00:00:00 2001 From: Jupeyy Date: Fri, 7 Feb 2025 14:57:14 +0100 Subject: [PATCH] Add indicator for tile selection size, range apply ratio, quad count, sound count. --- game/editor/src/editor_ui.rs | 1 + game/editor/src/tools/tile_layer/brush.rs | 78 ++++--- game/editor/src/ui/main_frame.rs | 2 + game/editor/src/ui/mod.rs | 1 + game/editor/src/ui/tool_overlays/mod.rs | 1 + .../editor/src/ui/tool_overlays/tile_brush.rs | 193 ++++++++++++++++++ 6 files changed, 246 insertions(+), 30 deletions(-) create mode 100644 game/editor/src/ui/tool_overlays/mod.rs create mode 100644 game/editor/src/ui/tool_overlays/tile_brush.rs diff --git a/game/editor/src/editor_ui.rs b/game/editor/src/editor_ui.rs index fedc9b9..d79b160 100644 --- a/game/editor/src/editor_ui.rs +++ b/game/editor/src/editor_ui.rs @@ -87,6 +87,7 @@ impl EditorUiRender { } pub fn render(&mut self, pipe: EditorUiRenderPipe) -> egui::PlatformOutput { + self.ui.load_monospace_fonts(); let mut needs_pointer = false; generic_ui_renderer::render( &self.backend_handle, diff --git a/game/editor/src/tools/tile_layer/brush.rs b/game/editor/src/tools/tile_layer/brush.rs index 13f500e..7e54db8 100644 --- a/game/editor/src/tools/tile_layer/brush.rs +++ b/game/editor/src/tools/tile_layer/brush.rs @@ -132,7 +132,7 @@ impl TileBrushTilePicker { } } -#[derive(Debug, Hiarc)] +#[derive(Debug, Hiarc, Clone, Copy)] pub struct TileBrushDownPos { pub world: vec2, pub ui: egui::Pos2, @@ -1408,6 +1408,49 @@ impl TileBrush { } } + pub fn selection_size(old: &vec2, cur: &vec2) -> (vec2, vec2, vec2, u16, u16) { + let pos_old = vec2::new( + (old.x / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, + (old.y / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, + ); + let pos_cur = vec2::new( + (cur.x / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, + (cur.y / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, + ); + let width = (pos_cur.x - pos_old.x).abs() as u16 + 1; + let height = (pos_cur.y - pos_old.y).abs() as u16 + 1; + let pos_min = vec2::new(pos_cur.x.min(pos_old.x), pos_cur.y.min(pos_old.y)); + + (pos_min, pos_old, pos_cur, width, height) + } + + pub fn pos_on_map( + map: &EditorMap, + ui_canvas: &UiCanvasSize, + canvas_handle: &GraphicsCanvasHandle, + pos: &egui::Pos2, + offset: &vec2, + parallax: &vec2, + ) -> vec2 { + let pos_on_map = ui_pos_to_world_pos( + canvas_handle, + ui_canvas, + map.groups.user.zoom, + vec2::new(pos.x, pos.y), + map.groups.user.pos.x, + map.groups.user.pos.y, + offset.x, + offset.y, + parallax.x, + parallax.y, + map.groups.user.parallax_aware_zoom, + ); + vec2::new( + (pos_on_map.x / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, + (pos_on_map.y / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, + ) + } + fn render_brush( &self, ui_canvas: &UiCanvasSize, @@ -1428,23 +1471,8 @@ impl TileBrush { let brush = self.brush.as_ref().unwrap(); let pos = current_pointer_pos; - let pos_on_map = ui_pos_to_world_pos( - canvas_handle, - ui_canvas, - map.groups.user.zoom, - vec2::new(pos.x, pos.y), - map.groups.user.pos.x, - map.groups.user.pos.y, - offset.x, - offset.y, - parallax.x, - parallax.y, - map.groups.user.parallax_aware_zoom, - ); - let pos_on_map = vec2::new( - (pos_on_map.x / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, - (pos_on_map.y / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, - ); + + let pos_on_map = Self::pos_on_map(map, ui_canvas, canvas_handle, pos, &offset, ¶llax); let pos = pos_on_map; let mut pos = vec2::new( pos.x - brush.negative_offset.x as f32 * TILE_VISUAL_SIZE, @@ -1468,17 +1496,8 @@ impl TileBrush { egui::Rect::from_min_max(pos, egui::pos2(pos.x + brush_size.x, pos.y + brush_size.y)); if let Some(TileBrushDownPos { world, .. }) = &self.shift_pointer_down_world_pos { - let pos_old = vec2::new( - (world.x / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, - (world.y / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, - ); - let pos_cur = vec2::new( - (pos_on_map.x / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, - (pos_on_map.y / TILE_VISUAL_SIZE).floor() * TILE_VISUAL_SIZE, - ); - let width = (pos_cur.x - pos_old.x).abs() as u16 + 1; - let height = (pos_cur.y - pos_old.y).abs() as u16 + 1; - let pos_min = vec2::new(pos_cur.x.min(pos_old.x), pos_cur.y.min(pos_old.y)); + let (pos_min, pos_old, pos_cur, width, height) = + Self::selection_size(world, &pos_on_map); let rect = egui::Rect::from_min_max( egui::pos2(pos_min.x, pos_min.y), @@ -1514,7 +1533,6 @@ impl TileBrush { brush, map, canvas_handle, - //map.groups.user.pos - pos_min, -vec2::new(pos_min.x, pos_min.y), layer.map(|layer| layer.get_or_fake_group_attr()), usvec2::new( diff --git a/game/editor/src/ui/main_frame.rs b/game/editor/src/ui/main_frame.rs index 587f9cf..ae3beb5 100644 --- a/game/editor/src/ui/main_frame.rs +++ b/game/editor/src/ui/main_frame.rs @@ -48,6 +48,8 @@ pub fn render(ui: &mut egui::Ui, pipe: &mut UiRenderPipe, ui_state: &m super::chat_panel::panel::render(ui, &mut pipe, ui_state); + super::tool_overlays::tile_brush::render(ui, &mut pipe); + if let NetworkState::Client(state) = tab.client.net_state() { match state { NetworkClientState::Connecting(to) => { diff --git a/game/editor/src/ui/mod.rs b/game/editor/src/ui/mod.rs index 1c8f7f5..be38422 100644 --- a/game/editor/src/ui/mod.rs +++ b/game/editor/src/ui/mod.rs @@ -11,6 +11,7 @@ pub mod main_frame; pub mod mapper_cursors; pub mod page; pub mod server_settings; +pub mod tool_overlays; pub mod top_menu; pub mod top_tabs; pub mod top_toolbar; diff --git a/game/editor/src/ui/tool_overlays/mod.rs b/game/editor/src/ui/tool_overlays/mod.rs new file mode 100644 index 0000000..d3b690e --- /dev/null +++ b/game/editor/src/ui/tool_overlays/mod.rs @@ -0,0 +1 @@ +pub mod tile_brush; diff --git a/game/editor/src/ui/tool_overlays/tile_brush.rs b/game/editor/src/ui/tool_overlays/tile_brush.rs new file mode 100644 index 0000000..c20380b --- /dev/null +++ b/game/editor/src/ui/tool_overlays/tile_brush.rs @@ -0,0 +1,193 @@ +use egui::{Color32, FontId, Shape}; +use ui_base::types::UiRenderPipe; + +use crate::{ + map::EditorMapInterface, + tools::{ + quad_layer::{self, selection::QuadPointerDownState}, + sound_layer, + tile_layer::brush::{TileBrush, TileBrushDownPos}, + tool::{ActiveTool, ActiveToolQuads, ActiveToolSounds, ActiveToolTiles}, + }, + ui::user_data::UserDataWithTab, +}; + +pub fn render(ui: &mut egui::Ui, pipe: &mut UiRenderPipe) { + let tools = &mut *pipe.user_data.tools; + + let pos = |ui_pos: egui::Pos2| { + ui.input(|i| { + i.pointer + .latest_pos() + .or(i.pointer.hover_pos()) + .or(i.pointer.interact_pos()) + }) + .unwrap_or(ui_pos) + }; + match tools.active_tool { + ActiveTool::Tiles(ty) => match ty { + ActiveToolTiles::Brush => { + let brush = &tools.tiles.brush; + let draw = |text: String, pointer_pos: &TileBrushDownPos| { + let pos = pos(pointer_pos.ui) - egui::vec2(0.0, 20.0); + // draw amount of tiles selected/drawn whatever + let bg = ui.painter().add(Shape::Noop); + let rect = ui.painter().text( + pos, + egui::Align2::CENTER_BOTTOM, + text, + FontId::monospace(24.0), + Color32::WHITE, + ); + ui.painter().set( + bg, + Shape::rect_filled(rect.expand(5.0), 5.0, Color32::from_black_alpha(125)), + ); + }; + if let Some(brush_tiles) = brush.brush.as_ref() { + if let Some(pointer_pos) = brush.pointer_down_world_pos { + draw( + format!("{}x{}", brush_tiles.w.get(), brush_tiles.h.get()), + &pointer_pos, + ); + } else if let Some(pointer_pos) = brush.shift_pointer_down_world_pos { + let layer = pipe.user_data.editor_tab.map.active_layer(); + let (offset, parallax) = if let Some(layer) = &layer { + layer.get_offset_and_parallax() + } else { + Default::default() + }; + let pos = pos(pointer_pos.ui); + let cur = TileBrush::pos_on_map( + &pipe.user_data.editor_tab.map, + &ui.ctx().screen_rect(), + pipe.user_data.canvas_handle, + &pos, + &offset, + ¶llax, + ); + let (_, _, _, width, height) = + TileBrush::selection_size(&pointer_pos.world, &cur); + draw( + format!( + "{}x{} - {:.2}x{:.2}", + width, + height, + (width as f64) / (brush_tiles.w.get() as f64), + (height as f64) / (brush_tiles.h.get() as f64), + ), + &pointer_pos, + ); + } + } + } + ActiveToolTiles::Selection => { + let selection = &tools.tiles.selection; + if let Some(range) = selection.range.as_ref() { + if let Some(pointer_pos) = &selection.pointer_down_state { + let pos = pos(pointer_pos.ui) - egui::vec2(0.0, 20.0); + // draw amount of tiles selected/drawn whatever + let bg = ui.painter().add(Shape::Noop); + let rect = ui.painter().text( + pos, + egui::Align2::CENTER_BOTTOM, + format!("{}x{}", range.w.get(), range.h.get()), + FontId::monospace(24.0), + Color32::WHITE, + ); + ui.painter().set( + bg, + Shape::rect_filled( + rect.expand(5.0), + 5.0, + Color32::from_black_alpha(125), + ), + ); + } + } + } + }, + ActiveTool::Quads(ty) => { + let count = match ty { + ActiveToolQuads::Brush => { + let selection = &tools.quads.brush; + if let Some(range) = selection.brush.as_ref() { + if let quad_layer::brush::QuadPointerDownState::Selection(pointer_pos) = + &selection.pointer_down_state + { + Some((range.quads.len(), *pointer_pos)) + } else { + None + } + } else { + None + } + } + ActiveToolQuads::Selection => { + let selection = &tools.quads.selection; + if let Some(range) = selection.range.as_ref() { + if let QuadPointerDownState::Selection(pointer_pos) = + &selection.pointer_down_state + { + Some((range.quads.len(), *pointer_pos)) + } else { + None + } + } else { + None + } + } + }; + if let Some((count, pointer_pos)) = count { + let pos = pos(egui::pos2(pointer_pos.x, pointer_pos.y)) - egui::vec2(0.0, 20.0); + // draw amount of tiles selected/drawn whatever + let bg = ui.painter().add(Shape::Noop); + let rect = ui.painter().text( + pos, + egui::Align2::CENTER_BOTTOM, + format!("{}x", count), + FontId::monospace(24.0), + Color32::WHITE, + ); + ui.painter().set( + bg, + Shape::rect_filled(rect.expand(5.0), 5.0, Color32::from_black_alpha(125)), + ); + } + } + ActiveTool::Sounds(ty) => { + let count = match ty { + ActiveToolSounds::Brush => { + let selection = &tools.sounds.brush; + if let Some(range) = selection.brush.as_ref() { + if let sound_layer::brush::SoundPointerDownState::Selection(pointer_pos) = + &selection.pointer_down_state + { + Some((range.sounds.len(), *pointer_pos)) + } else { + None + } + } else { + None + } + } + }; + if let Some((count, pointer_pos)) = count { + let pos = pos(egui::pos2(pointer_pos.x, pointer_pos.y)) - egui::vec2(0.0, 20.0); + // draw amount of tiles selected/drawn whatever + let bg = ui.painter().add(Shape::Noop); + let rect = ui.painter().text( + pos, + egui::Align2::CENTER_BOTTOM, + format!("{}x", count), + FontId::monospace(24.0), + Color32::WHITE, + ); + ui.painter().set( + bg, + Shape::rect_filled(rect.expand(5.0), 5.0, Color32::from_black_alpha(125)), + ); + } + } + } +}