rg3d_ui/vec/
vec3.rs

1use crate::{
2    core::{algebra::Vector3, color::Color, pool::Handle},
3    define_constructor,
4    grid::{Column, GridBuilder, Row},
5    message::{MessageDirection, UiMessage},
6    numeric::{NumericType, NumericUpDownMessage},
7    vec::{make_mark, make_numeric_input},
8    BuildContext, Control, NodeHandleMapping, UiNode, UserInterface, Widget, WidgetBuilder,
9};
10use std::{
11    any::{Any, TypeId},
12    ops::{Deref, DerefMut},
13};
14
15#[derive(Debug, Clone, PartialEq)]
16pub enum Vec3EditorMessage<T: NumericType> {
17    Value(Vector3<T>),
18}
19
20impl<T: NumericType> Vec3EditorMessage<T> {
21    define_constructor!(Vec3EditorMessage:Value => fn value(Vector3<T>), layout: false);
22}
23
24#[derive(Clone)]
25pub struct Vec3Editor<T: NumericType> {
26    widget: Widget,
27    x_field: Handle<UiNode>,
28    y_field: Handle<UiNode>,
29    z_field: Handle<UiNode>,
30    value: Vector3<T>,
31}
32
33impl<T: NumericType> Deref for Vec3Editor<T> {
34    type Target = Widget;
35
36    fn deref(&self) -> &Self::Target {
37        &self.widget
38    }
39}
40
41impl<T: NumericType> DerefMut for Vec3Editor<T> {
42    fn deref_mut(&mut self) -> &mut Self::Target {
43        &mut self.widget
44    }
45}
46
47impl<T: NumericType> Control for Vec3Editor<T> {
48    fn query_component(&self, type_id: TypeId) -> Option<&dyn Any> {
49        if type_id == TypeId::of::<Self>() {
50            Some(self)
51        } else {
52            None
53        }
54    }
55
56    fn resolve(&mut self, node_map: &NodeHandleMapping) {
57        node_map.resolve(&mut self.x_field);
58        node_map.resolve(&mut self.y_field);
59        node_map.resolve(&mut self.z_field);
60    }
61
62    fn handle_routed_message(&mut self, ui: &mut UserInterface, message: &mut UiMessage) {
63        self.widget.handle_routed_message(ui, message);
64
65        if let Some(&NumericUpDownMessage::Value(value)) = message.data::<NumericUpDownMessage<T>>()
66        {
67            if message.direction() == MessageDirection::FromWidget {
68                if message.destination() == self.x_field {
69                    ui.send_message(Vec3EditorMessage::value(
70                        self.handle(),
71                        MessageDirection::ToWidget,
72                        Vector3::new(value, self.value.y, self.value.z),
73                    ));
74                } else if message.destination() == self.y_field {
75                    ui.send_message(Vec3EditorMessage::value(
76                        self.handle(),
77                        MessageDirection::ToWidget,
78                        Vector3::new(self.value.x, value, self.value.z),
79                    ));
80                } else if message.destination() == self.z_field {
81                    ui.send_message(Vec3EditorMessage::value(
82                        self.handle(),
83                        MessageDirection::ToWidget,
84                        Vector3::new(self.value.x, self.value.y, value),
85                    ));
86                }
87            }
88        } else if let Some(&Vec3EditorMessage::Value(value)) =
89            message.data::<Vec3EditorMessage<T>>()
90        {
91            if message.direction() == MessageDirection::ToWidget {
92                let mut changed = false;
93                if self.value.x != value.x {
94                    self.value.x = value.x;
95                    ui.send_message(NumericUpDownMessage::value(
96                        self.x_field,
97                        MessageDirection::ToWidget,
98                        value.x,
99                    ));
100                    changed = true;
101                }
102                if self.value.y != value.y {
103                    self.value.y = value.y;
104                    ui.send_message(NumericUpDownMessage::value(
105                        self.y_field,
106                        MessageDirection::ToWidget,
107                        value.y,
108                    ));
109                    changed = true;
110                }
111                if self.value.z != value.z {
112                    self.value.z = value.z;
113                    ui.send_message(NumericUpDownMessage::value(
114                        self.z_field,
115                        MessageDirection::ToWidget,
116                        value.z,
117                    ));
118                    changed = true;
119                }
120                if changed {
121                    ui.send_message(message.reverse());
122                }
123            }
124        }
125    }
126}
127
128pub struct Vec3EditorBuilder<T: NumericType> {
129    widget_builder: WidgetBuilder,
130    value: Vector3<T>,
131}
132
133impl<T: NumericType> Vec3EditorBuilder<T> {
134    pub fn new(widget_builder: WidgetBuilder) -> Self {
135        Self {
136            widget_builder,
137            value: Vector3::new(T::zero(), T::zero(), T::zero()),
138        }
139    }
140
141    pub fn with_value(mut self, value: Vector3<T>) -> Self {
142        self.value = value;
143        self
144    }
145
146    pub fn build(self, ctx: &mut BuildContext) -> Handle<UiNode> {
147        let x_field;
148        let y_field;
149        let z_field;
150        let grid = GridBuilder::new(
151            WidgetBuilder::new()
152                .with_child(make_mark(ctx, "X", 0, Color::opaque(120, 0, 0)))
153                .with_child({
154                    x_field = make_numeric_input(ctx, 1, self.value.x);
155                    x_field
156                })
157                .with_child(make_mark(ctx, "Y", 2, Color::opaque(0, 120, 0)))
158                .with_child({
159                    y_field = make_numeric_input(ctx, 3, self.value.y);
160                    y_field
161                })
162                .with_child(make_mark(ctx, "Z", 4, Color::opaque(0, 0, 120)))
163                .with_child({
164                    z_field = make_numeric_input(ctx, 5, self.value.z);
165                    z_field
166                }),
167        )
168        .add_row(Row::stretch())
169        .add_column(Column::auto())
170        .add_column(Column::stretch())
171        .add_column(Column::auto())
172        .add_column(Column::stretch())
173        .add_column(Column::auto())
174        .add_column(Column::stretch())
175        .build(ctx);
176
177        let node = Vec3Editor {
178            widget: self.widget_builder.with_child(grid).build(),
179            x_field,
180            y_field,
181            z_field,
182            value: self.value,
183        };
184
185        ctx.add_node(UiNode::new(node))
186    }
187}