use super::core::NodeEditorFrame;
use super::validation::{
assert_finite_f32, assert_finite_rect, assert_finite_vec2, assert_finite_vec4,
assert_non_negative_finite_f32, assert_non_negative_finite_vec2, assert_style_var_type,
};
use crate::{
EditorContext, FlowDirection, LinkId, NodeEditorStyle, NodeId, PinId, PinKind, StyleColor,
StyleVar, StyleVarType, from_vec2, sys, vec2, vec4,
};
use dear_imgui_rs::{DrawListMut, Ui};
use std::{cell::Cell, marker::PhantomData, rc::Rc};
impl<'ui> NodeEditorFrame<'ui> {
pub fn begin_node<'a>(&'a self, node: NodeId) -> NodeToken<'a> {
let _current_editor = self.bind("NodeEditorFrame::begin_node()");
unsafe { sys::dne_begin_node(node.raw()) };
NodeToken {
editor: self._editor,
ended: false,
_not_send_sync: PhantomData,
}
}
pub fn node<R>(&self, node: NodeId, f: impl FnOnce(&NodeToken<'_>) -> R) -> R {
let token = self.begin_node(node);
let result = f(&token);
token.end();
result
}
pub fn begin_group_hint<'a>(&'a self, node: NodeId) -> Option<GroupHintToken<'a>> {
let _current_editor = self.bind("NodeEditorFrame::begin_group_hint()");
unsafe { sys::dne_begin_group_hint(node.raw()) }.then_some(GroupHintToken {
editor: self._editor,
ui: self._ui,
ended: false,
_not_send_sync: PhantomData,
})
}
pub fn node_background_draw_list(&self, node: NodeId) -> DrawListMut<'_> {
let _current_editor = self.bind("NodeEditorFrame::node_background_draw_list()");
let draw_list = unsafe { sys::dne_get_node_background_draw_list(node.raw()) };
unsafe { DrawListMut::from_raw_mut(self._ui, draw_list.cast()) }
}
#[doc(alias = "GetStyle")]
pub fn style(&self) -> NodeEditorStyle {
self._editor.style()
}
pub fn group(&self, size: [f32; 2]) {
assert_non_negative_finite_vec2("NodeEditorFrame::group()", "size", size);
let _current_editor = self.bind("NodeEditorFrame::group()");
unsafe { sys::dne_group(vec2(size)) };
}
pub fn set_group_size(&self, node: NodeId, size: [f32; 2]) {
assert_non_negative_finite_vec2("NodeEditorFrame::set_group_size()", "size", size);
let _current_editor = self.bind("NodeEditorFrame::set_group_size()");
unsafe { sys::dne_set_group_size(node.raw(), vec2(size)) };
}
pub fn link(&self, link: LinkId, start_pin: PinId, end_pin: PinId) -> bool {
self.link_colored(link, start_pin, end_pin, [1.0, 1.0, 1.0, 1.0], 1.0)
}
pub fn link_colored(
&self,
link: LinkId,
start_pin: PinId,
end_pin: PinId,
color: [f32; 4],
thickness: f32,
) -> bool {
assert_finite_vec4("NodeEditorFrame::link_colored()", "color", color);
assert_non_negative_finite_f32("NodeEditorFrame::link_colored()", "thickness", thickness);
let _current_editor = self.bind("NodeEditorFrame::link_colored()");
unsafe {
sys::dne_link(
link.raw(),
start_pin.raw(),
end_pin.raw(),
vec4(color),
thickness,
)
}
}
pub fn flow(&self, link: LinkId, direction: FlowDirection) {
let _current_editor = self.bind("NodeEditorFrame::flow()");
unsafe { sys::dne_flow(link.raw(), direction.raw()) };
}
pub fn push_style_color<'a>(
&'a self,
color: StyleColor,
value: [f32; 4],
) -> StyleColorToken<'a> {
assert_finite_vec4("NodeEditorFrame::push_style_color()", "value", value);
let _current_editor = self.bind("NodeEditorFrame::push_style_color()");
unsafe { sys::dne_push_style_color(color.raw(), vec4(value)) };
StyleColorToken {
editor: self._editor,
count: 1,
popped: false,
_not_send_sync: PhantomData,
}
}
pub fn push_style_var_float<'a>(&'a self, var: StyleVar, value: f32) -> StyleVarToken<'a> {
assert_style_var_type(
"NodeEditorFrame::push_style_var_float()",
var,
StyleVarType::Float,
);
assert_finite_f32("NodeEditorFrame::push_style_var_float()", "value", value);
let _current_editor = self.bind("NodeEditorFrame::push_style_var_float()");
unsafe { sys::dne_push_style_var_float(var.raw(), value) };
StyleVarToken {
editor: self._editor,
count: 1,
popped: false,
_not_send_sync: PhantomData,
}
}
pub fn push_style_var_vec2<'a>(&'a self, var: StyleVar, value: [f32; 2]) -> StyleVarToken<'a> {
assert_style_var_type(
"NodeEditorFrame::push_style_var_vec2()",
var,
StyleVarType::Vec2,
);
assert_finite_vec2("NodeEditorFrame::push_style_var_vec2()", "value", value);
let _current_editor = self.bind("NodeEditorFrame::push_style_var_vec2()");
unsafe { sys::dne_push_style_var_vec2(var.raw(), vec2(value)) };
StyleVarToken {
editor: self._editor,
count: 1,
popped: false,
_not_send_sync: PhantomData,
}
}
pub fn push_style_var_vec4<'a>(&'a self, var: StyleVar, value: [f32; 4]) -> StyleVarToken<'a> {
assert_style_var_type(
"NodeEditorFrame::push_style_var_vec4()",
var,
StyleVarType::Vec4,
);
assert_finite_vec4("NodeEditorFrame::push_style_var_vec4()", "value", value);
let _current_editor = self.bind("NodeEditorFrame::push_style_var_vec4()");
unsafe { sys::dne_push_style_var_vec4(var.raw(), vec4(value)) };
StyleVarToken {
editor: self._editor,
count: 1,
popped: false,
_not_send_sync: PhantomData,
}
}
pub fn suspend<'a>(&'a self) -> SuspensionToken<'a> {
assert!(
!self.suspended.replace(true),
"NodeEditorFrame::suspend() cannot be called while the editor is already suspended"
);
let _current_editor = self.bind("NodeEditorFrame::suspend()");
unsafe { sys::dne_suspend() };
SuspensionToken {
editor: self._editor,
suspended: &self.suspended,
resumed: false,
}
}
pub fn is_suspended(&self) -> bool {
let _current_editor = self.bind("NodeEditorFrame::is_suspended()");
self.suspended.get() || unsafe { sys::dne_is_suspended() }
}
}
pub struct NodeToken<'a> {
editor: &'a EditorContext,
ended: bool,
_not_send_sync: PhantomData<Rc<()>>,
}
impl NodeToken<'_> {
pub fn begin_pin<'a>(&'a self, pin: PinId, kind: PinKind) -> PinToken<'a> {
let _current_editor = self.editor.bind_current("NodeToken::begin_pin()");
unsafe { sys::dne_begin_pin(pin.raw(), kind.raw()) };
PinToken {
editor: self.editor,
ended: false,
_not_send_sync: PhantomData,
}
}
pub fn pin<R>(&self, pin: PinId, kind: PinKind, f: impl FnOnce(&PinToken<'_>) -> R) -> R {
let token = self.begin_pin(pin, kind);
let result = f(&token);
token.end();
result
}
pub fn end(mut self) {
self.end_inner();
}
fn end_inner(&mut self) {
if !self.ended {
let _current_editor = self.editor.bind_current("NodeToken::end()");
unsafe { sys::dne_end_node() };
self.ended = true;
}
}
}
impl Drop for NodeToken<'_> {
fn drop(&mut self) {
self.end_inner();
}
}
pub struct PinToken<'a> {
editor: &'a EditorContext,
ended: bool,
_not_send_sync: PhantomData<Rc<()>>,
}
impl PinToken<'_> {
pub fn end(mut self) {
self.end_inner();
}
pub fn rect(&self, min: [f32; 2], max: [f32; 2]) {
assert_finite_rect("PinToken::rect()", min, max);
let _current_editor = self.editor.bind_current("PinToken::rect()");
unsafe { sys::dne_pin_rect(vec2(min), vec2(max)) };
}
pub fn pivot_rect(&self, min: [f32; 2], max: [f32; 2]) {
assert_finite_rect("PinToken::pivot_rect()", min, max);
let _current_editor = self.editor.bind_current("PinToken::pivot_rect()");
unsafe { sys::dne_pin_pivot_rect(vec2(min), vec2(max)) };
}
pub fn pivot_size(&self, size: [f32; 2]) {
assert_non_negative_finite_vec2("PinToken::pivot_size()", "size", size);
let _current_editor = self.editor.bind_current("PinToken::pivot_size()");
unsafe { sys::dne_pin_pivot_size(vec2(size)) };
}
pub fn pivot_scale(&self, scale: [f32; 2]) {
assert_finite_vec2("PinToken::pivot_scale()", "scale", scale);
let _current_editor = self.editor.bind_current("PinToken::pivot_scale()");
unsafe { sys::dne_pin_pivot_scale(vec2(scale)) };
}
pub fn pivot_alignment(&self, alignment: [f32; 2]) {
assert_finite_vec2("PinToken::pivot_alignment()", "alignment", alignment);
let _current_editor = self.editor.bind_current("PinToken::pivot_alignment()");
unsafe { sys::dne_pin_pivot_alignment(vec2(alignment)) };
}
fn end_inner(&mut self) {
if !self.ended {
let _current_editor = self.editor.bind_current("PinToken::end()");
unsafe { sys::dne_end_pin() };
self.ended = true;
}
}
}
impl Drop for PinToken<'_> {
fn drop(&mut self) {
self.end_inner();
}
}
pub struct GroupHintToken<'a> {
editor: &'a EditorContext,
ui: &'a Ui,
ended: bool,
_not_send_sync: PhantomData<Rc<()>>,
}
impl<'a> GroupHintToken<'a> {
pub fn min(&self) -> [f32; 2] {
let _current_editor = self.editor.bind_current("GroupHintToken::min()");
from_vec2(unsafe { sys::dne_get_group_min() })
}
pub fn max(&self) -> [f32; 2] {
let _current_editor = self.editor.bind_current("GroupHintToken::max()");
from_vec2(unsafe { sys::dne_get_group_max() })
}
pub fn foreground_draw_list(&self) -> DrawListMut<'_> {
let _current_editor = self
.editor
.bind_current("GroupHintToken::foreground_draw_list()");
let draw_list = unsafe { sys::dne_get_hint_foreground_draw_list() };
unsafe { DrawListMut::from_raw_mut(self.ui, draw_list.cast()) }
}
pub fn background_draw_list(&self) -> DrawListMut<'_> {
let _current_editor = self
.editor
.bind_current("GroupHintToken::background_draw_list()");
let draw_list = unsafe { sys::dne_get_hint_background_draw_list() };
unsafe { DrawListMut::from_raw_mut(self.ui, draw_list.cast()) }
}
pub fn end(mut self) {
self.end_inner();
}
fn end_inner(&mut self) {
if !self.ended {
let _current_editor = self.editor.bind_current("GroupHintToken::end()");
unsafe { sys::dne_end_group_hint() };
self.ended = true;
}
}
}
impl Drop for GroupHintToken<'_> {
fn drop(&mut self) {
self.end_inner();
}
}
pub struct SuspensionToken<'a> {
editor: &'a EditorContext,
suspended: &'a Cell<bool>,
resumed: bool,
}
impl SuspensionToken<'_> {
pub fn resume(mut self) {
self.resume_inner();
}
fn resume_inner(&mut self) {
if !self.resumed {
let _current_editor = self.editor.bind_current("SuspensionToken::resume()");
unsafe { sys::dne_resume() };
self.suspended.set(false);
self.resumed = true;
}
}
}
impl Drop for SuspensionToken<'_> {
fn drop(&mut self) {
self.resume_inner();
}
}
pub struct StyleColorToken<'a> {
editor: &'a EditorContext,
count: i32,
popped: bool,
_not_send_sync: PhantomData<Rc<()>>,
}
impl StyleColorToken<'_> {
pub fn pop(mut self) {
self.pop_inner();
}
fn pop_inner(&mut self) {
if !self.popped {
let _current_editor = self.editor.bind_current("StyleColorToken::pop()");
unsafe { sys::dne_pop_style_color(self.count) };
self.popped = true;
}
}
}
impl Drop for StyleColorToken<'_> {
fn drop(&mut self) {
self.pop_inner();
}
}
pub struct StyleVarToken<'a> {
editor: &'a EditorContext,
count: i32,
popped: bool,
_not_send_sync: PhantomData<Rc<()>>,
}
impl StyleVarToken<'_> {
pub fn pop(mut self) {
self.pop_inner();
}
fn pop_inner(&mut self) {
if !self.popped {
let _current_editor = self.editor.bind_current("StyleVarToken::pop()");
unsafe { sys::dne_pop_style_var(self.count) };
self.popped = true;
}
}
}
impl Drop for StyleVarToken<'_> {
fn drop(&mut self) {
self.pop_inner();
}
}