Skip to main content

dear_node_editor/frame/
tokens.rs

1use super::core::NodeEditorFrame;
2use super::validation::{
3    assert_finite_f32, assert_finite_rect, assert_finite_vec2, assert_finite_vec4,
4    assert_non_negative_finite_f32, assert_non_negative_finite_vec2, assert_style_var_type,
5};
6use crate::{
7    EditorContext, FlowDirection, LinkId, NodeEditorStyle, NodeId, PinId, PinKind, StyleColor,
8    StyleVar, StyleVarType, from_vec2, sys, vec2, vec4,
9};
10use dear_imgui_rs::{DrawListMut, Ui};
11use std::{cell::Cell, marker::PhantomData, rc::Rc};
12
13impl<'ui> NodeEditorFrame<'ui> {
14    pub fn begin_node<'a>(&'a self, node: NodeId) -> NodeToken<'a> {
15        let _current_editor = self.bind("NodeEditorFrame::begin_node()");
16        unsafe { sys::dne_begin_node(node.raw()) };
17        NodeToken {
18            editor: self._editor,
19            ended: false,
20            _not_send_sync: PhantomData,
21        }
22    }
23
24    pub fn node<R>(&self, node: NodeId, f: impl FnOnce(&NodeToken<'_>) -> R) -> R {
25        let token = self.begin_node(node);
26        let result = f(&token);
27        token.end();
28        result
29    }
30
31    pub fn begin_group_hint<'a>(&'a self, node: NodeId) -> Option<GroupHintToken<'a>> {
32        let _current_editor = self.bind("NodeEditorFrame::begin_group_hint()");
33        unsafe { sys::dne_begin_group_hint(node.raw()) }.then_some(GroupHintToken {
34            editor: self._editor,
35            ui: self._ui,
36            ended: false,
37            _not_send_sync: PhantomData,
38        })
39    }
40
41    pub fn node_background_draw_list(&self, node: NodeId) -> DrawListMut<'_> {
42        let _current_editor = self.bind("NodeEditorFrame::node_background_draw_list()");
43        let draw_list = unsafe { sys::dne_get_node_background_draw_list(node.raw()) };
44        unsafe { DrawListMut::from_raw_mut(self._ui, draw_list.cast()) }
45    }
46
47    #[doc(alias = "GetStyle")]
48    pub fn style(&self) -> NodeEditorStyle {
49        self._editor.style()
50    }
51
52    pub fn group(&self, size: [f32; 2]) {
53        assert_non_negative_finite_vec2("NodeEditorFrame::group()", "size", size);
54        let _current_editor = self.bind("NodeEditorFrame::group()");
55        unsafe { sys::dne_group(vec2(size)) };
56    }
57
58    pub fn set_group_size(&self, node: NodeId, size: [f32; 2]) {
59        assert_non_negative_finite_vec2("NodeEditorFrame::set_group_size()", "size", size);
60        let _current_editor = self.bind("NodeEditorFrame::set_group_size()");
61        unsafe { sys::dne_set_group_size(node.raw(), vec2(size)) };
62    }
63
64    pub fn link(&self, link: LinkId, start_pin: PinId, end_pin: PinId) -> bool {
65        self.link_colored(link, start_pin, end_pin, [1.0, 1.0, 1.0, 1.0], 1.0)
66    }
67
68    pub fn link_colored(
69        &self,
70        link: LinkId,
71        start_pin: PinId,
72        end_pin: PinId,
73        color: [f32; 4],
74        thickness: f32,
75    ) -> bool {
76        assert_finite_vec4("NodeEditorFrame::link_colored()", "color", color);
77        assert_non_negative_finite_f32("NodeEditorFrame::link_colored()", "thickness", thickness);
78        let _current_editor = self.bind("NodeEditorFrame::link_colored()");
79        unsafe {
80            sys::dne_link(
81                link.raw(),
82                start_pin.raw(),
83                end_pin.raw(),
84                vec4(color),
85                thickness,
86            )
87        }
88    }
89
90    pub fn flow(&self, link: LinkId, direction: FlowDirection) {
91        let _current_editor = self.bind("NodeEditorFrame::flow()");
92        unsafe { sys::dne_flow(link.raw(), direction.raw()) };
93    }
94
95    pub fn push_style_color<'a>(
96        &'a self,
97        color: StyleColor,
98        value: [f32; 4],
99    ) -> StyleColorToken<'a> {
100        assert_finite_vec4("NodeEditorFrame::push_style_color()", "value", value);
101        let _current_editor = self.bind("NodeEditorFrame::push_style_color()");
102        unsafe { sys::dne_push_style_color(color.raw(), vec4(value)) };
103        StyleColorToken {
104            editor: self._editor,
105            count: 1,
106            popped: false,
107            _not_send_sync: PhantomData,
108        }
109    }
110
111    pub fn push_style_var_float<'a>(&'a self, var: StyleVar, value: f32) -> StyleVarToken<'a> {
112        assert_style_var_type(
113            "NodeEditorFrame::push_style_var_float()",
114            var,
115            StyleVarType::Float,
116        );
117        assert_finite_f32("NodeEditorFrame::push_style_var_float()", "value", value);
118        let _current_editor = self.bind("NodeEditorFrame::push_style_var_float()");
119        unsafe { sys::dne_push_style_var_float(var.raw(), value) };
120        StyleVarToken {
121            editor: self._editor,
122            count: 1,
123            popped: false,
124            _not_send_sync: PhantomData,
125        }
126    }
127
128    pub fn push_style_var_vec2<'a>(&'a self, var: StyleVar, value: [f32; 2]) -> StyleVarToken<'a> {
129        assert_style_var_type(
130            "NodeEditorFrame::push_style_var_vec2()",
131            var,
132            StyleVarType::Vec2,
133        );
134        assert_finite_vec2("NodeEditorFrame::push_style_var_vec2()", "value", value);
135        let _current_editor = self.bind("NodeEditorFrame::push_style_var_vec2()");
136        unsafe { sys::dne_push_style_var_vec2(var.raw(), vec2(value)) };
137        StyleVarToken {
138            editor: self._editor,
139            count: 1,
140            popped: false,
141            _not_send_sync: PhantomData,
142        }
143    }
144
145    pub fn push_style_var_vec4<'a>(&'a self, var: StyleVar, value: [f32; 4]) -> StyleVarToken<'a> {
146        assert_style_var_type(
147            "NodeEditorFrame::push_style_var_vec4()",
148            var,
149            StyleVarType::Vec4,
150        );
151        assert_finite_vec4("NodeEditorFrame::push_style_var_vec4()", "value", value);
152        let _current_editor = self.bind("NodeEditorFrame::push_style_var_vec4()");
153        unsafe { sys::dne_push_style_var_vec4(var.raw(), vec4(value)) };
154        StyleVarToken {
155            editor: self._editor,
156            count: 1,
157            popped: false,
158            _not_send_sync: PhantomData,
159        }
160    }
161
162    pub fn suspend<'a>(&'a self) -> SuspensionToken<'a> {
163        assert!(
164            !self.suspended.replace(true),
165            "NodeEditorFrame::suspend() cannot be called while the editor is already suspended"
166        );
167        let _current_editor = self.bind("NodeEditorFrame::suspend()");
168        unsafe { sys::dne_suspend() };
169        SuspensionToken {
170            editor: self._editor,
171            suspended: &self.suspended,
172            resumed: false,
173        }
174    }
175
176    pub fn is_suspended(&self) -> bool {
177        let _current_editor = self.bind("NodeEditorFrame::is_suspended()");
178        self.suspended.get() || unsafe { sys::dne_is_suspended() }
179    }
180}
181
182pub struct NodeToken<'a> {
183    editor: &'a EditorContext,
184    ended: bool,
185    _not_send_sync: PhantomData<Rc<()>>,
186}
187
188impl NodeToken<'_> {
189    pub fn begin_pin<'a>(&'a self, pin: PinId, kind: PinKind) -> PinToken<'a> {
190        let _current_editor = self.editor.bind_current("NodeToken::begin_pin()");
191        unsafe { sys::dne_begin_pin(pin.raw(), kind.raw()) };
192        PinToken {
193            editor: self.editor,
194            ended: false,
195            _not_send_sync: PhantomData,
196        }
197    }
198
199    pub fn pin<R>(&self, pin: PinId, kind: PinKind, f: impl FnOnce(&PinToken<'_>) -> R) -> R {
200        let token = self.begin_pin(pin, kind);
201        let result = f(&token);
202        token.end();
203        result
204    }
205
206    pub fn end(mut self) {
207        self.end_inner();
208    }
209
210    fn end_inner(&mut self) {
211        if !self.ended {
212            let _current_editor = self.editor.bind_current("NodeToken::end()");
213            unsafe { sys::dne_end_node() };
214            self.ended = true;
215        }
216    }
217}
218
219impl Drop for NodeToken<'_> {
220    fn drop(&mut self) {
221        self.end_inner();
222    }
223}
224
225pub struct PinToken<'a> {
226    editor: &'a EditorContext,
227    ended: bool,
228    _not_send_sync: PhantomData<Rc<()>>,
229}
230
231impl PinToken<'_> {
232    pub fn end(mut self) {
233        self.end_inner();
234    }
235
236    pub fn rect(&self, min: [f32; 2], max: [f32; 2]) {
237        assert_finite_rect("PinToken::rect()", min, max);
238        let _current_editor = self.editor.bind_current("PinToken::rect()");
239        unsafe { sys::dne_pin_rect(vec2(min), vec2(max)) };
240    }
241
242    pub fn pivot_rect(&self, min: [f32; 2], max: [f32; 2]) {
243        assert_finite_rect("PinToken::pivot_rect()", min, max);
244        let _current_editor = self.editor.bind_current("PinToken::pivot_rect()");
245        unsafe { sys::dne_pin_pivot_rect(vec2(min), vec2(max)) };
246    }
247
248    pub fn pivot_size(&self, size: [f32; 2]) {
249        assert_non_negative_finite_vec2("PinToken::pivot_size()", "size", size);
250        let _current_editor = self.editor.bind_current("PinToken::pivot_size()");
251        unsafe { sys::dne_pin_pivot_size(vec2(size)) };
252    }
253
254    pub fn pivot_scale(&self, scale: [f32; 2]) {
255        assert_finite_vec2("PinToken::pivot_scale()", "scale", scale);
256        let _current_editor = self.editor.bind_current("PinToken::pivot_scale()");
257        unsafe { sys::dne_pin_pivot_scale(vec2(scale)) };
258    }
259
260    pub fn pivot_alignment(&self, alignment: [f32; 2]) {
261        assert_finite_vec2("PinToken::pivot_alignment()", "alignment", alignment);
262        let _current_editor = self.editor.bind_current("PinToken::pivot_alignment()");
263        unsafe { sys::dne_pin_pivot_alignment(vec2(alignment)) };
264    }
265
266    fn end_inner(&mut self) {
267        if !self.ended {
268            let _current_editor = self.editor.bind_current("PinToken::end()");
269            unsafe { sys::dne_end_pin() };
270            self.ended = true;
271        }
272    }
273}
274
275impl Drop for PinToken<'_> {
276    fn drop(&mut self) {
277        self.end_inner();
278    }
279}
280
281pub struct GroupHintToken<'a> {
282    editor: &'a EditorContext,
283    ui: &'a Ui,
284    ended: bool,
285    _not_send_sync: PhantomData<Rc<()>>,
286}
287
288impl<'a> GroupHintToken<'a> {
289    pub fn min(&self) -> [f32; 2] {
290        let _current_editor = self.editor.bind_current("GroupHintToken::min()");
291        from_vec2(unsafe { sys::dne_get_group_min() })
292    }
293
294    pub fn max(&self) -> [f32; 2] {
295        let _current_editor = self.editor.bind_current("GroupHintToken::max()");
296        from_vec2(unsafe { sys::dne_get_group_max() })
297    }
298
299    pub fn foreground_draw_list(&self) -> DrawListMut<'_> {
300        let _current_editor = self
301            .editor
302            .bind_current("GroupHintToken::foreground_draw_list()");
303        let draw_list = unsafe { sys::dne_get_hint_foreground_draw_list() };
304        unsafe { DrawListMut::from_raw_mut(self.ui, draw_list.cast()) }
305    }
306
307    pub fn background_draw_list(&self) -> DrawListMut<'_> {
308        let _current_editor = self
309            .editor
310            .bind_current("GroupHintToken::background_draw_list()");
311        let draw_list = unsafe { sys::dne_get_hint_background_draw_list() };
312        unsafe { DrawListMut::from_raw_mut(self.ui, draw_list.cast()) }
313    }
314
315    pub fn end(mut self) {
316        self.end_inner();
317    }
318
319    fn end_inner(&mut self) {
320        if !self.ended {
321            let _current_editor = self.editor.bind_current("GroupHintToken::end()");
322            unsafe { sys::dne_end_group_hint() };
323            self.ended = true;
324        }
325    }
326}
327
328impl Drop for GroupHintToken<'_> {
329    fn drop(&mut self) {
330        self.end_inner();
331    }
332}
333
334pub struct SuspensionToken<'a> {
335    editor: &'a EditorContext,
336    suspended: &'a Cell<bool>,
337    resumed: bool,
338}
339
340impl SuspensionToken<'_> {
341    pub fn resume(mut self) {
342        self.resume_inner();
343    }
344
345    fn resume_inner(&mut self) {
346        if !self.resumed {
347            let _current_editor = self.editor.bind_current("SuspensionToken::resume()");
348            unsafe { sys::dne_resume() };
349            self.suspended.set(false);
350            self.resumed = true;
351        }
352    }
353}
354
355impl Drop for SuspensionToken<'_> {
356    fn drop(&mut self) {
357        self.resume_inner();
358    }
359}
360
361pub struct StyleColorToken<'a> {
362    editor: &'a EditorContext,
363    count: i32,
364    popped: bool,
365    _not_send_sync: PhantomData<Rc<()>>,
366}
367
368impl StyleColorToken<'_> {
369    pub fn pop(mut self) {
370        self.pop_inner();
371    }
372
373    fn pop_inner(&mut self) {
374        if !self.popped {
375            let _current_editor = self.editor.bind_current("StyleColorToken::pop()");
376            unsafe { sys::dne_pop_style_color(self.count) };
377            self.popped = true;
378        }
379    }
380}
381
382impl Drop for StyleColorToken<'_> {
383    fn drop(&mut self) {
384        self.pop_inner();
385    }
386}
387
388pub struct StyleVarToken<'a> {
389    editor: &'a EditorContext,
390    count: i32,
391    popped: bool,
392    _not_send_sync: PhantomData<Rc<()>>,
393}
394
395impl StyleVarToken<'_> {
396    pub fn pop(mut self) {
397        self.pop_inner();
398    }
399
400    fn pop_inner(&mut self) {
401        if !self.popped {
402            let _current_editor = self.editor.bind_current("StyleVarToken::pop()");
403            unsafe { sys::dne_pop_style_var(self.count) };
404            self.popped = true;
405        }
406    }
407}
408
409impl Drop for StyleVarToken<'_> {
410    fn drop(&mut self) {
411        self.pop_inner();
412    }
413}