1use std::cell::RefCell;
2use std::rc::Rc;
3use crate::makepad_math::{Rect, Vec4, DVec2};
4use crate::cx::Cx;
5use crate::makepad_error_log::*;
6use crate::draw_list::DrawListId;
7use std::fmt::Write;
8
9#[derive(Clone, Default)]
10pub struct DebugInner {
11 pub rects: Vec<(Rect, Vec4)>,
12 pub points: Vec<(DVec2, Vec4)>,
13 pub labels: Vec<(DVec2, Vec4, String)>,
14 pub marker: u64,
15}
16
17#[derive(Clone, Default)]
18pub struct Debug(Rc<RefCell<DebugInner >>);
19
20impl Debug {
21 const R: Vec4 = Vec4 {x: 1.0, y: 0.0, z: 0.0, w: 1.0};
22 const G: Vec4 = Vec4 {x: 0.0, y: 1.0, z: 0.0, w: 1.0};
23 const B: Vec4 = Vec4 {x: 0.0, y: 0.0, z: 1.0, w: 1.0};
24
25 pub fn marker(&self)->u64{
26 let inner = self.0.borrow();
27 inner.marker
28 }
29
30 pub fn set_marker(&mut self, v:u64){
31 let mut inner = self.0.borrow_mut();
32 inner.marker = v
33 }
34
35 pub fn point(&self, color: Vec4, p: DVec2) {
36 let mut inner = self.0.borrow_mut();
37 inner.points.push((p, color));
38 }
39
40 pub fn point_r(&self, p: DVec2) {self.point(Self::R, p)}
41 pub fn point_g(&self, p: DVec2) {self.point(Self::G, p)}
42 pub fn point_b(&self, p: DVec2) {self.point(Self::B, p)}
43
44 pub fn label(&self, color: Vec4, p: DVec2, label:String) {
45 let mut inner = self.0.borrow_mut();
46 inner.labels.push((p, color,label));
47 }
48
49 pub fn label_r(&self, p: DVec2, label:String) {self.label(Self::R, p, label)}
50 pub fn label_g(&self, p: DVec2, label:String) {self.label(Self::G, p, label)}
51 pub fn label_b(&self, p: DVec2, label:String) {self.label(Self::B, p, label)}
52
53 pub fn rect(&self, color: Vec4, p: Rect) {
54 let mut inner = self.0.borrow_mut();
55 inner.rects.push((p, color));
56 }
57 pub fn rect_r(&self, r: Rect) {self.rect(Self::R, r)}
58 pub fn rect_g(&self, r: Rect) {self.rect(Self::G, r)}
59 pub fn rect_b(&self, r: Rect) {self.rect(Self::B, r)}
60
61 pub fn has_data(&self)->bool{
62 let inner = self.0.borrow();
63 !inner.points.is_empty() || !inner.rects.is_empty() || !inner.labels.is_empty()
64 }
65
66 pub fn take_rects(&self)->Vec<(Rect, Vec4)>{
67 let mut inner = self.0.borrow_mut();
68 let mut swap = Vec::new();
69 std::mem::swap(&mut swap, &mut inner.rects);
70 swap
71 }
72
73 pub fn take_points(&self)->Vec<(DVec2, Vec4)>{
74 let mut inner = self.0.borrow_mut();
75 let mut swap = Vec::new();
76 std::mem::swap(&mut swap, &mut inner.points);
77 swap
78 }
79
80 pub fn take_labels(&self)->Vec<(DVec2, Vec4, String)>{
81 let mut inner = self.0.borrow_mut();
82 let mut swap = Vec::new();
83 std::mem::swap(&mut swap, &mut inner.labels);
84 swap
85 }
86}
87
88impl Cx{
89
90 pub fn debug_draw_tree(&self, dump_instances: bool, draw_list_id: DrawListId) {
91 fn debug_draw_tree_recur(cx: &Cx, dump_instances: bool, s: &mut String, draw_list_id: DrawListId, depth: usize) {
92 let mut indent = String::new();
97 for _i in 0..depth {
98 indent.push_str("| ");
99 }
100 let draw_items_len = cx.draw_lists[draw_list_id].draw_items.len();
101 writeln!(
107 s,
108 "{}{} {:?}: len:{}",
109 indent,
110 cx.draw_lists[draw_list_id].debug_id,
111 draw_list_id,
112 draw_items_len,
113 ).unwrap();
114 indent.push_str(" ");
115 let mut indent = String::new();
116 for _i in 0..depth + 1 {
117 indent.push_str("| ");
118 }
119 for draw_item_id in 0..draw_items_len {
120 if let Some(sub_list_id) = cx.draw_lists[draw_list_id].draw_items[draw_item_id].sub_list() {
121 debug_draw_tree_recur(cx, dump_instances, s, sub_list_id, depth + 1);
122 }
123 else {
124 let cxview = &cx.draw_lists[draw_list_id];
125 let darw_item = &cxview.draw_items[draw_item_id];
126 let draw_call = darw_item.draw_call().unwrap();
127 let sh = &cx.draw_shaders.shaders[draw_call.draw_shader.draw_shader_id];
128 let slots = sh.mapping.instances.total_slots;
129 let instances = darw_item.instances.as_ref().unwrap().len() / slots;
130 writeln!(
131 s,
132 "{}{}({}) sid:{} inst:{}",
133 indent,
134 draw_call.options.debug_id.unwrap_or(sh.class_prop),
135 sh.type_name,
136 draw_call.draw_shader.draw_shader_id,
137 instances,
138 ).unwrap();
139 if dump_instances {
141 for inst in 0..instances.min(1) {
142 let mut out = String::new();
143 let mut off = 0;
144 for input in &sh.mapping.instances.inputs {
145 let buf = darw_item.instances.as_ref().unwrap();
146 match input.slots {
147 1 => out.push_str(&format!("{}:{} ", input.id, buf[inst * slots + off])),
148 2 => out.push_str(&format!("{}:v2({},{}) ", input.id, buf[inst * slots + off], buf[inst * slots + 1 + off])),
149 3 => out.push_str(&format!("{}:v3({},{},{}) ", input.id, buf[inst * slots + off], buf[inst * slots + 1 + off], buf[inst * slots + 1 + off])),
150 4 => out.push_str(&format!("{}:v4({},{},{},{}) ", input.id, buf[inst * slots + off], buf[inst * slots + 1 + off], buf[inst * slots + 2 + off], buf[inst * slots + 3 + off])),
151 _ => {}
152 }
153 off += input.slots;
154 }
155 writeln!(s, " {}instance {}: {}", indent, inst, out).unwrap();
156 }
157 }
158 }
159 }
160 }
164
165 let mut s = String::new();
166 debug_draw_tree_recur(self, dump_instances, &mut s, draw_list_id, 0);
167 log!("{}", s);
168 }
169
170}