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