pub trait NodeTemplate {
// Required methods
fn node_ui(
&self,
ui: &mut Ui,
_viewport_position: Pos2,
_zoom: f32,
_point: &MapPoint,
);
fn selection_ui(&self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32);
fn notification_ui(
&self,
ui: &mut Ui,
_viewport_position: Pos2,
_zoom: f32,
initial_time: Instant,
color: Color32,
) -> bool;
fn marker_ui(&self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32);
}Expand description
Customizes how nodes and their visual effects are rendered.
When a template is installed with
Map::set_node_template, the widget
delegates all node painting to it instead of using the built-in shapes and
animations — including the node name labels, so draw the name yourself in
NodeTemplate::node_ui if you need it.
The positions passed to these methods are in screen coordinates: already
scaled by zoom and translated to the viewport origin. Multiply every size
by zoom so your shapes scale together with the map.
§Animation idioms
egui only repaints on demand, so any method that animates (a blinking
marker, a fading notification, …) must call
ui.ctx().request_repaint() to keep the
frames coming. Time-driven effects are usually computed from
Instant::now() (see initial_time in
NodeTemplate::notification_ui) or from the system clock.
§Examples
A node drawn as a rounded box with its name inside, plus a notification animation that expands and fades out over two seconds:
use egui_map::map::objects::{MapPoint, NodeTemplate};
use egui::{Align2, Color32, CornerRadius, FontId, Pos2, Rect, Stroke, Ui, Vec2};
use std::time::Instant;
struct BoxedNodes;
impl NodeTemplate for BoxedNodes {
fn node_ui(&self, ui: &mut Ui, position: Pos2, zoom: f32, point: &MapPoint) {
// Multiply every size by `zoom` so the node scales with the map.
let rect = Rect::from_center_size(position, Vec2::new(90.0 * zoom, 35.0 * zoom));
let rounding = CornerRadius::same((10.0 * zoom) as u8);
let painter = ui.painter();
painter.rect_filled(rect, rounding, ui.visuals().extreme_bg_color);
painter.rect_stroke(
rect,
rounding,
Stroke::new(4.0 * zoom, Color32::WHITE),
egui::StrokeKind::Middle,
);
painter.text(
position,
Align2::CENTER_CENTER,
point.get_name(),
FontId::proportional(12.0 * zoom),
Color32::WHITE,
);
}
fn notification_ui(
&self,
ui: &mut Ui,
position: Pos2,
zoom: f32,
initial_time: Instant,
color: Color32,
) -> bool {
let secs = Instant::now().duration_since(initial_time).as_secs_f32();
// Expand the stroke and fade the color out over 2 seconds.
let alpha = (1.0 - secs / 2.0).clamp(0.0, 1.0);
let fading =
Color32::from_rgba_unmultiplied(color.r(), color.g(), color.b(), (255.0 * alpha) as u8);
let rect = Rect::from_center_size(position, Vec2::new(90.0 * zoom, 35.0 * zoom));
ui.painter().rect_stroke(
rect,
CornerRadius::same((10.0 * zoom) as u8),
Stroke::new((4.0 + 25.0 * secs) * zoom, fading),
egui::StrokeKind::Middle,
);
// Keep the animation frames coming.
ui.ctx().request_repaint();
// Returning `false` removes the notification.
secs < 2.0
}
}Required Methods§
Sourcefn node_ui(
&self,
ui: &mut Ui,
_viewport_position: Pos2,
_zoom: f32,
_point: &MapPoint,
)
fn node_ui( &self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32, _point: &MapPoint, )
Draws a node, replacing the default filled circle.
Called every frame for each visible node. The widget no longer draws
the node name once a template is installed, so render it here (e.g.
with Painter::text) if you need it.
Sourcefn selection_ui(&self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32)
fn selection_ui(&self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32)
Draws the highlight over the node closest to the mouse pointer.
The nearest node is only computed while the pointer is over the map and
MapSettings::node_text_visibility is VisibilitySetting::Hover.
Sourcefn notification_ui(
&self,
ui: &mut Ui,
_viewport_position: Pos2,
_zoom: f32,
initial_time: Instant,
color: Color32,
) -> bool
fn notification_ui( &self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32, initial_time: Instant, color: Color32, ) -> bool
Draws the notification effect of a node notified at initial_time.
Called every frame for each node passed to
Map::notify. Should return true while the
animation is still playing — remember to call
ui.ctx().request_repaint() —; once
it returns false the notification is discarded.
Sourcefn marker_ui(&self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32)
fn marker_ui(&self, ui: &mut Ui, _viewport_position: Pos2, _zoom: f32)
Draws a marker over the given node.
Called every frame for each marker registered with
Map::update_marker. For animated markers
(e.g. a blinking light), drive the effect from the system clock and
call ui.ctx().request_repaint().
Dyn Compatibility§
This trait is dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".