1use {
2 crate::{
3 makepad_math::*,
4 makepad_shader_compiler::{
5 ShaderTy
6 },
7 makepad_live_compiler::{
8 LiveId,
9 },
10 draw_list::DrawListId,
11 cx::Cx
12 }
13};
14
15#[derive(Clone, Hash, Ord, PartialOrd, Eq, Debug, PartialEq, Copy)]
16pub struct InstanceArea {
17 pub draw_list_id: DrawListId,
18 pub draw_item_id: usize,
19 pub instance_offset: usize,
20 pub instance_count: usize,
21 pub redraw_id: u64
22}
23#[derive(Clone, Hash, Ord, PartialOrd, Eq, Debug, PartialEq, Copy)]
31pub struct RectArea {
32 pub draw_list_id: DrawListId,
33 pub rect_id: usize,
34 pub redraw_id: u64
35}
36
37#[derive(Clone, Debug, Hash, PartialEq, Ord, PartialOrd, Eq, Copy)]
38pub enum Area {
39 Empty,
40 Instance(InstanceArea),
41 Rect(RectArea)
43}
44
45impl Default for Area {
46 fn default() -> Area {
47 Area::Empty
48 }
49}
50
51pub struct DrawReadRef<'a> {
52 pub repeat: usize,
53 pub stride: usize,
54 pub buffer: &'a [f32]
55}
56
57pub struct DrawWriteRef<'a> {
58 pub repeat: usize,
59 pub stride: usize,
60 pub buffer: &'a mut [f32]
61}
62
63impl Into<Area> for InstanceArea {
64 fn into(self) -> Area {
65 Area::Instance(self)
66 }
67}
68
69impl Area {
70 pub fn area(&self)->Self{
71 self.clone()
72 }
73
74 pub fn redraw(&self, cx: &mut Cx) {
75 cx.redraw_area(*self);
76 }
77
78
79 pub fn valid_instance(&self, cx: &Cx) -> Option<&InstanceArea> {
80 if self.is_valid(cx) {
81 if let Self::Instance(inst) = self {
82 return Some(inst)
83 }
84 }
85 None
86 }
87
88 pub fn is_empty(&self) -> bool {
89 if let Area::Empty = self {
90 return true
91 }
92 false
93 }
94
95 pub fn draw_list_id(&self) -> Option<DrawListId> {
96 return match self {
97 Area::Instance(inst) => {
98 Some(inst.draw_list_id)
99 },
100 Area::Rect(list) => {
101 Some(list.draw_list_id)
102 }
103 _ => None
104 }
105 }
106
107 pub fn redraw_id(&self) -> Option<u64> {
108 return match self {
109 Area::Instance(inst) => {
110 Some(inst.redraw_id)
111 },
112 Area::Rect(list) => {
113 Some(list.redraw_id)
114 }
115 _ => None
116 }
117 }
118
119 pub fn is_first_instance(&self) -> bool {
120 return match self {
121 Area::Instance(inst) => {
122 inst.instance_offset == 0
123 },
124 _ => false,
125 }
126 }
127
128 pub fn is_valid(&self, cx: &Cx) -> bool {
129 return match self {
130 Area::Instance(inst) => {
131 if inst.instance_count == 0 {
132 return false
133 }
134 if let Some(draw_list) = cx.draw_lists.checked_index(inst.draw_list_id){
135 if draw_list.redraw_id != inst.redraw_id {
136 return false
137 }
138 return true
139 }
140 return false
141 },
142 Area::Rect(list) => {
143 if let Some(draw_list) = cx.draw_lists.checked_index(list.draw_list_id){
144 if draw_list.redraw_id != list.redraw_id {
145 return false
146 }
147 return true
148 }
149 return false
150 },
151 _ => false,
152 }
153 }
154
155 pub fn clipped_rect(&self, cx: &Cx) -> Rect {
157
158 return match self {
159 Area::Instance(inst) => {
160 if inst.instance_count == 0 {
161 error!("get_rect called on instance_count ==0 area pointer, use mark/sweep correctly!");
163 return Rect::default()
164 }
165 let draw_list = &cx.draw_lists[inst.draw_list_id];
166 if draw_list.redraw_id != inst.redraw_id {
167 return Rect::default();
168 }
169 let draw_item = &draw_list.draw_items[inst.draw_item_id];
170 let draw_call = draw_item.draw_call().unwrap();
171
172 if draw_item.instances.as_ref().unwrap().len() == 0 {
173 error!("No instances but everything else valid?");
174 return Rect::default()
175 }
176 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
177 error!("Generation invalid get_rect {} {:?} {} {}", draw_list.debug_id, inst, cx.draw_shaders.generation, draw_call.draw_shader.draw_shader_generation);
178 return Rect::default()
179 }
180 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id];
181 let buf = draw_item.instances.as_ref().unwrap();
183 if let Some(rect_pos) = sh.mapping.rect_pos {
184 let pos = dvec2(
185 buf[inst.instance_offset + rect_pos + 0] as f64,
186 buf[inst.instance_offset + rect_pos + 1] as f64
187 );
188 if let Some(rect_size) = sh.mapping.rect_size {
189 let size = dvec2(buf[inst.instance_offset + rect_size + 0] as f64, buf[inst.instance_offset + rect_size + 1] as f64);
190 if let Some(draw_clip) = sh.mapping.draw_clip {
191 let p1= dvec2(
192 buf[inst.instance_offset + draw_clip + 0] as f64,
193 buf[inst.instance_offset + draw_clip + 1] as f64,
194 );
195 let p2 = dvec2(
196 buf[inst.instance_offset + draw_clip + 2] as f64,
197 buf[inst.instance_offset + draw_clip + 3] as f64
198 );
199 if draw_list.draw_list_has_clip{
200 let p3 = dvec2(
201 draw_list.draw_list_uniforms.view_clip.x as f64,
202 draw_list.draw_list_uniforms.view_clip.y as f64,
203 );
204 let p4 = dvec2(
205 draw_list.draw_list_uniforms.view_clip.z as f64,
206 draw_list.draw_list_uniforms.view_clip.w as f64,
207 );
208 let shift = dvec2(
209 draw_list.draw_list_uniforms.view_shift.x as f64,
210 draw_list.draw_list_uniforms.view_shift.y as f64
211 );
212 return Rect{pos,size}.clip((p1,p2)).translate(shift).clip((p3,p4));
213 }
214 else{
215 return Rect{pos,size}.clip((p1,p2));
216 }
217 }
218 }
219 }
220 Rect::default()
221 },
222 Area::Rect(ra) => {
223 let draw_list = &cx.draw_lists[ra.draw_list_id];
225 let rect_area = &draw_list.rect_areas[ra.rect_id];
226 if draw_list.draw_list_has_clip{
227 let p3 = dvec2(
228 draw_list.draw_list_uniforms.view_clip.x as f64,
229 draw_list.draw_list_uniforms.view_clip.y as f64,
230 );
231 let p4 = dvec2(
232 draw_list.draw_list_uniforms.view_clip.z as f64,
233 draw_list.draw_list_uniforms.view_clip.w as f64,
234 );
235 let shift = dvec2(
236 draw_list.draw_list_uniforms.view_shift.x as f64,
237 draw_list.draw_list_uniforms.view_shift.y as f64
238 );
239 return rect_area.rect.clip(rect_area.draw_clip).translate(shift).clip((p3,p4));
240 }
241 else{
242 return rect_area.rect.clip(rect_area.draw_clip);
243 }
244 },
245 _ => Rect::default(),
246 }
247 }
248
249 pub fn rect(&self, cx: &Cx) -> Rect {
250
251 return match self {
252 Area::Instance(inst) => {
253 if inst.instance_count == 0 {
254 error!("get_rect called on instance_count ==0 area pointer, use mark/sweep correctly!");
256 return Rect::default()
257 }
258 let draw_list = &cx.draw_lists[inst.draw_list_id];
259 if draw_list.redraw_id != inst.redraw_id {
260 return Rect::default();
261 }
262 let draw_item = &draw_list.draw_items[inst.draw_item_id];
263 let draw_call = draw_item.draw_call().unwrap();
264
265 if draw_item.instances.as_ref().unwrap().len() == 0 {
266 error!("No instances but everything else valid?");
267 return Rect::default()
268 }
269 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
270 error!("Generation invalid get_rect {} {:?} {} {}", draw_list.debug_id, inst, cx.draw_shaders.generation, draw_call.draw_shader.draw_shader_generation);
271 return Rect::default()
272 }
273 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id];
274 let buf = draw_item.instances.as_ref().unwrap();
276 if let Some(rect_pos) = sh.mapping.rect_pos {
277 let pos = dvec2(buf[inst.instance_offset + rect_pos + 0] as f64, buf[inst.instance_offset + rect_pos + 1] as f64);
278 if let Some(rect_size) = sh.mapping.rect_size {
279 let size = dvec2(buf[inst.instance_offset + rect_size + 0] as f64, buf[inst.instance_offset + rect_size + 1] as f64);
280 return Rect{pos,size};
281 }
282 }
283 Rect::default()
284 },
285 Area::Rect(ra) => {
286 let draw_list = &cx.draw_lists[ra.draw_list_id];
287 if draw_list.redraw_id == ra.redraw_id{
288 let rect_area = &draw_list.rect_areas[ra.rect_id];
289 return rect_area.rect;
290 }
291 Rect::default()
292 },
293 _ => Rect::default(),
294 }
295 }
296
297 pub fn abs_to_rel(&self, cx: &Cx, abs: DVec2) -> DVec2 {
298 return match self {
299 Area::Instance(inst) => {
300 if inst.instance_count == 0 {
301 error!("abs_to_rel_scroll called on instance_count ==0 area pointer, use mark/sweep correctly!");
302 return abs
303 }
304 let draw_list = &cx.draw_lists[inst.draw_list_id];
305 if draw_list.redraw_id != inst.redraw_id {
306 return abs;
307 }
308 let draw_item = &draw_list.draw_items[inst.draw_item_id];
309 let draw_call = draw_item.draw_call().unwrap();
310 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
311 error!("Generation invalid abs_to_rel {} {:?} {} {}", draw_list.debug_id, inst, cx.draw_shaders.generation, draw_call.draw_shader.draw_shader_generation);
312 return abs;
313 }
314
315 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id];
316 if let Some(rect_pos) = sh.mapping.rect_pos {
318 let buf = draw_item.instances.as_ref().unwrap();
319 let x = buf[inst.instance_offset + rect_pos + 0] as f64;
320 let y = buf[inst.instance_offset + rect_pos + 1] as f64;
321 return DVec2 {
322 x: abs.x - x,
323 y: abs.y - y
324 }
325 }
326 abs
327 },
328 Area::Rect(ra) => {
329 let draw_list = &cx.draw_lists[ra.draw_list_id];
330 let rect_area = &draw_list.rect_areas[ra.rect_id];
331 DVec2 {
332 x: abs.x - rect_area.rect.pos.x,
333 y: abs.y - rect_area.rect.pos.y
334 }
335 },
336 _ => abs,
337 }
338 }
339
340 pub fn set_rect(&self, cx: &mut Cx, rect: &Rect) {
341 match self {
342 Area::Instance(inst) => {
343 let cxview = &mut cx.draw_lists[inst.draw_list_id];
344 if cxview.redraw_id != inst.redraw_id {
345 return;
347 }
348 let draw_item = &mut cxview.draw_items[inst.draw_item_id];
349 let draw_call = draw_item.kind.draw_call().unwrap();
351 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
352 return;
353 }
354 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id]; let buf = draw_item.instances.as_mut().unwrap();
356 if let Some(rect_pos) = sh.mapping.rect_pos {
357 buf[inst.instance_offset + rect_pos + 0] = rect.pos.x as f32;
358 buf[inst.instance_offset + rect_pos + 1] = rect.pos.y as f32;
359 }
360 if let Some(rect_size) = sh.mapping.rect_size {
361 buf[inst.instance_offset + rect_size + 0] = rect.size.x as f32;
362 buf[inst.instance_offset + rect_size + 1] = rect.size.y as f32;
363 }
364 },
365 Area::Rect(ra) => {
366 let draw_list = &mut cx.draw_lists[ra.draw_list_id];
367 let rect_area = &mut draw_list.rect_areas[ra.rect_id];
368 rect_area.rect = *rect
369 },
370 _ => ()
371 }
372 }
373
374 pub fn get_read_ref<'a>(&self, cx: &'a Cx, id: LiveId, ty: ShaderTy) -> Option<DrawReadRef<'a >> {
375 match self {
376 Area::Instance(inst) => {
377 let draw_list = &cx.draw_lists[inst.draw_list_id];
378 let draw_item = &draw_list.draw_items[inst.draw_item_id];
379 let draw_call = draw_item.draw_call().unwrap();
380 if draw_list.redraw_id != inst.redraw_id {
381 error!("get_instance_read_ref called on invalid area pointer, use mark/sweep correctly!");
382 return None;
383 }
384 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
385 return None;
386 }
387 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id];
388 if let Some(input) = sh.mapping.user_uniforms.inputs.iter().find( | input | input.id == id) {
389 if input.ty != ty {
390 panic!("get_read_ref wrong uniform type, expected {:?} got: {:?}!", input.ty, ty);
391 }
392 return Some(
393 DrawReadRef {
394 repeat: 1,
395 stride: 0,
396 buffer: &draw_call.user_uniforms[input.offset..]
397 }
398 )
399 }
400 if let Some(input) = sh.mapping.instances.inputs.iter().find( | input | input.id == id) {
401 if input.ty != ty {
402 panic!("get_read_ref wrong instance type, expected {:?} got: {:?}!", input.ty, ty);
403 }
404 if inst.instance_count == 0 {
405 return None
406 }
407 return Some(
408 DrawReadRef {
409 repeat: inst.instance_count,
410 stride: sh.mapping.instances.total_slots,
411 buffer: &draw_item.instances.as_ref().unwrap()[(inst.instance_offset + input.offset)..],
412 }
413 )
414 }
415 panic!("get_read_ref property not found! {}", id);
416 }
417 _ => (),
418 }
419 None
420 }
421
422 pub fn get_write_ref<'a>(&self, cx: &'a mut Cx, id: LiveId, ty: ShaderTy, name: &str) -> Option<DrawWriteRef<'a >> {
423 match self {
424 Area::Instance(inst) => {
425 let draw_list = &mut cx.draw_lists[inst.draw_list_id];
426 if draw_list.redraw_id != inst.redraw_id {
427 return None;
428 }
429 let draw_item = &mut draw_list.draw_items[inst.draw_item_id];
430 let draw_call = draw_item.kind.draw_call_mut().unwrap();
431 if cx.draw_shaders.generation != draw_call.draw_shader.draw_shader_generation {
432 return None;
433 }
434 let sh = &cx.draw_shaders[draw_call.draw_shader.draw_shader_id];
435
436 if let Some(input) = sh.mapping.user_uniforms.inputs.iter().find( | input | input.id == id) {
437 if input.ty != ty {
438 panic!("get_write_ref {} wrong uniform type, expected {:?} got: {:?}!", name, input.ty, ty);
439 }
440
441 cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
442 draw_call.uniforms_dirty = true;
443
444 return Some(
445 DrawWriteRef {
446 repeat: 1,
447 stride: 0,
448 buffer: &mut draw_call.user_uniforms[input.offset..]
449 }
450 )
451 }
452 if let Some(input) = sh.mapping.instances.inputs.iter().find( | input | input.id == id) {
453 if input.ty != ty {
454 panic!("get_write_ref {} wrong instance type, expected {:?} got: {:?}!", name, input.ty, ty);
455 }
456
457 cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
458 draw_call.instance_dirty = true;
459 if inst.instance_count == 0 {
460 return None
461 }
462 return Some(
463 DrawWriteRef {
464 repeat: inst.instance_count,
465 stride: sh.mapping.instances.total_slots,
466 buffer: &mut draw_item.instances.as_mut().unwrap()[(inst.instance_offset + input.offset)..]
467 }
468 )
469 }
470 panic!("get_write_ref {} property not found!", name);
471 }
472 _ => (),
473 }
474 None
475 }
476}
477