1use crate::{
2 util::geom::{Rect, Vec2},
3 vulkano_render::{lyon::ColoredBuffersBuilder, subpass_stack::AbstractImageView},
4 CallbackContext,
5 Color,
6 Dimension,
7 Key,
8 WidgetContext,
9};
10use derivative::Derivative;
11use freelist::Idx;
12use rutter_layout::Layout;
13use smallvec::{smallvec, SmallVec};
14use std::{rc::Rc, sync::Arc};
15use vulkano::{
16 command_buffer::SecondaryAutoCommandBuffer,
17 pipeline::graphics::viewport::Viewport,
18 render_pass::RenderPass,
19};
20
21#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
38pub struct Fragment(pub(crate) u32);
39impl From<Key> for Fragment {
40 fn from(key: Key) -> Self { Fragment(key.0) }
41}
42impl From<Fragment> for Idx {
43 fn from(fragment: Fragment) -> Self { unsafe { Idx::new_unchecked(fragment.0 as _) } }
44}
45impl From<Fragment> for Key {
46 fn from(fragment: Fragment) -> Self { Key(fragment.0) }
47}
48impl From<Fragment> for FragmentChildren {
49 fn from(fragment: Fragment) -> Self { smallvec![fragment] }
50}
51impl From<Idx> for Fragment {
52 fn from(idx: Idx) -> Self { Fragment(idx.get() as _) }
53}
54pub type FragmentChildren = SmallVec<[Fragment; 8]>;
55
56
57#[derive(Derivative)]
58#[derivative(Debug)]
59pub struct UnevaluatedFragment {
60 pub key: Key,
61 #[derivative(Debug = "ignore")]
62 pub gen: Option<Box<dyn Fn(&mut WidgetContext) -> FragmentInner>>,
63}
64impl PartialEq for UnevaluatedFragment {
65 fn eq(&self, other: &Self) -> bool { self.key == other.key }
66}
67
68pub type SubPassRenderFunction = Rc<
69 dyn Fn(
70 &CallbackContext,
71 AbstractImageView, AbstractImageView, Arc<RenderPass>,
74 Viewport, [u32; 2], Rect, Rect, f32, ) -> SecondaryAutoCommandBuffer,
80>;
81
82#[derive(Clone)]
83pub struct SubPassSetup {
84 pub resolve: SubPassRenderFunction,
85 pub finish: Option<(SubPassRenderFunction, Option<usize>)>,
89}
90
91#[derive(Derivative)]
92#[derivative(Debug)]
93pub enum FragmentInner {
94 Leaf {
95 render_object: RenderObject,
96 layout: Box<dyn Layout>,
97 },
98 Node {
99 children: FragmentChildren,
100 layout: Box<dyn Layout>,
101 is_clipper: bool,
102 #[derivative(Debug = "ignore")]
103 subpass: Option<SubPassSetup>,
104 },
105}
106impl FragmentInner {
107 pub fn unpack(
108 self,
109 ) -> (Box<dyn Layout>, Option<RenderObject>, FragmentChildren, bool, Option<SubPassSetup>) {
110 match self {
111 Self::Leaf { render_object, layout } => {
112 (layout, Some(render_object), SmallVec::new(), false, None)
113 }
114 Self::Node { children, layout, is_clipper, subpass } => {
115 (layout, None, children, is_clipper, subpass)
116 }
117 }
118 }
119
120 pub fn from_fragment(fragment: Fragment) -> Self {
121 FragmentInner::Node {
122 children: smallvec![fragment],
123 layout: Box::new(rutter_layout::layouts::Transparent),
124 is_clipper: false,
125 subpass: None,
126 }
127 }
128}
129
130pub type PathGenInner = dyn Fn(
131 Vec2, &mut lyon::tessellation::FillTessellator,
133 &mut lyon::tessellation::StrokeTessellator,
134 ColoredBuffersBuilder,
135);
136pub type RenderFnInner = dyn Fn(
137 &Viewport,
138 f32, Rect, Vec2, ) -> SecondaryAutoCommandBuffer;
142#[derive(Derivative, Clone)]
144#[derivative(Debug)]
145pub enum RenderObject {
146 DebugRect,
147 RoundedRect {
148 inverted: bool,
149 stroke_color: Option<Color>,
150 fill_color: Option<Color>,
151 stroke_width: f32,
152 border_radius: Dimension,
153 for_clipping: bool,
154 },
155 Path {
156 #[derivative(Debug = "ignore")]
157 path_gen: Arc<PathGenInner>,
158 },
159 Text {
160 key: Key,
161 text: Rc<String>,
162 size: f32,
163 color: Color,
164 },
165 Input {
166 key: Key,
167 #[derivative(Debug = "ignore")]
170 on_click: Arc<dyn Fn(&CallbackContext, bool, Vec2, Vec2)>,
171 #[derivative(Debug = "ignore")]
172 on_hover: Arc<dyn Fn(&CallbackContext, bool, Vec2, Vec2)>,
173 #[derivative(Debug = "ignore")]
174 on_move: Arc<dyn Fn(&CallbackContext, Vec2, Vec2)>,
175 },
176 Raw {
177 #[derivative(Debug = "ignore")]
178 render_fn: Arc<RenderFnInner>,
179 },
180 None,
181}