rg3d_ui/vec/
vec4.rs

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