use serde::{Deserialize, Serialize};
use crate::nodegraph::WireKind;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum BrushWireType {
Scalar,
Int,
Bool,
Vec2,
Vec4,
}
impl WireKind for BrushWireType {
fn compatible(from: Self, to: Self) -> bool {
use BrushWireType::*;
if from == to {
return true;
}
matches!(
(from, to),
(Scalar, Int) | (Int, Scalar)
)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
pub enum ScalarValue {
Scalar(f32),
Int(i32),
Bool(bool),
Vec2([f32; 2]),
Vec4([f32; 4]),
}
impl ScalarValue {
pub fn as_f32(self) -> f32 {
match self {
Self::Scalar(v) => v,
Self::Int(v) => v as f32,
Self::Bool(v) => v as u8 as f32,
_ => 0.0,
}
}
pub fn as_color(self) -> [f32; 4] {
match self {
Self::Vec4(v) => v,
Self::Scalar(v) => [v, v, v, 1.0],
_ => [0.0, 0.0, 0.0, 1.0],
}
}
pub fn as_vec2(self) -> [f32; 2] {
match self {
Self::Vec2(v) => v,
Self::Scalar(v) => [v, v],
_ => [0.0, 0.0],
}
}
pub fn coerce(self, target: BrushWireType) -> Self {
match target {
BrushWireType::Scalar => Self::Scalar(self.as_f32()),
BrushWireType::Int => Self::Int(self.as_f32() as i32),
BrushWireType::Bool => Self::Bool(self.as_f32() > 0.5),
BrushWireType::Vec2 => Self::Vec2(self.as_vec2()),
BrushWireType::Vec4 => Self::Vec4(self.as_color()),
}
}
}
impl Default for ScalarValue {
fn default() -> Self {
Self::Scalar(0.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn compatible_same_type() {
for ty in [
BrushWireType::Scalar,
BrushWireType::Int,
BrushWireType::Vec2,
BrushWireType::Vec4,
] {
assert!(BrushWireType::compatible(ty, ty));
}
}
#[test]
fn compatible_scalar_int_coercions() {
assert!(BrushWireType::compatible(
BrushWireType::Scalar,
BrushWireType::Int
));
assert!(BrushWireType::compatible(
BrushWireType::Int,
BrushWireType::Scalar
));
}
#[test]
fn incompatible_unrelated_types() {
assert!(!BrushWireType::compatible(
BrushWireType::Vec4,
BrushWireType::Scalar
));
assert!(!BrushWireType::compatible(
BrushWireType::Vec2,
BrushWireType::Vec4
));
}
#[test]
fn scalar_value_coerce_to_vec4_broadcasts_grayscale() {
let v = ScalarValue::Scalar(0.75);
assert_eq!(
v.coerce(BrushWireType::Vec4),
ScalarValue::Vec4([0.75, 0.75, 0.75, 1.0])
);
assert_eq!(v.as_f32(), 0.75);
}
}