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}