diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 47a17540..f5bc5030 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,4 +1,4 @@ -name: Rust + name: Rust on: pull_request: diff --git a/demo/src/plugins.rs b/demo/src/plugins.rs index f7a6a665..477f4e0f 100644 --- a/demo/src/plugins.rs +++ b/demo/src/plugins.rs @@ -1,4 +1,4 @@ -use egui::{Color32, Painter, Response}; +use egui::{Color32, Response, Ui}; use walkers::{ extras::{Image, Images, Place, Places, Style, Texture}, Plugin, Position, Projector, @@ -57,7 +57,7 @@ pub fn images(images_plugin_data: &mut ImagesPluginData) -> impl Plugin { pub struct CustomShapes {} impl Plugin for CustomShapes { - fn run(&mut self, response: &Response, painter: Painter, projector: &Projector) { + fn run(self: Box, ui: &mut Ui, response: &Response, projector: &Projector) { // Position of the point we want to put our shapes. let position = places::capitol(); @@ -66,12 +66,13 @@ impl Plugin for CustomShapes { let radius = 30.; + let hovered = response .hover_pos() .map(|hover_pos| hover_pos.distance(position) < radius) .unwrap_or(false); - painter.circle_filled( + ui.painter().circle_filled( position, radius, Color32::BLACK.gamma_multiply(if hovered { 0.5 } else { 0.2 }), @@ -101,7 +102,7 @@ impl ClickWatcher { } impl Plugin for &mut ClickWatcher { - fn run(&mut self, response: &Response, painter: Painter, projector: &Projector) { + fn run(self: Box, ui: &mut Ui, response: &Response, projector: &Projector) { if !response.changed() && response.clicked_by(egui::PointerButton::Primary) { self.clicked_at = response .interact_pointer_pos() @@ -109,7 +110,7 @@ impl Plugin for &mut ClickWatcher { } if let Some(position) = self.clicked_at { - painter.circle_filled(projector.project(position).to_pos2(), 5.0, Color32::BLUE); + ui.painter().circle_filled(projector.project(position).to_pos2(), 5.0, Color32::BLUE); } } } diff --git a/walkers/src/extras/images.rs b/walkers/src/extras/images.rs index c3f2a448..f5440aa4 100644 --- a/walkers/src/extras/images.rs +++ b/walkers/src/extras/images.rs @@ -1,7 +1,6 @@ -use crate::tiles::Texture; -use crate::{Plugin, Position}; -use egui::epaint::emath::Rot2; -use egui::{Painter, Rect, Response, Vec2}; +use egui::{Rect, Ui, Vec2, emath::Rot2, Response}; + +use crate::{Plugin, Position, tiles::Texture}; /// An image to be drawn on the map. pub struct Image { @@ -34,7 +33,8 @@ impl Image { self.angle = Rot2::from_angle(angle); } - pub fn draw(&self, _response: &Response, painter: Painter, projector: &crate::Projector) { + pub fn draw(&self, ui: &Ui, projector: &crate::Projector) { + let painter = ui.painter(); let rect = Rect::from_center_size( projector.project(self.position).to_pos2(), self.texture.size() * self.scale, @@ -60,9 +60,9 @@ impl Images { } impl Plugin for Images { - fn run(&mut self, response: &Response, painter: Painter, projector: &crate::Projector) { + fn run(self: Box, ui: &mut Ui, _response: &Response, projector: &crate::Projector) { for image in &self.images { - image.draw(response, painter.clone(), projector); + image.draw(ui, projector); } } } diff --git a/walkers/src/extras/places.rs b/walkers/src/extras/places.rs index b7359177..45919f76 100644 --- a/walkers/src/extras/places.rs +++ b/walkers/src/extras/places.rs @@ -1,4 +1,4 @@ -use egui::{vec2, Align2, Color32, FontId, Painter, Response, Stroke}; +use egui::{vec2, Align2, Color32, FontId, Ui, Stroke, Response}; use crate::{Plugin, Position}; @@ -45,8 +45,9 @@ pub struct Place { } impl Place { - fn draw(&self, _response: &Response, painter: Painter, projector: &crate::Projector) { + fn draw(&self, ui: &Ui, projector: &crate::Projector) { let screen_position = projector.project(self.position); + let painter = ui.painter(); let label = painter.layout_no_wrap( self.label.to_owned(), @@ -70,7 +71,7 @@ impl Place { painter.galley( (screen_position + offset).to_pos2(), label, - egui::Color32::BLACK, + Color32::BLACK, ); painter.circle( @@ -102,9 +103,9 @@ impl Places { } impl Plugin for Places { - fn run(&mut self, response: &Response, painter: Painter, projector: &crate::Projector) { + fn run(self: Box, ui: &mut Ui, _response: &Response, projector: &crate::Projector) { for place in &self.places { - place.draw(response, painter.clone(), projector); + place.draw(ui, projector); } } } diff --git a/walkers/src/map.rs b/walkers/src/map.rs index 528b85f4..5770023e 100644 --- a/walkers/src/map.rs +++ b/walkers/src/map.rs @@ -1,6 +1,6 @@ use std::collections::{hash_map::Entry, HashMap}; -use egui::{Mesh, Painter, Rect, Response, Sense, Ui, Vec2, Widget}; +use egui::{Mesh, Rect, Response, Sense, Ui, UiBuilder, Vec2, Widget}; use crate::{ center::Center, @@ -14,7 +14,15 @@ use crate::{ /// you can add it to the map with [`Map::with_plugin`] pub trait Plugin { /// Function called at each frame. - fn run(&mut self, response: &Response, painter: Painter, projector: &Projector); + /// + /// The provided [`Ui`] has its [`egui::Ui::max_rect`] set to the full rect that was allocated + /// by the map widget. Implementations should typically use the provided [`Projector`] to + /// compute target screen coordinates and use one of the various egui methods to draw at these + /// coordinates instead of relying on [`egui:Ui`] layout system. + /// + /// The provided [`Response`] is the response of the map widget itself and can be used to test + /// if the mouse is hovering or clicking on the map. + fn run(self: Box, ui: &mut Ui, response: &Response, projector: &Projector); } /// The actual map widget. Instances are to be created on each frame, as all necessary state is @@ -223,10 +231,10 @@ impl Widget for Map<'_, '_, '_> { } } - for mut plugin in self.plugins { - let projector = Projector::new(response.rect, self.memory, self.my_position); - - plugin.run(&response, painter.to_owned(), &projector); + let projector = Projector::new(response.rect, self.memory, self.my_position); + for (idx, plugin) in self.plugins.into_iter().enumerate() { + let mut child_ui = ui.new_child(UiBuilder::new().max_rect(rect).id_salt(idx)); + plugin.run(&mut child_ui, &response, &projector); } response