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