1use {
2 std::{
3 ops::Deref,
4 ops::DerefMut,
5 },
6 crate::{
7 makepad_platform::*,
8 nav::*,
9 cx_2d::{Cx2d},
10 cx_draw::CxDraw,
11 turtle::{Walk,AlignEntry}
12 }
13};
14
15
16pub trait DrawListExt{
17 fn draw_list_id(&self) -> DrawListId;
18 fn set_view_transform(&self, cx: &mut Cx, mat: &Mat4);
19 fn begin_always(&mut self, cx: &mut CxDraw);
20 fn begin_maybe(&mut self, cx: &mut CxDraw, will_redraw: bool) -> Redrawing ;
21 fn end(&mut self, cx: &mut CxDraw) ;
22 fn get_view_transform(&self, cx: &Cx) -> Mat4;
23 fn redraw(&self, cx: &mut Cx) ;
24 fn redraw_self_and_children(&self, cx: &mut Cx);
25}
26
27impl DrawListExt for DrawList{
28 fn draw_list_id(&self) -> DrawListId {self.id()}
29 fn set_view_transform(&self, cx: &mut Cx, mat: &Mat4) {
30
31 fn set_view_transform_recur(draw_list_id: DrawListId, cx: &mut Cx, mat: &Mat4) {
32 cx.draw_lists[draw_list_id].draw_list_uniforms.view_transform = *mat;
36 let draw_items_len = cx.draw_lists[draw_list_id].draw_items.len();
37 for draw_item_id in 0..draw_items_len {
38 if let Some(sub_list_id) = cx.draw_lists[draw_list_id].draw_items[draw_item_id].sub_list() {
39 set_view_transform_recur(sub_list_id, cx, mat);
40 }
41 }
42 }
43 set_view_transform_recur(self.id(), cx, mat);
44 }
45
46 fn begin_always(&mut self, cx: &mut CxDraw) {
47 self.begin_maybe(cx, true).expect_redraw();
48 }
49
50 fn begin_maybe(&mut self, cx: &mut CxDraw, will_redraw: bool) -> Redrawing {
51
52 let pass_id = cx.pass_stack.last().unwrap().pass_id;
54 let redraw_id = cx.cx.redraw_id;
55
56 cx.draw_lists[self.id()].pass_id = Some(pass_id);
57
58 let codeflow_parent_id = cx.draw_list_stack.last().cloned();
59
60 let is_main_draw_list = if cx.passes[pass_id].main_draw_list_id.is_none() {
61 cx.passes[pass_id].main_draw_list_id = Some(self.id());
62 true
63 }
64 else{
65 false
66 };
67
68 if let Some(parent_id) = codeflow_parent_id {
70 if !is_main_draw_list{
71 let parent = &mut cx.cx.draw_lists[parent_id];
72 parent.append_sub_list(redraw_id, self.id());
73
74 cx.nav_list_item_push(parent_id, NavItem::Child(self.id()));
75 }
76 }
77
78 cx.cx.draw_lists[self.id()].codeflow_parent_id = codeflow_parent_id;
80
81 if cx.cx.draw_lists[self.id()].draw_items.len() != 0 && !will_redraw {
83 return Redrawing::no();
84 }
85
86 if cx.passes[pass_id].main_draw_list_id.unwrap() == self.id() {
87 cx.passes[pass_id].paint_dirty = true;
88 }
89
90 cx.cx.draw_lists[self.id()].clear_draw_items(redraw_id);
91
92 cx.nav_list_clear(self.id());
93
94 cx.draw_list_stack.push(self.id());
95
96 Redrawing::yes()
97 }
98
99 fn end(&mut self, cx: &mut CxDraw) {
100 let draw_list_id = cx.draw_list_stack.pop().unwrap();
101 if draw_list_id != self.id() {
102 panic!("Mismatch in drawlist id in view.end, check your begin/end pairs");
103 }
104 if cx.cx.draw_lists[draw_list_id].redraw_id != cx.cx.redraw_id {
105 panic!("calling end on a view that didnt get begin called this redraw cycle");
106 }
107 }
108
109 fn get_view_transform(&self, cx: &Cx) -> Mat4 {
110 let cxview = &cx.draw_lists[self.id()];
111 return cxview.draw_list_uniforms.view_transform
112 }
113
114 fn redraw(&self, cx: &mut Cx) {
115 cx.redraw_list(self.id());
116 }
117
118 fn redraw_self_and_children(&self, cx: &mut Cx) {
119 cx.redraw_list_and_children(self.id());
120 }
121}
122
123#[derive(Debug)]
124pub struct DrawList2d { pub (crate) draw_list: DrawList,
126 pub (crate) dirty_check_rect: Rect,
127}
128
129impl Deref for DrawList2d{type Target = DrawList; fn deref(&self) -> &Self::Target {&self.draw_list}}
130impl DerefMut for DrawList2d{fn deref_mut(&mut self) -> &mut Self::Target {&mut self.draw_list}}
131
132
133impl LiveHook for DrawList2d {}
134impl LiveNew for DrawList2d {
135 fn new(cx: &mut Cx) -> Self {
136 let draw_list = cx.draw_lists.alloc();
137 Self {
138 dirty_check_rect: Default::default(),
139 draw_list,
140 }
141 }
142
143 fn live_type_info(_cx: &mut Cx) -> LiveTypeInfo {
144 LiveTypeInfo {
145 module_id: LiveModuleId::from_str(&module_path!()).unwrap(),
146 live_type: LiveType::of::<Self>(),
147 live_ignore: true,
148 fields: Vec::new(),
149 type_name: id_lut!(View)
150 }
151 }
152}
153impl LiveApply for DrawList2d {
154 fn apply(&mut self, cx: &mut Cx, apply: &mut Apply, start_index: usize, nodes: &[LiveNode]) -> usize {
156
157 if !nodes[start_index].value.is_structy_type() {
158 cx.apply_error_wrong_type_for_struct(live_error_origin!(), start_index, nodes, live_id!(View));
159 return nodes.skip_node(start_index);
160 }
161 cx.draw_lists[self.draw_list.id()].debug_id = nodes[start_index].id;
162 let mut index = start_index + 1;
163 loop {
164 if nodes[index].value.is_close() {
165 index += 1;
166 break;
167 }
168 match nodes[index].id {
169 live_id!(debug_id) => cx.draw_lists[self.draw_list.id()].debug_id = LiveNew::new_apply_mut_index(cx, apply, &mut index, nodes),
170 _ => {
171 cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
172 index = nodes.skip_node(index);
173 }
174 }
175 }
176 return index;
177 }
178}
179
180impl DrawList2d {
181 pub fn begin_overlay_last(&mut self, cx: &mut Cx2d) {
182 self.begin_overlay_inner(cx, true)
183 }
184
185 pub fn begin_overlay_reuse(&mut self, cx: &mut Cx2d) {
186 self.begin_overlay_inner(cx, false)
187 }
188
189 pub fn begin_overlay_inner(&mut self, cx: &mut Cx2d, always_last:bool) {
190 let pass_id = cx.pass_stack.last().unwrap().pass_id;
191 let redraw_id = cx.cx.redraw_id;
192
193 cx.draw_lists[self.draw_list.id()].pass_id = Some(pass_id);
194
195 let codeflow_parent_id = cx.draw_list_stack.last().cloned().unwrap();
196
197 let overlay_id = cx.overlay_id.unwrap();
198 if always_last{
199 cx.draw_lists[overlay_id].store_sub_list_last(redraw_id, self.draw_list.id());
200 }
201 else{
202 cx.draw_lists[overlay_id].store_sub_list(redraw_id, self.draw_list.id());
203 }
204
205 cx.nav_list_item_push(codeflow_parent_id, NavItem::Child(self.draw_list.id()));
206
207 cx.cx.draw_lists[self.draw_list.id()].codeflow_parent_id = Some(codeflow_parent_id);
208 if cx.passes[pass_id].main_draw_list_id.unwrap() == self.draw_list.id() {
209 cx.passes[pass_id].paint_dirty = true;
210 }
211
212 cx.cx.draw_lists[self.draw_list.id()].clear_draw_items(redraw_id);
213
214 cx.nav_list_clear(self.draw_list.id());
215
216 cx.draw_list_stack.push(self.draw_list.id());
217 }
218
219 pub fn begin(&mut self, cx: &mut Cx2d, walk: Walk) -> Redrawing {
220 let will_redraw = cx.will_redraw(self, walk);
221 self.begin_maybe(cx, will_redraw)
222 }
223}
224
225
226impl<'a> CxDraw<'a> {
227
228 pub fn new_draw_call(&mut self, draw_vars: &DrawVars) -> Option<&mut CxDrawItem> {
229 return self.get_draw_call(false, draw_vars);
230 }
231
232 pub fn append_to_draw_call(&mut self, draw_vars: &DrawVars) -> Option<&mut CxDrawItem> {
233 return self.get_draw_call(true, draw_vars);
234 }
235
236 pub fn get_current_draw_list_id(&self) -> Option<DrawListId> {
237 self.draw_list_stack.last().cloned()
238 }
239
240 pub fn get_draw_call(&mut self, append: bool, draw_vars: &DrawVars) -> Option<&mut CxDrawItem> {
241
242 if draw_vars.draw_shader.is_none() {
243 return None
244 }
245 let draw_shader = draw_vars.draw_shader.unwrap();
246
247 if draw_shader.draw_shader_generation != self.draw_shaders.generation {
248 return None
249 }
250
251 let sh = &self.cx.draw_shaders[draw_shader.draw_shader_id];
252
253 let current_draw_list_id = *self.draw_list_stack.last().unwrap();
254 let draw_list = &mut self.cx.draw_lists[current_draw_list_id];
255
256 if append && !sh.mapping.flags.draw_call_always {
257 if let Some(index) = draw_list.find_appendable_drawcall(sh, draw_vars) {
258 return Some(&mut draw_list.draw_items[index]);
259 }
260 }
261
262 Some(draw_list.append_draw_call(self.cx.redraw_id, sh, draw_vars))
263 }
264
265 pub fn begin_many_instances(&mut self, draw_vars: &DrawVars) -> Option<ManyInstances> {
266
267 let draw_list_id = self.get_current_draw_list_id().unwrap();
268 let draw_item = self.append_to_draw_call(draw_vars);
269 if draw_item.is_none() {
270 return None
271 }
272 let draw_item = draw_item.unwrap();
273 let mut instances = None;
275
276 std::mem::swap(&mut instances, &mut draw_item.instances);
277 Some(ManyInstances {
278 instance_area: InstanceArea {
279 draw_list_id,
280 draw_item_id: draw_item.draw_item_id,
281 instance_count: 0,
282 instance_offset: instances.as_ref().unwrap().len(),
283 redraw_id: draw_item.redraw_id
284 },
285 aligned: None,
286 instances: instances.unwrap()
287 })
288 }
289
290 pub fn end_many_instances(&mut self, many_instances: ManyInstances) -> Area {
291 let mut ia = many_instances.instance_area;
292 let draw_list = &mut self.draw_lists[ia.draw_list_id];
293 let draw_item = &mut draw_list.draw_items[ia.draw_item_id];
294 let draw_call = draw_item.kind.draw_call().unwrap();
295
296 let mut instances = Some(many_instances.instances);
297 std::mem::swap(&mut instances, &mut draw_item.instances);
298 ia.instance_count = (draw_item.instances.as_ref().unwrap().len() - ia.instance_offset) / draw_call.total_instance_slots;
299 ia.into()
300 }
301
302 pub fn add_instance(&mut self, draw_vars: &DrawVars) -> Area {
303 let data = draw_vars.as_slice();
304 let draw_list_id = self.get_current_draw_list_id().unwrap();
305 let draw_item = self.append_to_draw_call(draw_vars);
306 if draw_item.is_none() {
307 return Area::Empty
308 }
309 let draw_item = draw_item.unwrap();
310 let draw_call = draw_item.draw_call().unwrap();
311 let instance_count = data.len() / draw_call.total_instance_slots;
312 let check = data.len() % draw_call.total_instance_slots;
313 if check > 0 {
314 panic!("Data not multiple of total slots");
315 }
316 let ia = InstanceArea {
317 draw_list_id,
318 draw_item_id: draw_item.draw_item_id,
319 instance_count: instance_count,
320 instance_offset: draw_item.instances.as_ref().unwrap().len(),
321 redraw_id: draw_item.redraw_id
322 };
323 draw_item.instances.as_mut().unwrap().extend_from_slice(data);
324 ia.into()
325 }
326
327}
328
329impl<'a,'b> Cx2d<'a,'b> {
330 pub fn begin_many_aligned_instances(&mut self, draw_vars: &DrawVars) -> Option<ManyInstances> {
331 let mut li = self.begin_many_instances(draw_vars);
332 if li.is_none() {
333 return None;
334 }
335 li.as_mut().unwrap().aligned = Some(self.align_list.len());
336 self.align_list.push(AlignEntry::Unset);
337 li
338 }
339
340 pub fn end_many_instances(&mut self, many_instances: ManyInstances) -> Area {
341 let mut ia = many_instances.instance_area;
342 let draw_list = &mut self.draw_lists[ia.draw_list_id];
343 let draw_item = &mut draw_list.draw_items[ia.draw_item_id];
344 let draw_call = draw_item.kind.draw_call().unwrap();
345
346 let mut instances = Some(many_instances.instances);
347 std::mem::swap(&mut instances, &mut draw_item.instances);
348 ia.instance_count = (draw_item.instances.as_ref().unwrap().len() - ia.instance_offset) / draw_call.total_instance_slots;
349 if let Some(aligned) = many_instances.aligned {
350 self.align_list[aligned] = AlignEntry::Area(ia.clone().into());
351 }
352 ia.into()
353 }
354
355
356 pub fn add_aligned_instance(&mut self, draw_vars: &DrawVars) -> Area {
357 let data = draw_vars.as_slice();
358 let draw_list_id = self.get_current_draw_list_id().unwrap();
359 let draw_item = self.append_to_draw_call(draw_vars);
360 if draw_item.is_none() {
361 return Area::Empty
362 }
363 let draw_item = draw_item.unwrap();
364 let draw_call = draw_item.draw_call().unwrap();
365 let instance_count = data.len() / draw_call.total_instance_slots;
366 let check = data.len() % draw_call.total_instance_slots;
367 if check > 0 {
368 error!("Data not multiple of total slots");
369 return Area::Empty
370 }
371 let ia: Area = (InstanceArea {
372 draw_list_id,
373 draw_item_id: draw_item.draw_item_id,
374 instance_count: instance_count,
375 instance_offset: draw_item.instances.as_ref().unwrap().len(),
376 redraw_id: draw_item.redraw_id
377 }).into();
378 draw_item.instances.as_mut().unwrap().extend_from_slice(data);
379 self.align_list.push(AlignEntry::Area(ia.clone()));
380 ia
381 }
382
383 pub fn add_aligned_rect_area(&mut self, area: &mut Area, rect: Rect) {
384 let draw_list_id = *self.draw_list_stack.last().unwrap();
385 let draw_list = &mut self.cx.draw_lists[draw_list_id];
386 let rect_id = draw_list.rect_areas.len();
388 draw_list.rect_areas.push(CxRectArea {
389 rect,
390 draw_clip:Default::default(),
391 });
392
393 let new_area = Area::Rect(RectArea {
394 draw_list_id,
395 redraw_id: self.redraw_id,
396 rect_id
397 });
398 self.align_list.push(AlignEntry::Area(new_area));
399 self.update_area_refs(*area, new_area);
400 *area = new_area;
401 }
402}
403
404#[derive(Debug)]
405pub struct ManyInstances {
406 pub instance_area: InstanceArea,
407 pub aligned: Option<usize>,
408 pub instances: Vec<f32>
409}
410
411#[derive(Clone)]
412pub struct AlignedInstance {
413 pub inst: InstanceArea,
414 pub index: usize
415}
416
417pub type Redrawing = Result<(), ()>;
418
419pub trait RedrawingApi {
420 fn no() -> Redrawing {Result::Err(())}
421 fn yes() -> Redrawing {Result::Ok(())}
422 fn is_redrawing(&self) -> bool;
423 fn is_not_redrawing(&self) -> bool;
424 fn expect_redraw(&self);
425}
426
427impl RedrawingApi for Redrawing {
428 fn is_redrawing(&self) -> bool {
429 match *self {
430 Result::Ok(_) => true,
431 Result::Err(_) => false
432 }
433 }
434 fn is_not_redrawing(&self) -> bool {
435 match *self {
436 Result::Ok(_) => false,
437 Result::Err(_) => true
438 }
439 }
440 fn expect_redraw(&self) {
441 if !self.is_redrawing() {
442 panic!("assume_redraw_yes it should redraw")
443 }
444 }
445}