Skip to main content

dear_node_editor/frame/
queries.rs

1use super::core::NodeEditorFrame;
2use super::validation::{assert_finite_f32, assert_finite_vec2};
3use crate::{LinkId, NodeId, PinId, from_vec2, sys, vec2};
4use dear_imgui_rs::MouseButton;
5
6impl<'ui> NodeEditorFrame<'ui> {
7    pub fn set_node_position(&self, node: NodeId, position: [f32; 2]) {
8        assert_finite_vec2("NodeEditorFrame::set_node_position()", "position", position);
9        unsafe { sys::dne_set_node_position(node.raw(), vec2(position)) };
10    }
11
12    pub fn node_position(&self, node: NodeId) -> [f32; 2] {
13        from_vec2(unsafe { sys::dne_get_node_position(node.raw()) })
14    }
15
16    pub fn node_size(&self, node: NodeId) -> [f32; 2] {
17        from_vec2(unsafe { sys::dne_get_node_size(node.raw()) })
18    }
19
20    pub fn set_node_z_position(&self, node: NodeId, z: f32) {
21        assert_finite_f32("NodeEditorFrame::set_node_z_position()", "z", z);
22        unsafe { sys::dne_set_node_z_position(node.raw(), z) };
23    }
24
25    pub fn node_z_position(&self, node: NodeId) -> f32 {
26        unsafe { sys::dne_get_node_z_position(node.raw()) }
27    }
28
29    pub fn restore_node_state(&self, node: NodeId) {
30        unsafe { sys::dne_restore_node_state(node.raw()) };
31    }
32
33    pub fn center_node_on_screen(&self, node: NodeId) {
34        unsafe { sys::dne_center_node_on_screen(node.raw()) };
35    }
36
37    pub fn navigate_to_content(&self, duration: f32) {
38        assert_finite_f32(
39            "NodeEditorFrame::navigate_to_content()",
40            "duration",
41            duration,
42        );
43        unsafe { sys::dne_navigate_to_content(duration) };
44    }
45
46    pub fn navigate_to_selection(&self, zoom_in: bool, duration: f32) {
47        assert_finite_f32(
48            "NodeEditorFrame::navigate_to_selection()",
49            "duration",
50            duration,
51        );
52        unsafe { sys::dne_navigate_to_selection(zoom_in, duration) };
53    }
54
55    pub fn is_active(&self) -> bool {
56        unsafe { sys::dne_is_active() }
57    }
58
59    pub fn has_selection_changed(&self) -> bool {
60        unsafe { sys::dne_has_selection_changed() }
61    }
62
63    pub fn selected_object_count(&self) -> usize {
64        unsafe { sys::dne_get_selected_object_count() }.max(0) as usize
65    }
66
67    pub fn selected_nodes(&self) -> Vec<NodeId> {
68        let count = self.selected_object_count();
69        collect_node_ids(count, |ptr, len| unsafe {
70            sys::dne_get_selected_nodes(ptr, len)
71        })
72    }
73
74    pub fn selected_links(&self) -> Vec<LinkId> {
75        let count = self.selected_object_count();
76        collect_link_ids(count, |ptr, len| unsafe {
77            sys::dne_get_selected_links(ptr, len)
78        })
79    }
80
81    pub fn is_node_selected(&self, node: NodeId) -> bool {
82        unsafe { sys::dne_is_node_selected(node.raw()) }
83    }
84
85    pub fn is_link_selected(&self, link: LinkId) -> bool {
86        unsafe { sys::dne_is_link_selected(link.raw()) }
87    }
88
89    pub fn clear_selection(&self) {
90        unsafe { sys::dne_clear_selection() };
91    }
92
93    pub fn select_node(&self, node: NodeId) {
94        unsafe { sys::dne_select_node(node.raw(), false) };
95    }
96
97    pub fn add_node_to_selection(&self, node: NodeId) {
98        unsafe { sys::dne_select_node(node.raw(), true) };
99    }
100
101    pub fn select_link(&self, link: LinkId) {
102        unsafe { sys::dne_select_link(link.raw(), false) };
103    }
104
105    pub fn add_link_to_selection(&self, link: LinkId) {
106        unsafe { sys::dne_select_link(link.raw(), true) };
107    }
108
109    pub fn deselect_node(&self, node: NodeId) {
110        unsafe { sys::dne_deselect_node(node.raw()) };
111    }
112
113    pub fn deselect_link(&self, link: LinkId) {
114        unsafe { sys::dne_deselect_link(link.raw()) };
115    }
116
117    pub fn delete_node(&self, node: NodeId) -> bool {
118        unsafe { sys::dne_delete_node(node.raw()) }
119    }
120
121    pub fn delete_link(&self, link: LinkId) -> bool {
122        unsafe { sys::dne_delete_link(link.raw()) }
123    }
124
125    pub fn node_has_any_links(&self, node: NodeId) -> bool {
126        unsafe { sys::dne_has_any_links_node(node.raw()) }
127    }
128
129    pub fn pin_has_any_links(&self, pin: PinId) -> bool {
130        unsafe { sys::dne_has_any_links_pin(pin.raw()) }
131    }
132
133    pub fn break_node_links(&self, node: NodeId) -> usize {
134        unsafe { sys::dne_break_links_node(node.raw()) }.max(0) as usize
135    }
136
137    pub fn break_pin_links(&self, pin: PinId) -> usize {
138        unsafe { sys::dne_break_links_pin(pin.raw()) }.max(0) as usize
139    }
140
141    pub fn hovered_node(&self) -> Option<NodeId> {
142        optional_id(NodeId, |ptr| unsafe { sys::dne_get_hovered_node(ptr) })
143    }
144
145    pub fn hovered_pin(&self) -> Option<PinId> {
146        optional_id(PinId, |ptr| unsafe { sys::dne_get_hovered_pin(ptr) })
147    }
148
149    pub fn hovered_link(&self) -> Option<LinkId> {
150        optional_id(LinkId, |ptr| unsafe { sys::dne_get_hovered_link(ptr) })
151    }
152
153    pub fn double_clicked_node(&self) -> Option<NodeId> {
154        optional_id(NodeId, |ptr| unsafe {
155            sys::dne_get_double_clicked_node(ptr)
156        })
157    }
158
159    pub fn double_clicked_pin(&self) -> Option<PinId> {
160        optional_id(PinId, |ptr| unsafe { sys::dne_get_double_clicked_pin(ptr) })
161    }
162
163    pub fn double_clicked_link(&self) -> Option<LinkId> {
164        optional_id(LinkId, |ptr| unsafe {
165            sys::dne_get_double_clicked_link(ptr)
166        })
167    }
168
169    pub fn show_node_context_menu(&self) -> Option<NodeId> {
170        optional_id(NodeId, |ptr| unsafe {
171            sys::dne_show_node_context_menu(ptr)
172        })
173    }
174
175    pub fn show_pin_context_menu(&self) -> Option<PinId> {
176        optional_id(PinId, |ptr| unsafe { sys::dne_show_pin_context_menu(ptr) })
177    }
178
179    pub fn show_link_context_menu(&self) -> Option<LinkId> {
180        optional_id(LinkId, |ptr| unsafe {
181            sys::dne_show_link_context_menu(ptr)
182        })
183    }
184
185    pub fn show_background_context_menu(&self) -> bool {
186        unsafe { sys::dne_show_background_context_menu() }
187    }
188
189    pub fn set_shortcuts_enabled(&self, enabled: bool) {
190        unsafe { sys::dne_enable_shortcuts(enabled) };
191    }
192
193    pub fn shortcuts_enabled(&self) -> bool {
194        unsafe { sys::dne_are_shortcuts_enabled() }
195    }
196
197    pub fn current_zoom(&self) -> f32 {
198        unsafe { sys::dne_get_current_zoom() }
199    }
200
201    pub fn is_background_clicked(&self) -> bool {
202        unsafe { sys::dne_is_background_clicked() }
203    }
204
205    pub fn is_background_double_clicked(&self) -> bool {
206        unsafe { sys::dne_is_background_double_clicked() }
207    }
208
209    pub fn background_click_button(&self) -> Option<MouseButton> {
210        mouse_button_from_index(unsafe { sys::dne_get_background_click_button_index() })
211    }
212
213    pub fn background_double_click_button(&self) -> Option<MouseButton> {
214        mouse_button_from_index(unsafe { sys::dne_get_background_double_click_button_index() })
215    }
216
217    pub fn link_pins(&self, link: LinkId) -> Option<(PinId, PinId)> {
218        let mut start = 0usize;
219        let mut end = 0usize;
220        unsafe { sys::dne_get_link_pins(link.raw(), &mut start, &mut end) }
221            .then_some((PinId(start), PinId(end)))
222    }
223
224    pub fn pin_had_any_links(&self, pin: PinId) -> bool {
225        unsafe { sys::dne_pin_had_any_links(pin.raw()) }
226    }
227
228    pub fn screen_size(&self) -> [f32; 2] {
229        from_vec2(unsafe { sys::dne_get_screen_size() })
230    }
231
232    pub fn screen_to_canvas(&self, pos: [f32; 2]) -> [f32; 2] {
233        assert_finite_vec2("NodeEditorFrame::screen_to_canvas()", "pos", pos);
234        from_vec2(unsafe { sys::dne_screen_to_canvas(vec2(pos)) })
235    }
236
237    pub fn canvas_to_screen(&self, pos: [f32; 2]) -> [f32; 2] {
238        assert_finite_vec2("NodeEditorFrame::canvas_to_screen()", "pos", pos);
239        from_vec2(unsafe { sys::dne_canvas_to_screen(vec2(pos)) })
240    }
241
242    pub fn node_count(&self) -> usize {
243        unsafe { sys::dne_get_node_count() }.max(0) as usize
244    }
245
246    pub fn ordered_node_ids(&self) -> Vec<NodeId> {
247        let count = self.node_count();
248        collect_node_ids(count, |ptr, len| unsafe {
249            sys::dne_get_ordered_node_ids(ptr, len)
250        })
251    }
252}
253
254fn optional_id<T>(make: fn(usize) -> T, f: impl FnOnce(*mut usize) -> bool) -> Option<T> {
255    let mut raw = 0usize;
256    f(&mut raw).then_some(make(raw))
257}
258
259pub(super) fn collect_node_ids(
260    count: usize,
261    f: impl FnOnce(*mut usize, i32) -> i32,
262) -> Vec<NodeId> {
263    collect_ids(count, f).into_iter().map(NodeId).collect()
264}
265
266pub(super) fn collect_link_ids(
267    count: usize,
268    f: impl FnOnce(*mut usize, i32) -> i32,
269) -> Vec<LinkId> {
270    collect_ids(count, f).into_iter().map(LinkId).collect()
271}
272
273fn collect_ids(count: usize, f: impl FnOnce(*mut usize, i32) -> i32) -> Vec<usize> {
274    if count == 0 {
275        return Vec::new();
276    }
277    let count = count.min(i32::MAX as usize);
278    let mut values = vec![0usize; count];
279    let written = f(values.as_mut_ptr(), values.len() as i32).max(0) as usize;
280    values.truncate(written.min(count));
281    values
282}
283
284fn mouse_button_from_index(index: sys::ImGuiMouseButton) -> Option<MouseButton> {
285    match index {
286        value if value == MouseButton::Left as i32 => Some(MouseButton::Left),
287        value if value == MouseButton::Right as i32 => Some(MouseButton::Right),
288        value if value == MouseButton::Middle as i32 => Some(MouseButton::Middle),
289        value if value == MouseButton::Extra1 as i32 => Some(MouseButton::Extra1),
290        value if value == MouseButton::Extra2 as i32 => Some(MouseButton::Extra2),
291        _ => None,
292    }
293}
294
295#[cfg(test)]
296mod tests {
297    use super::*;
298
299    #[test]
300    fn mouse_button_indices_map_known_imgui_buttons() {
301        assert_eq!(mouse_button_from_index(0), Some(MouseButton::Left));
302        assert_eq!(mouse_button_from_index(1), Some(MouseButton::Right));
303        assert_eq!(mouse_button_from_index(2), Some(MouseButton::Middle));
304        assert_eq!(mouse_button_from_index(3), Some(MouseButton::Extra1));
305        assert_eq!(mouse_button_from_index(4), Some(MouseButton::Extra2));
306        assert_eq!(mouse_button_from_index(-1), None);
307        assert_eq!(mouse_button_from_index(99), None);
308    }
309}