makepad_platform/
draw_vars.rs

1use {
2    crate::{
3        makepad_live_compiler::{
4            LiveRegistry,
5            TokenSpan,
6            LivePtr,
7            LiveValue,
8            LiveTypeInfo,
9            LiveFieldKind,
10            LiveModuleId,
11            LiveType,
12            LiveNode,
13            LiveNodeSliceApi
14        },
15        makepad_live_tokenizer::{LiveErrorOrigin, live_error_origin},
16        makepad_shader_compiler::*,
17        makepad_live_id::*,
18        makepad_math::*,
19        cx::Cx,
20        texture::{Texture},
21        geometry::GeometryId,
22        area::Area,
23        geometry::{GeometryFields},
24        live_traits::*,
25        draw_shader::*
26    },
27};
28
29/*
30pub enum ShaderCompileResult {
31    Nop,
32    Ok
33}*/
34
35
36#[cfg(any(target_arch = "wasm32", target_os="android", target_os="linux"))]
37pub const fn shader_enum(i: u32) -> u32 {
38    match i {
39        1 => 0x3f800000,
40        2 => 0x40000000,
41        3 => 0x40400000,
42        4 => 0x40800000,
43        5 => 0x40a00000,
44        6 => 0x40c00000,
45        7 => 0x40e00000,
46        8 => 0x41000000,
47        9 => 0x41100000,
48        10 => 0x41200000,
49        11 => 0x41300000,
50        12 => 0x41400000,
51        13 => 0x41500000,
52        14 => 0x41600000,
53        15 => 0x41700000,
54        16 => 0x41800000,
55        17 => 0x41880000,
56        18 => 0x41900000,
57        19 => 0x41980000,
58        20 => 0x41a00000,
59        21 => 0x41a80000,
60        22 => 0x41b00000,
61        23 => 0x41b80000,
62        24 => 0x41c00000,
63        25 => 0x41c80000,
64        26 => 0x41d00000,
65        27 => 0x41d80000,
66        28 => 0x41e00000,
67        29 => 0x41e80000,
68        30 => 0x41f00000,
69        31 => 0x41f80000,
70        _ => panic!()
71    }
72}
73
74#[cfg(not(any(target_arch = "wasm32", target_os="android", target_os="linux")))]
75pub const fn shader_enum(i: u32) -> u32 {
76    if i<1 || i > 31 {
77        panic!();
78    }
79    i
80}
81
82pub const DRAW_CALL_USER_UNIFORMS: usize = 256;
83pub const DRAW_CALL_TEXTURE_SLOTS: usize = 4;
84pub const DRAW_CALL_VAR_INSTANCES: usize = 32;
85
86#[derive(Clone)]
87#[repr(C)]
88pub struct DrawVars {
89    pub area: Area,
90    pub (crate) var_instance_start: usize,
91    pub (crate) var_instance_slots: usize,
92    pub (crate) options: CxDrawShaderOptions,
93    pub draw_shader: Option<DrawShader>,
94    pub (crate) geometry_id: Option<GeometryId>,
95    pub user_uniforms: [f32; DRAW_CALL_USER_UNIFORMS],
96    pub texture_slots: [Option<Texture>; DRAW_CALL_TEXTURE_SLOTS],
97    pub var_instances: [f32; DRAW_CALL_VAR_INSTANCES]
98}
99
100impl Default for DrawVars{
101    fn default()->Self{
102        Self{
103            area: Default::default(),
104            var_instance_start: Default::default(),
105            var_instance_slots: Default::default(),
106            options: Default::default(),
107            draw_shader: Default::default(),
108            geometry_id: Default::default(),
109            user_uniforms: [0f32; DRAW_CALL_USER_UNIFORMS],
110            texture_slots: Default::default(),
111            var_instances: [0f32; DRAW_CALL_VAR_INSTANCES]
112        }
113    }
114}
115
116impl LiveHookDeref for DrawVars{}
117
118impl LiveNew for DrawVars {
119    fn new(_cx: &mut Cx) -> Self {
120        Self::default()
121    }
122    
123    fn live_type_info(_cx: &mut Cx) -> LiveTypeInfo {
124        LiveTypeInfo {
125            module_id: LiveModuleId::from_str(&module_path!()).unwrap(),
126            live_type: std::any::TypeId::of::<Self>(),
127            live_ignore: true,
128            fields: Vec::new(),
129            type_name: id_lut!(DrawVars)
130        }
131    }
132}
133
134impl LiveApply for DrawVars {
135    fn apply(&mut self, _cx: &mut Cx, _applyl: &mut Apply, _index: usize, _nodes: &[LiveNode]) -> usize {
136        panic!()
137    }
138}
139
140impl LiveApplyReset for DrawVars {
141    fn apply_reset(&mut self, _cx: &mut Cx, _applyl: &mut Apply, _index: usize, _nodes: &[LiveNode]) {
142        // do nothing
143    }
144}
145
146impl LiveHook for DrawVars {}
147
148impl DrawVars {
149    
150    pub fn set_texture(&mut self, slot: usize, texture: &Texture) {
151        self.texture_slots[slot] = Some(texture.clone());
152    }
153    
154    pub fn empty_texture(&mut self, slot: usize) {
155        self.texture_slots[slot] = None;
156    }
157
158    pub fn redraw(&self, cx: &mut Cx) {
159        self.area.redraw(cx);
160    }
161    
162    pub fn area(&self) -> Area {
163        self.area
164    }
165    
166    pub fn can_instance(&self) -> bool {
167        self.draw_shader.is_some()
168    }
169    
170    pub fn as_slice<'a>(&'a self) -> &'a [f32] {
171        unsafe {
172            std::slice::from_raw_parts((&self.var_instances[self.var_instance_start - 1] as *const _ as *const f32).offset(1), self.var_instance_slots)
173        }
174    }
175    
176    pub fn init_shader(&mut self, cx: &mut Cx, apply: &mut Apply, draw_shader_ptr: DrawShaderPtr, geometry_fields: &dyn GeometryFields) {
177        self.draw_shader = None;
178        
179        if cx.draw_shaders.error_set.contains(&draw_shader_ptr) {
180            return
181        }
182        
183        if let Some(item) = cx.draw_shaders.ptr_to_item.get(&draw_shader_ptr) {
184            self.draw_shader = Some(DrawShader {
185                draw_shader_generation: cx.draw_shaders.generation,
186                draw_shader_ptr,
187                draw_shader_id: item.draw_shader_id
188            });
189            self.options = item.options.clone();
190        }
191        else {
192            // create a fingerprint from all the dsl nodes only
193            let fingerprint = DrawShaderFingerprint::from_ptr(cx, draw_shader_ptr);
194            
195            // see if we have it already
196            if let Some(fp) = cx.draw_shaders.fingerprints.iter().find( | fp | fp.fingerprint == fingerprint) {
197                self.options = CxDrawShaderOptions::from_ptr(cx, draw_shader_ptr);
198                cx.draw_shaders.ptr_to_item.insert(draw_shader_ptr, CxDrawShaderItem {
199                    draw_shader_id: fp.draw_shader_id,
200                    options: self.options.clone()
201                });
202                self.draw_shader = Some(DrawShader {
203                    draw_shader_generation: cx.draw_shaders.generation,
204                    draw_shader_ptr,
205                    draw_shader_id: fp.draw_shader_id
206                });
207                return;
208            }
209            
210            // see if another variant errored
211            if cx.draw_shaders.error_fingerprints.iter().find( | fp | **fp == fingerprint).is_some() {
212                return;
213            }
214
215            fn live_type_to_shader_ty(live_type: LiveType) -> Option<ShaderTy> {
216                if live_type == LiveType::of::<f32>() {Some(ShaderTy::Float)}
217                else if live_type == LiveType::of::<Vec2>() {Some(ShaderTy::Vec2)}
218                else if live_type == LiveType::of::<Vec3>() {Some(ShaderTy::Vec3)}
219                else if live_type == LiveType::of::<Vec4>() {Some(ShaderTy::Vec4)}
220                else if live_type == LiveType::of::<Mat4>() {Some(ShaderTy::Mat4)}
221                else {None}
222            }
223            // ok ! we have to compile it
224            //let live_factories = &cx.live_factories;
225            let live_registry_cp = cx.live_registry.clone();
226            let live_registry = live_registry_cp.borrow();
227            
228            let result = cx.shader_registry.analyse_draw_shader(&live_registry, draw_shader_ptr, | live_registry, shader_registry, span, draw_shader_query, live_type, draw_shader_def | {
229                match draw_shader_query {
230                    DrawShaderQuery::DrawShader => {
231                        fn recur_expand(
232                            live_registry: &LiveRegistry,
233                            shader_registry: &ShaderRegistry,
234                            level: usize,
235                            after_draw_vars: &mut bool,
236                            live_type: LiveType,
237                            draw_shader_def: &mut DrawShaderDef,
238                            span: TokenSpan
239                        ) {
240                            if let Some(lf) = live_registry.live_type_infos.get(&live_type) {
241                                
242                                let mut slots = 0;
243                                for field in &lf.fields {
244                                    if let LiveFieldKind::Deref = field.live_field_kind {
245                                        if field.live_type_info.live_type != LiveType::of::<DrawVars>() {
246                                            recur_expand(live_registry, shader_registry, level + 1, after_draw_vars, field.live_type_info.live_type, draw_shader_def, span);
247                                            continue
248                                        }
249                                        else{
250                                            *after_draw_vars = true;
251                                            continue
252                                        }
253                                    }
254                                    if *after_draw_vars {
255                                        // lets count sizes
256                                        //
257                                        let live_type = field.live_type_info.live_type;
258                                        if shader_registry.enums.get(&live_type).is_some() {
259                                            slots += 1;
260                                            //draw_shader_def.enums
261                                            
262                                            draw_shader_def.add_instance(field.id, ShaderTy::Enum(live_type), span, field.live_field_kind);
263                                        }
264                                        else {
265                                            let ty = live_type_to_shader_ty(live_type).expect("Please only put shader-understandable instance fields after draw_vars");
266                                            slots += ty.slots();
267                                            draw_shader_def.add_instance(field.id, ty, span, field.live_field_kind);
268                                        }
269                                    }
270                                }
271                                // insert padding
272                                if level >0 && slots % 2 == 1 {
273                                    draw_shader_def.add_instance(LiveId(0), ShaderTy::Float, span, LiveFieldKind::Calc);
274                                }
275                            }
276                        }
277                        recur_expand(live_registry, shader_registry, 0, &mut false, live_type, draw_shader_def, span);
278                    }
279                    DrawShaderQuery::Geometry => {
280                        if live_type == geometry_fields.live_type_check() {
281                            let mut fields = Vec::new();
282                            geometry_fields.geometry_fields(&mut fields);
283                            for field in fields {
284                                draw_shader_def.add_geometry(field.id, field.ty, span);
285                            }
286                        }
287                        else {
288                            eprintln!("lf.get_type() != geometry_fields.live_type_check()");
289                        }
290                    }
291                }
292            });
293            // ok lets print an error
294            match result {
295                Err(e) => {
296                    cx.draw_shaders.error_set.insert(draw_shader_ptr);
297                    cx.draw_shaders.error_fingerprints.push(fingerprint);
298                    // ok so. lets get the source for this file id
299                    let err = live_registry.live_error_to_live_file_error(e);
300                    if std::env::args().find(|v| v == "--message-format=json").is_some(){
301                        crate::log::log_with_level(
302                            &err.file,
303                            err.span.start.line,
304                            err.span.start.column,
305                            err.span.end.line,
306                            err.span.end.column,
307                            err.message,
308                            crate::log::LogLevel::Error
309                        );
310                    }
311                    else{
312                        log!("Error {}", err);
313                    }
314                }
315                Ok(()) => {
316                    // OK! SO the shader parsed
317                    let draw_shader_id = cx.draw_shaders.shaders.len();
318                    
319                    //let const_table = DrawShaderConstTable::default();
320                    let const_table = cx.shader_registry.compute_const_table(draw_shader_ptr);
321                    
322                    let mut mapping = CxDrawShaderMapping::from_draw_shader_def(
323                        cx.shader_registry.draw_shader_defs.get(&draw_shader_ptr).unwrap(),
324                        const_table,
325                        DRAW_SHADER_INPUT_PACKING
326                    );
327                    
328                    mapping.update_live_and_user_uniforms(cx, apply);
329                    
330                    let live_registry_rc = cx.live_registry.clone();
331                    let live_registry = live_registry_rc.borrow();
332                    let class_node = live_registry.ptr_to_node(draw_shader_ptr.0);
333                    
334                    let shader_type_name = match &class_node.value {
335                        LiveValue::Class {live_type, ..} => {
336                            // lets get the type name
337                            let lti = live_registry.live_type_infos.get(live_type).unwrap();
338                            lti.type_name
339                        }
340                        _ => LiveId(0)
341                    };
342                    cx.draw_shaders.fingerprints.push(DrawShaderFingerprint {
343                        draw_shader_id,
344                        fingerprint
345                    });
346                    cx.draw_shaders.shaders.push(CxDrawShader {
347                        class_prop: class_node.id,
348                        type_name: shader_type_name,
349                        os_shader_id: None,
350                        mapping: mapping
351                    });
352                    // ok so. maybe we should fill the live_uniforms buffer?
353                    self.options = CxDrawShaderOptions::from_ptr(cx, draw_shader_ptr);
354                    cx.draw_shaders.ptr_to_item.insert(draw_shader_ptr, CxDrawShaderItem {
355                        draw_shader_id,
356                        options: self.options.clone()
357                    });
358                    cx.draw_shaders.compile_set.insert(draw_shader_ptr);
359                    // now we simply queue it somewhere somehow to compile.
360                    self.draw_shader = Some(DrawShader {
361                        draw_shader_generation: cx.draw_shaders.generation,
362                        draw_shader_id,
363                        draw_shader_ptr
364                    });
365                    
366                    // self.geometry_id = geometry_fields.get_geometry_id();
367                    //println!("{:?}", self.geometry_id);
368                    // also we should allocate it a Shader object
369                }
370            }
371        }
372    }
373    
374    pub fn update_area_with_self(&mut self, cx: &mut Cx, index: usize, nodes: &[LiveNode]) {
375        if let Some(draw_shader) = self.draw_shader {
376            if let Some(inst) = self.area.valid_instance(cx) {
377                if draw_shader.draw_shader_generation != cx.draw_shaders.generation {
378                    return;
379                }
380                let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
381                let draw_list = &mut cx.draw_lists[inst.draw_list_id];
382                let draw_item = &mut draw_list.draw_items[inst.draw_item_id];
383                let draw_call = draw_item.kind.draw_call_mut().unwrap();
384                
385                let repeat = inst.instance_count;
386                let stride = sh.mapping.instances.total_slots;
387                let instances = &mut draw_item.instances.as_mut().unwrap()[inst.instance_offset..];
388                let inst_slice = self.as_slice();
389                let mut uniform_updated = false;
390                let mut node_iter = nodes.first_child(index);
391                while let Some(node_index) = node_iter {
392                    let id = nodes[node_index].id;
393                    
394                    // lets iterate the /*
395                    for input in &sh.mapping.live_instances.inputs {
396                        if input.id == id {
397                            for j in 0..repeat {
398                                for i in 0..input.slots {
399                                    instances[input.offset + i + j * stride] = inst_slice[input.offset + i]
400                                }
401                            }
402                            draw_call.instance_dirty = true;
403                        }
404                    }
405                    for input in &sh.mapping.user_uniforms.inputs {
406                        if input.id == id {
407                            // if we are updating a uniform, make sure we redraw
408                            uniform_updated = true;
409                            for i in 0..input.slots {
410                                draw_call.user_uniforms[input.offset + i] = self.user_uniforms[input.offset + i]
411                            }
412                        }
413                        draw_call.uniforms_dirty = true;
414                    }
415                    node_iter = nodes.next_child(node_index);
416                }
417                // DONE!
418                cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
419                if uniform_updated{
420                    
421                    // not calling redraw when uniforms change might cause
422                    // incorrect drawcall splitting, so we have to. Unfortunately.
423                    self.area.redraw(cx);
424                }
425            }
426        }
427    }
428    
429    pub fn update_rect(&mut self, cx: &mut Cx, rect: Rect) {
430        if let Some(draw_shader) = self.draw_shader {
431            if let Some(inst) = self.area.valid_instance(cx) {
432                if draw_shader.draw_shader_generation != cx.draw_shaders.generation {
433                    return;
434                }
435                let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
436                let draw_list = &mut cx.draw_lists[inst.draw_list_id];
437                let draw_item = &mut draw_list.draw_items[inst.draw_item_id];
438                let draw_call = draw_item.kind.draw_call_mut().unwrap();
439                
440                let repeat = inst.instance_count;
441                let stride = sh.mapping.instances.total_slots;
442                let instances = &mut draw_item.instances.as_mut().unwrap()[inst.instance_offset..];
443                
444                for input in &sh.mapping.instances.inputs {
445                    if input.id == live_id!(rect_pos) {
446                        for j in 0..repeat {
447                            instances[input.offset + 0 + j * stride] = rect.pos.x as f32;
448                            instances[input.offset + 1 + j * stride] = rect.pos.y as f32;
449                        }
450                    }
451                    if input.id == live_id!(rect_size) {
452                        for j in 0..repeat {
453                            instances[input.offset + 0 + j * stride] = rect.size.x as f32;
454                            instances[input.offset + 1 + j * stride] = rect.size.y as f32;
455                        }
456                    }
457                }
458                draw_call.instance_dirty = true;
459                cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
460            }
461        }
462    }
463    
464    pub fn update_instance_area_value(&mut self, cx: &mut Cx,  id: &[LiveId]) {
465        if let Some(draw_shader) = self.draw_shader {
466            if let Some(inst) = self.area.valid_instance(cx) {
467                if draw_shader.draw_shader_generation != cx.draw_shaders.generation {
468                    return;
469                }
470                let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
471                let draw_list = &mut cx.draw_lists[inst.draw_list_id];
472                let draw_item = &mut draw_list.draw_items[inst.draw_item_id];
473                let draw_call = draw_item.kind.draw_call_mut().unwrap();
474                                
475                let repeat = inst.instance_count;
476                let stride = sh.mapping.instances.total_slots;
477                let instances = &mut draw_item.instances.as_mut().unwrap()[inst.instance_offset..];
478                let slice = self.as_slice();
479                for input in &sh.mapping.instances.inputs {
480                    if input.id == id[0] {
481                        for j in 0..repeat {
482                            for k in 0..input.slots{
483                                instances[input.offset + k + j * stride] = slice[input.offset + k];
484                            }
485                        }
486                    }
487                }
488                draw_call.instance_dirty = true;
489                cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
490            }
491        }
492    }
493        
494    /*
495    pub fn update_area_with_value(&mut self, cx: &mut Cx, id: LiveId, v: &[f32], start: usize, count: usize) {
496        if let Some(draw_shader) = self.draw_shader {
497            if let Some(inst) = self.area.valid_instance(cx) {
498                if draw_shader.draw_shader_generation != cx.draw_shaders.generation {
499                    return;
500                }
501                let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
502                let draw_list = &mut cx.draw_lists[inst.draw_list_id];
503                let draw_item = &mut draw_list.draw_items[inst.draw_item_id];
504                let draw_call = draw_item.kind.draw_call_mut().unwrap();
505                
506                let repeat = inst.instance_count.min(count);
507                let stride = sh.mapping.instances.total_slots;
508                let instances = &mut draw_item.instances.as_mut().unwrap()[inst.instance_offset..];
509                
510                cx.passes[draw_list.pass_id.unwrap()].paint_dirty = true;
511                
512                for input in &sh.mapping.live_instances.inputs {
513                    if input.id == id {
514                        for j in start..(start + repeat) {
515                            for i in 0..input.slots {
516                                instances[input.offset + i + j * stride] = v[i]
517                            }
518                        }
519                        draw_call.instance_dirty = true;
520                    }
521                    return
522                }
523                for input in &sh.mapping.user_uniforms.inputs {
524                    if input.id == id {
525                        for i in 0..input.slots {
526                            draw_call.user_uniforms[input.offset + i] = v[i]
527                        }
528                        draw_call.uniforms_dirty = true;
529                        return
530                    }
531                }
532            }
533        }
534    }*/
535    
536    pub fn get_instance(&self, cx: &mut Cx, inst: &[LiveId], value: &mut [f32]){
537        if let Some(draw_shader) = self.draw_shader {
538            let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
539            let self_slice = self.as_slice();
540            for input in &sh.mapping.instances.inputs {
541                let offset = input.offset;
542                let slots = input.slots;
543                if input.id == inst[0] {
544                    for i in 0..value.len().min(slots) {
545                        value[i] = self_slice[offset + i]
546                    }
547                }
548            }
549        }
550    }
551    
552    pub fn set_var_instance(&mut self, cx:&Cx, instance: &[LiveId], value: &[f32]) {
553        if let Some(draw_shader) = self.draw_shader {
554            let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
555            for input in &sh.mapping.var_instances.inputs {
556                let offset = (self.var_instances.len() - sh.mapping.var_instances.total_slots) + input.offset;
557                let slots = input.slots;
558                if input.id == instance[0] {
559                    for i in 0..value.len().min(slots) {
560                        self.var_instances[offset + i] = value[i];
561                    }
562                }
563            }
564        }
565    }
566    
567    pub fn get_uniform(&self, cx: &mut Cx, uniform: &[LiveId], value: &mut [f32]){
568        if let Some(draw_shader) = self.draw_shader {
569            let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
570            for input in &sh.mapping.user_uniforms.inputs {
571                let offset = input.offset;
572                let slots = input.slots;
573                if input.id == uniform[0] {
574                    for i in 0..value.len().min(slots) {
575                        value[i] = self.user_uniforms[offset + i];
576                    }
577                }
578            }
579        }
580    }
581    
582    pub fn set_uniform(&mut self, cx:&Cx, uniform: &[LiveId], value: &[f32]) {
583        if let Some(draw_shader) = self.draw_shader { 
584            let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
585            for input in &sh.mapping.user_uniforms.inputs {
586                let offset = input.offset;
587                let slots = input.slots;
588                if input.id == uniform[0] {
589                    for i in 0..value.len().min(slots) {
590                        self.user_uniforms[offset + i] = value[i]
591                    }
592                }
593            }
594        }
595    }
596    
597        
598    pub fn init_slicer(
599        &mut self,
600        cx: &mut Cx,
601    ) {
602        if let Some(draw_shader) = self.draw_shader {
603            let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
604            self.var_instance_start = self.var_instances.len() - sh.mapping.var_instances.total_slots;
605            self.var_instance_slots = sh.mapping.instances.total_slots;
606        }
607    }
608    
609    pub fn before_apply_init_shader(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, _nodes: &[LiveNode], geometry_fields: &dyn GeometryFields) {
610        
611        let draw_shader_ptr = if let Some(file_id) = apply.from.file_id() {
612            let generation = cx.live_registry.borrow().file_id_to_file(file_id).generation;
613            DrawShaderPtr(LivePtr::from_index(file_id, index, generation))
614        }
615        else {
616            return
617        };
618        self.init_shader(cx, apply, draw_shader_ptr, geometry_fields)
619    }
620    
621    pub fn apply_slots(cx: &mut Cx, slots: usize, output: &mut [f32], offset: usize, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
622        match slots {
623            1 => {
624                let mut v: f32 = 0.0;
625                let index = v.apply(cx, apply, index, nodes);
626                output[offset + 0] = v;
627                return index;
628            }
629            2 => {
630                let mut v: Vec2 = Vec2::default();
631                let index = v.apply(cx, apply, index, nodes);
632                output[offset + 0] = v.x;
633                output[offset + 1] = v.y;
634                return index;
635            }
636            3 => {
637                let mut v: Vec3 = Vec3::default();
638                let index = v.apply(cx, apply, index, nodes);
639                output[offset + 0] = v.x;
640                output[offset + 1] = v.y;
641                output[offset + 2] = v.z;
642                return index;
643            }
644            4 => {
645                let mut v: Vec4 = Vec4::default();
646                let index = v.apply(cx, apply, index, nodes);
647                output[offset + 0] = v.x;
648                output[offset + 1] = v.y;
649                output[offset + 2] = v.z;
650                output[offset + 3] = v.w;
651                return index;
652            }
653            _ => {
654                return nodes.skip_node(index)
655            }
656        }
657    }
658    
659    pub fn apply_value(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode]) -> usize {
660        
661        if nodes[index].origin.node_has_prefix() && nodes[index].value.is_id() {
662            return nodes.skip_node(index)
663        }
664        
665        if let Some(draw_shader) = self.draw_shader {
666            let id = nodes[index].id;
667            if draw_shader.draw_shader_generation != cx.draw_shaders.generation {
668                return nodes.skip_node(index);
669            }
670            let sh = &cx.draw_shaders[draw_shader.draw_shader_id];
671            for input in &sh.mapping.user_uniforms.inputs {
672                let offset = input.offset;
673                let slots = input.slots;
674                if input.id == id {
675                    return Self::apply_slots(cx, slots, &mut self.user_uniforms, offset, apply, index, nodes);
676                }
677            }
678            for input in &sh.mapping.var_instances.inputs {
679                
680                let offset = (self.var_instances.len() - sh.mapping.var_instances.total_slots) + input.offset;
681                let slots = input.slots;
682                if input.id == id {
683                    return Self::apply_slots(cx, slots, &mut self.var_instances, offset, apply, index, nodes);
684                }
685            }
686        }
687        else { // our shader simply didnt compile
688            return nodes.skip_node(index);
689        }
690        
691        if nodes[index].origin.node_has_prefix() {
692            return nodes.skip_node(index)
693        }
694        
695        let unknown_shader_props = match nodes[index].id {
696            live_id!(debug) => false,
697            live_id!(debug_id) => false,
698            live_id!(draw_call_group) => false,
699            _ => true
700        };
701        
702        if unknown_shader_props && nodes[index].value.is_value_type() {
703            cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
704        }
705        nodes.skip_node(index)
706    }
707    
708    pub fn after_apply_update_self(&mut self, cx: &mut Cx, apply: &mut Apply, index: usize, nodes: &[LiveNode], geometry_fields: &dyn GeometryFields) {
709        // alright. so.if we are ApplyFrom::
710        if apply.from.is_from_doc() {
711            self.init_slicer(cx);
712        }
713        self.geometry_id = geometry_fields.get_geometry_id();
714        self.update_area_with_self(cx, index, nodes);
715    }
716    
717}