1use alloc::vec::Vec;
15use core::fmt;
16
17use azul_core::{
18 callbacks::{CoreCallback, CoreCallbackData, Update},
19 dom::{Dom, EventFilter, HoverEventFilter, IdOrClass, IdOrClass::Class, IdOrClassVec},
20 geom::{LogicalPosition, LogicalRect, LogicalSize, PhysicalSizeU32},
21 gl::Texture,
22 menu::{Menu, MenuItem, StringMenuItem},
23 refany::{OptionRefAny, RefAny},
24 resources::{ImageRef, RawImageFormat},
25 svg::{SvgPath, SvgPathElement, SvgStrokeStyle, TessellatedGPUSvgNode},
26 window::CursorPosition::InWindow,
27};
28use azul_css::{
29 dynamic_selector::{CssPropertyWithConditions, CssPropertyWithConditionsVec},
30 props::{
31 basic::*,
32 layout::*,
33 property::{CssProperty, *},
34 style::*,
35 },
36 *,
37};
38use azul_css::css::BoxOrStatic;
39
40use crate::{
41 callbacks::{Callback, CallbackInfo},
42 extra::coloru_from_str,
43 widgets::{
44 check_box::{CheckBox, CheckBoxOnToggleCallbackType, CheckBoxState},
45 color_input::{ColorInput, ColorInputOnValueChangeCallbackType, ColorInputState},
46 file_input::{FileInput, FileInputOnPathChangeCallbackType, FileInputState},
47 number_input::{NumberInput, NumberInputOnFocusLostCallbackType, NumberInputState},
48 text_input::{TextInput, TextInputOnFocusLostCallbackType, TextInputState},
49 },
50};
51
52#[derive(Debug, Clone)]
54#[repr(C)]
55pub struct NodeGraph {
56 pub node_types: NodeTypeIdInfoMapVec,
57 pub input_output_types: InputOutputTypeIdInfoMapVec,
58 pub nodes: NodeIdNodeMapVec,
59 pub allow_multiple_root_nodes: bool,
60 pub offset: LogicalPosition,
61 pub style: NodeGraphStyle,
62 pub callbacks: NodeGraphCallbacks,
63 pub add_node_str: AzString,
64 pub scale_factor: f32,
65}
66
67impl Default for NodeGraph {
68 fn default() -> Self {
69 Self {
70 node_types: NodeTypeIdInfoMapVec::from_const_slice(&[]),
71 input_output_types: InputOutputTypeIdInfoMapVec::from_const_slice(&[]),
72 nodes: NodeIdNodeMapVec::from_const_slice(&[]),
73 allow_multiple_root_nodes: false,
74 offset: LogicalPosition::zero(),
75 style: NodeGraphStyle::Default,
76 callbacks: NodeGraphCallbacks::default(),
77 add_node_str: AzString::from_const_str(""),
78 scale_factor: 1.0,
79 }
80 }
81}
82
83impl NodeGraph {
84 pub fn generate_unique_node_id(&self) -> NodeGraphNodeId {
86 NodeGraphNodeId {
87 inner: self
88 .nodes
89 .iter()
90 .map(|i| i.node_id.inner)
91 .max()
92 .unwrap_or(0)
93 .saturating_add(1),
94 }
95 }
96}
97
98#[derive(Debug, Clone)]
100#[repr(C)]
101pub struct NodeTypeIdInfoMap {
102 pub node_type_id: NodeTypeId,
103 pub node_type_info: NodeTypeInfo,
104}
105
106impl_option!(NodeTypeIdInfoMap, OptionNodeTypeIdInfoMap, copy = false, [Debug, Clone]);
107impl_vec!(NodeTypeIdInfoMap, NodeTypeIdInfoMapVec, NodeTypeIdInfoMapVecDestructor, NodeTypeIdInfoMapVecDestructorType, NodeTypeIdInfoMapVecSlice, OptionNodeTypeIdInfoMap);
108impl_vec_clone!(
109 NodeTypeIdInfoMap,
110 NodeTypeIdInfoMapVec,
111 NodeTypeIdInfoMapVecDestructor
112);
113impl_vec_mut!(NodeTypeIdInfoMap, NodeTypeIdInfoMapVec);
114impl_vec_debug!(NodeTypeIdInfoMap, NodeTypeIdInfoMapVec);
115
116#[derive(Debug, Clone)]
118#[repr(C)]
119pub struct InputOutputTypeIdInfoMap {
120 pub io_type_id: InputOutputTypeId,
121 pub io_info: InputOutputInfo,
122}
123
124impl_option!(InputOutputTypeIdInfoMap, OptionInputOutputTypeIdInfoMap, copy = false, [Debug, Clone]);
125impl_vec!(InputOutputTypeIdInfoMap, InputOutputTypeIdInfoMapVec, InputOutputTypeIdInfoMapVecDestructor, InputOutputTypeIdInfoMapVecDestructorType, InputOutputTypeIdInfoMapVecSlice, OptionInputOutputTypeIdInfoMap);
126impl_vec_clone!(
127 InputOutputTypeIdInfoMap,
128 InputOutputTypeIdInfoMapVec,
129 InputOutputTypeIdInfoMapVecDestructor
130);
131impl_vec_mut!(InputOutputTypeIdInfoMap, InputOutputTypeIdInfoMapVec);
132impl_vec_debug!(InputOutputTypeIdInfoMap, InputOutputTypeIdInfoMapVec);
133
134#[derive(Debug, Clone)]
136#[repr(C)]
137pub struct NodeIdNodeMap {
138 pub node_id: NodeGraphNodeId,
139 pub node: Node,
140}
141
142impl_option!(NodeIdNodeMap, OptionNodeIdNodeMap, copy = false, [Debug, Clone]);
143impl_vec!(NodeIdNodeMap, NodeIdNodeMapVec, NodeIdNodeMapVecDestructor, NodeIdNodeMapVecDestructorType, NodeIdNodeMapVecSlice, OptionNodeIdNodeMap);
144impl_vec_clone!(NodeIdNodeMap, NodeIdNodeMapVec, NodeIdNodeMapVecDestructor);
145impl_vec_mut!(NodeIdNodeMap, NodeIdNodeMapVec);
146impl_vec_debug!(NodeIdNodeMap, NodeIdNodeMapVec);
147
148#[derive(Debug, Copy, Clone)]
149#[repr(C)]
150pub enum NodeGraphStyle {
151 Default,
152 }
154
155#[derive(Default, Debug, Clone)]
157#[repr(C)]
158pub struct NodeGraphCallbacks {
159 pub on_node_added: OptionOnNodeAdded,
160 pub on_node_removed: OptionOnNodeRemoved,
161 pub on_node_dragged: OptionOnNodeDragged,
162 pub on_node_graph_dragged: OptionOnNodeGraphDragged,
163 pub on_node_connected: OptionOnNodeConnected,
164 pub on_node_input_disconnected: OptionOnNodeInputDisconnected,
165 pub on_node_output_disconnected: OptionOnNodeOutputDisconnected,
166 pub on_node_field_edited: OptionOnNodeFieldEdited,
167}
168
169pub type OnNodeAddedCallbackType = extern "C" fn(
170 refany: RefAny,
171 info: CallbackInfo,
172 new_node_type: NodeTypeId,
173 new_node_id: NodeGraphNodeId,
174 new_node_position: NodeGraphNodePosition,
175) -> Update;
176impl_widget_callback!(
177 OnNodeAdded,
178 OptionOnNodeAdded,
179 OnNodeAddedCallback,
180 OnNodeAddedCallbackType
181);
182
183pub type OnNodeRemovedCallbackType =
184 extern "C" fn(refany: RefAny, info: CallbackInfo, node_id_to_remove: NodeGraphNodeId) -> Update;
185impl_widget_callback!(
186 OnNodeRemoved,
187 OptionOnNodeRemoved,
188 OnNodeRemovedCallback,
189 OnNodeRemovedCallbackType
190);
191
192pub type OnNodeGraphDraggedCallbackType =
193 extern "C" fn(refany: RefAny, info: CallbackInfo, drag_amount: GraphDragAmount) -> Update;
194impl_widget_callback!(
195 OnNodeGraphDragged,
196 OptionOnNodeGraphDragged,
197 OnNodeGraphDraggedCallback,
198 OnNodeGraphDraggedCallbackType
199);
200
201pub type OnNodeDraggedCallbackType = extern "C" fn(
202 refany: RefAny,
203 info: CallbackInfo,
204 node_dragged: NodeGraphNodeId,
205 drag_amount: NodeDragAmount,
206) -> Update;
207impl_widget_callback!(
208 OnNodeDragged,
209 OptionOnNodeDragged,
210 OnNodeDraggedCallback,
211 OnNodeDraggedCallbackType
212);
213
214pub type OnNodeConnectedCallbackType = extern "C" fn(
215 refany: RefAny,
216 info: CallbackInfo,
217 input: NodeGraphNodeId,
218 input_index: usize,
219 output: NodeGraphNodeId,
220 output_index: usize,
221) -> Update;
222impl_widget_callback!(
223 OnNodeConnected,
224 OptionOnNodeConnected,
225 OnNodeConnectedCallback,
226 OnNodeConnectedCallbackType
227);
228
229pub type OnNodeInputDisconnectedCallbackType = extern "C" fn(
230 refany: RefAny,
231 info: CallbackInfo,
232 input: NodeGraphNodeId,
233 input_index: usize,
234) -> Update;
235impl_widget_callback!(
236 OnNodeInputDisconnected,
237 OptionOnNodeInputDisconnected,
238 OnNodeInputDisconnectedCallback,
239 OnNodeInputDisconnectedCallbackType
240);
241
242pub type OnNodeOutputDisconnectedCallbackType = extern "C" fn(
243 refany: RefAny,
244 info: CallbackInfo,
245 output: NodeGraphNodeId,
246 output_index: usize,
247) -> Update;
248impl_widget_callback!(
249 OnNodeOutputDisconnected,
250 OptionOnNodeOutputDisconnected,
251 OnNodeOutputDisconnectedCallback,
252 OnNodeOutputDisconnectedCallbackType
253);
254
255pub type OnNodeFieldEditedCallbackType = extern "C" fn(
256 refany: RefAny,
257 info: CallbackInfo,
258 node_id: NodeGraphNodeId,
259 field_id: usize,
260 node_type: NodeTypeId,
261 new_value: NodeTypeFieldValue,
262) -> Update;
263impl_widget_callback!(
264 OnNodeFieldEdited,
265 OptionOnNodeFieldEdited,
266 OnNodeFieldEditedCallback,
267 OnNodeFieldEditedCallbackType
268);
269
270#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
272#[repr(C)]
273pub struct InputOutputTypeId {
274 pub inner: u64,
275}
276
277impl_option!(InputOutputTypeId, OptionInputOutputTypeId, copy = false, [Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash]);
278impl_vec!(InputOutputTypeId, InputOutputTypeIdVec, InputOutputTypeIdVecDestructor, InputOutputTypeIdVecDestructorType, InputOutputTypeIdVecSlice, OptionInputOutputTypeId);
279impl_vec_clone!(
280 InputOutputTypeId,
281 InputOutputTypeIdVec,
282 InputOutputTypeIdVecDestructor
283);
284impl_vec_mut!(InputOutputTypeId, InputOutputTypeIdVec);
285impl_vec_debug!(InputOutputTypeId, InputOutputTypeIdVec);
286
287#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
289#[repr(C)]
290pub struct NodeTypeId {
291 pub inner: u64,
292}
293
294#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
296#[repr(C)]
297pub struct NodeGraphNodeId {
298 pub inner: u64,
299}
300
301#[derive(Debug, Clone)]
303#[repr(C)]
304pub struct Node {
305 pub node_type: NodeTypeId,
306 pub position: NodeGraphNodePosition,
307 pub fields: NodeTypeFieldVec,
308 pub connect_in: InputConnectionVec,
309 pub connect_out: OutputConnectionVec,
310}
311
312#[derive(Debug, Clone)]
314#[repr(C)]
315pub struct NodeTypeField {
316 pub key: AzString,
317 pub value: NodeTypeFieldValue,
318}
319
320impl_option!(NodeTypeField, OptionNodeTypeField, copy = false, [Debug, Clone]);
321impl_vec!(NodeTypeField, NodeTypeFieldVec, NodeTypeFieldVecDestructor, NodeTypeFieldVecDestructorType, NodeTypeFieldVecSlice, OptionNodeTypeField);
322impl_vec_clone!(NodeTypeField, NodeTypeFieldVec, NodeTypeFieldVecDestructor);
323impl_vec_debug!(NodeTypeField, NodeTypeFieldVec);
324impl_vec_mut!(NodeTypeField, NodeTypeFieldVec);
325
326#[derive(Debug, Clone)]
328#[repr(C, u8)]
329pub enum NodeTypeFieldValue {
330 TextInput(AzString),
331 NumberInput(f32),
332 CheckBox(bool),
333 ColorInput(ColorU),
334 FileInput(OptionString),
335}
336
337#[derive(Debug, Clone)]
339#[repr(C)]
340pub struct InputConnection {
341 pub input_index: usize,
342 pub connects_to: OutputNodeAndIndexVec,
343}
344
345impl_option!(InputConnection, OptionInputConnection, copy = false, [Debug, Clone]);
346impl_vec!(InputConnection, InputConnectionVec, InputConnectionVecDestructor, InputConnectionVecDestructorType, InputConnectionVecSlice, OptionInputConnection);
347impl_vec_clone!(
348 InputConnection,
349 InputConnectionVec,
350 InputConnectionVecDestructor
351);
352impl_vec_debug!(InputConnection, InputConnectionVec);
353impl_vec_mut!(InputConnection, InputConnectionVec);
354
355#[derive(Debug, Clone)]
357#[repr(C)]
358pub struct OutputNodeAndIndex {
359 pub node_id: NodeGraphNodeId,
360 pub output_index: usize,
361}
362
363impl_option!(OutputNodeAndIndex, OptionOutputNodeAndIndex, copy = false, [Debug, Clone]);
364impl_vec!(OutputNodeAndIndex, OutputNodeAndIndexVec, OutputNodeAndIndexVecDestructor, OutputNodeAndIndexVecDestructorType, OutputNodeAndIndexVecSlice, OptionOutputNodeAndIndex);
365impl_vec_clone!(
366 OutputNodeAndIndex,
367 OutputNodeAndIndexVec,
368 OutputNodeAndIndexVecDestructor
369);
370impl_vec_debug!(OutputNodeAndIndex, OutputNodeAndIndexVec);
371impl_vec_mut!(OutputNodeAndIndex, OutputNodeAndIndexVec);
372
373#[derive(Debug, Clone)]
375#[repr(C)]
376pub struct OutputConnection {
377 pub output_index: usize,
378 pub connects_to: InputNodeAndIndexVec,
379}
380
381impl_option!(OutputConnection, OptionOutputConnection, copy = false, [Debug, Clone]);
382impl_vec!(OutputConnection, OutputConnectionVec, OutputConnectionVecDestructor, OutputConnectionVecDestructorType, OutputConnectionVecSlice, OptionOutputConnection);
383impl_vec_clone!(
384 OutputConnection,
385 OutputConnectionVec,
386 OutputConnectionVecDestructor
387);
388impl_vec_debug!(OutputConnection, OutputConnectionVec);
389impl_vec_mut!(OutputConnection, OutputConnectionVec);
390
391#[derive(Debug, Clone, PartialEq)]
393#[repr(C)]
394pub struct InputNodeAndIndex {
395 pub node_id: NodeGraphNodeId,
396 pub input_index: usize,
397}
398
399impl_option!(InputNodeAndIndex, OptionInputNodeAndIndex, copy = false, [Debug, Clone]);
400impl_vec!(InputNodeAndIndex, InputNodeAndIndexVec, InputNodeAndIndexVecDestructor, InputNodeAndIndexVecDestructorType, InputNodeAndIndexVecSlice, OptionInputNodeAndIndex);
401impl_vec_clone!(
402 InputNodeAndIndex,
403 InputNodeAndIndexVec,
404 InputNodeAndIndexVecDestructor
405);
406impl_vec_debug!(InputNodeAndIndex, InputNodeAndIndexVec);
407impl_vec_mut!(InputNodeAndIndex, InputNodeAndIndexVec);
408
409#[derive(Debug, Clone)]
411#[repr(C)]
412pub struct NodeTypeInfo {
413 pub is_root: bool,
415 pub node_type_name: AzString,
417 pub inputs: InputOutputTypeIdVec,
419 pub outputs: InputOutputTypeIdVec,
421}
422
423#[derive(Debug, Clone)]
425#[repr(C)]
426pub struct InputOutputInfo {
427 pub data_type: AzString,
429 pub color: ColorU,
431}
432
433#[derive(Debug, Copy, Clone)]
436#[repr(C)]
437pub struct NodeGraphNodePosition {
438 pub x: f32,
440 pub y: f32,
442}
443
444#[derive(Debug, Copy, Clone, PartialEq, Eq)]
445#[repr(C)]
446pub enum NodeGraphError {
447 NodeMimeTypeMismatch,
450 NodeInvalidIndex,
452 NodeInvalidNode,
454 NoRootNode,
456}
457
458impl fmt::Display for NodeGraphError {
459 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
460 use self::NodeGraphError::*;
461 match self {
462 NodeMimeTypeMismatch => write!(f, "MIME type mismatch"),
463 NodeInvalidIndex => write!(f, "Invalid node index"),
464 NodeInvalidNode => write!(f, "Invalid node"),
465 NoRootNode => write!(f, "No root node found"),
466 }
467 }
468}
469
470#[derive(Debug, Copy, Clone, PartialEq)]
472#[repr(C)]
473pub struct GraphDragAmount {
474 pub x: f32,
475 pub y: f32,
476}
477
478#[derive(Debug, Copy, Clone, PartialEq)]
480#[repr(C)]
481pub struct NodeDragAmount {
482 pub x: f32,
483 pub y: f32,
484}
485
486impl NodeGraph {
487 pub fn swap_with_default(&mut self) -> Self {
488 let mut default = Self::default();
489 ::core::mem::swap(&mut default, self);
490 default
491 }
492
493 fn connect_input_output(
512 &mut self,
513 input_node_id: NodeGraphNodeId,
514 input_index: usize,
515 output_node_id: NodeGraphNodeId,
516 output_index: usize,
517 ) -> Result<(), NodeGraphError> {
518 let _ =
520 self.verify_nodetype_match(output_node_id, output_index, input_node_id, input_index)?;
521
522 if let Some(input_node) = self
524 .nodes
525 .as_mut()
526 .iter_mut()
527 .find(|i| i.node_id == input_node_id)
528 {
529 if let Some(position) = input_node
530 .node
531 .connect_in
532 .as_ref()
533 .iter()
534 .position(|i| i.input_index == input_index)
535 {
536 input_node.node.connect_in.as_mut()[position]
537 .connects_to
538 .push(OutputNodeAndIndex {
539 node_id: output_node_id,
540 output_index,
541 });
542 } else {
543 input_node.node.connect_in.push(InputConnection {
544 input_index,
545 connects_to: vec![OutputNodeAndIndex {
546 node_id: output_node_id,
547 output_index,
548 }]
549 .into(),
550 })
551 }
552 } else {
553 return Err(NodeGraphError::NodeInvalidNode);
554 }
555
556 if let Some(output_node) = self
558 .nodes
559 .as_mut()
560 .iter_mut()
561 .find(|i| i.node_id == output_node_id)
562 {
563 if let Some(position) = output_node
564 .node
565 .connect_out
566 .as_ref()
567 .iter()
568 .position(|i| i.output_index == output_index)
569 {
570 output_node.node.connect_out.as_mut()[position]
571 .connects_to
572 .push(InputNodeAndIndex {
573 node_id: input_node_id,
574 input_index,
575 });
576 } else {
577 output_node.node.connect_out.push(OutputConnection {
578 output_index,
579 connects_to: vec![InputNodeAndIndex {
580 node_id: input_node_id,
581 input_index,
582 }]
583 .into(),
584 })
585 }
586 } else {
587 return Err(NodeGraphError::NodeInvalidNode);
588 }
589
590 Ok(())
591 }
592
593 fn disconnect_input(
610 &mut self,
611 input_node_id: NodeGraphNodeId,
612 input_index: usize,
613 ) -> Result<(), NodeGraphError> {
614 let output_connections = {
615 let input_node = self
616 .nodes
617 .as_ref()
618 .iter()
619 .find(|i| i.node_id == input_node_id)
620 .ok_or(NodeGraphError::NodeInvalidNode)?;
621
622 match input_node
623 .node
624 .connect_in
625 .iter()
626 .find(|i| i.input_index == input_index)
627 {
628 None => return Ok(()),
629 Some(s) => s.connects_to.clone(),
630 }
631 };
632
633 for OutputNodeAndIndex {
635 node_id,
636 output_index,
637 } in output_connections.as_ref().iter()
638 {
639 let output_node_id = *node_id;
640 let output_index = *output_index;
641
642 let _ = self.verify_nodetype_match(
644 output_node_id,
645 output_index,
646 input_node_id,
647 input_index,
648 )?;
649
650 if let Some(input_node) = self
653 .nodes
654 .as_mut()
655 .iter_mut()
656 .find(|i| i.node_id == input_node_id)
657 {
658 if let Some(position) = input_node
659 .node
660 .connect_in
661 .iter()
662 .position(|i| i.input_index == input_index)
663 {
664 input_node.node.connect_in.remove(position);
665 }
666 } else {
667 return Err(NodeGraphError::NodeInvalidNode);
668 }
669
670 if let Some(output_node) = self
671 .nodes
672 .as_mut()
673 .iter_mut()
674 .find(|i| i.node_id == output_node_id)
675 {
676 if let Some(position) = output_node
677 .node
678 .connect_out
679 .iter()
680 .position(|i| i.output_index == output_index)
681 {
682 output_node.node.connect_out.remove(position);
683 }
684 } else {
685 return Err(NodeGraphError::NodeInvalidNode);
686 }
687 }
688
689 Ok(())
690 }
691
692 fn disconnect_output(
707 &mut self,
708 output_node_id: NodeGraphNodeId,
709 output_index: usize,
710 ) -> Result<(), NodeGraphError> {
711 let input_connections = {
712 let output_node = self
713 .nodes
714 .as_ref()
715 .iter()
716 .find(|i| i.node_id == output_node_id)
717 .ok_or(NodeGraphError::NodeInvalidNode)?;
718
719 match output_node
720 .node
721 .connect_out
722 .iter()
723 .find(|i| i.output_index == output_index)
724 {
725 None => return Ok(()),
726 Some(s) => s.connects_to.clone(),
727 }
728 };
729
730 for InputNodeAndIndex {
731 node_id,
732 input_index,
733 } in input_connections.iter()
734 {
735 let input_node_id = *node_id;
736 let input_index = *input_index;
737
738 let _ = self.verify_nodetype_match(
740 output_node_id,
741 output_index,
742 input_node_id,
743 input_index,
744 )?;
745
746 if let Some(output_node) = self
747 .nodes
748 .as_mut()
749 .iter_mut()
750 .find(|i| i.node_id == output_node_id)
751 {
752 if let Some(position) = output_node
753 .node
754 .connect_out
755 .iter()
756 .position(|i| i.output_index == output_index)
757 {
758 output_node.node.connect_out.remove(position);
759 }
760 } else {
761 return Err(NodeGraphError::NodeInvalidNode);
762 }
763
764 if let Some(input_node) = self
765 .nodes
766 .as_mut()
767 .iter_mut()
768 .find(|i| i.node_id == input_node_id)
769 {
770 if let Some(position) = input_node
771 .node
772 .connect_in
773 .iter()
774 .position(|i| i.input_index == input_index)
775 {
776 input_node.node.connect_in.remove(position);
777 }
778 } else {
779 return Err(NodeGraphError::NodeInvalidNode);
780 }
781 }
782
783 Ok(())
784 }
785
786 fn verify_nodetype_match(
788 &self,
789 output_node_id: NodeGraphNodeId,
790 output_index: usize,
791 input_node_id: NodeGraphNodeId,
792 input_index: usize,
793 ) -> Result<(), NodeGraphError> {
794 let output_node = self
795 .nodes
796 .iter()
797 .find(|i| i.node_id == output_node_id)
798 .ok_or(NodeGraphError::NodeInvalidNode)?;
799
800 let output_node_type = self
801 .node_types
802 .iter()
803 .find(|i| i.node_type_id == output_node.node.node_type)
804 .ok_or(NodeGraphError::NodeInvalidNode)?;
805
806 let output_type = output_node_type
807 .node_type_info
808 .outputs
809 .as_ref()
810 .get(output_index)
811 .copied()
812 .ok_or(NodeGraphError::NodeInvalidIndex)?;
813
814 let input_node = self
815 .nodes
816 .iter()
817 .find(|i| i.node_id == input_node_id)
818 .ok_or(NodeGraphError::NodeInvalidNode)?;
819
820 let input_node_type = self
821 .node_types
822 .iter()
823 .find(|i| i.node_type_id == input_node.node.node_type)
824 .ok_or(NodeGraphError::NodeInvalidNode)?;
825
826 let input_type = input_node_type
827 .node_type_info
828 .inputs
829 .as_ref()
830 .get(input_index)
831 .copied()
832 .ok_or(NodeGraphError::NodeInvalidIndex)?;
833
834 if input_type != output_type {
836 return Err(NodeGraphError::NodeMimeTypeMismatch);
837 }
838
839 Ok(())
840 }
841
842 pub fn dom(self) -> Dom {
843 static NODEGRAPH_CLASS: &[IdOrClass] = &[Class(AzString::from_const_str("nodegraph"))];
844
845 static NODEGRAPH_BACKGROUND: &[StyleBackgroundContent] = &[StyleBackgroundContent::Image(
846 AzString::from_const_str("nodegraph-background"),
847 )];
848
849 static NODEGRAPH_NODES_CONTAINER_CLASS: &[IdOrClass] =
850 &[Class(AzString::from_const_str("nodegraph-nodes-container"))];
851
852 static NODEGRAPH_NODES_CONTAINER_PROPS: &[CssPropertyWithConditions] = &[
853 CssPropertyWithConditions::simple(CssProperty::flex_grow(LayoutFlexGrow::const_new(1))),
854 CssPropertyWithConditions::simple(CssProperty::position(LayoutPosition::Absolute)),
855 ];
856
857 let nodegraph_wrapper_props = vec![
858 CssPropertyWithConditions::simple(CssProperty::overflow_x(LayoutOverflow::Hidden)),
859 CssPropertyWithConditions::simple(CssProperty::overflow_y(LayoutOverflow::Hidden)),
860 CssPropertyWithConditions::simple(CssProperty::flex_grow(LayoutFlexGrow::const_new(1))),
861 CssPropertyWithConditions::simple(CssProperty::background_content(
862 StyleBackgroundContentVec::from_const_slice(NODEGRAPH_BACKGROUND),
863 )),
864 CssPropertyWithConditions::simple(CssProperty::background_repeat(
865 vec![StyleBackgroundRepeat::PatternRepeat].into(),
866 )),
867 CssPropertyWithConditions::simple(CssProperty::background_position(
868 vec![StyleBackgroundPosition {
869 horizontal: BackgroundPositionHorizontal::Exact(PixelValue::const_px(0)),
870 vertical: BackgroundPositionVertical::Exact(PixelValue::const_px(0)),
871 }]
872 .into(),
873 )),
874 ];
875
876 let nodegraph_props = vec![
877 CssPropertyWithConditions::simple(CssProperty::overflow_x(LayoutOverflow::Hidden)),
878 CssPropertyWithConditions::simple(CssProperty::overflow_y(LayoutOverflow::Hidden)),
879 CssPropertyWithConditions::simple(CssProperty::flex_grow(LayoutFlexGrow::const_new(1))),
880 CssPropertyWithConditions::simple(CssProperty::position(LayoutPosition::Relative)),
881 ];
882
883 let node_connection_marker = RefAny::new(NodeConnectionMarkerDataset {});
884
885 let node_graph_local_dataset = RefAny::new(NodeGraphLocalDataset {
886 node_graph: self.clone(), last_input_or_output_clicked: None,
888 active_node_being_dragged: None,
889 node_connection_marker: node_connection_marker.clone(),
890 callbacks: self.callbacks.clone(),
891 });
892
893 let context_menu = Menu::create(
894 vec![MenuItem::String(
895 StringMenuItem::create(self.add_node_str.clone()).with_children(
896 self.node_types
897 .iter()
898 .map(
899 |NodeTypeIdInfoMap {
900 node_type_id,
901 node_type_info,
902 }| {
903 let context_menu_local_dataset =
904 RefAny::new(ContextMenuEntryLocalDataset {
905 node_type: *node_type_id,
906 backref: node_graph_local_dataset.clone(),
908 });
909
910 MenuItem::String(
911 StringMenuItem::create(
912 node_type_info.node_type_name.clone().into(),
913 )
914 .with_callback(
915 context_menu_local_dataset,
916 nodegraph_context_menu_click as usize,
917 ),
918 )
919 },
920 )
921 .collect::<Vec<_>>()
922 .into(),
923 ),
924 )]
925 .into(),
926 );
927
928 Dom::create_div()
929 .with_css_props(nodegraph_wrapper_props.into())
930 .with_context_menu(context_menu)
931 .with_children(
932 vec![Dom::create_div()
933 .with_ids_and_classes(IdOrClassVec::from_const_slice(NODEGRAPH_CLASS))
934 .with_css_props(nodegraph_props.into())
935 .with_callbacks(
936 vec![
937 CoreCallbackData {
938 event: EventFilter::Hover(HoverEventFilter::MouseOver),
939 refany: node_graph_local_dataset.clone(),
940 callback: CoreCallback {
941 cb: nodegraph_drag_graph_or_nodes as usize,
942 ctx: OptionRefAny::None,
943 },
944 },
945 CoreCallbackData {
946 event: EventFilter::Hover(HoverEventFilter::LeftMouseUp),
947 refany: node_graph_local_dataset.clone(),
948 callback: CoreCallback {
949 cb: nodegraph_unset_active_node as usize,
950 ctx: OptionRefAny::None,
951 },
952 },
953 ]
954 .into(),
955 )
956 .with_children({
957 vec![
958 render_connections(&self, node_connection_marker),
960 self.nodes
962 .iter()
963 .filter_map(|NodeIdNodeMap { node_id, node }| {
964 let node_type_info = self
965 .node_types
966 .iter()
967 .find(|i| i.node_type_id == node.node_type)?;
968 let node_local_dataset = NodeLocalDataset {
969 node_id: *node_id,
970 backref: node_graph_local_dataset.clone(),
971 };
972
973 Some(render_node(
974 node,
975 (self.offset.x, self.offset.y),
976 &node_type_info.node_type_info,
977 node_local_dataset,
978 self.scale_factor,
979 ))
980 })
981 .collect::<Dom>()
982 .with_ids_and_classes(IdOrClassVec::from_const_slice(
983 NODEGRAPH_NODES_CONTAINER_CLASS,
984 ))
985 .with_css_props(CssPropertyWithConditionsVec::from_const_slice(
986 NODEGRAPH_NODES_CONTAINER_PROPS,
987 )),
988 ]
989 .into()
990 })]
991 .into(),
992 )
993 .with_dataset(Some(node_graph_local_dataset).into())
994 }
995}
996
997struct NodeGraphLocalDataset {
1000 node_graph: NodeGraph,
1001 last_input_or_output_clicked: Option<(NodeGraphNodeId, InputOrOutput)>,
1002 active_node_being_dragged: Option<(NodeGraphNodeId, RefAny)>,
1004 node_connection_marker: RefAny, callbacks: NodeGraphCallbacks,
1006}
1007
1008struct ContextMenuEntryLocalDataset {
1009 node_type: NodeTypeId,
1010 backref: RefAny, }
1012
1013struct NodeConnectionMarkerDataset {}
1014
1015struct NodeLocalDataset {
1016 node_id: NodeGraphNodeId,
1017 backref: RefAny, }
1019
1020#[derive(Debug, Copy, Clone)]
1021enum InputOrOutput {
1022 Input(usize),
1023 Output(usize),
1024}
1025
1026struct NodeInputOutputLocalDataset {
1027 io_id: InputOrOutput,
1028 backref: RefAny, }
1030
1031struct NodeFieldLocalDataset {
1032 field_idx: usize,
1033 backref: RefAny, }
1035
1036#[derive(Copy, Clone)]
1037struct ConnectionLocalDataset {
1038 out_node_id: NodeGraphNodeId,
1039 out_idx: usize,
1040 in_node_id: NodeGraphNodeId,
1041 in_idx: usize,
1042 swap_vert: bool,
1043 swap_horz: bool,
1044 color: ColorU,
1045}
1046
1047fn render_node(
1048 node: &Node,
1049 graph_offset: (f32, f32),
1050 node_info: &NodeTypeInfo,
1051 mut node_local_dataset: NodeLocalDataset,
1052 scale_factor: f32,
1053) -> Dom {
1054 use azul_core::dom::{
1055 CssPropertyWithConditions, CssPropertyWithConditionsVec, Dom, DomVec, IdOrClass,
1056 IdOrClass::Class, IdOrClassVec,
1057 };
1058 use azul_css::*;
1059
1060 const STRING_9416190750059025162: AzString = AzString::from_const_str("Material Icons");
1061 const STRING_16146701490593874959: AzString = AzString::from_const_str("system:ui");
1062 const STYLE_BACKGROUND_CONTENT_524016094839686509_ITEMS: &[StyleBackgroundContent] =
1063 &[StyleBackgroundContent::Color(ColorU {
1064 r: 34,
1065 g: 34,
1066 b: 34,
1067 a: 255,
1068 })];
1069 const STYLE_BACKGROUND_CONTENT_10430246856047584562_ITEMS: &[StyleBackgroundContent] =
1070 &[StyleBackgroundContent::LinearGradient(LinearGradient {
1071 direction: Direction::FromTo(DirectionCorners {
1072 dir_from: DirectionCorner::Left,
1073 dir_to: DirectionCorner::Right,
1074 }),
1075 extend_mode: ExtendMode::Clamp,
1076 stops: NormalizedLinearColorStopVec::from_const_slice(
1077 LINEAR_COLOR_STOP_4373556077110009258_ITEMS,
1078 ),
1079 })];
1080 const STYLE_BACKGROUND_CONTENT_11535310356736632656_ITEMS: &[StyleBackgroundContent] =
1081 &[StyleBackgroundContent::RadialGradient(RadialGradient {
1082 shape: Shape::Ellipse,
1083 extend_mode: ExtendMode::Clamp,
1084 position: StyleBackgroundPosition {
1085 horizontal: BackgroundPositionHorizontal::Left,
1086 vertical: BackgroundPositionVertical::Top,
1087 },
1088 size: RadialGradientSize::FarthestCorner,
1089 stops: NormalizedLinearColorStopVec::from_const_slice(
1090 LINEAR_COLOR_STOP_15596411095679453272_ITEMS,
1091 ),
1092 })];
1093 const STYLE_BACKGROUND_CONTENT_11936041127084538304_ITEMS: &[StyleBackgroundContent] =
1094 &[StyleBackgroundContent::LinearGradient(LinearGradient {
1095 direction: Direction::FromTo(DirectionCorners {
1096 dir_from: DirectionCorner::Right,
1097 dir_to: DirectionCorner::Left,
1098 }),
1099 extend_mode: ExtendMode::Clamp,
1100 stops: NormalizedLinearColorStopVec::from_const_slice(
1101 LINEAR_COLOR_STOP_4373556077110009258_ITEMS,
1102 ),
1103 })];
1104 const STYLE_BACKGROUND_CONTENT_15813232491335471489_ITEMS: &[StyleBackgroundContent] =
1105 &[StyleBackgroundContent::Color(ColorU {
1106 r: 0,
1107 g: 0,
1108 b: 0,
1109 a: 85,
1110 })];
1111 const STYLE_BACKGROUND_CONTENT_17648039690071193942_ITEMS: &[StyleBackgroundContent] =
1112 &[StyleBackgroundContent::LinearGradient(LinearGradient {
1113 direction: Direction::FromTo(DirectionCorners {
1114 dir_from: DirectionCorner::Top,
1115 dir_to: DirectionCorner::Bottom,
1116 }),
1117 extend_mode: ExtendMode::Clamp,
1118 stops: NormalizedLinearColorStopVec::from_const_slice(
1119 LINEAR_COLOR_STOP_7397113864565941600_ITEMS,
1120 ),
1121 })];
1122 const STYLE_TRANSFORM_347117342922946953_ITEMS: &[StyleTransform] =
1123 &[StyleTransform::Translate(StyleTransformTranslate2D {
1124 x: PixelValue::const_px(200),
1125 y: PixelValue::const_px(100),
1126 })];
1127 const STYLE_TRANSFORM_14683950870521466298_ITEMS: &[StyleTransform] =
1128 &[StyleTransform::Translate(StyleTransformTranslate2D {
1129 x: PixelValue::const_px(240),
1130 y: PixelValue::const_px(-10),
1131 })];
1132 const STYLE_FONT_FAMILY_8122988506401935406_ITEMS: &[StyleFontFamily] =
1133 &[StyleFontFamily::System(STRING_16146701490593874959)];
1134 const STYLE_FONT_FAMILY_11383897783350685780_ITEMS: &[StyleFontFamily] =
1135 &[StyleFontFamily::System(STRING_9416190750059025162)];
1136 const LINEAR_COLOR_STOP_4373556077110009258_ITEMS: &[NormalizedLinearColorStop] = &[
1137 NormalizedLinearColorStop {
1138 offset: PercentageValue::const_new(20),
1139 color: ColorOrSystem::color(ColorU {
1140 r: 0,
1141 g: 0,
1142 b: 0,
1143 a: 204,
1144 }),
1145 },
1146 NormalizedLinearColorStop {
1147 offset: PercentageValue::const_new(100),
1148 color: ColorOrSystem::color(ColorU {
1149 r: 0,
1150 g: 0,
1151 b: 0,
1152 a: 0,
1153 }),
1154 },
1155 ];
1156 const LINEAR_COLOR_STOP_7397113864565941600_ITEMS: &[NormalizedLinearColorStop] = &[
1157 NormalizedLinearColorStop {
1158 offset: PercentageValue::const_new(0),
1159 color: ColorOrSystem::color(ColorU {
1160 r: 229,
1161 g: 57,
1162 b: 53,
1163 a: 255,
1164 }),
1165 },
1166 NormalizedLinearColorStop {
1167 offset: PercentageValue::const_new(100),
1168 color: ColorOrSystem::color(ColorU {
1169 r: 227,
1170 g: 93,
1171 b: 91,
1172 a: 255,
1173 }),
1174 },
1175 ];
1176 const LINEAR_COLOR_STOP_15596411095679453272_ITEMS: &[NormalizedLinearColorStop] = &[
1177 NormalizedLinearColorStop {
1178 offset: PercentageValue::const_new(0),
1179 color: ColorOrSystem::color(ColorU {
1180 r: 47,
1181 g: 49,
1182 b: 54,
1183 a: 255,
1184 }),
1185 },
1186 NormalizedLinearColorStop {
1187 offset: PercentageValue::const_new(50),
1188 color: ColorOrSystem::color(ColorU {
1189 r: 47,
1190 g: 49,
1191 b: 54,
1192 a: 255,
1193 }),
1194 },
1195 NormalizedLinearColorStop {
1196 offset: PercentageValue::const_new(100),
1197 color: ColorOrSystem::color(ColorU {
1198 r: 32,
1199 g: 34,
1200 b: 37,
1201 a: 255,
1202 }),
1203 },
1204 ];
1205
1206 const CSS_MATCH_10339190304804100510_PROPERTIES: &[CssPropertyWithConditions] = &[
1207 CssPropertyWithConditions::simple(CssProperty::Display(LayoutDisplayValue::Exact(
1209 LayoutDisplay::Flex,
1210 ))),
1211 CssPropertyWithConditions::simple(CssProperty::FlexDirection(
1212 LayoutFlexDirectionValue::Exact(LayoutFlexDirection::Column),
1213 )),
1214 CssPropertyWithConditions::simple(CssProperty::Left(LayoutLeftValue::Exact(LayoutLeft {
1215 inner: PixelValue::const_px(0),
1216 }))),
1217 CssPropertyWithConditions::simple(CssProperty::OverflowX(LayoutOverflowValue::Exact(
1218 LayoutOverflow::Visible,
1219 ))),
1220 CssPropertyWithConditions::simple(CssProperty::OverflowY(LayoutOverflowValue::Exact(
1221 LayoutOverflow::Visible,
1222 ))),
1223 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
1224 LayoutPosition::Absolute,
1225 ))),
1226 ];
1227 const CSS_MATCH_10339190304804100510: CssPropertyWithConditionsVec =
1228 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_10339190304804100510_PROPERTIES);
1229
1230 const CSS_MATCH_11452431279102104133_PROPERTIES: &[CssPropertyWithConditions] = &[
1231 CssPropertyWithConditions::simple(CssProperty::FontFamily(StyleFontFamilyVecValue::Exact(
1233 StyleFontFamilyVec::from_const_slice(STYLE_FONT_FAMILY_8122988506401935406_ITEMS),
1234 ))),
1235 CssPropertyWithConditions::simple(CssProperty::FontSize(StyleFontSizeValue::Exact(
1236 StyleFontSize {
1237 inner: PixelValue::const_px(12),
1238 },
1239 ))),
1240 CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
1241 LayoutHeight::Px(PixelValue::const_px(15)),
1242 ))),
1243 CssPropertyWithConditions::simple(CssProperty::TextAlign(StyleTextAlignValue::Exact(
1244 StyleTextAlign::Right,
1245 ))),
1246 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
1247 LayoutWidth::Px(PixelValue::const_px(100)),
1248 ))),
1249 ];
1250 const CSS_MATCH_11452431279102104133: CssPropertyWithConditionsVec =
1251 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_11452431279102104133_PROPERTIES);
1252
1253 const CSS_MATCH_1173826950760010563_PROPERTIES: &[CssPropertyWithConditions] = &[
1254 CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
1256 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
1257 inner: ColorU {
1258 r: 0,
1259 g: 131,
1260 b: 176,
1261 a: 119,
1262 },
1263 }),
1264 )),
1265 CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
1266 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
1267 inner: ColorU {
1268 r: 0,
1269 g: 131,
1270 b: 176,
1271 a: 119,
1272 },
1273 }),
1274 )),
1275 CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
1276 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
1277 inner: ColorU {
1278 r: 0,
1279 g: 131,
1280 b: 176,
1281 a: 119,
1282 },
1283 }),
1284 )),
1285 CssPropertyWithConditions::simple(CssProperty::BorderBottomColor(
1286 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
1287 inner: ColorU {
1288 r: 0,
1289 g: 131,
1290 b: 176,
1291 a: 119,
1292 },
1293 }),
1294 )),
1295 CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
1296 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
1297 inner: BorderStyle::Solid,
1298 }),
1299 )),
1300 CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
1301 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
1302 inner: BorderStyle::Solid,
1303 }),
1304 )),
1305 CssPropertyWithConditions::simple(CssProperty::BorderLeftStyle(
1306 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
1307 inner: BorderStyle::Solid,
1308 }),
1309 )),
1310 CssPropertyWithConditions::simple(CssProperty::BorderBottomStyle(
1311 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
1312 inner: BorderStyle::Solid,
1313 }),
1314 )),
1315 CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
1316 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
1317 inner: PixelValue::const_px(1),
1318 }),
1319 )),
1320 CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
1321 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
1322 inner: PixelValue::const_px(1),
1323 }),
1324 )),
1325 CssPropertyWithConditions::simple(CssProperty::BorderLeftWidth(
1326 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
1327 inner: PixelValue::const_px(1),
1328 }),
1329 )),
1330 CssPropertyWithConditions::simple(CssProperty::BorderBottomWidth(
1331 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
1332 inner: PixelValue::const_px(1),
1333 }),
1334 )),
1335 CssPropertyWithConditions::simple(CssProperty::AlignItems(LayoutAlignItemsValue::Exact(
1337 LayoutAlignItems::Center,
1338 ))),
1339 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
1340 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
1341 STYLE_BACKGROUND_CONTENT_524016094839686509_ITEMS,
1342 )),
1343 )),
1344 CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
1345 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
1346 inner: ColorU {
1347 r: 54,
1348 g: 57,
1349 b: 63,
1350 a: 255,
1351 },
1352 }),
1353 )),
1354 CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
1355 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
1356 inner: ColorU {
1357 r: 54,
1358 g: 57,
1359 b: 63,
1360 a: 255,
1361 },
1362 }),
1363 )),
1364 CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
1365 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
1366 inner: ColorU {
1367 r: 54,
1368 g: 57,
1369 b: 63,
1370 a: 255,
1371 },
1372 }),
1373 )),
1374 CssPropertyWithConditions::simple(CssProperty::BorderBottomColor(
1375 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
1376 inner: ColorU {
1377 r: 54,
1378 g: 57,
1379 b: 63,
1380 a: 255,
1381 },
1382 }),
1383 )),
1384 CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
1385 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
1386 inner: BorderStyle::Solid,
1387 }),
1388 )),
1389 CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
1390 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
1391 inner: BorderStyle::Solid,
1392 }),
1393 )),
1394 CssPropertyWithConditions::simple(CssProperty::BorderLeftStyle(
1395 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
1396 inner: BorderStyle::Solid,
1397 }),
1398 )),
1399 CssPropertyWithConditions::simple(CssProperty::BorderBottomStyle(
1400 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
1401 inner: BorderStyle::Solid,
1402 }),
1403 )),
1404 CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
1405 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
1406 inner: PixelValue::const_px(1),
1407 }),
1408 )),
1409 CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
1410 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
1411 inner: PixelValue::const_px(1),
1412 }),
1413 )),
1414 CssPropertyWithConditions::simple(CssProperty::BorderLeftWidth(
1415 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
1416 inner: PixelValue::const_px(1),
1417 }),
1418 )),
1419 CssPropertyWithConditions::simple(CssProperty::BorderBottomWidth(
1420 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
1421 inner: PixelValue::const_px(1),
1422 }),
1423 )),
1424 CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
1425 LayoutFlexGrow {
1426 inner: FloatValue::const_new(1),
1427 },
1428 ))),
1429 CssPropertyWithConditions::simple(CssProperty::TextAlign(StyleTextAlignValue::Exact(
1430 StyleTextAlign::Left,
1431 ))),
1432 ];
1433 const CSS_MATCH_1173826950760010563: CssPropertyWithConditionsVec =
1434 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_1173826950760010563_PROPERTIES);
1435
1436 const CSS_MATCH_1198521124955124418_PROPERTIES: &[CssPropertyWithConditions] = &[
1437 CssPropertyWithConditions::simple(CssProperty::AlignItems(LayoutAlignItemsValue::Exact(
1439 LayoutAlignItems::Center,
1440 ))),
1441 CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
1442 LayoutFlexGrow {
1443 inner: FloatValue::const_new(1),
1444 },
1445 ))),
1446 CssPropertyWithConditions::simple(CssProperty::MaxWidth(LayoutMaxWidthValue::Exact(
1447 LayoutMaxWidth {
1448 inner: PixelValue::const_px(120),
1449 },
1450 ))),
1451 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
1452 LayoutPaddingLeft {
1453 inner: PixelValue::const_px(10),
1454 },
1455 ))),
1456 CssPropertyWithConditions::simple(CssProperty::TextAlign(StyleTextAlignValue::Exact(
1457 StyleTextAlign::Left,
1458 ))),
1459 ];
1460 const CSS_MATCH_1198521124955124418: CssPropertyWithConditionsVec =
1461 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_1198521124955124418_PROPERTIES);
1462
1463 const CSS_MATCH_12038890904436132038_PROPERTIES: &[CssPropertyWithConditions] = &[
1464 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
1466 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
1467 STYLE_BACKGROUND_CONTENT_10430246856047584562_ITEMS,
1468 )),
1469 )),
1470 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
1471 LayoutPaddingLeft {
1472 inner: PixelValue::const_px(5),
1473 },
1474 ))),
1475 ];
1476 const CSS_MATCH_12038890904436132038: CssPropertyWithConditionsVec =
1477 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_12038890904436132038_PROPERTIES);
1478
1479 const CSS_MATCH_12400244273289328300_PROPERTIES: &[CssPropertyWithConditions] = &[
1480 CssPropertyWithConditions::simple(CssProperty::Display(LayoutDisplayValue::Exact(
1482 LayoutDisplay::Flex,
1483 ))),
1484 CssPropertyWithConditions::simple(CssProperty::FlexDirection(
1485 LayoutFlexDirectionValue::Exact(LayoutFlexDirection::Row),
1486 )),
1487 CssPropertyWithConditions::simple(CssProperty::MarginTop(LayoutMarginTopValue::Exact(
1488 LayoutMarginTop {
1489 inner: PixelValue::const_px(10),
1490 },
1491 ))),
1492 ];
1493 const CSS_MATCH_12400244273289328300: CssPropertyWithConditionsVec =
1494 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_12400244273289328300_PROPERTIES);
1495
1496 const CSS_MATCH_14906563417280941890_PROPERTIES: &[CssPropertyWithConditions] = &[
1497 CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
1499 LayoutFlexGrow {
1500 inner: FloatValue::const_new(0),
1501 },
1502 ))),
1503 CssPropertyWithConditions::simple(CssProperty::OverflowX(LayoutOverflowValue::Exact(
1504 LayoutOverflow::Visible,
1505 ))),
1506 CssPropertyWithConditions::simple(CssProperty::OverflowY(LayoutOverflowValue::Exact(
1507 LayoutOverflow::Visible,
1508 ))),
1509 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
1510 LayoutPosition::Relative,
1511 ))),
1512 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
1513 LayoutWidth::Px(PixelValue::const_px(0)),
1514 ))),
1515 ];
1516 const CSS_MATCH_14906563417280941890: CssPropertyWithConditionsVec =
1517 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_14906563417280941890_PROPERTIES);
1518
1519 const CSS_MATCH_16946967739775705757_PROPERTIES: &[CssPropertyWithConditions] = &[
1520 CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
1522 LayoutFlexGrow {
1523 inner: FloatValue::const_new(0),
1524 },
1525 ))),
1526 CssPropertyWithConditions::simple(CssProperty::OverflowX(LayoutOverflowValue::Exact(
1527 LayoutOverflow::Visible,
1528 ))),
1529 CssPropertyWithConditions::simple(CssProperty::OverflowY(LayoutOverflowValue::Exact(
1530 LayoutOverflow::Visible,
1531 ))),
1532 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
1533 LayoutPosition::Relative,
1534 ))),
1535 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
1536 LayoutWidth::Px(PixelValue::const_px(0)),
1537 ))),
1538 ];
1539 const CSS_MATCH_16946967739775705757: CssPropertyWithConditionsVec =
1540 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_16946967739775705757_PROPERTIES);
1541
1542 const CSS_MATCH_1739273067404038547_PROPERTIES: &[CssPropertyWithConditions] = &[
1543 CssPropertyWithConditions::simple(CssProperty::FontSize(StyleFontSizeValue::Exact(
1545 StyleFontSize {
1546 inner: PixelValue::const_px(18),
1547 },
1548 ))),
1549 CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
1550 LayoutHeight::Px(PixelValue::const_px(50)),
1551 ))),
1552 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
1553 LayoutPaddingLeft {
1554 inner: PixelValue::const_px(5),
1555 },
1556 ))),
1557 CssPropertyWithConditions::simple(CssProperty::PaddingTop(LayoutPaddingTopValue::Exact(
1558 LayoutPaddingTop {
1559 inner: PixelValue::const_px(10),
1560 },
1561 ))),
1562 ];
1563 const CSS_MATCH_1739273067404038547: CssPropertyWithConditionsVec =
1564 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_1739273067404038547_PROPERTIES);
1565
1566 const CSS_MATCH_2008162367868363199_PROPERTIES: &[CssPropertyWithConditions] = &[
1567 CssPropertyWithConditions::simple(CssProperty::FontFamily(StyleFontFamilyVecValue::Exact(
1569 StyleFontFamilyVec::from_const_slice(STYLE_FONT_FAMILY_8122988506401935406_ITEMS),
1570 ))),
1571 CssPropertyWithConditions::simple(CssProperty::FontSize(StyleFontSizeValue::Exact(
1572 StyleFontSize {
1573 inner: PixelValue::const_px(12),
1574 },
1575 ))),
1576 CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
1577 LayoutHeight::Px(PixelValue::const_px(15)),
1578 ))),
1579 CssPropertyWithConditions::simple(CssProperty::TextAlign(StyleTextAlignValue::Exact(
1580 StyleTextAlign::Left,
1581 ))),
1582 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
1583 LayoutWidth::Px(PixelValue::const_px(100)),
1584 ))),
1585 ];
1586 const CSS_MATCH_2008162367868363199: CssPropertyWithConditionsVec =
1587 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_2008162367868363199_PROPERTIES);
1588
1589 const CSS_MATCH_2639191696846875011_PROPERTIES: &[CssPropertyWithConditions] = &[
1590 CssPropertyWithConditions::simple(CssProperty::FlexDirection(
1592 LayoutFlexDirectionValue::Exact(LayoutFlexDirection::Column),
1593 )),
1594 CssPropertyWithConditions::simple(CssProperty::PaddingTop(LayoutPaddingTopValue::Exact(
1595 LayoutPaddingTop {
1596 inner: PixelValue::const_px(3),
1597 },
1598 ))),
1599 CssPropertyWithConditions::simple(CssProperty::PaddingBottom(
1600 LayoutPaddingBottomValue::Exact(LayoutPaddingBottom {
1601 inner: PixelValue::const_px(3),
1602 }),
1603 )),
1604 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
1605 LayoutPaddingLeft {
1606 inner: PixelValue::const_px(5),
1607 },
1608 ))),
1609 CssPropertyWithConditions::simple(CssProperty::PaddingRight(
1610 LayoutPaddingRightValue::Exact(LayoutPaddingRight {
1611 inner: PixelValue::const_px(5),
1612 }),
1613 )),
1614 ];
1615 const CSS_MATCH_2639191696846875011: CssPropertyWithConditionsVec =
1616 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_2639191696846875011_PROPERTIES);
1617
1618 const CSS_MATCH_3354247437065914166_PROPERTIES: &[CssPropertyWithConditions] = &[
1619 CssPropertyWithConditions::simple(CssProperty::FlexDirection(
1621 LayoutFlexDirectionValue::Exact(LayoutFlexDirection::Row),
1622 )),
1623 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
1624 LayoutPosition::Relative,
1625 ))),
1626 ];
1627 const CSS_MATCH_3354247437065914166: CssPropertyWithConditionsVec =
1628 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_3354247437065914166_PROPERTIES);
1629
1630 const CSS_MATCH_4700400755767504372_PROPERTIES: &[CssPropertyWithConditions] = &[
1631 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
1633 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
1634 STYLE_BACKGROUND_CONTENT_11936041127084538304_ITEMS,
1635 )),
1636 )),
1637 CssPropertyWithConditions::simple(CssProperty::PaddingRight(
1638 LayoutPaddingRightValue::Exact(LayoutPaddingRight {
1639 inner: PixelValue::const_px(5),
1640 }),
1641 )),
1642 ];
1643 const CSS_MATCH_4700400755767504372: CssPropertyWithConditionsVec =
1644 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_4700400755767504372_PROPERTIES);
1645
1646 const CSS_MATCH_705881630351954657_PROPERTIES: &[CssPropertyWithConditions] = &[
1647 CssPropertyWithConditions::simple(CssProperty::Display(LayoutDisplayValue::Exact(
1649 LayoutDisplay::Flex,
1650 ))),
1651 CssPropertyWithConditions::simple(CssProperty::FlexDirection(
1652 LayoutFlexDirectionValue::Exact(LayoutFlexDirection::Column),
1653 )),
1654 CssPropertyWithConditions::simple(CssProperty::OverflowX(LayoutOverflowValue::Exact(
1655 LayoutOverflow::Visible,
1656 ))),
1657 CssPropertyWithConditions::simple(CssProperty::OverflowY(LayoutOverflowValue::Exact(
1658 LayoutOverflow::Visible,
1659 ))),
1660 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
1661 LayoutPosition::Absolute,
1662 ))),
1663 CssPropertyWithConditions::simple(CssProperty::Right(LayoutRightValue::Exact(
1664 LayoutRight {
1665 inner: PixelValue::const_px(0),
1666 },
1667 ))),
1668 ];
1669 const CSS_MATCH_705881630351954657: CssPropertyWithConditionsVec =
1670 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_705881630351954657_PROPERTIES);
1671
1672 const CSS_MATCH_7395766480280098891_PROPERTIES: &[CssPropertyWithConditions] = &[
1673 CssPropertyWithConditions::simple(CssProperty::AlignItems(LayoutAlignItemsValue::Exact(
1675 LayoutAlignItems::Center,
1676 ))),
1677 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
1678 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
1679 STYLE_BACKGROUND_CONTENT_17648039690071193942_ITEMS,
1680 )),
1681 )),
1682 CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
1683 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
1684 inner: ColorU {
1685 r: 255,
1686 g: 255,
1687 b: 255,
1688 a: 153,
1689 },
1690 }),
1691 )),
1692 CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
1693 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
1694 inner: ColorU {
1695 r: 255,
1696 g: 255,
1697 b: 255,
1698 a: 153,
1699 },
1700 }),
1701 )),
1702 CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
1703 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
1704 inner: ColorU {
1705 r: 255,
1706 g: 255,
1707 b: 255,
1708 a: 153,
1709 },
1710 }),
1711 )),
1712 CssPropertyWithConditions::simple(CssProperty::BorderBottomColor(
1713 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
1714 inner: ColorU {
1715 r: 255,
1716 g: 255,
1717 b: 255,
1718 a: 153,
1719 },
1720 }),
1721 )),
1722 CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
1723 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
1724 inner: BorderStyle::Solid,
1725 }),
1726 )),
1727 CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
1728 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
1729 inner: BorderStyle::Solid,
1730 }),
1731 )),
1732 CssPropertyWithConditions::simple(CssProperty::BorderLeftStyle(
1733 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
1734 inner: BorderStyle::Solid,
1735 }),
1736 )),
1737 CssPropertyWithConditions::simple(CssProperty::BorderBottomStyle(
1738 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
1739 inner: BorderStyle::Solid,
1740 }),
1741 )),
1742 CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
1743 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
1744 inner: PixelValue::const_px(1),
1745 }),
1746 )),
1747 CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
1748 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
1749 inner: PixelValue::const_px(1),
1750 }),
1751 )),
1752 CssPropertyWithConditions::simple(CssProperty::BorderLeftWidth(
1753 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
1754 inner: PixelValue::const_px(1),
1755 }),
1756 )),
1757 CssPropertyWithConditions::simple(CssProperty::BorderBottomWidth(
1758 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
1759 inner: PixelValue::const_px(1),
1760 }),
1761 )),
1762 CssPropertyWithConditions::simple(CssProperty::BoxShadowLeft(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
1763 StyleBoxShadow {
1764 offset_x: PixelValueNoPercent {
1765 inner: PixelValue::const_px(0),
1766 },
1767 offset_y: PixelValueNoPercent {
1768 inner: PixelValue::const_px(0),
1769 },
1770 color: ColorU {
1771 r: 229,
1772 g: 57,
1773 b: 53,
1774 a: 255,
1775 },
1776 blur_radius: PixelValueNoPercent {
1777 inner: PixelValue::const_px(2),
1778 },
1779 spread_radius: PixelValueNoPercent {
1780 inner: PixelValue::const_px(0),
1781 },
1782 clip_mode: BoxShadowClipMode::Outset,
1783 },
1784 )))),
1785 CssPropertyWithConditions::simple(CssProperty::BoxShadowRight(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
1786 StyleBoxShadow {
1787 offset_x: PixelValueNoPercent {
1788 inner: PixelValue::const_px(0),
1789 },
1790 offset_y: PixelValueNoPercent {
1791 inner: PixelValue::const_px(0),
1792 },
1793 color: ColorU {
1794 r: 229,
1795 g: 57,
1796 b: 53,
1797 a: 255,
1798 },
1799 blur_radius: PixelValueNoPercent {
1800 inner: PixelValue::const_px(2),
1801 },
1802 spread_radius: PixelValueNoPercent {
1803 inner: PixelValue::const_px(0),
1804 },
1805 clip_mode: BoxShadowClipMode::Outset,
1806 },
1807 )))),
1808 CssPropertyWithConditions::simple(CssProperty::BoxShadowTop(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
1809 StyleBoxShadow {
1810 offset_x: PixelValueNoPercent {
1811 inner: PixelValue::const_px(0),
1812 },
1813 offset_y: PixelValueNoPercent {
1814 inner: PixelValue::const_px(0),
1815 },
1816 color: ColorU {
1817 r: 229,
1818 g: 57,
1819 b: 53,
1820 a: 255,
1821 },
1822 blur_radius: PixelValueNoPercent {
1823 inner: PixelValue::const_px(2),
1824 },
1825 spread_radius: PixelValueNoPercent {
1826 inner: PixelValue::const_px(0),
1827 },
1828 clip_mode: BoxShadowClipMode::Outset,
1829 },
1830 )))),
1831 CssPropertyWithConditions::simple(CssProperty::BoxShadowBottom(
1832 StyleBoxShadowValue::Exact(BoxOrStatic::Static(&StyleBoxShadow {
1833 offset_x: PixelValueNoPercent {
1834 inner: PixelValue::const_px(0),
1835 },
1836 offset_y: PixelValueNoPercent {
1837 inner: PixelValue::const_px(0),
1838 },
1839 color: ColorU {
1840 r: 229,
1841 g: 57,
1842 b: 53,
1843 a: 255,
1844 },
1845 blur_radius: PixelValueNoPercent {
1846 inner: PixelValue::const_px(2),
1847 },
1848 spread_radius: PixelValueNoPercent {
1849 inner: PixelValue::const_px(0),
1850 },
1851 clip_mode: BoxShadowClipMode::Outset,
1852 })),
1853 )),
1854 CssPropertyWithConditions::simple(CssProperty::Cursor(StyleCursorValue::Exact(
1855 StyleCursor::Pointer,
1856 ))),
1857 CssPropertyWithConditions::simple(CssProperty::FontFamily(StyleFontFamilyVecValue::Exact(
1858 StyleFontFamilyVec::from_const_slice(STYLE_FONT_FAMILY_11383897783350685780_ITEMS),
1859 ))),
1860 CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
1861 LayoutHeight::Px(PixelValue::const_px(20)),
1862 ))),
1863 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
1864 LayoutPosition::Absolute,
1865 ))),
1866 CssPropertyWithConditions::simple(CssProperty::TextAlign(StyleTextAlignValue::Exact(
1867 StyleTextAlign::Center,
1868 ))),
1869 CssPropertyWithConditions::simple(CssProperty::Transform(StyleTransformVecValue::Exact(
1870 StyleTransformVec::from_const_slice(STYLE_TRANSFORM_14683950870521466298_ITEMS),
1871 ))),
1872 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
1873 LayoutWidth::Px(PixelValue::const_px(20)),
1874 ))),
1875 ];
1876 const CSS_MATCH_7395766480280098891: CssPropertyWithConditionsVec =
1877 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_7395766480280098891_PROPERTIES);
1878
1879 const CSS_MATCH_7432473243011547380_PROPERTIES: &[CssPropertyWithConditions] = &[
1880 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
1882 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
1883 STYLE_BACKGROUND_CONTENT_15813232491335471489_ITEMS,
1884 )),
1885 )),
1886 CssPropertyWithConditions::simple(CssProperty::BoxShadowLeft(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
1887 StyleBoxShadow {
1888 offset_x: PixelValueNoPercent {
1889 inner: PixelValue::const_px(0),
1890 },
1891 offset_y: PixelValueNoPercent {
1892 inner: PixelValue::const_px(0),
1893 },
1894 color: ColorU {
1895 r: 0,
1896 g: 0,
1897 b: 0,
1898 a: 255,
1899 },
1900 blur_radius: PixelValueNoPercent {
1901 inner: PixelValue::const_px(4),
1902 },
1903 spread_radius: PixelValueNoPercent {
1904 inner: PixelValue::const_px(0),
1905 },
1906 clip_mode: BoxShadowClipMode::Inset,
1907 },
1908 )))),
1909 CssPropertyWithConditions::simple(CssProperty::BoxShadowRight(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
1910 StyleBoxShadow {
1911 offset_x: PixelValueNoPercent {
1912 inner: PixelValue::const_px(0),
1913 },
1914 offset_y: PixelValueNoPercent {
1915 inner: PixelValue::const_px(0),
1916 },
1917 color: ColorU {
1918 r: 0,
1919 g: 0,
1920 b: 0,
1921 a: 255,
1922 },
1923 blur_radius: PixelValueNoPercent {
1924 inner: PixelValue::const_px(4),
1925 },
1926 spread_radius: PixelValueNoPercent {
1927 inner: PixelValue::const_px(0),
1928 },
1929 clip_mode: BoxShadowClipMode::Inset,
1930 },
1931 )))),
1932 CssPropertyWithConditions::simple(CssProperty::BoxShadowTop(StyleBoxShadowValue::Exact(BoxOrStatic::Static(&
1933 StyleBoxShadow {
1934 offset_x: PixelValueNoPercent {
1935 inner: PixelValue::const_px(0),
1936 },
1937 offset_y: PixelValueNoPercent {
1938 inner: PixelValue::const_px(0),
1939 },
1940 color: ColorU {
1941 r: 0,
1942 g: 0,
1943 b: 0,
1944 a: 255,
1945 },
1946 blur_radius: PixelValueNoPercent {
1947 inner: PixelValue::const_px(4),
1948 },
1949 spread_radius: PixelValueNoPercent {
1950 inner: PixelValue::const_px(0),
1951 },
1952 clip_mode: BoxShadowClipMode::Inset,
1953 },
1954 )))),
1955 CssPropertyWithConditions::simple(CssProperty::BoxShadowBottom(
1956 StyleBoxShadowValue::Exact(BoxOrStatic::Static(&StyleBoxShadow {
1957 offset_x: PixelValueNoPercent {
1958 inner: PixelValue::const_px(0),
1959 },
1960 offset_y: PixelValueNoPercent {
1961 inner: PixelValue::const_px(0),
1962 },
1963 color: ColorU {
1964 r: 0,
1965 g: 0,
1966 b: 0,
1967 a: 255,
1968 },
1969 blur_radius: PixelValueNoPercent {
1970 inner: PixelValue::const_px(4),
1971 },
1972 spread_radius: PixelValueNoPercent {
1973 inner: PixelValue::const_px(0),
1974 },
1975 clip_mode: BoxShadowClipMode::Inset,
1976 })),
1977 )),
1978 CssPropertyWithConditions::simple(CssProperty::FlexGrow(LayoutFlexGrowValue::Exact(
1979 LayoutFlexGrow {
1980 inner: FloatValue::const_new(1),
1981 },
1982 ))),
1983 ];
1984 const CSS_MATCH_7432473243011547380: CssPropertyWithConditionsVec =
1985 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_7432473243011547380_PROPERTIES);
1986
1987 const CSS_MATCH_9863994880298313101_PROPERTIES: &[CssPropertyWithConditions] = &[
1988 CssPropertyWithConditions::simple(CssProperty::Display(LayoutDisplayValue::Exact(
1990 LayoutDisplay::Flex,
1991 ))),
1992 CssPropertyWithConditions::simple(CssProperty::FlexDirection(
1993 LayoutFlexDirectionValue::Exact(LayoutFlexDirection::Row),
1994 )),
1995 CssPropertyWithConditions::simple(CssProperty::MarginTop(LayoutMarginTopValue::Exact(
1996 LayoutMarginTop {
1997 inner: PixelValue::const_px(10),
1998 },
1999 ))),
2000 ];
2001 const CSS_MATCH_9863994880298313101: CssPropertyWithConditionsVec =
2002 CssPropertyWithConditionsVec::from_const_slice(CSS_MATCH_9863994880298313101_PROPERTIES);
2003
2004 let node_transform = StyleTransformTranslate2D {
2007 x: PixelValue::px(graph_offset.0 + node.position.x),
2008 y: PixelValue::px(graph_offset.1 + node.position.y),
2009 };
2010
2011 let inputs = node_info
2013 .inputs
2014 .iter()
2015 .filter_map(|io_id| {
2016 let node_graph_ref = node_local_dataset
2017 .backref
2018 .downcast_ref::<NodeGraphLocalDataset>()?;
2019 let io_info = node_graph_ref
2020 .node_graph
2021 .input_output_types
2022 .iter()
2023 .find(|i| i.io_type_id == *io_id)?;
2024 Some((
2025 io_info.io_info.data_type.clone(),
2026 io_info.io_info.color.clone(),
2027 ))
2028 })
2029 .collect::<Vec<_>>();
2030
2031 let outputs = node_info
2032 .outputs
2033 .iter()
2034 .filter_map(|io_id| {
2035 let node_graph_ref = node_local_dataset
2036 .backref
2037 .downcast_ref::<NodeGraphLocalDataset>()?;
2038 let io_info = node_graph_ref
2039 .node_graph
2040 .input_output_types
2041 .iter()
2042 .find(|i| i.io_type_id == *io_id)?;
2043 Some((
2044 io_info.io_info.data_type.clone(),
2045 io_info.io_info.color.clone(),
2046 ))
2047 })
2048 .collect::<Vec<_>>();
2049
2050 let node_local_dataset = RefAny::new(node_local_dataset);
2051
2052 Dom::create_div()
2053 .with_css_props(vec![
2054 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
2055 LayoutPosition::Absolute,
2056 ))),
2057 ].into())
2058 .with_children(vec![
2059 Dom::create_div()
2060 .with_callbacks(vec![
2061 CoreCallbackData {
2062 event: EventFilter::Hover(HoverEventFilter::LeftMouseDown),
2063 refany: node_local_dataset.clone(),
2064 callback: CoreCallback { cb: nodegraph_set_active_node as usize, ctx: OptionRefAny::None },
2065 },
2066 ].into())
2067 .with_css_props(vec![
2068 CssPropertyWithConditions::simple(CssProperty::OverflowX(
2070 LayoutOverflowValue::Exact(LayoutOverflow::Visible)
2071 )),
2072 CssPropertyWithConditions::simple(CssProperty::Position(LayoutPositionValue::Exact(
2073 LayoutPosition::Relative,
2074 ))),
2075 CssPropertyWithConditions::simple(CssProperty::OverflowY(
2076 LayoutOverflowValue::Exact(LayoutOverflow::Visible)
2077 )),
2078 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
2079 StyleBackgroundContentVecValue::Exact(StyleBackgroundContentVec::from_const_slice(
2080 STYLE_BACKGROUND_CONTENT_11535310356736632656_ITEMS,
2081 )),
2082 )),
2083 CssPropertyWithConditions::simple(CssProperty::BorderTopColor(
2084 StyleBorderTopColorValue::Exact(StyleBorderTopColor {
2085 inner: ColorU {
2086 r: 0,
2087 g: 180,
2088 b: 219,
2089 a: 255,
2090 },
2091 }),
2092 )),
2093 CssPropertyWithConditions::simple(CssProperty::BorderRightColor(
2094 StyleBorderRightColorValue::Exact(StyleBorderRightColor {
2095 inner: ColorU {
2096 r: 0,
2097 g: 180,
2098 b: 219,
2099 a: 255,
2100 },
2101 }),
2102 )),
2103 CssPropertyWithConditions::simple(CssProperty::BorderLeftColor(
2104 StyleBorderLeftColorValue::Exact(StyleBorderLeftColor {
2105 inner: ColorU {
2106 r: 0,
2107 g: 180,
2108 b: 219,
2109 a: 255,
2110 },
2111 }),
2112 )),
2113 CssPropertyWithConditions::simple(CssProperty::BorderBottomColor(
2114 StyleBorderBottomColorValue::Exact(StyleBorderBottomColor {
2115 inner: ColorU {
2116 r: 0,
2117 g: 180,
2118 b: 219,
2119 a: 255,
2120 },
2121 }),
2122 )),
2123 CssPropertyWithConditions::simple(CssProperty::BorderTopStyle(
2124 StyleBorderTopStyleValue::Exact(StyleBorderTopStyle {
2125 inner: BorderStyle::Solid,
2126 }),
2127 )),
2128 CssPropertyWithConditions::simple(CssProperty::BorderRightStyle(
2129 StyleBorderRightStyleValue::Exact(StyleBorderRightStyle {
2130 inner: BorderStyle::Solid,
2131 }),
2132 )),
2133 CssPropertyWithConditions::simple(CssProperty::BorderLeftStyle(
2134 StyleBorderLeftStyleValue::Exact(StyleBorderLeftStyle {
2135 inner: BorderStyle::Solid,
2136 }),
2137 )),
2138 CssPropertyWithConditions::simple(CssProperty::BorderBottomStyle(
2139 StyleBorderBottomStyleValue::Exact(StyleBorderBottomStyle {
2140 inner: BorderStyle::Solid,
2141 }),
2142 )),
2143 CssPropertyWithConditions::simple(CssProperty::BorderTopWidth(
2144 LayoutBorderTopWidthValue::Exact(LayoutBorderTopWidth {
2145 inner: PixelValue::const_px(1),
2146 }),
2147 )),
2148 CssPropertyWithConditions::simple(CssProperty::BorderRightWidth(
2149 LayoutBorderRightWidthValue::Exact(LayoutBorderRightWidth {
2150 inner: PixelValue::const_px(1),
2151 }),
2152 )),
2153 CssPropertyWithConditions::simple(CssProperty::BorderLeftWidth(
2154 LayoutBorderLeftWidthValue::Exact(LayoutBorderLeftWidth {
2155 inner: PixelValue::const_px(1),
2156 }),
2157 )),
2158 CssPropertyWithConditions::simple(CssProperty::BorderBottomWidth(
2159 LayoutBorderBottomWidthValue::Exact(LayoutBorderBottomWidth {
2160 inner: PixelValue::const_px(1),
2161 }),
2162 )),
2163 CssPropertyWithConditions::simple(CssProperty::BoxShadowLeft(StyleBoxShadowValue::Exact(BoxOrStatic::heap(
2164 StyleBoxShadow {
2165 offset_x: PixelValueNoPercent { inner: PixelValue::const_px(0) }, offset_y: PixelValueNoPercent { inner: PixelValue::const_px(0) },
2166 color: ColorU {
2167 r: 0,
2168 g: 131,
2169 b: 176,
2170 a: 119,
2171 },
2172 blur_radius: PixelValueNoPercent {
2173 inner: PixelValue::const_px(3),
2174 },
2175 spread_radius: PixelValueNoPercent {
2176 inner: PixelValue::const_px(0),
2177 },
2178 clip_mode: BoxShadowClipMode::Outset,
2179 },
2180 )))),
2181 CssPropertyWithConditions::simple(CssProperty::BoxShadowRight(StyleBoxShadowValue::Exact(BoxOrStatic::heap(
2182 StyleBoxShadow {
2183 offset_x: PixelValueNoPercent { inner: PixelValue::const_px(0) }, offset_y: PixelValueNoPercent { inner: PixelValue::const_px(0) },
2184 color: ColorU {
2185 r: 0,
2186 g: 131,
2187 b: 176,
2188 a: 119,
2189 },
2190 blur_radius: PixelValueNoPercent {
2191 inner: PixelValue::const_px(3),
2192 },
2193 spread_radius: PixelValueNoPercent {
2194 inner: PixelValue::const_px(0),
2195 },
2196 clip_mode: BoxShadowClipMode::Outset,
2197 },
2198 )))),
2199 CssPropertyWithConditions::simple(CssProperty::BoxShadowTop(StyleBoxShadowValue::Exact(BoxOrStatic::heap(
2200 StyleBoxShadow {
2201 offset_x: PixelValueNoPercent { inner: PixelValue::const_px(0) }, offset_y: PixelValueNoPercent { inner: PixelValue::const_px(0) },
2202 color: ColorU {
2203 r: 0,
2204 g: 131,
2205 b: 176,
2206 a: 119,
2207 },
2208 blur_radius: PixelValueNoPercent {
2209 inner: PixelValue::const_px(3),
2210 },
2211 spread_radius: PixelValueNoPercent {
2212 inner: PixelValue::const_px(0),
2213 },
2214 clip_mode: BoxShadowClipMode::Outset,
2215 },
2216 )))),
2217 CssPropertyWithConditions::simple(CssProperty::BoxShadowBottom(
2218 StyleBoxShadowValue::Exact(BoxOrStatic::heap(StyleBoxShadow {
2219 offset_x: PixelValueNoPercent { inner: PixelValue::const_px(0) }, offset_y: PixelValueNoPercent { inner: PixelValue::const_px(0) },
2220 color: ColorU {
2221 r: 0,
2222 g: 131,
2223 b: 176,
2224 a: 119,
2225 },
2226 blur_radius: PixelValueNoPercent {
2227 inner: PixelValue::const_px(3),
2228 },
2229 spread_radius: PixelValueNoPercent {
2230 inner: PixelValue::const_px(0),
2231 },
2232 clip_mode: BoxShadowClipMode::Outset,
2233 })),
2234 )),
2235 CssPropertyWithConditions::simple(CssProperty::TextColor(StyleTextColorValue::Exact(
2236 StyleTextColor {
2237 inner: ColorU {
2238 r: 255,
2239 g: 255,
2240 b: 255,
2241 a: 255,
2242 },
2243 },
2244 ))),
2245
2246 CssPropertyWithConditions::simple(CssProperty::Display(LayoutDisplayValue::Exact(
2247 LayoutDisplay::Block
2248 ))),
2249 CssPropertyWithConditions::simple(CssProperty::FontFamily(StyleFontFamilyVecValue::Exact(
2250 StyleFontFamilyVec::from_const_slice(STYLE_FONT_FAMILY_8122988506401935406_ITEMS),
2251 ))),
2252 CssPropertyWithConditions::simple(CssProperty::PaddingTop(LayoutPaddingTopValue::Exact(
2253 LayoutPaddingTop {
2254 inner: PixelValue::const_px(10),
2255 },
2256 ))),
2257 CssPropertyWithConditions::simple(CssProperty::PaddingBottom(
2258 LayoutPaddingBottomValue::Exact(LayoutPaddingBottom {
2259 inner: PixelValue::const_px(10),
2260 }),
2261 )),
2262 CssPropertyWithConditions::simple(CssProperty::PaddingLeft(LayoutPaddingLeftValue::Exact(
2263 LayoutPaddingLeft {
2264 inner: PixelValue::const_px(10),
2265 },
2266 ))),
2267 CssPropertyWithConditions::simple(CssProperty::PaddingRight(
2268 LayoutPaddingRightValue::Exact(LayoutPaddingRight {
2269 inner: PixelValue::const_px(10),
2270 }),
2271 )),
2272 CssPropertyWithConditions::simple(CssProperty::Transform(StyleTransformVecValue::Exact(
2273 if scale_factor != 1.0 {
2274 vec![
2275 StyleTransform::Translate(node_transform),
2276 StyleTransform::ScaleX(PercentageValue::new(scale_factor * 100.0)),
2277 StyleTransform::ScaleY(PercentageValue::new(scale_factor * 100.0)),
2278 ]
2279 } else {
2280 vec![
2281 StyleTransform::Translate(node_transform)
2282 ]
2283 }.into()
2284 ))),
2285 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
2286 LayoutWidth::Px(PixelValue::const_px(250),),
2287 ))),
2288 ].into())
2289 .with_ids_and_classes({
2290 const IDS_AND_CLASSES_4480169002427296613: &[IdOrClass] =
2291 &[Class(AzString::from_const_str("node_graph_node"))];
2292 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_4480169002427296613)
2293 })
2294 .with_children(DomVec::from_vec(vec![
2295 Dom::create_text(AzString::from_const_str("X"))
2296 .with_css_props(CSS_MATCH_7395766480280098891)
2297 .with_callbacks(vec![
2298 CoreCallbackData {
2299 event: EventFilter::Hover(HoverEventFilter::MouseUp),
2300 refany: node_local_dataset.clone(),
2301 callback: CoreCallback { cb: nodegraph_delete_node as usize, ctx: OptionRefAny::None },
2302 },
2303 ].into())
2304 .with_ids_and_classes({
2305 const IDS_AND_CLASSES_7122017923389407516: &[IdOrClass] =
2306 &[Class(AzString::from_const_str("node_close_button"))];
2307 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_7122017923389407516)
2308 }),
2309 Dom::create_text(node_info.node_type_name.clone())
2310 .with_css_props(CSS_MATCH_1739273067404038547)
2311 .with_ids_and_classes({
2312 const IDS_AND_CLASSES_15777790571346582635: &[IdOrClass] =
2313 &[Class(AzString::from_const_str("node_label"))];
2314 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_15777790571346582635)
2315 }),
2316 Dom::create_div()
2317 .with_css_props(CSS_MATCH_3354247437065914166)
2318 .with_ids_and_classes({
2319 const IDS_AND_CLASSES_5590500152394859708: &[IdOrClass] =
2320 &[Class(AzString::from_const_str("node_body"))];
2321 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_5590500152394859708)
2322 })
2323 .with_children(DomVec::from_vec(vec![
2324 Dom::create_div()
2325 .with_css_props(CSS_MATCH_16946967739775705757)
2326 .with_ids_and_classes({
2327 const IDS_AND_CLASSES_3626404106673061698: &[IdOrClass] =
2328 &[Class(AzString::from_const_str("inputs"))];
2329 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_3626404106673061698)
2330 })
2331 .with_children(DomVec::from_vec(vec![Dom::create_div()
2332 .with_css_props(CSS_MATCH_705881630351954657)
2333 .with_ids_and_classes({
2334 const IDS_AND_CLASSES_12825690349660780627: &[IdOrClass] =
2335 &[Class(AzString::from_const_str("node_input_wrapper"))];
2336 IdOrClassVec::from_const_slice(
2337 IDS_AND_CLASSES_12825690349660780627,
2338 )
2339 })
2340 .with_children(DomVec::from_vec(
2341 inputs
2342 .into_iter()
2343 .enumerate()
2344 .map(|(io_id, (input_label, input_color))| {
2345 use self::InputOrOutput::*;
2346
2347 Dom::create_div()
2348 .with_css_props(CSS_MATCH_9863994880298313101)
2349 .with_ids_and_classes({
2350 const IDS_AND_CLASSES_5020681879750641508:
2351 &[IdOrClass] = &[Class(AzString::from_const_str(
2352 "node_input_container",
2353 ))];
2354 IdOrClassVec::from_const_slice(
2355 IDS_AND_CLASSES_5020681879750641508,
2356 )
2357 })
2358 .with_children(DomVec::from_vec(vec![
2359 Dom::create_div()
2360 .with_css_props(
2361 CSS_MATCH_4700400755767504372,
2362 )
2363 .with_ids_and_classes({
2364 const IDS_AND_CLASSES_9154857442066749879:
2365 &[IdOrClass] =
2366 &[Class(AzString::from_const_str(
2367 "node_input_connection_label_wrapper",
2368 ))];
2369 IdOrClassVec::from_const_slice(
2370 IDS_AND_CLASSES_9154857442066749879,
2371 )
2372 })
2373 .with_children(DomVec::from_vec(vec![Dom::create_text(
2374 input_label.clone(),
2375 )
2376 .with_css_props(
2377 CSS_MATCH_11452431279102104133,
2378 )
2379 .with_ids_and_classes({
2380 const IDS_AND_CLASSES_16291496011772407931:
2381 &[IdOrClass] =
2382 &[Class(AzString::from_const_str(
2383 "node_input_connection_label",
2384 ))];
2385 IdOrClassVec::from_const_slice(
2386 IDS_AND_CLASSES_16291496011772407931,
2387 )
2388 })])),
2389 Dom::create_div()
2390 .with_callbacks(vec![
2391 CoreCallbackData {
2392 event: EventFilter::Hover(HoverEventFilter::LeftMouseUp),
2393 refany: RefAny::new(NodeInputOutputLocalDataset {
2394 io_id: Input(io_id),
2395 backref: node_local_dataset.clone(),
2396 }),
2397 callback: CoreCallback { cb: nodegraph_input_output_connect as usize, ctx: OptionRefAny::None },
2398 },
2399 CoreCallbackData {
2400 event: EventFilter::Hover(HoverEventFilter::MiddleMouseUp),
2401 refany: RefAny::new(NodeInputOutputLocalDataset {
2402 io_id: Input(io_id),
2403 backref: node_local_dataset.clone(),
2404 }),
2405 callback: CoreCallback { cb: nodegraph_input_output_disconnect as usize, ctx: OptionRefAny::None },
2406 },
2407 ].into())
2408 .with_css_props(CssPropertyWithConditionsVec::from_vec(vec![
2409 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
2411 StyleBackgroundContentVecValue::Exact(vec![StyleBackgroundContent::Color(input_color)].into()),
2412 )),
2413 CssPropertyWithConditions::simple(CssProperty::Cursor(StyleCursorValue::Exact(
2414 StyleCursor::Pointer,
2415 ))),
2416 CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
2417 LayoutHeight::Px(PixelValue::const_px(15),),
2418 ))),
2419 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
2420 LayoutWidth::Px(PixelValue::const_px(15),),
2421 ))),
2422 ])
2423 )
2424 .with_ids_and_classes({
2425 const IDS_AND_CLASSES_2128818677168244823:
2426 &[IdOrClass] = &[Class(
2427 AzString::from_const_str("node_input"),
2428 )];
2429 IdOrClassVec::from_const_slice(
2430 IDS_AND_CLASSES_2128818677168244823,
2431 )
2432 }),
2433 ]))
2434 }).collect()
2435 ))
2436 ])),
2437 Dom::create_div()
2438 .with_css_props(CSS_MATCH_7432473243011547380)
2439 .with_ids_and_classes({
2440 const IDS_AND_CLASSES_746059979773622802: &[IdOrClass] =
2441 &[Class(AzString::from_const_str("node_content_wrapper"))];
2442 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_746059979773622802)
2443 })
2444 .with_children({
2445
2446 let mut fields = Vec::new();
2447
2448 for (field_idx, field) in node.fields.iter().enumerate() {
2449
2450 let field_local_dataset = RefAny::new(NodeFieldLocalDataset {
2451 field_idx,
2452 backref: node_local_dataset.clone(),
2453 });
2454
2455 let div = Dom::create_div()
2456 .with_css_props(CSS_MATCH_2639191696846875011)
2457 .with_ids_and_classes({
2458 const IDS_AND_CLASSES_4413230059125905311: &[IdOrClass] =
2459 &[Class(AzString::from_const_str(
2460 "node_configuration_field_container",
2461 ))];
2462 IdOrClassVec::from_const_slice(
2463 IDS_AND_CLASSES_4413230059125905311,
2464 )
2465 })
2466 .with_children(DomVec::from_vec(vec![
2467 Dom::create_text(field.key.clone())
2468 .with_css_props(CSS_MATCH_1198521124955124418)
2469 .with_ids_and_classes({
2470 const IDS_AND_CLASSES_12334207996395559585:
2471 &[IdOrClass] =
2472 &[Class(AzString::from_const_str(
2473 "node_configuration_field_label",
2474 ))];
2475 IdOrClassVec::from_const_slice(
2476 IDS_AND_CLASSES_12334207996395559585,
2477 )
2478 }),
2479
2480 match &field.value {
2481 NodeTypeFieldValue::TextInput(initial_text) => {
2482 TextInput::create()
2483 .with_text(initial_text.clone())
2484 .with_on_focus_lost(field_local_dataset, nodegraph_on_textinput_focus_lost as TextInputOnFocusLostCallbackType)
2485 .dom()
2486 },
2487 NodeTypeFieldValue::NumberInput(initial_value) => {
2488 NumberInput::create(*initial_value)
2489 .with_on_focus_lost(field_local_dataset, nodegraph_on_numberinput_focus_lost as NumberInputOnFocusLostCallbackType)
2490 .dom()
2491 },
2492 NodeTypeFieldValue::CheckBox(initial_checked) => {
2493 CheckBox::create(*initial_checked)
2494 .with_on_toggle(field_local_dataset, nodegraph_on_checkbox_value_changed as CheckBoxOnToggleCallbackType)
2495 .dom()
2496 },
2497 NodeTypeFieldValue::ColorInput(initial_color) => {
2498 ColorInput::create(*initial_color)
2499 .with_on_value_change(field_local_dataset, nodegraph_on_colorinput_value_changed as ColorInputOnValueChangeCallbackType)
2500 .dom()
2501 },
2502 NodeTypeFieldValue::FileInput(file_path) => {
2503 let cb: FileInputOnPathChangeCallbackType = nodegraph_on_fileinput_button_clicked;
2504 FileInput::create(file_path.clone())
2505 .with_on_path_change(field_local_dataset, cb)
2506 .dom()
2507 },
2508 }
2509 ]));
2510
2511 fields.push(div);
2512 }
2513
2514 DomVec::from_vec(fields)
2515 }),
2516 Dom::create_div()
2517 .with_css_props(CSS_MATCH_14906563417280941890)
2518 .with_ids_and_classes({
2519 const IDS_AND_CLASSES_4737474624251936466: &[IdOrClass] =
2520 &[Class(AzString::from_const_str("outputs"))];
2521 IdOrClassVec::from_const_slice(IDS_AND_CLASSES_4737474624251936466)
2522 })
2523 .with_children(DomVec::from_vec(vec![Dom::create_div()
2524 .with_css_props(CSS_MATCH_10339190304804100510)
2525 .with_ids_and_classes({
2526 const IDS_AND_CLASSES_12883576328110161157: &[IdOrClass] =
2527 &[Class(AzString::from_const_str("node_output_wrapper"))];
2528 IdOrClassVec::from_const_slice(
2529 IDS_AND_CLASSES_12883576328110161157,
2530 )
2531 })
2532 .with_children(DomVec::from_vec(
2533 outputs
2534 .into_iter()
2535 .enumerate()
2536 .map(|(io_id, (output_label, output_color))| {
2537 use self::InputOrOutput::*;
2538 Dom::create_div()
2539 .with_css_props(CSS_MATCH_12400244273289328300)
2540 .with_ids_and_classes({
2541 const IDS_AND_CLASSES_10917819668096233812:
2542 &[IdOrClass] = &[Class(AzString::from_const_str(
2543 "node_output_container",
2544 ))];
2545 IdOrClassVec::from_const_slice(
2546 IDS_AND_CLASSES_10917819668096233812,
2547 )
2548 })
2549 .with_children(DomVec::from_vec(vec![
2550 Dom::create_div()
2551 .with_callbacks(vec![
2552 CoreCallbackData {
2553 event: EventFilter::Hover(HoverEventFilter::LeftMouseUp),
2554 refany: RefAny::new(NodeInputOutputLocalDataset {
2555 io_id: Output(io_id),
2556 backref: node_local_dataset.clone(),
2557 }),
2558 callback: CoreCallback { cb: nodegraph_input_output_connect as usize, ctx: OptionRefAny::None },
2559 },
2560 CoreCallbackData {
2561 event: EventFilter::Hover(HoverEventFilter::MiddleMouseUp),
2562 refany: RefAny::new(NodeInputOutputLocalDataset {
2563 io_id: Output(io_id),
2564 backref: node_local_dataset.clone(),
2565 }),
2566 callback: CoreCallback { cb: nodegraph_input_output_disconnect as usize, ctx: OptionRefAny::None },
2567 },
2568 ].into())
2569 .with_css_props(
2570 CssPropertyWithConditionsVec::from_vec(vec![
2571 CssPropertyWithConditions::simple(CssProperty::BackgroundContent(
2573 StyleBackgroundContentVecValue::Exact(vec![
2574 StyleBackgroundContent::Color(output_color)
2575 ].into()),
2576 )),
2577 CssPropertyWithConditions::simple(CssProperty::Cursor(StyleCursorValue::Exact(
2578 StyleCursor::Pointer,
2579 ))),
2580 CssPropertyWithConditions::simple(CssProperty::Height(LayoutHeightValue::Exact(
2581 LayoutHeight::Px(PixelValue::const_px(15),),
2582 ))),
2583 CssPropertyWithConditions::simple(CssProperty::Width(LayoutWidthValue::Exact(
2584 LayoutWidth::Px(PixelValue::const_px(15),),
2585 ))),
2586 ])
2587 )
2588 .with_ids_and_classes({
2589 const IDS_AND_CLASSES_17632471664405317563:
2590 &[IdOrClass] = &[Class(
2591 AzString::from_const_str("node_output"),
2592 )];
2593 IdOrClassVec::from_const_slice(
2594 IDS_AND_CLASSES_17632471664405317563,
2595 )
2596 }),
2597 Dom::create_div()
2598 .with_css_props(
2599 CSS_MATCH_12038890904436132038,
2600 )
2601 .with_ids_and_classes({
2602 const IDS_AND_CLASSES_1667960214206134147:
2603 &[IdOrClass] =
2604 &[Class(AzString::from_const_str(
2605 "node_output_connection_label_wrapper",
2606 ))];
2607 IdOrClassVec::from_const_slice(
2608 IDS_AND_CLASSES_1667960214206134147,
2609 )
2610 })
2611 .with_children(DomVec::from_vec(vec![Dom::create_text(
2612 output_label.clone(),
2613 )
2614 .with_css_props(
2615 CSS_MATCH_2008162367868363199,
2616 )
2617 .with_ids_and_classes({
2618 const IDS_AND_CLASSES_2974914452796301884:
2619 &[IdOrClass] =
2620 &[Class(AzString::from_const_str(
2621 "node_output_connection_label",
2622 ))];
2623 IdOrClassVec::from_const_slice(
2624 IDS_AND_CLASSES_2974914452796301884,
2625 )
2626 })])),
2627 ]))
2628 }).collect()
2629 ))])),
2630 ])),
2631 ]))
2632 .with_dataset(Some(node_local_dataset).into())
2633 ].into())
2634}
2635
2636fn render_connections(node_graph: &NodeGraph, root_marker_nodedata: RefAny) -> Dom {
2637 static NODEGRAPH_CONNECTIONS_CONTAINER_CLASS: &[IdOrClass] = &[Class(
2638 AzString::from_const_str("nodegraph-connections-container"),
2639 )];
2640
2641 static NODEGRAPH_CONNECTIONS_CONTAINER_PROPS: &[CssPropertyWithConditions] = &[
2642 CssPropertyWithConditions::simple(CssProperty::position(LayoutPosition::Absolute)),
2643 CssPropertyWithConditions::simple(CssProperty::flex_grow(LayoutFlexGrow::const_new(1))),
2644 ];
2645
2646 Dom::create_div()
2647 .with_ids_and_classes(IdOrClassVec::from_const_slice(
2648 NODEGRAPH_CONNECTIONS_CONTAINER_CLASS,
2649 ))
2650 .with_css_props(CssPropertyWithConditionsVec::from_const_slice(
2651 NODEGRAPH_CONNECTIONS_CONTAINER_PROPS,
2652 ))
2653 .with_dataset(Some(root_marker_nodedata).into())
2654 .with_children({
2655 let mut children = Vec::new();
2656
2657 for NodeIdNodeMap { node_id, node } in node_graph.nodes.as_ref().iter() {
2658 let out_node_id = node_id;
2659 let node_type_info = match node_graph
2660 .node_types
2661 .iter()
2662 .find(|i| i.node_type_id == node.node_type)
2663 {
2664 Some(s) => &s.node_type_info,
2665 None => continue,
2666 };
2667
2668 for OutputConnection {
2669 output_index,
2670 connects_to,
2671 } in node.connect_out.as_ref().iter()
2672 {
2673 let output_type_id = match node_type_info.outputs.get(*output_index) {
2674 Some(s) => s,
2675 None => continue,
2676 };
2677
2678 let output_color = match node_graph
2679 .input_output_types
2680 .iter()
2681 .find(|o| o.io_type_id == *output_type_id)
2682 {
2683 Some(s) => s.io_info.color.clone(),
2684 None => continue,
2685 };
2686
2687 for InputNodeAndIndex {
2688 node_id,
2689 input_index,
2690 } in connects_to.as_ref().iter()
2691 {
2692 let in_node_id = node_id;
2693
2694 let mut cld = ConnectionLocalDataset {
2695 out_node_id: *out_node_id,
2696 out_idx: *output_index,
2697 in_node_id: *in_node_id,
2698 in_idx: *input_index,
2699 swap_vert: false,
2700 swap_horz: false,
2701 color: output_color,
2702 };
2703
2704 let (rect, swap_vert, swap_horz) = match get_rect(&node_graph, cld) {
2705 Some(s) => s,
2706 None => continue,
2707 };
2708
2709 cld.swap_vert = swap_vert;
2710 cld.swap_horz = swap_horz;
2711
2712 let cld_refany = RefAny::new(cld);
2713 let connection_div = Dom::create_image(ImageRef::callback(
2714 draw_connection as usize,
2715 cld_refany.clone(),
2716 ))
2717 .with_dataset(Some(cld_refany).into())
2718 .with_css_props(
2719 vec![
2720 CssPropertyWithConditions::simple(CssProperty::Transform(
2721 StyleTransformVecValue::Exact(
2722 vec![
2723 StyleTransform::Translate(StyleTransformTranslate2D {
2724 x: PixelValue::px(
2725 node_graph.offset.x + rect.origin.x,
2726 ),
2727 y: PixelValue::px(
2728 node_graph.offset.y + rect.origin.y,
2729 ),
2730 }),
2731 StyleTransform::ScaleX(PercentageValue::new(
2732 node_graph.scale_factor * 100.0,
2733 )),
2734 StyleTransform::ScaleY(PercentageValue::new(
2735 node_graph.scale_factor * 100.0,
2736 )),
2737 ]
2738 .into(),
2739 ),
2740 )),
2741 CssPropertyWithConditions::simple(CssProperty::Width(
2742 LayoutWidthValue::Exact(LayoutWidth::Px(PixelValue::px(
2743 rect.size.width,
2744 ))),
2745 )),
2746 CssPropertyWithConditions::simple(CssProperty::Height(
2747 LayoutHeightValue::Exact(LayoutHeight::Px(PixelValue::px(
2748 rect.size.height,
2749 ))),
2750 )),
2751 ]
2752 .into(),
2753 );
2754
2755 children.push(
2756 Dom::create_div()
2757 .with_css(
2758 "flex-grow: 1; position: absolute; overflow: hidden;",
2759 )
2760 .with_children(vec![connection_div].into()),
2761 );
2762 }
2763 }
2764 }
2765
2766 children.into()
2767 })
2768}
2769
2770extern "C" fn draw_connection(mut refany: RefAny, _info: ()) -> ImageRef {
2771 let size = azul_core::geom::LogicalSize {
2774 width: 100.0,
2775 height: 100.0,
2776 };
2777 let invalid = ImageRef::null_image(
2778 size.width as usize,
2779 size.height as usize,
2780 RawImageFormat::R8,
2781 Vec::new(),
2782 );
2783
2784 invalid
2786}
2787
2788const NODE_WIDTH: f32 = 250.0;
2789const V_OFFSET: f32 = 71.0;
2790const DIST_BETWEEN_NODES: f32 = 10.0;
2791const CONNECTION_DOT_HEIGHT: f32 = 15.0;
2792
2793fn get_rect(
2795 node_graph: &NodeGraph,
2796 connection: ConnectionLocalDataset,
2797) -> Option<(LogicalRect, bool, bool)> {
2798 let ConnectionLocalDataset {
2799 out_node_id,
2800 out_idx,
2801 in_node_id,
2802 in_idx,
2803 ..
2804 } = connection;
2805 let out_node = node_graph.nodes.iter().find(|i| i.node_id == out_node_id)?;
2806 let in_node = node_graph.nodes.iter().find(|i| i.node_id == in_node_id)?;
2807
2808 let x_out = out_node.node.position.x + NODE_WIDTH;
2809 let y_out = out_node.node.position.y
2810 + V_OFFSET
2811 + (out_idx as f32 * (DIST_BETWEEN_NODES + CONNECTION_DOT_HEIGHT));
2812
2813 let x_in = in_node.node.position.x;
2814 let y_in = in_node.node.position.y
2815 + V_OFFSET
2816 + (in_idx as f32 * (DIST_BETWEEN_NODES + CONNECTION_DOT_HEIGHT));
2817
2818 let should_swap_vertical = y_in > y_out;
2819 let should_swap_horizontal = x_in < x_out;
2820
2821 let width = (x_in - x_out).abs();
2822 let height = (y_in - y_out).abs() + CONNECTION_DOT_HEIGHT;
2823
2824 let x = x_in.min(x_out);
2825 let y = y_in.min(y_out);
2826
2827 Some((
2828 LogicalRect {
2829 size: LogicalSize { width, height },
2830 origin: LogicalPosition { x, y },
2831 },
2832 should_swap_vertical,
2833 should_swap_horizontal,
2834 ))
2835}
2836
2837extern "C" fn nodegraph_set_active_node(mut refany: RefAny, _info: CallbackInfo) -> Update {
2838 let data_clone = refany.clone();
2839 if let Some(mut refany) = refany.downcast_mut::<NodeLocalDataset>() {
2840 let node_id = refany.node_id.clone();
2841 if let Some(mut backref) = refany.backref.downcast_mut::<NodeGraphLocalDataset>() {
2842 backref.active_node_being_dragged = Some((node_id, data_clone));
2843 }
2844 }
2845 Update::DoNothing
2846}
2847
2848extern "C" fn nodegraph_unset_active_node(mut refany: RefAny, _info: CallbackInfo) -> Update {
2849 if let Some(mut refany) = refany.downcast_mut::<NodeGraphLocalDataset>() {
2850 refany.active_node_being_dragged = None;
2851 }
2852 Update::DoNothing
2853}
2854
2855extern "C" fn nodegraph_drag_graph_or_nodes(mut refany: RefAny, mut info: CallbackInfo) -> Update {
2857 let mut refany = match refany.downcast_mut::<NodeGraphLocalDataset>() {
2858 Some(s) => s,
2859 None => return Update::DoNothing,
2860 };
2861 let refany = &mut *refany;
2862
2863 let prev = match info.get_previous_mouse_state() {
2864 Some(s) => s,
2865 None => return Update::DoNothing,
2866 };
2867 let cur = info.get_current_mouse_state();
2868 if !(cur.left_down && prev.left_down) {
2869 return Update::DoNothing;
2871 }
2872
2873 let (current_mouse_pos, previous_mouse_pos) = match (cur.cursor_position, prev.cursor_position)
2874 {
2875 (InWindow(c), InWindow(p)) => (c, p),
2876 _ => return Update::DoNothing,
2877 };
2878
2879 let dx = (current_mouse_pos.x - previous_mouse_pos.x) * (1.0 / refany.node_graph.scale_factor);
2880 let dy = (current_mouse_pos.y - previous_mouse_pos.y) * (1.0 / refany.node_graph.scale_factor);
2881 let nodegraph_node = info.get_hit_node();
2882
2883 let should_update = match refany.active_node_being_dragged.clone() {
2884 Some((node_graph_node_id, data_marker)) => {
2886 let node_connection_marker = &mut refany.node_connection_marker;
2887
2888 let _nodegraph_node = info.get_hit_node();
2889 let result = match refany.callbacks.on_node_dragged.as_ref() {
2890 Some(OnNodeDragged { callback, refany }) => (callback.cb)(
2891 refany.clone(),
2892 info.clone(),
2893 node_graph_node_id,
2894 NodeDragAmount { x: dx, y: dy },
2895 ),
2896 None => Update::DoNothing,
2897 };
2898
2899 let node_position = match refany
2901 .node_graph
2902 .nodes
2903 .iter_mut()
2904 .find(|i| i.node_id == node_graph_node_id)
2905 {
2906 Some(s) => {
2907 s.node.position.x += dx;
2908 s.node.position.y += dy;
2909 s.node.position
2910 }
2911 None => return Update::DoNothing,
2912 };
2913
2914 let visual_node_id = match info.get_node_id_of_root_dataset(data_marker) {
2915 Some(s) => s,
2916 None => return Update::DoNothing,
2917 };
2918
2919 let node_transform = StyleTransformTranslate2D {
2920 x: PixelValue::px(node_position.x + refany.node_graph.offset.x),
2921 y: PixelValue::px(node_position.y + refany.node_graph.offset.y),
2922 };
2923
2924 info.set_css_property(
2925 visual_node_id,
2926 CssProperty::transform(
2927 if refany.node_graph.scale_factor != 1.0 {
2928 vec![
2929 StyleTransform::Translate(node_transform),
2930 StyleTransform::ScaleX(PercentageValue::new(
2931 refany.node_graph.scale_factor * 100.0,
2932 )),
2933 StyleTransform::ScaleY(PercentageValue::new(
2934 refany.node_graph.scale_factor * 100.0,
2935 )),
2936 ]
2937 } else {
2938 vec![StyleTransform::Translate(node_transform)]
2939 }
2940 .into(),
2941 ),
2942 );
2943
2944 let connection_container_nodeid =
2946 match info.get_node_id_of_root_dataset(node_connection_marker.clone()) {
2947 Some(s) => s,
2948 None => return result,
2949 };
2950
2951 let mut first_connection_child = info.get_first_child(connection_container_nodeid);
2953
2954 while let Some(connection_nodeid) = first_connection_child {
2955 first_connection_child = info.get_next_sibling(connection_nodeid);
2956
2957 let first_child = match info.get_first_child(connection_nodeid) {
2958 Some(s) => s,
2959 None => continue,
2960 };
2961
2962 let mut dataset = match info.get_dataset(first_child) {
2963 Some(s) => s,
2964 None => continue,
2965 };
2966
2967 let mut cld = match dataset.downcast_mut::<ConnectionLocalDataset>() {
2968 Some(s) => s,
2969 None => continue,
2970 };
2971
2972 if !(cld.out_node_id == node_graph_node_id || cld.in_node_id == node_graph_node_id)
2973 {
2974 continue; }
2976
2977 let (new_rect, swap_vert, swap_horz) = match get_rect(&refany.node_graph, *cld) {
2978 Some(s) => s,
2979 None => continue,
2980 };
2981
2982 cld.swap_vert = swap_vert;
2983 cld.swap_horz = swap_horz;
2984
2985 let node_transform = StyleTransformTranslate2D {
2986 x: PixelValue::px(refany.node_graph.offset.x + new_rect.origin.x),
2987 y: PixelValue::px(refany.node_graph.offset.y + new_rect.origin.y),
2988 };
2989
2990 info.set_css_property(
2991 first_child,
2992 CssProperty::transform(
2993 if refany.node_graph.scale_factor != 1.0 {
2994 vec![
2995 StyleTransform::Translate(node_transform),
2996 StyleTransform::ScaleX(PercentageValue::new(
2997 refany.node_graph.scale_factor * 100.0,
2998 )),
2999 StyleTransform::ScaleY(PercentageValue::new(
3000 refany.node_graph.scale_factor * 100.0,
3001 )),
3002 ]
3003 } else {
3004 vec![StyleTransform::Translate(node_transform)]
3005 }
3006 .into(),
3007 ),
3008 );
3009
3010 info.set_css_property(
3011 first_child,
3012 CssProperty::Width(LayoutWidthValue::Exact(LayoutWidth::Px(PixelValue::px(
3013 new_rect.size.width,
3014 )))),
3015 );
3016 info.set_css_property(
3017 first_child,
3018 CssProperty::Height(LayoutHeightValue::Exact(LayoutHeight::Px(
3019 PixelValue::px(new_rect.size.height),
3020 ))),
3021 );
3022 }
3023
3024 result
3025 }
3026 None => {
3028 let result = match refany.callbacks.on_node_graph_dragged.as_ref() {
3029 Some(OnNodeGraphDragged { callback, refany }) => (callback.cb)(
3030 refany.clone(),
3031 info.clone(),
3032 GraphDragAmount { x: dx, y: dy },
3033 ),
3034 None => Update::DoNothing,
3035 };
3036
3037 refany.node_graph.offset.x += dx;
3038 refany.node_graph.offset.y += dy;
3039
3040 let node_container = match info.get_first_child(nodegraph_node) {
3042 Some(s) => s,
3043 None => return Update::DoNothing,
3044 };
3045
3046 let node_container = match info.get_next_sibling(node_container) {
3047 Some(s) => s,
3048 None => return Update::DoNothing,
3049 };
3050
3051 let mut node = match info.get_first_child(node_container) {
3052 Some(s) => s,
3053 None => return Update::DoNothing,
3054 };
3055
3056 loop {
3057 let node_first_child = match info.get_first_child(node) {
3058 Some(s) => s,
3059 None => return Update::DoNothing,
3060 };
3061
3062 let mut node_local_dataset = match info.get_dataset(node_first_child) {
3063 None => return Update::DoNothing,
3064 Some(s) => s,
3065 };
3066
3067 let node_graph_node_id = match node_local_dataset.downcast_ref::<NodeLocalDataset>()
3068 {
3069 Some(s) => s,
3070 None => continue,
3071 };
3072
3073 let node_graph_node_id = node_graph_node_id.node_id;
3074
3075 let node_position = match refany
3076 .node_graph
3077 .nodes
3078 .iter()
3079 .find(|i| i.node_id == node_graph_node_id)
3080 {
3081 Some(s) => s.node.position,
3082 None => continue,
3083 };
3084
3085 let node_transform = StyleTransformTranslate2D {
3086 x: PixelValue::px(node_position.x + refany.node_graph.offset.x),
3087 y: PixelValue::px(node_position.y + refany.node_graph.offset.y),
3088 };
3089
3090 info.set_css_property(
3091 node_first_child,
3092 CssProperty::transform(
3093 if refany.node_graph.scale_factor != 1.0 {
3094 vec![
3095 StyleTransform::Translate(node_transform),
3096 StyleTransform::ScaleX(PercentageValue::new(
3097 refany.node_graph.scale_factor * 100.0,
3098 )),
3099 StyleTransform::ScaleY(PercentageValue::new(
3100 refany.node_graph.scale_factor * 100.0,
3101 )),
3102 ]
3103 } else {
3104 vec![StyleTransform::Translate(node_transform)]
3105 }
3106 .into(),
3107 ),
3108 );
3109
3110 node = match info.get_next_sibling(node) {
3111 Some(s) => s,
3112 None => break,
3113 };
3114 }
3115
3116 let node_connection_marker = &mut refany.node_connection_marker;
3117
3118 let connection_container_nodeid =
3120 match info.get_node_id_of_root_dataset(node_connection_marker.clone()) {
3121 Some(s) => s,
3122 None => return result,
3123 };
3124
3125 let mut first_connection_child = info.get_first_child(connection_container_nodeid);
3126
3127 while let Some(connection_nodeid) = first_connection_child {
3128 first_connection_child = info.get_next_sibling(connection_nodeid);
3129
3130 let first_child = match info.get_first_child(connection_nodeid) {
3131 Some(s) => s,
3132 None => continue,
3133 };
3134
3135 let mut dataset = match info.get_dataset(first_child) {
3136 Some(s) => s,
3137 None => continue,
3138 };
3139
3140 let cld = match dataset.downcast_ref::<ConnectionLocalDataset>() {
3141 Some(s) => s,
3142 None => continue,
3143 };
3144
3145 let (new_rect, _, _) = match get_rect(&refany.node_graph, *cld) {
3146 Some(s) => s,
3147 None => continue,
3148 };
3149
3150 info.set_css_property(
3151 first_child,
3152 CssProperty::transform(
3153 vec![
3154 StyleTransform::Translate(StyleTransformTranslate2D {
3155 x: PixelValue::px(refany.node_graph.offset.x + new_rect.origin.x),
3156 y: PixelValue::px(refany.node_graph.offset.y + new_rect.origin.y),
3157 }),
3158 StyleTransform::ScaleX(PercentageValue::new(
3159 refany.node_graph.scale_factor * 100.0,
3160 )),
3161 StyleTransform::ScaleY(PercentageValue::new(
3162 refany.node_graph.scale_factor * 100.0,
3163 )),
3164 ]
3165 .into(),
3166 ),
3167 );
3168 }
3169
3170 result
3171 }
3172 };
3173
3174 info.stop_propagation();
3175
3176 should_update
3177}
3178
3179extern "C" fn nodegraph_duplicate_node(mut refany: RefAny, _info: CallbackInfo) -> Update {
3180 let _data = match refany.downcast_mut::<NodeLocalDataset>() {
3181 Some(s) => s,
3182 None => return Update::DoNothing,
3183 };
3184
3185 Update::DoNothing }
3187
3188extern "C" fn nodegraph_delete_node(mut refany: RefAny, mut info: CallbackInfo) -> Update {
3189 let mut refany = match refany.downcast_mut::<NodeLocalDataset>() {
3190 Some(s) => s,
3191 None => return Update::DoNothing,
3192 };
3193
3194 let node_id = refany.node_id.clone();
3195
3196 let mut backref = match refany.backref.downcast_mut::<NodeGraphLocalDataset>() {
3197 Some(s) => s,
3198 None => return Update::DoNothing,
3199 };
3200
3201 let result = match backref.callbacks.on_node_removed.as_ref() {
3202 Some(OnNodeRemoved { callback, refany }) => (callback.cb)(refany.clone(), info, node_id),
3203 None => Update::DoNothing,
3204 };
3205
3206 result
3207}
3208
3209extern "C" fn nodegraph_context_menu_click(mut refany: RefAny, mut info: CallbackInfo) -> Update {
3210 use azul_core::window::CursorPosition;
3211
3212 let mut refany = match refany.downcast_mut::<ContextMenuEntryLocalDataset>() {
3213 Some(s) => s,
3214 None => return Update::DoNothing,
3215 };
3216
3217 let new_node_type = refany.node_type.clone();
3218
3219 let node_graph_wrapper_id = match info.get_node_id_of_root_dataset(refany.backref.clone()) {
3220 Some(s) => s,
3221 None => return Update::DoNothing,
3222 };
3223
3224 let mut backref = match refany.backref.downcast_mut::<NodeGraphLocalDataset>() {
3225 Some(s) => s,
3226 None => return Update::DoNothing,
3227 };
3228
3229 let node_wrapper_offset = info
3230 .get_node_position(node_graph_wrapper_id)
3231 .map(|p| p)
3232 .map(|p| (p.x, p.y))
3233 .unwrap_or((0.0, 0.0));
3234
3235 let cursor_in_viewport = match info.get_current_mouse_state().cursor_position {
3236 CursorPosition::InWindow(i) => i,
3237 CursorPosition::OutOfWindow(i) => i,
3238 _ => LogicalPosition::zero(),
3239 };
3240
3241 let new_node_pos = NodeGraphNodePosition {
3242 x: (cursor_in_viewport.x - node_wrapper_offset.0) * (1.0 / backref.node_graph.scale_factor)
3243 - backref.node_graph.offset.x,
3244 y: (cursor_in_viewport.y - node_wrapper_offset.1) * (1.0 / backref.node_graph.scale_factor)
3245 - backref.node_graph.offset.y,
3246 };
3247
3248 let new_node_id = backref.node_graph.generate_unique_node_id();
3249
3250 let result = match backref.callbacks.on_node_added.as_ref() {
3251 Some(OnNodeAdded { callback, refany }) => (callback.cb)(
3252 refany.clone(),
3253 info,
3254 new_node_type,
3255 new_node_id,
3256 new_node_pos,
3257 ),
3258 None => Update::DoNothing,
3259 };
3260
3261 result
3262}
3263
3264extern "C" fn nodegraph_input_output_connect(mut refany: RefAny, mut info: CallbackInfo) -> Update {
3265 use self::InputOrOutput::*;
3266
3267 let mut refany = match refany.downcast_mut::<NodeInputOutputLocalDataset>() {
3268 Some(s) => s,
3269 None => return Update::DoNothing,
3270 };
3271
3272 let io_id = refany.io_id.clone();
3273
3274 let mut backref = match refany.backref.downcast_mut::<NodeLocalDataset>() {
3275 Some(s) => s,
3276 None => return Update::DoNothing,
3277 };
3278
3279 let node_id = backref.node_id.clone();
3280
3281 let mut backref = match backref.backref.downcast_mut::<NodeGraphLocalDataset>() {
3282 Some(s) => s,
3283 None => return Update::DoNothing,
3284 };
3285
3286 let (input_node, input_index, output_node, output_index) =
3287 match backref.last_input_or_output_clicked.clone() {
3288 None => {
3289 backref.last_input_or_output_clicked = Some((node_id, io_id));
3290 return Update::DoNothing;
3291 }
3292 Some((prev_node_id, prev_io_id)) => {
3293 match (prev_io_id, io_id) {
3294 (Input(i), Output(o)) => (prev_node_id, i, node_id, o),
3295 (Output(o), Input(i)) => (node_id, i, prev_node_id, o),
3296 _ => {
3297 backref.last_input_or_output_clicked = None;
3299 return Update::DoNothing;
3300 }
3301 }
3302 }
3303 };
3304
3305 match backref.node_graph.connect_input_output(
3307 input_node,
3308 input_index,
3309 output_node,
3310 output_index,
3311 ) {
3312 Ok(_) => {}
3313 Err(e) => {
3314 eprintln!("{:?}", e);
3315 backref.last_input_or_output_clicked = None;
3316 return Update::DoNothing;
3317 }
3318 }
3319
3320 let result = match backref.callbacks.on_node_connected.as_ref() {
3321 Some(OnNodeConnected { callback, refany }) => {
3322 let r = (callback.cb)(
3323 refany.clone(),
3324 info,
3325 input_node,
3326 input_index,
3327 output_node,
3328 output_index,
3329 );
3330 backref.last_input_or_output_clicked = None;
3331 r
3332 }
3333 None => Update::DoNothing,
3334 };
3335
3336 result
3337}
3338
3339extern "C" fn nodegraph_input_output_disconnect(mut refany: RefAny, info: CallbackInfo) -> Update {
3340 use self::InputOrOutput::*;
3341
3342 let mut refany = match refany.downcast_mut::<NodeInputOutputLocalDataset>() {
3343 Some(s) => s,
3344 None => return Update::DoNothing,
3345 };
3346
3347 let io_id = refany.io_id.clone();
3348
3349 let mut backref = match refany.backref.downcast_mut::<NodeLocalDataset>() {
3350 Some(s) => s,
3351 None => return Update::DoNothing,
3352 };
3353
3354 let node_id = backref.node_id.clone();
3355
3356 let mut backref = match backref.backref.downcast_mut::<NodeGraphLocalDataset>() {
3357 Some(s) => s,
3358 None => return Update::DoNothing,
3359 };
3360
3361 let mut result = Update::DoNothing;
3362 match io_id {
3363 Input(i) => {
3364 result.max_self(
3365 match backref.callbacks.on_node_input_disconnected.as_ref() {
3366 Some(OnNodeInputDisconnected { callback, refany }) => {
3367 (callback.cb)(refany.clone(), info, node_id, i)
3368 }
3369 None => Update::DoNothing,
3370 },
3371 );
3372 }
3373 Output(o) => {
3374 result.max_self(
3375 match backref.callbacks.on_node_output_disconnected.as_ref() {
3376 Some(OnNodeOutputDisconnected { callback, refany }) => {
3377 (callback.cb)(refany.clone(), info, node_id, o)
3378 }
3379 None => Update::DoNothing,
3380 },
3381 );
3382 }
3383 };
3384
3385 result
3386}
3387
3388extern "C" fn nodegraph_on_textinput_focus_lost(
3389 mut refany: RefAny,
3390 info: CallbackInfo,
3391 textinputstate: TextInputState,
3392) -> Update {
3393 let mut refany = match refany.downcast_mut::<NodeFieldLocalDataset>() {
3394 Some(s) => s,
3395 None => return Update::DoNothing,
3396 };
3397
3398 let field_idx = refany.field_idx;
3399
3400 let mut node_local_dataset = match refany.backref.downcast_mut::<NodeLocalDataset>() {
3401 Some(s) => s,
3402 None => return Update::DoNothing,
3403 };
3404
3405 let node_id = node_local_dataset.node_id;
3406
3407 let mut node_graph = match node_local_dataset
3408 .backref
3409 .downcast_mut::<NodeGraphLocalDataset>()
3410 {
3411 Some(s) => s,
3412 None => return Update::DoNothing,
3413 };
3414
3415 let node_type = match node_graph
3416 .node_graph
3417 .nodes
3418 .iter()
3419 .find(|i| i.node_id == node_id)
3420 {
3421 Some(s) => s.node.node_type,
3422 None => return Update::DoNothing,
3423 };
3424
3425 let result = match node_graph.callbacks.on_node_field_edited.as_ref() {
3426 Some(OnNodeFieldEdited { refany, callback }) => (callback.cb)(
3427 refany.clone(),
3428 info,
3429 node_id,
3430 field_idx,
3431 node_type,
3432 NodeTypeFieldValue::TextInput(textinputstate.get_text().into()),
3433 ),
3434 None => Update::DoNothing,
3435 };
3436
3437 result
3438}
3439
3440extern "C" fn nodegraph_on_numberinput_focus_lost(
3441 mut refany: RefAny,
3442 info: CallbackInfo,
3443 numberinputstate: NumberInputState,
3444) -> Update {
3445 let mut refany = match refany.downcast_mut::<NodeFieldLocalDataset>() {
3446 Some(s) => s,
3447 None => return Update::DoNothing,
3448 };
3449
3450 let field_idx = refany.field_idx;
3451
3452 let mut node_local_dataset = match refany.backref.downcast_mut::<NodeLocalDataset>() {
3453 Some(s) => s,
3454 None => return Update::DoNothing,
3455 };
3456
3457 let node_id = node_local_dataset.node_id;
3458
3459 let mut node_graph = match node_local_dataset
3460 .backref
3461 .downcast_mut::<NodeGraphLocalDataset>()
3462 {
3463 Some(s) => s,
3464 None => return Update::DoNothing,
3465 };
3466
3467 let node_type = match node_graph
3468 .node_graph
3469 .nodes
3470 .iter()
3471 .find(|i| i.node_id == node_id)
3472 {
3473 Some(s) => s.node.node_type,
3474 None => return Update::DoNothing,
3475 };
3476
3477 let result = match node_graph.callbacks.on_node_field_edited.as_ref() {
3478 Some(OnNodeFieldEdited { refany, callback }) => (callback.cb)(
3479 refany.clone(),
3480 info,
3481 node_id,
3482 field_idx,
3483 node_type,
3484 NodeTypeFieldValue::NumberInput(numberinputstate.number),
3485 ),
3486 None => Update::DoNothing,
3487 };
3488
3489 result
3490}
3491
3492extern "C" fn nodegraph_on_checkbox_value_changed(
3493 mut refany: RefAny,
3494 info: CallbackInfo,
3495 checkboxinputstate: CheckBoxState,
3496) -> Update {
3497 let mut refany = match refany.downcast_mut::<NodeFieldLocalDataset>() {
3498 Some(s) => s,
3499 None => return Update::DoNothing,
3500 };
3501
3502 let field_idx = refany.field_idx;
3503
3504 let mut node_local_dataset = match refany.backref.downcast_mut::<NodeLocalDataset>() {
3505 Some(s) => s,
3506 None => return Update::DoNothing,
3507 };
3508
3509 let node_id = node_local_dataset.node_id;
3510
3511 let mut node_graph = match node_local_dataset
3512 .backref
3513 .downcast_mut::<NodeGraphLocalDataset>()
3514 {
3515 Some(s) => s,
3516 None => return Update::DoNothing,
3517 };
3518
3519 let node_type = match node_graph
3520 .node_graph
3521 .nodes
3522 .iter()
3523 .find(|i| i.node_id == node_id)
3524 {
3525 Some(s) => s.node.node_type,
3526 None => return Update::DoNothing,
3527 };
3528
3529 let result = match node_graph.callbacks.on_node_field_edited.as_ref() {
3530 Some(OnNodeFieldEdited { refany, callback }) => (callback.cb)(
3531 refany.clone(),
3532 info,
3533 node_id,
3534 field_idx,
3535 node_type,
3536 NodeTypeFieldValue::CheckBox(checkboxinputstate.checked),
3537 ),
3538 None => Update::DoNothing,
3539 };
3540
3541 result
3542}
3543
3544extern "C" fn nodegraph_on_colorinput_value_changed(
3545 mut refany: RefAny,
3546 info: CallbackInfo,
3547 colorinputstate: ColorInputState,
3548) -> Update {
3549 let mut refany = match refany.downcast_mut::<NodeFieldLocalDataset>() {
3550 Some(s) => s,
3551 None => return Update::DoNothing,
3552 };
3553
3554 let field_idx = refany.field_idx;
3555
3556 let mut node_local_dataset = match refany.backref.downcast_mut::<NodeLocalDataset>() {
3557 Some(s) => s,
3558 None => return Update::DoNothing,
3559 };
3560
3561 let node_id = node_local_dataset.node_id;
3562 let mut node_graph = match node_local_dataset
3563 .backref
3564 .downcast_mut::<NodeGraphLocalDataset>()
3565 {
3566 Some(s) => s,
3567 None => return Update::DoNothing,
3568 };
3569
3570 let node_type = match node_graph
3571 .node_graph
3572 .nodes
3573 .iter()
3574 .find(|i| i.node_id == node_id)
3575 {
3576 Some(s) => s.node.node_type,
3577 None => return Update::DoNothing,
3578 };
3579
3580 let result = match node_graph.callbacks.on_node_field_edited.as_ref() {
3581 Some(OnNodeFieldEdited { refany, callback }) => (callback.cb)(
3582 refany.clone(),
3583 info,
3584 node_id,
3585 field_idx,
3586 node_type,
3587 NodeTypeFieldValue::ColorInput(colorinputstate.color),
3588 ),
3589 None => Update::DoNothing,
3590 };
3591
3592 result
3593}
3594
3595extern "C" fn nodegraph_on_fileinput_button_clicked(
3596 mut refany: RefAny,
3597 info: CallbackInfo,
3598 file: FileInputState,
3599) -> Update {
3600 let mut refany = match refany.downcast_mut::<NodeFieldLocalDataset>() {
3601 Some(s) => s,
3602 None => return Update::DoNothing,
3603 };
3604
3605 let field_idx = refany.field_idx;
3606
3607 let mut node_local_dataset = match refany.backref.downcast_mut::<NodeLocalDataset>() {
3608 Some(s) => s,
3609 None => return Update::DoNothing,
3610 };
3611
3612 let node_id = node_local_dataset.node_id;
3613 let mut node_graph = match node_local_dataset
3614 .backref
3615 .downcast_mut::<NodeGraphLocalDataset>()
3616 {
3617 Some(s) => s,
3618 None => return Update::DoNothing,
3619 };
3620
3621 let node_type = match node_graph
3622 .node_graph
3623 .nodes
3624 .iter()
3625 .find(|i| i.node_id == node_id)
3626 {
3627 Some(s) => s.node.node_type,
3628 None => return Update::DoNothing,
3629 };
3630
3631 let result = match node_graph.callbacks.on_node_field_edited.as_ref() {
3633 Some(OnNodeFieldEdited { refany, callback }) => (callback.cb)(
3634 refany.clone(),
3635 info,
3636 node_id,
3637 field_idx,
3638 node_type,
3639 NodeTypeFieldValue::FileInput(file.path.clone()),
3640 ),
3641 None => return Update::DoNothing,
3642 };
3643
3644 result
3645}