graphic design tool
git clone https://git.lucas.co/cce-designer.git
feat: Plane gains the same Color toggle as the Sphere
On by default, the gradient the plane has always carried; off, DEFAULT_COLOR,
the grey geometry without Cd renders at. The colour-toggle test is now one
helper run over both templates.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
nodes/plane.json | 7 ++++++-
src/main.rs | 37 +++++++++++++++++++++++--------------
2 files changed, 29 insertions(+), 15 deletions(-)
diff --git a/nodes/plane.json b/nodes/plane.json
index 6c5d35f..bea95b0 100644
--- a/nodes/plane.json
+++ b/nodes/plane.json
@@ -44,6 +44,11 @@
"name": "Center Z",
"default": "0.0",
"type": "slider:-2:2"
+ },
+ {
+ "name": "Color",
+ "default": "true",
+ "type": "toggle"
}
],
"children": [
@@ -53,7 +58,7 @@
"params": [
{
"name": "Code",
- "default": "__kernel void process(__global const float* in_pos, __global const float* in_col, int in_count, __global float* out_pos, __global float* out_col, __global int* out_count, int max_vertices) {\n int id = get_global_id(0);\n if (id == 0) {\n float size_x = chf(\"Width\", 1.0f);\n float size_z = chf(\"Length\", 1.0f);\n int cols = chi(\"Columns\", 16);\n int rows = chi(\"Rows\", 16);\n if (cols < 1) cols = 1;\n if (cols > 128) cols = 128;\n if (rows < 1) rows = 1;\n if (rows > 128) rows = 128;\n float center_x = chf(\"Center X\", 0.0f);\n float center_y = chf(\"Center Y\", 0.0f);\n float center_z = chf(\"Center Z\", 0.0f);\n float half_x = size_x * 0.5f;\n float half_z = size_z * 0.5f;\n float step_x = size_x / (float)cols;\n float step_z = size_z / (float)rows;\n float inv_x = size_x > 0.0f ? 1.0f / size_x : 0.0f;\n float inv_z = size_z > 0.0f ? 1.0f / size_z : 0.0f;\n int count = 0;\n for (int i = 0; i < cols; i++) {\n float x0 = -half_x + (float)i * step_x;\n float x1 = x0 + step_x;\n for (int j = 0; j < rows; j++) {\n float z0 = -half_z + (float)j * step_z;\n float z1 = z0 + step_z;\n float px[6] = {x0, x1, x1, x0, x0, x1};\n float pz[6] = {z0, z1, z0, z0, z1, z1};\n for (int v = 0; v < 6; v++) {\n int idx = count++;\n if (idx < max_vertices) {\n out_pos[idx * 3 + 0] = center_x + px[v];\n out_pos[idx * 3 + 1] = center_y;\n out_pos[idx * 3 + 2] = center_z + pz[v];\n float fx = (px[v] + half_x) * inv_x;\n float fz = (pz[v] + half_z) * inv_z;\n out_col[idx * 3 + 0] = 0.35f + fx * 0.35f;\n out_col[idx * 3 + 1] = 0.45f + fz * 0.35f;\n out_col[idx * 3 + 2] = 0.85f;\n }\n }\n }\n }\n *out_count = count;\n }\n}"
+ "default": "__kernel void process(__global const float* in_pos, __global const float* in_col, int in_count, __global float* out_pos, __global float* out_col, __global int* out_count, int max_vertices) {\n int id = get_global_id(0);\n if (id == 0) {\n float size_x = chf(\"Width\", 1.0f);\n float size_z = chf(\"Length\", 1.0f);\n int cols = chi(\"Columns\", 16);\n int rows = chi(\"Rows\", 16);\n int colored = chb(\"Color\", true) > 0.5f ? 1 : 0;\n if (cols < 1) cols = 1;\n if (cols > 128) cols = 128;\n if (rows < 1) rows = 1;\n if (rows > 128) rows = 128;\n float center_x = chf(\"Center X\", 0.0f);\n float center_y = chf(\"Center Y\", 0.0f);\n float center_z = chf(\"Center Z\", 0.0f);\n float half_x = size_x * 0.5f;\n float half_z = size_z * 0.5f;\n float step_x = size_x / (float)cols;\n float step_z = size_z / (float)rows;\n float inv_x = size_x > 0.0f ? 1.0f / size_x : 0.0f;\n float inv_z = size_z > 0.0f ? 1.0f / size_z : 0.0f;\n int count = 0;\n for (int i = 0; i < cols; i++) {\n float x0 = -half_x + (float)i * step_x;\n float x1 = x0 + step_x;\n for (int j = 0; j < rows; j++) {\n float z0 = -half_z + (float)j * step_z;\n float z1 = z0 + step_z;\n float px[6] = {x0, x1, x1, x0, x0, x1};\n float pz[6] = {z0, z1, z0, z0, z1, z1};\n for (int v = 0; v < 6; v++) {\n int idx = count++;\n if (idx < max_vertices) {\n out_pos[idx * 3 + 0] = center_x + px[v];\n out_pos[idx * 3 + 1] = center_y;\n out_pos[idx * 3 + 2] = center_z + pz[v];\n float fx = (px[v] + half_x) * inv_x;\n float fz = (pz[v] + half_z) * inv_z;\n if (colored) {\n out_col[idx * 3 + 0] = 0.35f + fx * 0.35f;\n out_col[idx * 3 + 1] = 0.45f + fz * 0.35f;\n out_col[idx * 3 + 2] = 0.85f;\n } else {\n out_col[idx * 3 + 0] = 0.8f;\n out_col[idx * 3 + 1] = 0.8f;\n out_col[idx * 3 + 2] = 0.8f;\n }\n }\n }\n }\n }\n *out_count = count;\n }\n}"
}
],
"position": [
diff --git a/src/main.rs b/src/main.rs
index eae34b9..2bb8f6b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1445,25 +1445,24 @@ mod tests {
);
}
- /// The Sphere's Color toggle: on, the normal-mapped gradient the sphere
- /// has always had; off, `DEFAULT_COLOR` — the same grey geometry with no
- /// `Cd` at all renders at, so an uncoloured sphere looks like an
+ /// A template's Color toggle: on, the gradient the shape has always
+ /// carried; off, `DEFAULT_COLOR` — the same grey geometry with no `Cd`
+ /// at all renders at, so an uncoloured sphere or plane looks like an
/// uncoloured anything else rather than like a second colour scheme.
- #[test]
- fn sphere_color_toggle_switches_between_gradient_and_default() {
+ fn assert_color_toggle_switches_between_gradient_and_default(template_name: &str) {
let templates_root = crate::app::load_fs_tree();
- let sphere_template = templates_root
+ let template = templates_root
.children
.iter()
- .find(|t| t.name == "Sphere")
- .expect("Sphere template should be loaded");
- let color = sphere_template.params.iter().find(|p| p.name == "Color").expect("a Color param");
+ .find(|t| t.name == template_name)
+ .unwrap_or_else(|| panic!("{template_name} template should be loaded"));
+ let color = template.params.iter().find(|p| p.name == "Color").expect("a Color param");
assert_eq!(color.param_type, "toggle");
assert_eq!(color.default, "true", "coloured by default, as it always was");
let generate = |on: &str| {
- let mut inst = sphere_template.clone();
- inst.id = format!("sphere_{on}");
+ let mut inst = template.clone();
+ inst.id = format!("{template_name}_{on}");
for child in &mut inst.children {
child.id = format!("{}_{}", inst.id, child.name);
}
@@ -1489,14 +1488,14 @@ mod tests {
&mut crate::geometry::EvalSim::new(0, 0, &mut crate::geometry::SimCache::default()),
)
.expect("geometry");
- assert!(err.is_none(), "kernel error: {err:?}");
+ assert!(err.is_none(), "{template_name} kernel error: {err:?}");
geom
};
let off = generate("false");
assert!(off.num_points() > 0);
for p in 0..off.num_points() {
- assert_eq!(off.color(p), crate::detail::DEFAULT_COLOR, "point {p} off");
+ assert_eq!(off.color(p), crate::detail::DEFAULT_COLOR, "{template_name} point {p} off");
}
let on = generate("true");
@@ -1504,10 +1503,20 @@ mod tests {
let first = on.color(0);
assert!(
(0..on.num_points()).any(|p| on.color(p) != first),
- "on, the sphere carries its gradient"
+ "on, the {template_name} carries its gradient"
);
}
+ #[test]
+ fn sphere_color_toggle_switches_between_gradient_and_default() {
+ assert_color_toggle_switches_between_gradient_and_default("Sphere");
+ }
+
+ #[test]
+ fn plane_color_toggle_switches_between_gradient_and_default() {
+ assert_color_toggle_switches_between_gradient_and_default("Plane");
+ }
+
#[test]
fn test_sphere_subnet_geometry_generation() {
let templates_root = crate::app::load_fs_tree();