1use super::NodeId;
7use std::collections::HashMap;
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub enum SocketType {
14 Float,
15 Vec2,
16 Vec3,
17 Vec4,
18 Int,
19 Bool,
20 Sampler2D,
21 Any,
23}
24
25impl SocketType {
26 pub fn glsl_type(self) -> &'static str {
27 match self {
28 SocketType::Float => "float",
29 SocketType::Vec2 => "vec2",
30 SocketType::Vec3 => "vec3",
31 SocketType::Vec4 => "vec4",
32 SocketType::Int => "int",
33 SocketType::Bool => "bool",
34 SocketType::Sampler2D => "sampler2D",
35 SocketType::Any => "float",
36 }
37 }
38
39 pub fn default_value(self) -> &'static str {
40 match self {
41 SocketType::Float => "0.0",
42 SocketType::Vec2 => "vec2(0.0)",
43 SocketType::Vec3 => "vec3(0.0)",
44 SocketType::Vec4 => "vec4(0.0, 0.0, 0.0, 1.0)",
45 SocketType::Int => "0",
46 SocketType::Bool => "false",
47 SocketType::Sampler2D => "/* sampler */",
48 SocketType::Any => "0.0",
49 }
50 }
51
52 pub fn is_compatible_with(self, other: SocketType) -> bool {
53 if self == other { return true; }
54 if self == SocketType::Any || other == SocketType::Any { return true; }
55 matches!((self, other),
57 (SocketType::Vec3, SocketType::Vec4) | (SocketType::Vec4, SocketType::Vec3) |
58 (SocketType::Float, SocketType::Vec2) | (SocketType::Vec2, SocketType::Float)
59 )
60 }
61}
62
63#[derive(Debug, Clone)]
67pub struct NodeSocket {
68 pub name: String,
69 pub socket_type: SocketType,
70 pub required: bool,
71 pub default: String,
73}
74
75impl NodeSocket {
76 pub fn required(name: &str, t: SocketType) -> Self {
77 Self { name: name.to_string(), socket_type: t, required: true, default: t.default_value().to_string() }
78 }
79 pub fn optional(name: &str, t: SocketType, default: &str) -> Self {
80 Self { name: name.to_string(), socket_type: t, required: false, default: default.to_string() }
81 }
82}
83
84#[derive(Debug, Clone, PartialEq)]
88pub enum NodeType {
89 UvCoord,
92 WorldPos,
94 CameraPos,
96 Time,
98 Resolution,
100 ConstFloat(f32),
102 ConstVec2(f32, f32),
104 ConstVec3(f32, f32, f32),
106 ConstVec4(f32, f32, f32, f32),
108 Uniform(String, SocketType),
110 TextureSample,
112 VertexColor,
114 ScreenCoord,
116
117 Add,
120 Subtract,
122 Multiply,
124 Divide,
126 Power,
128 Sqrt,
130 Abs,
132 Sign,
134 Floor,
136 Ceil,
138 Fract,
140 Min,
142 Max,
144 Clamp,
146 Mix,
148 Smoothstep,
150 Step,
152 Dot,
154 Cross,
156 Normalize,
158 Length,
160 Distance,
162 Reflect,
164 Refract,
166 Mod,
168 Sin,
170 Cos,
172 Tan,
174 Atan,
176 Exp,
178 Log,
180 Log2,
182 Remap,
184 OneMinus,
186 Saturate,
188 Negate,
190 Reciprocal,
192
193 CombineVec2,
196 CombineVec3,
198 CombineVec4,
200 SplitVec2,
202 SplitVec3,
204 SplitVec4,
206 Swizzle(String),
208 LengthSquared,
210 RotateVec2,
212
213 HsvToRgb,
216 RgbToHsv,
218 Luminance,
220 Saturation,
222 HueRotate,
224 ColorBurn,
226 ColorDodge,
228 ScreenBlend,
230 OverlayBlend,
232 HardLight,
234 SoftLight,
236 Difference,
238 GammaCorrect,
240 LinearToSrgb,
242 SrgbToLinear,
244
245 ValueNoise,
248 PerlinNoise,
250 SimplexNoise,
252 Fbm,
254 Voronoi,
256 Worley,
258 Checkerboard,
260 PolkaDots,
262 SineWave,
264 SquareWave,
266 TriangleWave,
268 SawtoothWave,
270 Grid,
272 RadialGradient,
274 LinearGradient,
276 Spiral,
278 Rings,
280 StarBurst,
282 HexTile,
284
285 ChromaticAberration,
288 EdgeDetect,
290 Pixelate,
292 BarrelDistort,
294 FishEye,
296 Vignette,
298 FilmGrain,
300 Scanlines,
302 HeatHaze,
304 GlitchOffset,
306 ScreenShake,
308 BoxBlur,
310 Sharpen,
312 Emboss,
314 Invert,
316 Posterize,
318 Duotone,
320 Outline,
322
323 SdfCircle,
326 SdfBox,
328 SdfLine,
330 SdfTriangle,
332 SdfRing,
334 SdfStar,
336 SdfSmoothUnion,
338 SdfSmoothSubtract,
340 SdfSmoothIntersect,
342 SdfToAlpha,
344 SdfToSoftAlpha,
346
347 LorenzAttractor,
350 Mandelbrot,
352 Julia,
354 BurningShip,
356 NewtonFractal,
358 LyapunovViz,
360
361 IfGreater,
364 IfLess,
366 ConditionalBlend,
368 BoolAnd,
370 BoolOr,
372 BoolNot,
374
375 OutputColor,
378 OutputTarget(String),
380 OutputWithBloom,
382}
383
384impl NodeType {
385 pub fn label(&self) -> &str {
386 match self {
387 NodeType::UvCoord => "UV Coord",
388 NodeType::WorldPos => "World Pos",
389 NodeType::CameraPos => "Camera Pos",
390 NodeType::Time => "Time",
391 NodeType::Resolution => "Resolution",
392 NodeType::ConstFloat(_) => "Float",
393 NodeType::ConstVec2(_, _) => "Vec2",
394 NodeType::ConstVec3(..) => "Vec3",
395 NodeType::ConstVec4(..) => "Vec4",
396 NodeType::Uniform(n, _) => n.as_str(),
397 NodeType::TextureSample => "Texture Sample",
398 NodeType::VertexColor => "Vertex Color",
399 NodeType::ScreenCoord => "Screen Coord",
400 NodeType::Add => "Add",
401 NodeType::Subtract => "Subtract",
402 NodeType::Multiply => "Multiply",
403 NodeType::Divide => "Divide",
404 NodeType::Power => "Power",
405 NodeType::Sqrt => "Sqrt",
406 NodeType::Abs => "Abs",
407 NodeType::Sign => "Sign",
408 NodeType::Floor => "Floor",
409 NodeType::Ceil => "Ceil",
410 NodeType::Fract => "Fract",
411 NodeType::Min => "Min",
412 NodeType::Max => "Max",
413 NodeType::Clamp => "Clamp",
414 NodeType::Mix => "Mix",
415 NodeType::Smoothstep => "Smoothstep",
416 NodeType::Step => "Step",
417 NodeType::Dot => "Dot",
418 NodeType::Cross => "Cross",
419 NodeType::Normalize => "Normalize",
420 NodeType::Length => "Length",
421 NodeType::Distance => "Distance",
422 NodeType::Reflect => "Reflect",
423 NodeType::Refract => "Refract",
424 NodeType::Mod => "Mod",
425 NodeType::Sin => "Sin",
426 NodeType::Cos => "Cos",
427 NodeType::Tan => "Tan",
428 NodeType::Atan => "Atan",
429 NodeType::Exp => "Exp",
430 NodeType::Log => "Log",
431 NodeType::Log2 => "Log2",
432 NodeType::Remap => "Remap",
433 NodeType::OneMinus => "One Minus",
434 NodeType::Saturate => "Saturate",
435 NodeType::Negate => "Negate",
436 NodeType::Reciprocal => "Reciprocal",
437 NodeType::CombineVec2 => "Combine Vec2",
438 NodeType::CombineVec3 => "Combine Vec3",
439 NodeType::CombineVec4 => "Combine Vec4",
440 NodeType::SplitVec2 => "Split Vec2",
441 NodeType::SplitVec3 => "Split Vec3",
442 NodeType::SplitVec4 => "Split Vec4",
443 NodeType::Swizzle(s) => s.as_str(),
444 NodeType::LengthSquared => "Length²",
445 NodeType::RotateVec2 => "Rotate Vec2",
446 NodeType::HsvToRgb => "HSV → RGB",
447 NodeType::RgbToHsv => "RGB → HSV",
448 NodeType::Luminance => "Luminance",
449 NodeType::Saturation => "Saturation",
450 NodeType::HueRotate => "Hue Rotate",
451 NodeType::ColorBurn => "Color Burn",
452 NodeType::ColorDodge => "Color Dodge",
453 NodeType::ScreenBlend => "Screen",
454 NodeType::OverlayBlend => "Overlay",
455 NodeType::HardLight => "Hard Light",
456 NodeType::SoftLight => "Soft Light",
457 NodeType::Difference => "Difference",
458 NodeType::GammaCorrect => "Gamma",
459 NodeType::LinearToSrgb => "Linear→sRGB",
460 NodeType::SrgbToLinear => "sRGB→Linear",
461 NodeType::ValueNoise => "Value Noise",
462 NodeType::PerlinNoise => "Perlin Noise",
463 NodeType::SimplexNoise => "Simplex Noise",
464 NodeType::Fbm => "fBm",
465 NodeType::Voronoi => "Voronoi",
466 NodeType::Worley => "Worley",
467 NodeType::Checkerboard => "Checkerboard",
468 NodeType::PolkaDots => "Polka Dots",
469 NodeType::SineWave => "Sine Wave",
470 NodeType::SquareWave => "Square Wave",
471 NodeType::TriangleWave => "Triangle Wave",
472 NodeType::SawtoothWave => "Sawtooth Wave",
473 NodeType::Grid => "Grid",
474 NodeType::RadialGradient => "Radial Gradient",
475 NodeType::LinearGradient => "Linear Gradient",
476 NodeType::Spiral => "Spiral",
477 NodeType::Rings => "Rings",
478 NodeType::StarBurst => "Star Burst",
479 NodeType::HexTile => "Hex Tile",
480 NodeType::ChromaticAberration => "Chromatic Ab.",
481 NodeType::EdgeDetect => "Edge Detect",
482 NodeType::Pixelate => "Pixelate",
483 NodeType::BarrelDistort => "Barrel Distort",
484 NodeType::FishEye => "Fish Eye",
485 NodeType::Vignette => "Vignette",
486 NodeType::FilmGrain => "Film Grain",
487 NodeType::Scanlines => "Scanlines",
488 NodeType::HeatHaze => "Heat Haze",
489 NodeType::GlitchOffset => "Glitch",
490 NodeType::ScreenShake => "Screen Shake",
491 NodeType::BoxBlur => "Box Blur",
492 NodeType::Sharpen => "Sharpen",
493 NodeType::Emboss => "Emboss",
494 NodeType::Invert => "Invert",
495 NodeType::Posterize => "Posterize",
496 NodeType::Duotone => "Duotone",
497 NodeType::Outline => "Outline",
498 NodeType::SdfCircle => "SDF Circle",
499 NodeType::SdfBox => "SDF Box",
500 NodeType::SdfLine => "SDF Line",
501 NodeType::SdfTriangle => "SDF Triangle",
502 NodeType::SdfRing => "SDF Ring",
503 NodeType::SdfStar => "SDF Star",
504 NodeType::SdfSmoothUnion => "SDF Union",
505 NodeType::SdfSmoothSubtract => "SDF Subtract",
506 NodeType::SdfSmoothIntersect => "SDF Intersect",
507 NodeType::SdfToAlpha => "SDF Alpha",
508 NodeType::SdfToSoftAlpha => "SDF Soft Alpha",
509 NodeType::LorenzAttractor => "Lorenz",
510 NodeType::Mandelbrot => "Mandelbrot",
511 NodeType::Julia => "Julia",
512 NodeType::BurningShip => "Burning Ship",
513 NodeType::NewtonFractal => "Newton",
514 NodeType::LyapunovViz => "Lyapunov",
515 NodeType::IfGreater => "If Greater",
516 NodeType::IfLess => "If Less",
517 NodeType::ConditionalBlend => "Cond. Blend",
518 NodeType::BoolAnd => "AND",
519 NodeType::BoolOr => "OR",
520 NodeType::BoolNot => "NOT",
521 NodeType::OutputColor => "Output Color",
522 NodeType::OutputTarget(n) => n.as_str(),
523 NodeType::OutputWithBloom => "Output+Bloom",
524 }
525 }
526
527 pub fn input_sockets(&self) -> Vec<NodeSocket> {
529 match self {
530 NodeType::Add | NodeType::Subtract | NodeType::Multiply |
531 NodeType::Divide | NodeType::Power | NodeType::Mod |
532 NodeType::Min | NodeType::Max | NodeType::Dot | NodeType::Distance => vec![
533 NodeSocket::required("A", SocketType::Any),
534 NodeSocket::required("B", SocketType::Any),
535 ],
536 NodeType::Mix => vec![
537 NodeSocket::required("A", SocketType::Any),
538 NodeSocket::required("B", SocketType::Any),
539 NodeSocket::required("T", SocketType::Float),
540 ],
541 NodeType::Smoothstep => vec![
542 NodeSocket::optional("Edge0", SocketType::Float, "0.0"),
543 NodeSocket::optional("Edge1", SocketType::Float, "1.0"),
544 NodeSocket::required("X", SocketType::Any),
545 ],
546 NodeType::Step => vec![
547 NodeSocket::optional("Edge", SocketType::Float, "0.5"),
548 NodeSocket::required("X", SocketType::Any),
549 ],
550 NodeType::Clamp => vec![
551 NodeSocket::required("X", SocketType::Any),
552 NodeSocket::optional("Min", SocketType::Float, "0.0"),
553 NodeSocket::optional("Max", SocketType::Float, "1.0"),
554 ],
555 NodeType::Remap => vec![
556 NodeSocket::required("X", SocketType::Any),
557 NodeSocket::optional("InMin", SocketType::Float, "0.0"),
558 NodeSocket::optional("InMax", SocketType::Float, "1.0"),
559 NodeSocket::optional("OutMin", SocketType::Float, "0.0"),
560 NodeSocket::optional("OutMax", SocketType::Float, "1.0"),
561 ],
562 NodeType::Sqrt | NodeType::Abs | NodeType::Sign |
563 NodeType::Floor | NodeType::Ceil | NodeType::Fract |
564 NodeType::Normalize | NodeType::Length | NodeType::LengthSquared |
565 NodeType::OneMinus | NodeType::Saturate | NodeType::Negate |
566 NodeType::Reciprocal | NodeType::Exp | NodeType::Log |
567 NodeType::Log2 | NodeType::Sin | NodeType::Cos |
568 NodeType::Tan | NodeType::Atan | NodeType::HsvToRgb |
569 NodeType::RgbToHsv | NodeType::Luminance | NodeType::Invert |
570 NodeType::LinearToSrgb | NodeType::SrgbToLinear |
571 NodeType::BoolNot => vec![
572 NodeSocket::required("In", SocketType::Any),
573 ],
574 NodeType::Reflect | NodeType::Cross | NodeType::BoolAnd | NodeType::BoolOr => vec![
575 NodeSocket::required("A", SocketType::Any),
576 NodeSocket::required("B", SocketType::Any),
577 ],
578 NodeType::Refract => vec![
579 NodeSocket::required("I", SocketType::Vec3),
580 NodeSocket::required("N", SocketType::Vec3),
581 NodeSocket::optional("Eta", SocketType::Float, "1.5"),
582 ],
583 NodeType::CombineVec2 => vec![
584 NodeSocket::required("X", SocketType::Float),
585 NodeSocket::required("Y", SocketType::Float),
586 ],
587 NodeType::CombineVec3 => vec![
588 NodeSocket::required("X", SocketType::Float),
589 NodeSocket::required("Y", SocketType::Float),
590 NodeSocket::required("Z", SocketType::Float),
591 ],
592 NodeType::CombineVec4 => vec![
593 NodeSocket::required("RGB", SocketType::Vec3),
594 NodeSocket::required("A", SocketType::Float),
595 ],
596 NodeType::SplitVec2 | NodeType::SplitVec3 | NodeType::SplitVec4 |
597 NodeType::Swizzle(_) => vec![
598 NodeSocket::required("In", SocketType::Any),
599 ],
600 NodeType::RotateVec2 => vec![
601 NodeSocket::required("UV", SocketType::Vec2),
602 NodeSocket::optional("Angle", SocketType::Float, "0.0"),
603 NodeSocket::optional("Center",SocketType::Vec2, "vec2(0.5)"),
604 ],
605 NodeType::Saturation => vec![
606 NodeSocket::required("Color", SocketType::Vec3),
607 NodeSocket::optional("Sat", SocketType::Float, "1.0"),
608 ],
609 NodeType::HueRotate => vec![
610 NodeSocket::required("Color", SocketType::Vec3),
611 NodeSocket::optional("Degrees", SocketType::Float, "0.0"),
612 ],
613 NodeType::GammaCorrect => vec![
614 NodeSocket::required("Color", SocketType::Vec3),
615 NodeSocket::optional("Gamma", SocketType::Float, "2.2"),
616 ],
617 NodeType::ColorBurn | NodeType::ColorDodge | NodeType::ScreenBlend |
618 NodeType::OverlayBlend | NodeType::HardLight | NodeType::SoftLight |
619 NodeType::Difference => vec![
620 NodeSocket::required("A", SocketType::Vec3),
621 NodeSocket::required("B", SocketType::Vec3),
622 ],
623 NodeType::ValueNoise | NodeType::PerlinNoise | NodeType::SimplexNoise => vec![
624 NodeSocket::required("UV", SocketType::Vec2),
625 NodeSocket::optional("Scale", SocketType::Float, "1.0"),
626 NodeSocket::optional("Seed", SocketType::Float, "0.0"),
627 ],
628 NodeType::Fbm => vec![
629 NodeSocket::required("UV", SocketType::Vec2),
630 NodeSocket::optional("Octaves", SocketType::Float, "4.0"),
631 NodeSocket::optional("Lacunarity",SocketType::Float,"2.0"),
632 NodeSocket::optional("Gain", SocketType::Float, "0.5"),
633 ],
634 NodeType::Voronoi | NodeType::Worley => vec![
635 NodeSocket::required("UV", SocketType::Vec2),
636 NodeSocket::optional("Scale", SocketType::Float, "1.0"),
637 NodeSocket::optional("Jitter",SocketType::Float, "1.0"),
638 ],
639 NodeType::Checkerboard | NodeType::PolkaDots | NodeType::Grid => vec![
640 NodeSocket::required("UV", SocketType::Vec2),
641 NodeSocket::optional("Scale", SocketType::Float, "10.0"),
642 ],
643 NodeType::SineWave | NodeType::SquareWave | NodeType::TriangleWave |
644 NodeType::SawtoothWave => vec![
645 NodeSocket::required("UV", SocketType::Any),
646 NodeSocket::optional("Frequency", SocketType::Float, "1.0"),
647 NodeSocket::optional("Amplitude", SocketType::Float, "1.0"),
648 NodeSocket::optional("Phase", SocketType::Float, "0.0"),
649 ],
650 NodeType::RadialGradient => vec![
651 NodeSocket::required("UV", SocketType::Vec2),
652 NodeSocket::optional("Center", SocketType::Vec2, "vec2(0.5)"),
653 NodeSocket::optional("Radius", SocketType::Float, "0.5"),
654 ],
655 NodeType::LinearGradient => vec![
656 NodeSocket::required("UV", SocketType::Vec2),
657 NodeSocket::optional("Angle", SocketType::Float, "0.0"),
658 ],
659 NodeType::Spiral => vec![
660 NodeSocket::required("UV", SocketType::Vec2),
661 NodeSocket::optional("Arms", SocketType::Float, "3.0"),
662 NodeSocket::optional("Speed", SocketType::Float, "1.0"),
663 NodeSocket::optional("Time", SocketType::Float, "0.0"),
664 ],
665 NodeType::Rings => vec![
666 NodeSocket::required("UV", SocketType::Vec2),
667 NodeSocket::optional("Count", SocketType::Float, "5.0"),
668 NodeSocket::optional("Width", SocketType::Float, "0.5"),
669 ],
670 NodeType::StarBurst => vec![
671 NodeSocket::required("UV", SocketType::Vec2),
672 NodeSocket::optional("Arms", SocketType::Float, "8.0"),
673 NodeSocket::optional("Sharp", SocketType::Float, "0.5"),
674 ],
675 NodeType::HexTile => vec![
676 NodeSocket::required("UV", SocketType::Vec2),
677 NodeSocket::optional("Scale", SocketType::Float, "10.0"),
678 ],
679 NodeType::Vignette => vec![
680 NodeSocket::required("UV", SocketType::Vec2),
681 NodeSocket::optional("Strength", SocketType::Float, "0.5"),
682 NodeSocket::optional("Feather", SocketType::Float, "0.5"),
683 ],
684 NodeType::FilmGrain => vec![
685 NodeSocket::required("UV", SocketType::Vec2),
686 NodeSocket::optional("Time", SocketType::Float, "0.0"),
687 NodeSocket::optional("Strength", SocketType::Float, "0.05"),
688 ],
689 NodeType::Scanlines => vec![
690 NodeSocket::required("UV", SocketType::Vec2),
691 NodeSocket::optional("Intensity", SocketType::Float, "0.2"),
692 NodeSocket::optional("Count", SocketType::Float, "300.0"),
693 ],
694 NodeType::ChromaticAberration => vec![
695 NodeSocket::required("UV", SocketType::Vec2),
696 NodeSocket::optional("Strength", SocketType::Float, "0.005"),
697 ],
698 NodeType::EdgeDetect | NodeType::Sharpen | NodeType::Emboss => vec![
699 NodeSocket::required("Tex", SocketType::Sampler2D),
700 NodeSocket::required("UV", SocketType::Vec2),
701 NodeSocket::optional("Strength", SocketType::Float, "1.0"),
702 NodeSocket::optional("TexelSize", SocketType::Vec2, "vec2(0.001)"),
703 ],
704 NodeType::Pixelate => vec![
705 NodeSocket::required("UV", SocketType::Vec2),
706 NodeSocket::optional("Resolution",SocketType::Float,"64.0"),
707 ],
708 NodeType::BarrelDistort | NodeType::FishEye => vec![
709 NodeSocket::required("UV", SocketType::Vec2),
710 NodeSocket::optional("Strength", SocketType::Float, "0.3"),
711 ],
712 NodeType::HeatHaze => vec![
713 NodeSocket::required("UV", SocketType::Vec2),
714 NodeSocket::optional("Time", SocketType::Float, "0.0"),
715 NodeSocket::optional("Strength", SocketType::Float, "0.02"),
716 NodeSocket::optional("Speed", SocketType::Float, "1.0"),
717 ],
718 NodeType::GlitchOffset => vec![
719 NodeSocket::required("UV", SocketType::Vec2),
720 NodeSocket::optional("Time", SocketType::Float, "0.0"),
721 NodeSocket::optional("Intensity", SocketType::Float, "0.5"),
722 NodeSocket::optional("Seed", SocketType::Float, "0.0"),
723 ],
724 NodeType::BoxBlur => vec![
725 NodeSocket::required("Tex", SocketType::Sampler2D),
726 NodeSocket::required("UV", SocketType::Vec2),
727 NodeSocket::optional("Radius", SocketType::Float,"1.0"),
728 NodeSocket::optional("TexelSize",SocketType::Vec2, "vec2(0.001)"),
729 ],
730 NodeType::Posterize => vec![
731 NodeSocket::required("Color", SocketType::Vec3),
732 NodeSocket::optional("Steps", SocketType::Float, "4.0"),
733 ],
734 NodeType::Duotone => vec![
735 NodeSocket::required("Color", SocketType::Vec3),
736 NodeSocket::optional("Shadow", SocketType::Vec3, "vec3(0.0,0.0,0.3)"),
737 NodeSocket::optional("Highlight", SocketType::Vec3, "vec3(1.0,0.8,0.2)"),
738 ],
739 NodeType::Outline => vec![
740 NodeSocket::required("SDF", SocketType::Float),
741 NodeSocket::optional("Color", SocketType::Vec3, "vec3(1.0)"),
742 NodeSocket::optional("Thickness",SocketType::Float,"0.02"),
743 ],
744 NodeType::SdfCircle => vec![
745 NodeSocket::required("UV", SocketType::Vec2),
746 NodeSocket::optional("Center", SocketType::Vec2, "vec2(0.5)"),
747 NodeSocket::optional("Radius", SocketType::Float, "0.3"),
748 ],
749 NodeType::SdfBox => vec![
750 NodeSocket::required("UV", SocketType::Vec2),
751 NodeSocket::optional("Center", SocketType::Vec2, "vec2(0.5)"),
752 NodeSocket::optional("Size", SocketType::Vec2, "vec2(0.3)"),
753 NodeSocket::optional("Corner", SocketType::Float, "0.0"),
754 ],
755 NodeType::SdfLine => vec![
756 NodeSocket::required("UV", SocketType::Vec2),
757 NodeSocket::required("A", SocketType::Vec2),
758 NodeSocket::required("B", SocketType::Vec2),
759 ],
760 NodeType::SdfTriangle => vec![
761 NodeSocket::required("UV", SocketType::Vec2),
762 NodeSocket::required("A", SocketType::Vec2),
763 NodeSocket::required("B", SocketType::Vec2),
764 NodeSocket::required("C", SocketType::Vec2),
765 ],
766 NodeType::SdfRing => vec![
767 NodeSocket::required("UV", SocketType::Vec2),
768 NodeSocket::optional("Center", SocketType::Vec2, "vec2(0.5)"),
769 NodeSocket::optional("OuterRadius",SocketType::Float, "0.4"),
770 NodeSocket::optional("InnerRadius",SocketType::Float, "0.3"),
771 ],
772 NodeType::SdfStar => vec![
773 NodeSocket::required("UV", SocketType::Vec2),
774 NodeSocket::optional("Points", SocketType::Float, "5.0"),
775 NodeSocket::optional("Inner", SocketType::Float, "0.2"),
776 NodeSocket::optional("Outer", SocketType::Float, "0.4"),
777 ],
778 NodeType::SdfSmoothUnion | NodeType::SdfSmoothSubtract | NodeType::SdfSmoothIntersect => vec![
779 NodeSocket::required("A", SocketType::Float),
780 NodeSocket::required("B", SocketType::Float),
781 NodeSocket::optional("K", SocketType::Float, "0.1"),
782 ],
783 NodeType::SdfToAlpha | NodeType::SdfToSoftAlpha => vec![
784 NodeSocket::required("SDF", SocketType::Float),
785 NodeSocket::optional("Threshold", SocketType::Float, "0.0"),
786 NodeSocket::optional("Feather", SocketType::Float, "0.01"),
787 ],
788 NodeType::Mandelbrot | NodeType::Julia | NodeType::BurningShip |
789 NodeType::NewtonFractal => vec![
790 NodeSocket::required("UV", SocketType::Vec2),
791 NodeSocket::optional("MaxIter", SocketType::Float, "100.0"),
792 NodeSocket::optional("Zoom", SocketType::Float, "1.0"),
793 NodeSocket::optional("Cx", SocketType::Float, "-0.7"),
794 NodeSocket::optional("Cy", SocketType::Float, "0.27"),
795 ],
796 NodeType::LorenzAttractor => vec![
797 NodeSocket::required("UV", SocketType::Vec2),
798 NodeSocket::optional("Time", SocketType::Float, "0.0"),
799 NodeSocket::optional("Scale", SocketType::Float, "0.05"),
800 ],
801 NodeType::LyapunovViz => vec![
802 NodeSocket::required("UV", SocketType::Vec2),
803 NodeSocket::optional("Seq", SocketType::Float, "0.0"),
804 NodeSocket::optional("Iters", SocketType::Float, "100.0"),
805 ],
806 NodeType::IfGreater | NodeType::IfLess => vec![
807 NodeSocket::required("A", SocketType::Any),
808 NodeSocket::optional("Threshold", SocketType::Float, "0.5"),
809 NodeSocket::required("TrueVal", SocketType::Any),
810 NodeSocket::required("FalseVal", SocketType::Any),
811 ],
812 NodeType::ConditionalBlend => vec![
813 NodeSocket::required("Condition", SocketType::Float),
814 NodeSocket::required("A", SocketType::Any),
815 NodeSocket::required("B", SocketType::Any),
816 NodeSocket::optional("Feather", SocketType::Float, "0.05"),
817 ],
818 NodeType::TextureSample => vec![
819 NodeSocket::required("Tex", SocketType::Sampler2D),
820 NodeSocket::required("UV", SocketType::Vec2),
821 ],
822 NodeType::ScreenShake => vec![
823 NodeSocket::required("UV", SocketType::Vec2),
824 NodeSocket::optional("Strength", SocketType::Float, "0.0"),
825 NodeSocket::optional("Time", SocketType::Float, "0.0"),
826 ],
827 NodeType::OutputColor | NodeType::OutputWithBloom => vec![
828 NodeSocket::required("Color", SocketType::Vec4),
829 ],
830 NodeType::OutputTarget(_) => vec![
831 NodeSocket::required("Color", SocketType::Vec4),
832 ],
833 _ => vec![],
835 }
836 }
837
838 pub fn output_sockets(&self) -> Vec<NodeSocket> {
840 match self {
841 NodeType::UvCoord | NodeType::ScreenCoord | NodeType::RotateVec2 => vec![
842 NodeSocket::optional("UV", SocketType::Vec2, "vec2(0.0)"),
843 ],
844 NodeType::WorldPos | NodeType::CameraPos => vec![
845 NodeSocket::optional("Pos", SocketType::Vec3, "vec3(0.0)"),
846 ],
847 NodeType::Time => vec![
848 NodeSocket::optional("T", SocketType::Float, "0.0"),
849 ],
850 NodeType::Resolution => vec![
851 NodeSocket::optional("Res", SocketType::Vec2, "vec2(1.0)"),
852 ],
853 NodeType::ConstFloat(_) => vec![
854 NodeSocket::optional("Value", SocketType::Float, "0.0"),
855 ],
856 NodeType::ConstVec2(_, _) => vec![
857 NodeSocket::optional("Value", SocketType::Vec2, "vec2(0.0)"),
858 ],
859 NodeType::ConstVec3(..) => vec![
860 NodeSocket::optional("Value", SocketType::Vec3, "vec3(0.0)"),
861 ],
862 NodeType::ConstVec4(..) | NodeType::VertexColor => vec![
863 NodeSocket::optional("Value", SocketType::Vec4, "vec4(0.0)"),
864 ],
865 NodeType::Uniform(_, t) => vec![
866 NodeSocket::optional("Value", *t, t.default_value()),
867 ],
868 NodeType::TextureSample => vec![
869 NodeSocket::optional("RGBA", SocketType::Vec4, "vec4(0.0)"),
870 NodeSocket::optional("RGB", SocketType::Vec3, "vec3(0.0)"),
871 NodeSocket::optional("A", SocketType::Float, "0.0"),
872 ],
873 NodeType::CombineVec2 => vec![
874 NodeSocket::optional("XY", SocketType::Vec2, "vec2(0.0)"),
875 ],
876 NodeType::CombineVec3 | NodeType::HsvToRgb | NodeType::RgbToHsv |
877 NodeType::WorldPos | NodeType::Normalize | NodeType::Reflect | NodeType::Cross => vec![
878 NodeSocket::optional("Out", SocketType::Vec3, "vec3(0.0)"),
879 ],
880 NodeType::CombineVec4 => vec![
881 NodeSocket::optional("RGBA", SocketType::Vec4, "vec4(0.0)"),
882 ],
883 NodeType::SplitVec2 => vec![
884 NodeSocket::optional("X", SocketType::Float, "0.0"),
885 NodeSocket::optional("Y", SocketType::Float, "0.0"),
886 ],
887 NodeType::SplitVec3 => vec![
888 NodeSocket::optional("X", SocketType::Float, "0.0"),
889 NodeSocket::optional("Y", SocketType::Float, "0.0"),
890 NodeSocket::optional("Z", SocketType::Float, "0.0"),
891 ],
892 NodeType::SplitVec4 => vec![
893 NodeSocket::optional("X", SocketType::Float, "0.0"),
894 NodeSocket::optional("Y", SocketType::Float, "0.0"),
895 NodeSocket::optional("Z", SocketType::Float, "0.0"),
896 NodeSocket::optional("W", SocketType::Float, "0.0"),
897 ],
898 NodeType::OutputColor | NodeType::OutputTarget(_) | NodeType::OutputWithBloom => vec![],
900 _ => vec![
902 NodeSocket::optional("Out", SocketType::Any, "0.0"),
903 ],
904 }
905 }
906
907 pub fn is_input_node(&self) -> bool {
908 matches!(self,
909 NodeType::UvCoord | NodeType::WorldPos | NodeType::CameraPos |
910 NodeType::Time | NodeType::Resolution | NodeType::ConstFloat(_) |
911 NodeType::ConstVec2(..) | NodeType::ConstVec3(..) | NodeType::ConstVec4(..) |
912 NodeType::Uniform(..) | NodeType::VertexColor | NodeType::ScreenCoord
913 )
914 }
915
916 pub fn is_output_node(&self) -> bool {
917 matches!(self,
918 NodeType::OutputColor | NodeType::OutputTarget(_) | NodeType::OutputWithBloom
919 )
920 }
921
922 pub fn output_count(&self) -> usize { self.output_sockets().len() }
923 pub fn input_count(&self) -> usize { self.input_sockets().len() }
924}
925
926#[derive(Debug, Clone)]
930pub struct ShaderNode {
931 pub id: NodeId,
932 pub node_type: NodeType,
933 pub editor_x: f32,
935 pub editor_y: f32,
936 pub constant_inputs: HashMap<usize, String>,
938 pub label: Option<String>,
940 pub bypassed: bool,
942 pub muted: bool,
944}
945
946impl ShaderNode {
947 pub fn new(id: NodeId, node_type: NodeType) -> Self {
948 Self {
949 id, node_type,
950 editor_x: 0.0,
951 editor_y: 0.0,
952 constant_inputs: HashMap::new(),
953 label: None,
954 bypassed: false,
955 muted: false,
956 }
957 }
958
959 pub fn with_label(mut self, label: impl Into<String>) -> Self {
960 self.label = Some(label.into());
961 self
962 }
963
964 pub fn with_constant(mut self, slot: usize, value: impl Into<String>) -> Self {
965 self.constant_inputs.insert(slot, value.into());
966 self
967 }
968
969 pub fn display_label(&self) -> &str {
970 self.label.as_deref().unwrap_or_else(|| self.node_type.label())
971 }
972
973 pub fn var_name(&self, slot: usize) -> String {
975 format!("n{}_{}", self.id.0, slot)
976 }
977}
978
979#[cfg(test)]
982mod tests {
983 use super::*;
984
985 #[test]
986 fn test_all_node_types_have_labels() {
987 let types = [
988 NodeType::Add, NodeType::Multiply, NodeType::Sin, NodeType::Cos,
989 NodeType::PerlinNoise, NodeType::Mandelbrot, NodeType::OutputColor,
990 ];
991 for t in &types {
992 assert!(!t.label().is_empty());
993 }
994 }
995
996 #[test]
997 fn test_socket_compatibility() {
998 assert!(SocketType::Float.is_compatible_with(SocketType::Float));
999 assert!(SocketType::Any.is_compatible_with(SocketType::Vec3));
1000 assert!(!SocketType::Float.is_compatible_with(SocketType::Vec4));
1001 }
1002
1003 #[test]
1004 fn test_node_input_output_counts() {
1005 let add = NodeType::Add;
1006 assert_eq!(add.input_count(), 2);
1007 assert_eq!(add.output_count(), 1);
1008
1009 let uv = NodeType::UvCoord;
1010 assert_eq!(uv.input_count(), 0);
1011 assert_eq!(uv.output_count(), 1);
1012
1013 let out = NodeType::OutputColor;
1014 assert_eq!(out.input_count(), 1);
1015 assert_eq!(out.output_count(), 0);
1016 }
1017
1018 #[test]
1019 fn test_var_name() {
1020 let node = ShaderNode::new(NodeId(42), NodeType::Add);
1021 assert_eq!(node.var_name(0), "n42_0");
1022 assert_eq!(node.var_name(1), "n42_1");
1023 }
1024
1025 #[test]
1026 fn test_socket_default_values() {
1027 let s = NodeSocket::optional("test", SocketType::Vec3, "vec3(0.0)");
1028 assert_eq!(s.default, "vec3(0.0)");
1029 assert!(!s.required);
1030 }
1031
1032 #[test]
1033 fn test_is_input_output_node() {
1034 assert!(NodeType::UvCoord.is_input_node());
1035 assert!(!NodeType::Add.is_input_node());
1036 assert!(NodeType::OutputColor.is_output_node());
1037 assert!(!NodeType::Add.is_output_node());
1038 }
1039}