veloren_voxygen/ui/widgets/
ingame.rs

1use conrod_core::{Position, Sizeable, Ui, UiCell, Widget, WidgetCommon, widget};
2use vek::*;
3
4#[derive(Clone, WidgetCommon)]
5pub struct Ingame<W> {
6    #[conrod(common_builder)]
7    common: widget::CommonBuilder,
8    widget: W,
9    prim_num: usize,
10    pos: Vec3<f32>,
11}
12
13pub trait Ingameable: Widget + Sized {
14    fn prim_count(&self) -> usize;
15    // Note this is not responsible for the 3d positioning
16    // Only call this directly if using IngameAnchor
17    fn set_ingame(self, id: widget::Id, ui: &mut UiCell) -> Self::Event {
18        self
19            // should pass focus to the window if these are clicked
20            // (they are not displayed where conrod thinks they are)
21            .graphics_for(ui.window)
22            .set(id, ui)
23    }
24    fn position_ingame(self, pos: Vec3<f32>) -> Ingame<Self> { Ingame::new(pos, self) }
25}
26
27pub trait PrimitiveMarker {}
28impl PrimitiveMarker for widget::Line {}
29impl PrimitiveMarker for widget::Image {}
30impl<I> PrimitiveMarker for widget::PointPath<I> {}
31impl PrimitiveMarker for widget::Circle {}
32impl<S> PrimitiveMarker for widget::Oval<S> {}
33impl<I> PrimitiveMarker for widget::Polygon<I> {}
34impl PrimitiveMarker for widget::Rectangle {}
35impl<S, I> PrimitiveMarker for widget::Triangles<S, I> {}
36impl PrimitiveMarker for widget::Text<'_> {}
37
38impl<P> Ingameable for P
39where
40    P: Widget + PrimitiveMarker,
41{
42    fn prim_count(&self) -> usize { 1 }
43}
44
45// All ingame widgets are now fixed scale
46#[derive(Copy, Clone, PartialEq)]
47pub struct IngameParameters {
48    // Number of primitive widgets to position in the game at the specified position
49    // Note this could be more than the number of widgets in the widgets field since widgets can
50    // contain widgets
51    pub num: usize,
52    pub pos: Vec3<f32>,
53    pub dims: Vec2<f32>,
54}
55
56pub struct State {
57    id: widget::Id,
58    pub parameters: IngameParameters,
59}
60
61pub type Style = ();
62
63impl<W: Ingameable> Ingame<W> {
64    pub fn new(pos: Vec3<f32>, widget: W) -> Self {
65        Self {
66            common: widget::CommonBuilder::default(),
67            prim_num: widget.prim_count(),
68            pos,
69            widget,
70        }
71    }
72}
73
74impl<W: Ingameable> Widget for Ingame<W> {
75    type Event = W::Event;
76    type State = State;
77    type Style = Style;
78
79    fn init_state(&self, mut id_gen: widget::id::Generator) -> Self::State {
80        State {
81            id: id_gen.next(),
82            parameters: IngameParameters {
83                num: self.prim_num,
84                pos: self.pos,
85                dims: Vec2::zero(),
86            },
87        }
88    }
89
90    fn style(&self) -> Self::Style {}
91
92    fn update(self, args: widget::UpdateArgs<Self>) -> Self::Event {
93        let widget::UpdateArgs { state, ui, .. } = args;
94        let Ingame {
95            widget,
96            prim_num,
97            pos,
98            ..
99        } = self;
100
101        let parameters = IngameParameters {
102            num: prim_num,
103            pos,
104            dims: Vec2::<f64>::from(widget.get_wh(ui).unwrap_or([1.0, 1.0])).map(|e| e as f32),
105        };
106
107        // Update parameters if it has changed
108        if state.parameters != parameters {
109            state.update(|s| {
110                s.parameters = parameters;
111            });
112        }
113
114        widget.set_ingame(state.id, ui)
115    }
116
117    fn default_x_position(&self, _: &Ui) -> Position { Position::Absolute(0.0) }
118
119    fn default_y_position(&self, _: &Ui) -> Position { Position::Absolute(0.0) }
120}