Skip to main content

NodeTemplate

Trait NodeTemplate 

Source
pub trait NodeTemplate {
    // Required methods
    fn node_ui(
        &self,
        ui: &mut Ui,
        _viewport_point: Pos2,
        _zoom: f32,
        _system: &MapPoint,
    );
    fn selection_ui(&self, ui: &mut Ui, _viewport_point: Pos2, _zoom: f32);
    fn notification_ui(
        &self,
        ui: &mut Ui,
        _viewport_point: Pos2,
        _zoom: f32,
        initial_time: Instant,
        color: Color32,
    ) -> bool;
    fn marker_ui(&self, ui: &mut Ui, _viewport_point: 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, point: Pos2, zoom: f32, system: &MapPoint) {
        // Multiply every size by `zoom` so the node scales with the map.
        let rect = Rect::from_center_size(point, 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(
            point,
            Align2::CENTER_CENTER,
            system.get_name(),
            FontId::proportional(12.0 * zoom),
            Color32::WHITE,
        );
    }

    fn notification_ui(
        &self,
        ui: &mut Ui,
        point: 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(point, 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§

Source

fn node_ui( &self, ui: &mut Ui, _viewport_point: Pos2, _zoom: f32, _system: &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.

Source

fn selection_ui(&self, ui: &mut Ui, _viewport_point: 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.

Source

fn notification_ui( &self, ui: &mut Ui, _viewport_point: 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.

Source

fn marker_ui(&self, ui: &mut Ui, _viewport_point: 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".

Implementors§