use std::sync::Arc;
use crate::brush::eval::{BrushNodeEvaluator, EvalContext};
use crate::brush::node::BrushNodeRegistration;
use crate::brush::wgsl::{CompileWgslCtx, NodeWgsl, UniformField, WgslType};
use crate::brush::wire::BrushWireType;
use crate::brush::wire::ScalarValue;
use crate::nodegraph::{NodeRegistration, PortDef};
pub const TYPE_ID: &str = "paint_color";
pub fn register() -> BrushNodeRegistration {
BrushNodeRegistration::compute(
NodeRegistration {
type_id: TYPE_ID,
category: "color",
display_name: "Paint Color",
description: "The color currently selected in the toolbar.",
ports: vec![PortDef::output("color", BrushWireType::Vec4)
.with_description("Current foreground painting color (RGBA)")],
params: &[],
is_gpu: false,
is_terminal: false,
supports_erase: true,
},
|| Box::new(PaintColorEvaluator),
)
}
pub struct PaintColorEvaluator;
impl BrushNodeEvaluator for PaintColorEvaluator {
fn evaluate_cpu(&self, _ctx: &EvalContext) -> Vec<(String, ScalarValue)> {
vec![]
}
fn compile_wgsl(&self, cctx: &CompileWgslCtx) -> Result<NodeWgsl, String> {
let mut wgsl = NodeWgsl::default();
if !cctx.consumed_outputs.contains("color") {
return Ok(wgsl);
}
let field_name = cctx.uniform_field_name("color");
let key = field_name.clone();
wgsl.uniform_fields.push(UniformField {
name: field_name.clone(),
ty: WgslType::Vec4,
pack: Arc::new(move |outputs, bytes| {
let v = outputs
.get(&key)
.map(|s| s.as_color())
.unwrap_or([0.0, 0.0, 0.0, 1.0]);
bytes.extend_from_slice(bytemuck::bytes_of(&v));
}),
});
wgsl.outputs
.insert("color".into(), format!("u.{}", field_name));
Ok(wgsl)
}
}