clay_core/object/
covered.rs1use std::collections::HashSet;
2use crate::{
3 prelude::*,
4 shape::*,
5 material::*,
6 object::*,
7};
8
9
10#[derive(Clone, Debug, Default)]
11pub struct Covered<S: Shape, M: Material> {
13 pub shape: S,
14 pub material: M,
15}
16
17impl<S: Shape, M: Material> Covered<S, M> {
18 pub fn new(shape: S, material: M) -> Self {
19 Self { shape, material }
20 }
21
22 fn shape_source(cache: &mut HashSet<u64>) -> String {
23 [
24 S::source(cache),
25 ShapeClass::methods().into_iter().map(|method| {
26 format!(
27 "#define {}_{} {}_{}",
28 Self::inst_name(), method,
29 S::inst_name(), method,
30 )
31 }).collect::<Vec<_>>().join("\n"),
32 ].join("\n")
33 }
34
35 fn material_source(cache: &mut HashSet<u64>) -> String {
36 [
37 M::source(cache),
38 MaterialClass::methods().into_iter().map(|method| {
39 let cpref = format!("{}_{}", MaterialClass::name(), method).to_uppercase();
40 [
41 &format!("{}_RET {}_{}(", cpref, Self::inst_name(), method),
42 &format!("\t{}_ARGS_DEF", cpref),
43 ") {",
44 &format!(
45 "\treturn {}_{}({}_ARGS_B({}, {}));",
46 M::inst_name(), method, cpref, S::size_int(), S::size_float(),
47 ),
48 "}",
49 ].join("\n")
50 }).collect::<Vec<_>>().join("\n"),
51 ].join("\n")
52 }
53}
54
55impl<S: Shape, M: Material> Object for Covered<S, M> {}
56
57impl<S: Shape, M: Material> Instance<ObjectClass> for Covered<S, M> {
58 fn source(cache: &mut HashSet<u64>) -> String {
59 if !cache.insert(Self::type_hash()) {
60 return String::new()
61 }
62 [
63 Self::shape_source(cache),
64 Self::material_source(cache),
65 ].join("\n")
66 }
67 fn inst_name() -> String {
68 format!("__covered_{:x}", Self::type_hash())
69 }
70}
71
72impl<S: Shape, M: Material> Pack for Covered<S, M> {
73 fn size_int() -> usize {
74 S::size_int() + M::size_int()
75 }
76 fn size_float() -> usize {
77 S::size_float() + M::size_float()
78 }
79
80 fn pack_to(&self, buffer_int: &mut [i32], buffer_float: &mut [f32]) {
81 Packer::new(buffer_int, buffer_float)
82 .pack(&self.shape)
83 .pack(&self.material);
84 }
85}
86
87impl<B: Bound, S: Shape + Bounded<B>, M: Material> Bounded<B> for Covered<S, M> {
88 fn bound(&self) -> Option<B> {
89 self.shape.bound()
90 }
91}
92
93impl<T: Bound + Target, S: Shape + Bounded<T>, M: Material> Targeted<T> for Covered<S, M> {
94 fn target(&self) -> Option<(T, f64)> {
95 self.shape.bound()
96 .map(|t| (t, self.material.brightness()))
97 }
98}