@nice2dev/ui-3d 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/CHANGELOG.md +115 -1
  2. package/dist/cjs/collaborative/collaborativeScene.js +210 -0
  3. package/dist/cjs/collaborative/collaborativeScene.js.map +1 -0
  4. package/dist/cjs/core/i18n.js +3 -3
  5. package/dist/cjs/core/i18n.js.map +1 -1
  6. package/dist/cjs/dance/DanceBridge.js +162 -0
  7. package/dist/cjs/dance/DanceBridge.js.map +1 -0
  8. package/dist/cjs/dance/DanceScoreEngine.js +210 -0
  9. package/dist/cjs/dance/DanceScoreEngine.js.map +1 -0
  10. package/dist/cjs/dance/PoseDetector.js +199 -0
  11. package/dist/cjs/dance/PoseDetector.js.map +1 -0
  12. package/dist/cjs/index.js +254 -0
  13. package/dist/cjs/index.js.map +1 -1
  14. package/dist/cjs/material/MaterialEditor.module.css.js +6 -0
  15. package/dist/cjs/material/MaterialEditor.module.css.js.map +1 -0
  16. package/dist/cjs/material/NiceMaterialEditor.js +737 -0
  17. package/dist/cjs/material/NiceMaterialEditor.js.map +1 -0
  18. package/dist/cjs/material/materialEditorTypes.js +73 -0
  19. package/dist/cjs/material/materialEditorTypes.js.map +1 -0
  20. package/dist/cjs/material/materialEditorUtils.js +841 -0
  21. package/dist/cjs/material/materialEditorUtils.js.map +1 -0
  22. package/dist/cjs/material/materialNodeDefinitions.js +1285 -0
  23. package/dist/cjs/material/materialNodeDefinitions.js.map +1 -0
  24. package/dist/cjs/model/ModelEditor.js +4 -1
  25. package/dist/cjs/model/ModelEditor.js.map +1 -1
  26. package/dist/cjs/model/ModelEditor.module.css.js +1 -1
  27. package/dist/cjs/model/ModelEditorLeftPanel.js +5 -4
  28. package/dist/cjs/model/ModelEditorLeftPanel.js.map +1 -1
  29. package/dist/cjs/model/ModelEditorMenuBar.js +8 -3
  30. package/dist/cjs/model/ModelEditorMenuBar.js.map +1 -1
  31. package/dist/cjs/model/ModelEditorRightPanel.js +27 -26
  32. package/dist/cjs/model/ModelEditorRightPanel.js.map +1 -1
  33. package/dist/cjs/model/ModelEditorSubComponents.js +20 -16
  34. package/dist/cjs/model/ModelEditorSubComponents.js.map +1 -1
  35. package/dist/cjs/model/ModelEditorTimeline.js +5 -4
  36. package/dist/cjs/model/ModelEditorTimeline.js.map +1 -1
  37. package/dist/cjs/model/ModelEditorToolbar.js +4 -3
  38. package/dist/cjs/model/ModelEditorToolbar.js.map +1 -1
  39. package/dist/cjs/model/ModelEditorViewport.js +2 -2
  40. package/dist/cjs/model/ModelEditorViewport.js.map +1 -1
  41. package/dist/cjs/model/ModelViewer.js +68 -0
  42. package/dist/cjs/model/ModelViewer.js.map +1 -0
  43. package/dist/cjs/model/ModelViewer.module.css.js +6 -0
  44. package/dist/cjs/model/ModelViewer.module.css.js.map +1 -0
  45. package/dist/cjs/model/NiceArmatureEditor.js +255 -0
  46. package/dist/cjs/model/NiceArmatureEditor.js.map +1 -0
  47. package/dist/cjs/model/NiceMorphTargetEditor.js +206 -0
  48. package/dist/cjs/model/NiceMorphTargetEditor.js.map +1 -0
  49. package/dist/cjs/model/NiceOctree.js +339 -0
  50. package/dist/cjs/model/NiceOctree.js.map +1 -0
  51. package/dist/cjs/model/NicePhysicsSimulation.js +283 -0
  52. package/dist/cjs/model/NicePhysicsSimulation.js.map +1 -0
  53. package/dist/cjs/model/NiceProceduralGeometry.js +269 -0
  54. package/dist/cjs/model/NiceProceduralGeometry.js.map +1 -0
  55. package/dist/cjs/model/NiceTerrainEditor.js +343 -0
  56. package/dist/cjs/model/NiceTerrainEditor.js.map +1 -0
  57. package/dist/cjs/model/NiceWeightPainter.js +258 -0
  58. package/dist/cjs/model/NiceWeightPainter.js.map +1 -0
  59. package/dist/cjs/model/NiceXRPreview.js +269 -0
  60. package/dist/cjs/model/NiceXRPreview.js.map +1 -0
  61. package/dist/cjs/model/cadModeUtils.js +130 -0
  62. package/dist/cjs/model/cadModeUtils.js.map +1 -0
  63. package/dist/cjs/model/editorShortcuts.js +187 -0
  64. package/dist/cjs/model/editorShortcuts.js.map +1 -0
  65. package/dist/cjs/model/modelEditorTypes.js +11 -0
  66. package/dist/cjs/model/modelEditorTypes.js.map +1 -1
  67. package/dist/cjs/model/modelEditorUtils.js +1049 -0
  68. package/dist/cjs/model/modelEditorUtils.js.map +1 -0
  69. package/dist/cjs/model/simsModeUtils.js +358 -0
  70. package/dist/cjs/model/simsModeUtils.js.map +1 -0
  71. package/dist/cjs/model/useModelEditor.js +319 -115
  72. package/dist/cjs/model/useModelEditor.js.map +1 -1
  73. package/dist/cjs/model/useModelViewer.js +634 -0
  74. package/dist/cjs/model/useModelViewer.js.map +1 -0
  75. package/dist/cjs/nice2dev-ui-3d.css +1 -1
  76. package/dist/cjs/particle/NiceParticleEditor.js +526 -0
  77. package/dist/cjs/particle/NiceParticleEditor.js.map +1 -0
  78. package/dist/cjs/particle/ParticleEditor.module.css.js +6 -0
  79. package/dist/cjs/particle/ParticleEditor.module.css.js.map +1 -0
  80. package/dist/cjs/particle/particleEditorTypes.js +92 -0
  81. package/dist/cjs/particle/particleEditorTypes.js.map +1 -0
  82. package/dist/cjs/particle/particleEditorUtils.js +1084 -0
  83. package/dist/cjs/particle/particleEditorUtils.js.map +1 -0
  84. package/dist/cjs/rendering/NiceCascadedShadows.js +266 -0
  85. package/dist/cjs/rendering/NiceCascadedShadows.js.map +1 -0
  86. package/dist/cjs/rendering/NiceRenderExport.js +341 -0
  87. package/dist/cjs/rendering/NiceRenderExport.js.map +1 -0
  88. package/dist/cjs/rendering/NiceSSAO.js +359 -0
  89. package/dist/cjs/rendering/NiceSSAO.js.map +1 -0
  90. package/dist/cjs/rendering/NiceSSR.js +277 -0
  91. package/dist/cjs/rendering/NiceSSR.js.map +1 -0
  92. package/dist/cjs/rendering/NiceWebGPURenderer.js +215 -0
  93. package/dist/cjs/rendering/NiceWebGPURenderer.js.map +1 -0
  94. package/dist/cjs/ui/dist/index.js +50089 -0
  95. package/dist/cjs/ui/dist/index.js.map +1 -0
  96. package/dist/cjs/uv/NiceUVEditor.js +520 -0
  97. package/dist/cjs/uv/NiceUVEditor.js.map +1 -0
  98. package/dist/cjs/uv/UVEditor.module.css.js +6 -0
  99. package/dist/cjs/uv/UVEditor.module.css.js.map +1 -0
  100. package/dist/cjs/uv/uvEditorTypes.js +98 -0
  101. package/dist/cjs/uv/uvEditorTypes.js.map +1 -0
  102. package/dist/cjs/uv/uvEditorUtils.js +670 -0
  103. package/dist/cjs/uv/uvEditorUtils.js.map +1 -0
  104. package/dist/esm/collaborative/collaborativeScene.js +206 -0
  105. package/dist/esm/collaborative/collaborativeScene.js.map +1 -0
  106. package/dist/esm/dance/DanceBridge.js +158 -0
  107. package/dist/esm/dance/DanceBridge.js.map +1 -0
  108. package/dist/esm/dance/DanceScoreEngine.js +207 -0
  109. package/dist/esm/dance/DanceScoreEngine.js.map +1 -0
  110. package/dist/esm/dance/PoseDetector.js +195 -0
  111. package/dist/esm/dance/PoseDetector.js.map +1 -0
  112. package/dist/esm/index.js +35 -1
  113. package/dist/esm/index.js.map +1 -1
  114. package/dist/esm/material/MaterialEditor.module.css.js +4 -0
  115. package/dist/esm/material/MaterialEditor.module.css.js.map +1 -0
  116. package/dist/esm/material/NiceMaterialEditor.js +734 -0
  117. package/dist/esm/material/NiceMaterialEditor.js.map +1 -0
  118. package/dist/esm/material/materialEditorTypes.js +62 -0
  119. package/dist/esm/material/materialEditorTypes.js.map +1 -0
  120. package/dist/esm/material/materialEditorUtils.js +811 -0
  121. package/dist/esm/material/materialEditorUtils.js.map +1 -0
  122. package/dist/esm/material/materialNodeDefinitions.js +1280 -0
  123. package/dist/esm/material/materialNodeDefinitions.js.map +1 -0
  124. package/dist/esm/model/ModelEditor.js +4 -2
  125. package/dist/esm/model/ModelEditor.js.map +1 -1
  126. package/dist/esm/model/ModelEditor.module.css.js +1 -1
  127. package/dist/esm/model/ModelEditorLeftPanel.js +5 -4
  128. package/dist/esm/model/ModelEditorLeftPanel.js.map +1 -1
  129. package/dist/esm/model/ModelEditorMenuBar.js +8 -3
  130. package/dist/esm/model/ModelEditorMenuBar.js.map +1 -1
  131. package/dist/esm/model/ModelEditorRightPanel.js +27 -26
  132. package/dist/esm/model/ModelEditorRightPanel.js.map +1 -1
  133. package/dist/esm/model/ModelEditorSubComponents.js +17 -13
  134. package/dist/esm/model/ModelEditorSubComponents.js.map +1 -1
  135. package/dist/esm/model/ModelEditorTimeline.js +5 -4
  136. package/dist/esm/model/ModelEditorTimeline.js.map +1 -1
  137. package/dist/esm/model/ModelEditorToolbar.js +4 -3
  138. package/dist/esm/model/ModelEditorToolbar.js.map +1 -1
  139. package/dist/esm/model/ModelEditorViewport.js +2 -2
  140. package/dist/esm/model/ModelEditorViewport.js.map +1 -1
  141. package/dist/esm/model/ModelViewer.js +65 -0
  142. package/dist/esm/model/ModelViewer.js.map +1 -0
  143. package/dist/esm/model/ModelViewer.module.css.js +4 -0
  144. package/dist/esm/model/ModelViewer.module.css.js.map +1 -0
  145. package/dist/esm/model/NiceArmatureEditor.js +233 -0
  146. package/dist/esm/model/NiceArmatureEditor.js.map +1 -0
  147. package/dist/esm/model/NiceMorphTargetEditor.js +184 -0
  148. package/dist/esm/model/NiceMorphTargetEditor.js.map +1 -0
  149. package/dist/esm/model/NiceOctree.js +317 -0
  150. package/dist/esm/model/NiceOctree.js.map +1 -0
  151. package/dist/esm/model/NicePhysicsSimulation.js +261 -0
  152. package/dist/esm/model/NicePhysicsSimulation.js.map +1 -0
  153. package/dist/esm/model/NiceProceduralGeometry.js +242 -0
  154. package/dist/esm/model/NiceProceduralGeometry.js.map +1 -0
  155. package/dist/esm/model/NiceTerrainEditor.js +321 -0
  156. package/dist/esm/model/NiceTerrainEditor.js.map +1 -0
  157. package/dist/esm/model/NiceWeightPainter.js +236 -0
  158. package/dist/esm/model/NiceWeightPainter.js.map +1 -0
  159. package/dist/esm/model/NiceXRPreview.js +247 -0
  160. package/dist/esm/model/NiceXRPreview.js.map +1 -0
  161. package/dist/esm/model/cadModeUtils.js +103 -0
  162. package/dist/esm/model/cadModeUtils.js.map +1 -0
  163. package/dist/esm/model/editorShortcuts.js +185 -0
  164. package/dist/esm/model/editorShortcuts.js.map +1 -0
  165. package/dist/esm/model/modelEditorTypes.js +11 -0
  166. package/dist/esm/model/modelEditorTypes.js.map +1 -1
  167. package/dist/esm/model/modelEditorUtils.js +997 -0
  168. package/dist/esm/model/modelEditorUtils.js.map +1 -0
  169. package/dist/esm/model/simsModeUtils.js +325 -0
  170. package/dist/esm/model/simsModeUtils.js.map +1 -0
  171. package/dist/esm/model/useModelEditor.js +204 -0
  172. package/dist/esm/model/useModelEditor.js.map +1 -1
  173. package/dist/esm/model/useModelViewer.js +613 -0
  174. package/dist/esm/model/useModelViewer.js.map +1 -0
  175. package/dist/esm/nice2dev-ui-3d.css +1 -1
  176. package/dist/esm/particle/NiceParticleEditor.js +523 -0
  177. package/dist/esm/particle/NiceParticleEditor.js.map +1 -0
  178. package/dist/esm/particle/ParticleEditor.module.css.js +4 -0
  179. package/dist/esm/particle/ParticleEditor.module.css.js.map +1 -0
  180. package/dist/esm/particle/particleEditorTypes.js +84 -0
  181. package/dist/esm/particle/particleEditorTypes.js.map +1 -0
  182. package/dist/esm/particle/particleEditorUtils.js +1054 -0
  183. package/dist/esm/particle/particleEditorUtils.js.map +1 -0
  184. package/dist/esm/rendering/NiceCascadedShadows.js +244 -0
  185. package/dist/esm/rendering/NiceCascadedShadows.js.map +1 -0
  186. package/dist/esm/rendering/NiceRenderExport.js +319 -0
  187. package/dist/esm/rendering/NiceRenderExport.js.map +1 -0
  188. package/dist/esm/rendering/NiceSSAO.js +337 -0
  189. package/dist/esm/rendering/NiceSSAO.js.map +1 -0
  190. package/dist/esm/rendering/NiceSSR.js +255 -0
  191. package/dist/esm/rendering/NiceSSR.js.map +1 -0
  192. package/dist/esm/rendering/NiceWebGPURenderer.js +193 -0
  193. package/dist/esm/rendering/NiceWebGPURenderer.js.map +1 -0
  194. package/dist/esm/ui/dist/index.js +49686 -0
  195. package/dist/esm/ui/dist/index.js.map +1 -0
  196. package/dist/esm/uv/NiceUVEditor.js +518 -0
  197. package/dist/esm/uv/NiceUVEditor.js.map +1 -0
  198. package/dist/esm/uv/UVEditor.module.css.js +4 -0
  199. package/dist/esm/uv/UVEditor.module.css.js.map +1 -0
  200. package/dist/esm/uv/uvEditorTypes.js +88 -0
  201. package/dist/esm/uv/uvEditorTypes.js.map +1 -0
  202. package/dist/esm/uv/uvEditorUtils.js +621 -0
  203. package/dist/esm/uv/uvEditorUtils.js.map +1 -0
  204. package/package.json +3 -4
@@ -0,0 +1,1280 @@
1
+ /* ════════════════════════════════════════════════════════════════════════════
2
+ Material Node Definitions — Built-in Shader Nodes
3
+
4
+ Comprehensive library of 60+ shader nodes:
5
+ - Input nodes (constants, parameters, textures)
6
+ - Output nodes (PBR, unlit, custom)
7
+ - Math operations
8
+ - Vector operations
9
+ - Color manipulation
10
+ - Texture sampling
11
+ - Procedural generation
12
+ - Utility functions
13
+ - Logic/branching
14
+ ════════════════════════════════════════════════════════════════════════════ */
15
+ /* ═══════════════════════════════════════════════════════════════════════════
16
+ INPUT NODES
17
+ ═══════════════════════════════════════════════════════════════════════════ */
18
+ const inputNodes = [
19
+ {
20
+ type: 'constant_float',
21
+ category: 'input',
22
+ name: 'Float',
23
+ description: 'Constant float value',
24
+ icon: 'number',
25
+ inputs: [],
26
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'float' }],
27
+ properties: [{ id: 'value', name: 'Value', type: 'float', default: 0, min: -100, max: 100, step: 0.01 }],
28
+ shaderFunction: 'float {{nodeId}}_value = {{value}};',
29
+ },
30
+ {
31
+ type: 'constant_vec2',
32
+ category: 'input',
33
+ name: 'Vector 2',
34
+ description: 'Constant 2D vector',
35
+ icon: 'vector2',
36
+ inputs: [],
37
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'vec2' }],
38
+ properties: [
39
+ { id: 'x', name: 'X', type: 'float', default: 0 },
40
+ { id: 'y', name: 'Y', type: 'float', default: 0 },
41
+ ],
42
+ shaderFunction: 'vec2 {{nodeId}}_value = vec2({{x}}, {{y}});',
43
+ },
44
+ {
45
+ type: 'constant_vec3',
46
+ category: 'input',
47
+ name: 'Vector 3',
48
+ description: 'Constant 3D vector',
49
+ icon: 'vector3',
50
+ inputs: [],
51
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'vec3' }],
52
+ properties: [
53
+ { id: 'x', name: 'X', type: 'float', default: 0 },
54
+ { id: 'y', name: 'Y', type: 'float', default: 0 },
55
+ { id: 'z', name: 'Z', type: 'float', default: 0 },
56
+ ],
57
+ shaderFunction: 'vec3 {{nodeId}}_value = vec3({{x}}, {{y}}, {{z}});',
58
+ },
59
+ {
60
+ type: 'constant_vec4',
61
+ category: 'input',
62
+ name: 'Vector 4',
63
+ description: 'Constant 4D vector',
64
+ icon: 'vector4',
65
+ inputs: [],
66
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'vec4' }],
67
+ properties: [
68
+ { id: 'x', name: 'X', type: 'float', default: 0 },
69
+ { id: 'y', name: 'Y', type: 'float', default: 0 },
70
+ { id: 'z', name: 'Z', type: 'float', default: 0 },
71
+ { id: 'w', name: 'W', type: 'float', default: 1 },
72
+ ],
73
+ shaderFunction: 'vec4 {{nodeId}}_value = vec4({{x}}, {{y}}, {{z}}, {{w}});',
74
+ },
75
+ {
76
+ type: 'constant_color',
77
+ category: 'input',
78
+ name: 'Color',
79
+ description: 'Constant color value',
80
+ icon: 'palette',
81
+ inputs: [],
82
+ outputs: [
83
+ { id: 'rgb', name: 'RGB', direction: 'output', dataType: 'vec3' },
84
+ { id: 'rgba', name: 'RGBA', direction: 'output', dataType: 'vec4' },
85
+ { id: 'r', name: 'R', direction: 'output', dataType: 'float' },
86
+ { id: 'g', name: 'G', direction: 'output', dataType: 'float' },
87
+ { id: 'b', name: 'B', direction: 'output', dataType: 'float' },
88
+ { id: 'a', name: 'A', direction: 'output', dataType: 'float' },
89
+ ],
90
+ properties: [{ id: 'color', name: 'Color', type: 'color', default: '#ffffff' }],
91
+ previewable: true,
92
+ },
93
+ {
94
+ type: 'texture_2d',
95
+ category: 'input',
96
+ name: 'Texture 2D',
97
+ description: '2D texture input',
98
+ icon: 'image',
99
+ inputs: [],
100
+ outputs: [{ id: 'texture', name: 'Texture', direction: 'output', dataType: 'texture2d' }],
101
+ properties: [{ id: 'texture', name: 'Texture', type: 'texture', default: null }],
102
+ },
103
+ {
104
+ type: 'texture_cube',
105
+ category: 'input',
106
+ name: 'Cubemap',
107
+ description: 'Cubemap texture input',
108
+ icon: 'cube',
109
+ inputs: [],
110
+ outputs: [{ id: 'texture', name: 'Texture', direction: 'output', dataType: 'textureCube' }],
111
+ properties: [{ id: 'texture', name: 'Texture', type: 'texture', default: null }],
112
+ },
113
+ {
114
+ type: 'param_float',
115
+ category: 'input',
116
+ name: 'Float Parameter',
117
+ description: 'Exposed float parameter',
118
+ icon: 'slider',
119
+ inputs: [],
120
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'float' }],
121
+ properties: [
122
+ { id: 'name', name: 'Name', type: 'string', default: 'myFloat' },
123
+ { id: 'default', name: 'Default', type: 'float', default: 0 },
124
+ { id: 'min', name: 'Min', type: 'float', default: 0 },
125
+ { id: 'max', name: 'Max', type: 'float', default: 1 },
126
+ ],
127
+ shaderFunction: 'uniform float {{name}};',
128
+ },
129
+ {
130
+ type: 'param_color',
131
+ category: 'input',
132
+ name: 'Color Parameter',
133
+ description: 'Exposed color parameter',
134
+ icon: 'palette',
135
+ inputs: [],
136
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'vec4' }],
137
+ properties: [
138
+ { id: 'name', name: 'Name', type: 'string', default: 'myColor' },
139
+ { id: 'default', name: 'Default', type: 'color', default: '#ffffff' },
140
+ ],
141
+ shaderFunction: 'uniform vec4 {{name}};',
142
+ },
143
+ {
144
+ type: 'uv',
145
+ category: 'input',
146
+ name: 'UV Coordinates',
147
+ description: 'Mesh UV coordinates',
148
+ icon: 'grid',
149
+ inputs: [],
150
+ outputs: [
151
+ { id: 'uv', name: 'UV', direction: 'output', dataType: 'vec2' },
152
+ { id: 'u', name: 'U', direction: 'output', dataType: 'float' },
153
+ { id: 'v', name: 'V', direction: 'output', dataType: 'float' },
154
+ ],
155
+ properties: [{ id: 'channel', name: 'Channel', type: 'int', default: 0, min: 0, max: 3 }],
156
+ shaderFunction: 'vec2 {{nodeId}}_uv = vUv{{channel}};',
157
+ },
158
+ {
159
+ type: 'position',
160
+ category: 'input',
161
+ name: 'Position',
162
+ description: 'Vertex position',
163
+ icon: 'crosshair',
164
+ inputs: [],
165
+ outputs: [
166
+ { id: 'world', name: 'World', direction: 'output', dataType: 'vec3' },
167
+ { id: 'object', name: 'Object', direction: 'output', dataType: 'vec3' },
168
+ { id: 'view', name: 'View', direction: 'output', dataType: 'vec3' },
169
+ ],
170
+ },
171
+ {
172
+ type: 'normal',
173
+ category: 'input',
174
+ name: 'Normal',
175
+ description: 'Surface normal',
176
+ icon: 'arrow-up',
177
+ inputs: [],
178
+ outputs: [
179
+ { id: 'world', name: 'World', direction: 'output', dataType: 'vec3' },
180
+ { id: 'object', name: 'Object', direction: 'output', dataType: 'vec3' },
181
+ { id: 'view', name: 'View', direction: 'output', dataType: 'vec3' },
182
+ { id: 'tangent', name: 'Tangent', direction: 'output', dataType: 'vec3' },
183
+ { id: 'bitangent', name: 'Bitangent', direction: 'output', dataType: 'vec3' },
184
+ ],
185
+ },
186
+ {
187
+ type: 'view_direction',
188
+ category: 'input',
189
+ name: 'View Direction',
190
+ description: 'Camera view direction',
191
+ icon: 'eye',
192
+ inputs: [],
193
+ outputs: [{ id: 'direction', name: 'Direction', direction: 'output', dataType: 'vec3' }],
194
+ },
195
+ {
196
+ type: 'time',
197
+ category: 'input',
198
+ name: 'Time',
199
+ description: 'Shader time values',
200
+ icon: 'clock',
201
+ inputs: [],
202
+ outputs: [
203
+ { id: 'time', name: 'Time', direction: 'output', dataType: 'float' },
204
+ { id: 'sin', name: 'Sin Time', direction: 'output', dataType: 'float' },
205
+ { id: 'cos', name: 'Cos Time', direction: 'output', dataType: 'float' },
206
+ { id: 'delta', name: 'Delta', direction: 'output', dataType: 'float' },
207
+ ],
208
+ shaderFunction: 'float {{nodeId}}_time = uTime;',
209
+ },
210
+ {
211
+ type: 'screen_position',
212
+ category: 'input',
213
+ name: 'Screen Position',
214
+ description: 'Screen-space position',
215
+ icon: 'monitor',
216
+ inputs: [],
217
+ outputs: [
218
+ { id: 'position', name: 'Position', direction: 'output', dataType: 'vec4' },
219
+ { id: 'normalized', name: 'Normalized', direction: 'output', dataType: 'vec2' },
220
+ ],
221
+ },
222
+ ];
223
+ /* ═══════════════════════════════════════════════════════════════════════════
224
+ OUTPUT NODES
225
+ ═══════════════════════════════════════════════════════════════════════════ */
226
+ const outputNodes = [
227
+ {
228
+ type: 'output_pbr',
229
+ category: 'output',
230
+ name: 'PBR Output',
231
+ description: 'Physically-based rendering output',
232
+ icon: 'sphere',
233
+ color: '#F44336',
234
+ inputs: [
235
+ { id: 'albedo', name: 'Albedo', direction: 'input', dataType: 'vec3', defaultValue: [1, 1, 1] },
236
+ { id: 'metallic', name: 'Metallic', direction: 'input', dataType: 'float', defaultValue: 0, min: 0, max: 1 },
237
+ { id: 'roughness', name: 'Roughness', direction: 'input', dataType: 'float', defaultValue: 0.5, min: 0, max: 1 },
238
+ { id: 'normal', name: 'Normal', direction: 'input', dataType: 'vec3' },
239
+ { id: 'ao', name: 'AO', direction: 'input', dataType: 'float', defaultValue: 1, min: 0, max: 1 },
240
+ { id: 'emissive', name: 'Emissive', direction: 'input', dataType: 'vec3', defaultValue: [0, 0, 0] },
241
+ { id: 'alpha', name: 'Alpha', direction: 'input', dataType: 'float', defaultValue: 1, min: 0, max: 1 },
242
+ ],
243
+ outputs: [],
244
+ previewable: true,
245
+ },
246
+ {
247
+ type: 'output_unlit',
248
+ category: 'output',
249
+ name: 'Unlit Output',
250
+ description: 'Unlit material output',
251
+ icon: 'sun',
252
+ color: '#F44336',
253
+ inputs: [
254
+ { id: 'color', name: 'Color', direction: 'input', dataType: 'vec3', defaultValue: [1, 1, 1] },
255
+ { id: 'alpha', name: 'Alpha', direction: 'input', dataType: 'float', defaultValue: 1 },
256
+ ],
257
+ outputs: [],
258
+ previewable: true,
259
+ },
260
+ {
261
+ type: 'output_custom',
262
+ category: 'output',
263
+ name: 'Custom Output',
264
+ description: 'Custom shader output',
265
+ icon: 'code',
266
+ color: '#F44336',
267
+ inputs: [
268
+ { id: 'fragColor', name: 'Frag Color', direction: 'input', dataType: 'vec4' },
269
+ ],
270
+ outputs: [],
271
+ properties: [
272
+ { id: 'vertexCode', name: 'Vertex Code', type: 'string', default: '' },
273
+ { id: 'fragmentCode', name: 'Fragment Code', type: 'string', default: '' },
274
+ ],
275
+ },
276
+ ];
277
+ /* ═══════════════════════════════════════════════════════════════════════════
278
+ MATH NODES
279
+ ═══════════════════════════════════════════════════════════════════════════ */
280
+ const mathNodes = [
281
+ {
282
+ type: 'add',
283
+ category: 'math',
284
+ name: 'Add',
285
+ description: 'Add two values',
286
+ icon: 'plus',
287
+ inputs: [
288
+ { id: 'a', name: 'A', direction: 'input', dataType: 'any', defaultValue: 0 },
289
+ { id: 'b', name: 'B', direction: 'input', dataType: 'any', defaultValue: 0 },
290
+ ],
291
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
292
+ shaderFunction: '{{typeA}} {{nodeId}}_result = {{a}} + {{b}};',
293
+ },
294
+ {
295
+ type: 'subtract',
296
+ category: 'math',
297
+ name: 'Subtract',
298
+ description: 'Subtract two values',
299
+ icon: 'minus',
300
+ inputs: [
301
+ { id: 'a', name: 'A', direction: 'input', dataType: 'any', defaultValue: 0 },
302
+ { id: 'b', name: 'B', direction: 'input', dataType: 'any', defaultValue: 0 },
303
+ ],
304
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
305
+ shaderFunction: '{{typeA}} {{nodeId}}_result = {{a}} - {{b}};',
306
+ },
307
+ {
308
+ type: 'multiply',
309
+ category: 'math',
310
+ name: 'Multiply',
311
+ description: 'Multiply two values',
312
+ icon: 'x',
313
+ inputs: [
314
+ { id: 'a', name: 'A', direction: 'input', dataType: 'any', defaultValue: 1 },
315
+ { id: 'b', name: 'B', direction: 'input', dataType: 'any', defaultValue: 1 },
316
+ ],
317
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
318
+ shaderFunction: '{{typeA}} {{nodeId}}_result = {{a}} * {{b}};',
319
+ },
320
+ {
321
+ type: 'divide',
322
+ category: 'math',
323
+ name: 'Divide',
324
+ description: 'Divide two values',
325
+ icon: 'divide',
326
+ inputs: [
327
+ { id: 'a', name: 'A', direction: 'input', dataType: 'any', defaultValue: 1 },
328
+ { id: 'b', name: 'B', direction: 'input', dataType: 'any', defaultValue: 1 },
329
+ ],
330
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
331
+ shaderFunction: '{{typeA}} {{nodeId}}_result = {{a}} / max({{b}}, 0.0001);',
332
+ },
333
+ {
334
+ type: 'power',
335
+ category: 'math',
336
+ name: 'Power',
337
+ description: 'Raise to power',
338
+ icon: 'superscript',
339
+ inputs: [
340
+ { id: 'base', name: 'Base', direction: 'input', dataType: 'any', defaultValue: 2 },
341
+ { id: 'exp', name: 'Exponent', direction: 'input', dataType: 'float', defaultValue: 2 },
342
+ ],
343
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
344
+ shaderFunction: '{{typeBase}} {{nodeId}}_result = pow({{base}}, {{exp}});',
345
+ },
346
+ {
347
+ type: 'sqrt',
348
+ category: 'math',
349
+ name: 'Square Root',
350
+ description: 'Square root of value',
351
+ icon: 'radical',
352
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 1 }],
353
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
354
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = sqrt({{value}});',
355
+ },
356
+ {
357
+ type: 'abs',
358
+ category: 'math',
359
+ name: 'Absolute',
360
+ description: 'Absolute value',
361
+ icon: 'bar-chart',
362
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
363
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
364
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = abs({{value}});',
365
+ },
366
+ {
367
+ type: 'negate',
368
+ category: 'math',
369
+ name: 'Negate',
370
+ description: 'Negate value',
371
+ icon: 'minus-circle',
372
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
373
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
374
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = -{{value}};',
375
+ },
376
+ {
377
+ type: 'sin',
378
+ category: 'math',
379
+ name: 'Sine',
380
+ description: 'Sine function',
381
+ icon: 'activity',
382
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
383
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
384
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = sin({{value}});',
385
+ },
386
+ {
387
+ type: 'cos',
388
+ category: 'math',
389
+ name: 'Cosine',
390
+ description: 'Cosine function',
391
+ icon: 'activity',
392
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
393
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
394
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = cos({{value}});',
395
+ },
396
+ {
397
+ type: 'tan',
398
+ category: 'math',
399
+ name: 'Tangent',
400
+ description: 'Tangent function',
401
+ icon: 'activity',
402
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
403
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
404
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = tan({{value}});',
405
+ },
406
+ {
407
+ type: 'floor',
408
+ category: 'math',
409
+ name: 'Floor',
410
+ description: 'Floor value',
411
+ icon: 'corner-down-left',
412
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
413
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
414
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = floor({{value}});',
415
+ },
416
+ {
417
+ type: 'ceil',
418
+ category: 'math',
419
+ name: 'Ceiling',
420
+ description: 'Ceiling value',
421
+ icon: 'corner-up-right',
422
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
423
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
424
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = ceil({{value}});',
425
+ },
426
+ {
427
+ type: 'round',
428
+ category: 'math',
429
+ name: 'Round',
430
+ description: 'Round value',
431
+ icon: 'circle',
432
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
433
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
434
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = round({{value}});',
435
+ },
436
+ {
437
+ type: 'fract',
438
+ category: 'math',
439
+ name: 'Fraction',
440
+ description: 'Fractional part',
441
+ icon: 'percent',
442
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
443
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
444
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = fract({{value}});',
445
+ },
446
+ {
447
+ type: 'mod',
448
+ category: 'math',
449
+ name: 'Modulo',
450
+ description: 'Modulo operation',
451
+ icon: 'percent',
452
+ inputs: [
453
+ { id: 'a', name: 'A', direction: 'input', dataType: 'any', defaultValue: 0 },
454
+ { id: 'b', name: 'B', direction: 'input', dataType: 'any', defaultValue: 1 },
455
+ ],
456
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
457
+ shaderFunction: '{{typeA}} {{nodeId}}_result = mod({{a}}, {{b}});',
458
+ },
459
+ {
460
+ type: 'min',
461
+ category: 'math',
462
+ name: 'Minimum',
463
+ description: 'Minimum of two values',
464
+ icon: 'chevron-down',
465
+ inputs: [
466
+ { id: 'a', name: 'A', direction: 'input', dataType: 'any', defaultValue: 0 },
467
+ { id: 'b', name: 'B', direction: 'input', dataType: 'any', defaultValue: 1 },
468
+ ],
469
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
470
+ shaderFunction: '{{typeA}} {{nodeId}}_result = min({{a}}, {{b}});',
471
+ },
472
+ {
473
+ type: 'max',
474
+ category: 'math',
475
+ name: 'Maximum',
476
+ description: 'Maximum of two values',
477
+ icon: 'chevron-up',
478
+ inputs: [
479
+ { id: 'a', name: 'A', direction: 'input', dataType: 'any', defaultValue: 0 },
480
+ { id: 'b', name: 'B', direction: 'input', dataType: 'any', defaultValue: 1 },
481
+ ],
482
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
483
+ shaderFunction: '{{typeA}} {{nodeId}}_result = max({{a}}, {{b}});',
484
+ },
485
+ {
486
+ type: 'exp',
487
+ category: 'math',
488
+ name: 'Exponential',
489
+ description: 'e^x',
490
+ icon: 'trending-up',
491
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
492
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
493
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = exp({{value}});',
494
+ },
495
+ {
496
+ type: 'log',
497
+ category: 'math',
498
+ name: 'Logarithm',
499
+ description: 'Natural logarithm',
500
+ icon: 'trending-down',
501
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 1 }],
502
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
503
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = log(max({{value}}, 0.0001));',
504
+ },
505
+ ];
506
+ /* ═══════════════════════════════════════════════════════════════════════════
507
+ VECTOR NODES
508
+ ═══════════════════════════════════════════════════════════════════════════ */
509
+ const vectorNodes = [
510
+ {
511
+ type: 'split_vec2',
512
+ category: 'vector',
513
+ name: 'Split Vec2',
514
+ description: 'Split vector into components',
515
+ icon: 'git-branch',
516
+ inputs: [{ id: 'vector', name: 'Vector', direction: 'input', dataType: 'vec2' }],
517
+ outputs: [
518
+ { id: 'x', name: 'X', direction: 'output', dataType: 'float' },
519
+ { id: 'y', name: 'Y', direction: 'output', dataType: 'float' },
520
+ ],
521
+ },
522
+ {
523
+ type: 'split_vec3',
524
+ category: 'vector',
525
+ name: 'Split Vec3',
526
+ description: 'Split vector into components',
527
+ icon: 'git-branch',
528
+ inputs: [{ id: 'vector', name: 'Vector', direction: 'input', dataType: 'vec3' }],
529
+ outputs: [
530
+ { id: 'x', name: 'X', direction: 'output', dataType: 'float' },
531
+ { id: 'y', name: 'Y', direction: 'output', dataType: 'float' },
532
+ { id: 'z', name: 'Z', direction: 'output', dataType: 'float' },
533
+ ],
534
+ },
535
+ {
536
+ type: 'split_vec4',
537
+ category: 'vector',
538
+ name: 'Split Vec4',
539
+ description: 'Split vector into components',
540
+ icon: 'git-branch',
541
+ inputs: [{ id: 'vector', name: 'Vector', direction: 'input', dataType: 'vec4' }],
542
+ outputs: [
543
+ { id: 'x', name: 'X', direction: 'output', dataType: 'float' },
544
+ { id: 'y', name: 'Y', direction: 'output', dataType: 'float' },
545
+ { id: 'z', name: 'Z', direction: 'output', dataType: 'float' },
546
+ { id: 'w', name: 'W', direction: 'output', dataType: 'float' },
547
+ ],
548
+ },
549
+ {
550
+ type: 'combine_vec2',
551
+ category: 'vector',
552
+ name: 'Combine Vec2',
553
+ description: 'Combine components into vector',
554
+ icon: 'git-merge',
555
+ inputs: [
556
+ { id: 'x', name: 'X', direction: 'input', dataType: 'float', defaultValue: 0 },
557
+ { id: 'y', name: 'Y', direction: 'input', dataType: 'float', defaultValue: 0 },
558
+ ],
559
+ outputs: [{ id: 'vector', name: 'Vector', direction: 'output', dataType: 'vec2' }],
560
+ shaderFunction: 'vec2 {{nodeId}}_vector = vec2({{x}}, {{y}});',
561
+ },
562
+ {
563
+ type: 'combine_vec3',
564
+ category: 'vector',
565
+ name: 'Combine Vec3',
566
+ description: 'Combine components into vector',
567
+ icon: 'git-merge',
568
+ inputs: [
569
+ { id: 'x', name: 'X', direction: 'input', dataType: 'float', defaultValue: 0 },
570
+ { id: 'y', name: 'Y', direction: 'input', dataType: 'float', defaultValue: 0 },
571
+ { id: 'z', name: 'Z', direction: 'input', dataType: 'float', defaultValue: 0 },
572
+ ],
573
+ outputs: [{ id: 'vector', name: 'Vector', direction: 'output', dataType: 'vec3' }],
574
+ shaderFunction: 'vec3 {{nodeId}}_vector = vec3({{x}}, {{y}}, {{z}});',
575
+ },
576
+ {
577
+ type: 'combine_vec4',
578
+ category: 'vector',
579
+ name: 'Combine Vec4',
580
+ description: 'Combine components into vector',
581
+ icon: 'git-merge',
582
+ inputs: [
583
+ { id: 'x', name: 'X', direction: 'input', dataType: 'float', defaultValue: 0 },
584
+ { id: 'y', name: 'Y', direction: 'input', dataType: 'float', defaultValue: 0 },
585
+ { id: 'z', name: 'Z', direction: 'input', dataType: 'float', defaultValue: 0 },
586
+ { id: 'w', name: 'W', direction: 'input', dataType: 'float', defaultValue: 1 },
587
+ ],
588
+ outputs: [{ id: 'vector', name: 'Vector', direction: 'output', dataType: 'vec4' }],
589
+ shaderFunction: 'vec4 {{nodeId}}_vector = vec4({{x}}, {{y}}, {{z}}, {{w}});',
590
+ },
591
+ {
592
+ type: 'normalize',
593
+ category: 'vector',
594
+ name: 'Normalize',
595
+ description: 'Normalize vector to unit length',
596
+ icon: 'maximize-2',
597
+ inputs: [{ id: 'vector', name: 'Vector', direction: 'input', dataType: 'vec3' }],
598
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'vec3' }],
599
+ shaderFunction: 'vec3 {{nodeId}}_result = normalize({{vector}});',
600
+ },
601
+ {
602
+ type: 'length',
603
+ category: 'vector',
604
+ name: 'Length',
605
+ description: 'Vector length/magnitude',
606
+ icon: 'move',
607
+ inputs: [{ id: 'vector', name: 'Vector', direction: 'input', dataType: 'vec3' }],
608
+ outputs: [{ id: 'length', name: 'Length', direction: 'output', dataType: 'float' }],
609
+ shaderFunction: 'float {{nodeId}}_length = length({{vector}});',
610
+ },
611
+ {
612
+ type: 'distance',
613
+ category: 'vector',
614
+ name: 'Distance',
615
+ description: 'Distance between two points',
616
+ icon: 'maximize',
617
+ inputs: [
618
+ { id: 'a', name: 'A', direction: 'input', dataType: 'vec3' },
619
+ { id: 'b', name: 'B', direction: 'input', dataType: 'vec3' },
620
+ ],
621
+ outputs: [{ id: 'distance', name: 'Distance', direction: 'output', dataType: 'float' }],
622
+ shaderFunction: 'float {{nodeId}}_distance = distance({{a}}, {{b}});',
623
+ },
624
+ {
625
+ type: 'dot',
626
+ category: 'vector',
627
+ name: 'Dot Product',
628
+ description: 'Dot product of two vectors',
629
+ icon: 'target',
630
+ inputs: [
631
+ { id: 'a', name: 'A', direction: 'input', dataType: 'vec3' },
632
+ { id: 'b', name: 'B', direction: 'input', dataType: 'vec3' },
633
+ ],
634
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'float' }],
635
+ shaderFunction: 'float {{nodeId}}_result = dot({{a}}, {{b}});',
636
+ },
637
+ {
638
+ type: 'cross',
639
+ category: 'vector',
640
+ name: 'Cross Product',
641
+ description: 'Cross product of two vectors',
642
+ icon: 'x',
643
+ inputs: [
644
+ { id: 'a', name: 'A', direction: 'input', dataType: 'vec3' },
645
+ { id: 'b', name: 'B', direction: 'input', dataType: 'vec3' },
646
+ ],
647
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'vec3' }],
648
+ shaderFunction: 'vec3 {{nodeId}}_result = cross({{a}}, {{b}});',
649
+ },
650
+ {
651
+ type: 'reflect',
652
+ category: 'vector',
653
+ name: 'Reflect',
654
+ description: 'Reflect vector off surface',
655
+ icon: 'corner-up-left',
656
+ inputs: [
657
+ { id: 'incident', name: 'Incident', direction: 'input', dataType: 'vec3' },
658
+ { id: 'normal', name: 'Normal', direction: 'input', dataType: 'vec3' },
659
+ ],
660
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'vec3' }],
661
+ shaderFunction: 'vec3 {{nodeId}}_result = reflect({{incident}}, {{normal}});',
662
+ },
663
+ {
664
+ type: 'refract',
665
+ category: 'vector',
666
+ name: 'Refract',
667
+ description: 'Refract vector through surface',
668
+ icon: 'corner-down-right',
669
+ inputs: [
670
+ { id: 'incident', name: 'Incident', direction: 'input', dataType: 'vec3' },
671
+ { id: 'normal', name: 'Normal', direction: 'input', dataType: 'vec3' },
672
+ { id: 'ior', name: 'IOR', direction: 'input', dataType: 'float', defaultValue: 1.5 },
673
+ ],
674
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'vec3' }],
675
+ shaderFunction: 'vec3 {{nodeId}}_result = refract({{incident}}, {{normal}}, {{ior}});',
676
+ },
677
+ {
678
+ type: 'transform',
679
+ category: 'vector',
680
+ name: 'Transform',
681
+ description: 'Transform vector by matrix',
682
+ icon: 'rotate-cw',
683
+ inputs: [
684
+ { id: 'vector', name: 'Vector', direction: 'input', dataType: 'vec3' },
685
+ { id: 'matrix', name: 'Matrix', direction: 'input', dataType: 'matrix4' },
686
+ ],
687
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'vec3' }],
688
+ },
689
+ ];
690
+ /* ═══════════════════════════════════════════════════════════════════════════
691
+ COLOR NODES
692
+ ═══════════════════════════════════════════════════════════════════════════ */
693
+ const colorNodes = [
694
+ {
695
+ type: 'hsv_to_rgb',
696
+ category: 'color',
697
+ name: 'HSV to RGB',
698
+ description: 'Convert HSV to RGB',
699
+ icon: 'droplet',
700
+ inputs: [
701
+ { id: 'h', name: 'H', direction: 'input', dataType: 'float', defaultValue: 0, min: 0, max: 1 },
702
+ { id: 's', name: 'S', direction: 'input', dataType: 'float', defaultValue: 1, min: 0, max: 1 },
703
+ { id: 'v', name: 'V', direction: 'input', dataType: 'float', defaultValue: 1, min: 0, max: 1 },
704
+ ],
705
+ outputs: [{ id: 'rgb', name: 'RGB', direction: 'output', dataType: 'vec3' }],
706
+ previewable: true,
707
+ },
708
+ {
709
+ type: 'rgb_to_hsv',
710
+ category: 'color',
711
+ name: 'RGB to HSV',
712
+ description: 'Convert RGB to HSV',
713
+ icon: 'droplet',
714
+ inputs: [{ id: 'rgb', name: 'RGB', direction: 'input', dataType: 'vec3' }],
715
+ outputs: [
716
+ { id: 'h', name: 'H', direction: 'output', dataType: 'float' },
717
+ { id: 's', name: 'S', direction: 'output', dataType: 'float' },
718
+ { id: 'v', name: 'V', direction: 'output', dataType: 'float' },
719
+ ],
720
+ },
721
+ {
722
+ type: 'blend',
723
+ category: 'color',
724
+ name: 'Blend',
725
+ description: 'Blend two colors',
726
+ icon: 'layers',
727
+ inputs: [
728
+ { id: 'base', name: 'Base', direction: 'input', dataType: 'vec3' },
729
+ { id: 'blend', name: 'Blend', direction: 'input', dataType: 'vec3' },
730
+ { id: 'factor', name: 'Factor', direction: 'input', dataType: 'float', defaultValue: 0.5, min: 0, max: 1 },
731
+ ],
732
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'vec3' }],
733
+ properties: [
734
+ {
735
+ id: 'mode', name: 'Mode', type: 'enum', default: 'normal',
736
+ options: [
737
+ { label: 'Normal', value: 'normal' },
738
+ { label: 'Multiply', value: 'multiply' },
739
+ { label: 'Screen', value: 'screen' },
740
+ { label: 'Overlay', value: 'overlay' },
741
+ { label: 'Add', value: 'add' },
742
+ { label: 'Subtract', value: 'subtract' },
743
+ { label: 'Difference', value: 'difference' },
744
+ ],
745
+ },
746
+ ],
747
+ previewable: true,
748
+ },
749
+ {
750
+ type: 'brightness_contrast',
751
+ category: 'color',
752
+ name: 'Brightness/Contrast',
753
+ description: 'Adjust brightness and contrast',
754
+ icon: 'sun',
755
+ inputs: [
756
+ { id: 'color', name: 'Color', direction: 'input', dataType: 'vec3' },
757
+ { id: 'brightness', name: 'Brightness', direction: 'input', dataType: 'float', defaultValue: 0, min: -1, max: 1 },
758
+ { id: 'contrast', name: 'Contrast', direction: 'input', dataType: 'float', defaultValue: 1, min: 0, max: 2 },
759
+ ],
760
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'vec3' }],
761
+ previewable: true,
762
+ },
763
+ {
764
+ type: 'hue_saturation',
765
+ category: 'color',
766
+ name: 'Hue/Saturation',
767
+ description: 'Adjust hue, saturation, value',
768
+ icon: 'sliders',
769
+ inputs: [
770
+ { id: 'color', name: 'Color', direction: 'input', dataType: 'vec3' },
771
+ { id: 'hue', name: 'Hue', direction: 'input', dataType: 'float', defaultValue: 0, min: -1, max: 1 },
772
+ { id: 'saturation', name: 'Saturation', direction: 'input', dataType: 'float', defaultValue: 1, min: 0, max: 2 },
773
+ { id: 'value', name: 'Value', direction: 'input', dataType: 'float', defaultValue: 1, min: 0, max: 2 },
774
+ ],
775
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'vec3' }],
776
+ previewable: true,
777
+ },
778
+ {
779
+ type: 'invert',
780
+ category: 'color',
781
+ name: 'Invert',
782
+ description: 'Invert color',
783
+ icon: 'refresh-cw',
784
+ inputs: [{ id: 'color', name: 'Color', direction: 'input', dataType: 'vec3' }],
785
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'vec3' }],
786
+ shaderFunction: 'vec3 {{nodeId}}_result = vec3(1.0) - {{color}};',
787
+ previewable: true,
788
+ },
789
+ {
790
+ type: 'gamma',
791
+ category: 'color',
792
+ name: 'Gamma',
793
+ description: 'Apply gamma correction',
794
+ icon: 'zap',
795
+ inputs: [
796
+ { id: 'color', name: 'Color', direction: 'input', dataType: 'vec3' },
797
+ { id: 'gamma', name: 'Gamma', direction: 'input', dataType: 'float', defaultValue: 2.2 },
798
+ ],
799
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'vec3' }],
800
+ shaderFunction: 'vec3 {{nodeId}}_result = pow({{color}}, vec3(1.0 / {{gamma}}));',
801
+ previewable: true,
802
+ },
803
+ {
804
+ type: 'grayscale',
805
+ category: 'color',
806
+ name: 'Grayscale',
807
+ description: 'Convert to grayscale',
808
+ icon: 'circle',
809
+ inputs: [{ id: 'color', name: 'Color', direction: 'input', dataType: 'vec3' }],
810
+ outputs: [
811
+ { id: 'gray', name: 'Gray', direction: 'output', dataType: 'float' },
812
+ { id: 'rgb', name: 'RGB', direction: 'output', dataType: 'vec3' },
813
+ ],
814
+ shaderFunction: 'float {{nodeId}}_gray = dot({{color}}, vec3(0.299, 0.587, 0.114));',
815
+ previewable: true,
816
+ },
817
+ ];
818
+ /* ═══════════════════════════════════════════════════════════════════════════
819
+ TEXTURE NODES
820
+ ═══════════════════════════════════════════════════════════════════════════ */
821
+ const textureNodes = [
822
+ {
823
+ type: 'sample_texture',
824
+ category: 'texture',
825
+ name: 'Sample Texture',
826
+ description: 'Sample 2D texture',
827
+ icon: 'image',
828
+ inputs: [
829
+ { id: 'texture', name: 'Texture', direction: 'input', dataType: 'texture2d' },
830
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
831
+ ],
832
+ outputs: [
833
+ { id: 'rgba', name: 'RGBA', direction: 'output', dataType: 'vec4' },
834
+ { id: 'rgb', name: 'RGB', direction: 'output', dataType: 'vec3' },
835
+ { id: 'r', name: 'R', direction: 'output', dataType: 'float' },
836
+ { id: 'g', name: 'G', direction: 'output', dataType: 'float' },
837
+ { id: 'b', name: 'B', direction: 'output', dataType: 'float' },
838
+ { id: 'a', name: 'A', direction: 'output', dataType: 'float' },
839
+ ],
840
+ shaderFunction: 'vec4 {{nodeId}}_rgba = texture2D({{texture}}, {{uv}});',
841
+ previewable: true,
842
+ },
843
+ {
844
+ type: 'sample_cubemap',
845
+ category: 'texture',
846
+ name: 'Sample Cubemap',
847
+ description: 'Sample cubemap texture',
848
+ icon: 'box',
849
+ inputs: [
850
+ { id: 'texture', name: 'Texture', direction: 'input', dataType: 'textureCube' },
851
+ { id: 'direction', name: 'Direction', direction: 'input', dataType: 'vec3' },
852
+ ],
853
+ outputs: [
854
+ { id: 'rgba', name: 'RGBA', direction: 'output', dataType: 'vec4' },
855
+ { id: 'rgb', name: 'RGB', direction: 'output', dataType: 'vec3' },
856
+ ],
857
+ shaderFunction: 'vec4 {{nodeId}}_rgba = textureCube({{texture}}, {{direction}});',
858
+ previewable: true,
859
+ },
860
+ {
861
+ type: 'normal_map',
862
+ category: 'texture',
863
+ name: 'Normal Map',
864
+ description: 'Unpack normal map',
865
+ icon: 'arrow-up-right',
866
+ inputs: [
867
+ { id: 'texture', name: 'Texture', direction: 'input', dataType: 'texture2d' },
868
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
869
+ { id: 'strength', name: 'Strength', direction: 'input', dataType: 'float', defaultValue: 1, min: 0, max: 2 },
870
+ ],
871
+ outputs: [{ id: 'normal', name: 'Normal', direction: 'output', dataType: 'vec3' }],
872
+ previewable: true,
873
+ },
874
+ {
875
+ type: 'uv_tiling',
876
+ category: 'texture',
877
+ name: 'UV Tiling/Offset',
878
+ description: 'Tile and offset UVs',
879
+ icon: 'grid',
880
+ inputs: [
881
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
882
+ { id: 'tiling', name: 'Tiling', direction: 'input', dataType: 'vec2', defaultValue: [1, 1] },
883
+ { id: 'offset', name: 'Offset', direction: 'input', dataType: 'vec2', defaultValue: [0, 0] },
884
+ ],
885
+ outputs: [{ id: 'uv', name: 'UV', direction: 'output', dataType: 'vec2' }],
886
+ shaderFunction: 'vec2 {{nodeId}}_uv = {{uv}} * {{tiling}} + {{offset}};',
887
+ },
888
+ {
889
+ type: 'uv_rotate',
890
+ category: 'texture',
891
+ name: 'UV Rotate',
892
+ description: 'Rotate UVs',
893
+ icon: 'rotate-cw',
894
+ inputs: [
895
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
896
+ { id: 'angle', name: 'Angle', direction: 'input', dataType: 'float', defaultValue: 0 },
897
+ { id: 'center', name: 'Center', direction: 'input', dataType: 'vec2', defaultValue: [0.5, 0.5] },
898
+ ],
899
+ outputs: [{ id: 'uv', name: 'UV', direction: 'output', dataType: 'vec2' }],
900
+ },
901
+ {
902
+ type: 'parallax',
903
+ category: 'texture',
904
+ name: 'Parallax',
905
+ description: 'Parallax mapping',
906
+ icon: 'layers',
907
+ inputs: [
908
+ { id: 'heightMap', name: 'Height Map', direction: 'input', dataType: 'texture2d' },
909
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
910
+ { id: 'viewDir', name: 'View Dir', direction: 'input', dataType: 'vec3' },
911
+ { id: 'scale', name: 'Scale', direction: 'input', dataType: 'float', defaultValue: 0.1 },
912
+ ],
913
+ outputs: [{ id: 'uv', name: 'UV', direction: 'output', dataType: 'vec2' }],
914
+ },
915
+ {
916
+ type: 'triplanar',
917
+ category: 'texture',
918
+ name: 'Triplanar',
919
+ description: 'Triplanar texture projection',
920
+ icon: 'box',
921
+ inputs: [
922
+ { id: 'texture', name: 'Texture', direction: 'input', dataType: 'texture2d' },
923
+ { id: 'position', name: 'Position', direction: 'input', dataType: 'vec3' },
924
+ { id: 'normal', name: 'Normal', direction: 'input', dataType: 'vec3' },
925
+ { id: 'scale', name: 'Scale', direction: 'input', dataType: 'float', defaultValue: 1 },
926
+ { id: 'blend', name: 'Blend', direction: 'input', dataType: 'float', defaultValue: 0.5 },
927
+ ],
928
+ outputs: [{ id: 'color', name: 'Color', direction: 'output', dataType: 'vec4' }],
929
+ previewable: true,
930
+ },
931
+ ];
932
+ /* ═══════════════════════════════════════════════════════════════════════════
933
+ PROCEDURAL NODES
934
+ ═══════════════════════════════════════════════════════════════════════════ */
935
+ const proceduralNodes = [
936
+ {
937
+ type: 'noise_perlin',
938
+ category: 'procedural',
939
+ name: 'Perlin Noise',
940
+ description: 'Perlin noise generator',
941
+ icon: 'hash',
942
+ inputs: [
943
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
944
+ { id: 'scale', name: 'Scale', direction: 'input', dataType: 'float', defaultValue: 10 },
945
+ { id: 'octaves', name: 'Octaves', direction: 'input', dataType: 'int', defaultValue: 4 },
946
+ ],
947
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'float' }],
948
+ previewable: true,
949
+ },
950
+ {
951
+ type: 'noise_simplex',
952
+ category: 'procedural',
953
+ name: 'Simplex Noise',
954
+ description: 'Simplex noise generator',
955
+ icon: 'hash',
956
+ inputs: [
957
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
958
+ { id: 'scale', name: 'Scale', direction: 'input', dataType: 'float', defaultValue: 10 },
959
+ ],
960
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'float' }],
961
+ previewable: true,
962
+ },
963
+ {
964
+ type: 'noise_voronoi',
965
+ category: 'procedural',
966
+ name: 'Voronoi',
967
+ description: 'Voronoi/Worley noise',
968
+ icon: 'hexagon',
969
+ inputs: [
970
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
971
+ { id: 'scale', name: 'Scale', direction: 'input', dataType: 'float', defaultValue: 10 },
972
+ { id: 'jitter', name: 'Jitter', direction: 'input', dataType: 'float', defaultValue: 1 },
973
+ ],
974
+ outputs: [
975
+ { id: 'distance', name: 'Distance', direction: 'output', dataType: 'float' },
976
+ { id: 'cellId', name: 'Cell ID', direction: 'output', dataType: 'float' },
977
+ ],
978
+ previewable: true,
979
+ },
980
+ {
981
+ type: 'noise_fbm',
982
+ category: 'procedural',
983
+ name: 'FBM Noise',
984
+ description: 'Fractional Brownian Motion',
985
+ icon: 'cloud',
986
+ inputs: [
987
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
988
+ { id: 'scale', name: 'Scale', direction: 'input', dataType: 'float', defaultValue: 5 },
989
+ { id: 'octaves', name: 'Octaves', direction: 'input', dataType: 'int', defaultValue: 6 },
990
+ { id: 'lacunarity', name: 'Lacunarity', direction: 'input', dataType: 'float', defaultValue: 2 },
991
+ { id: 'gain', name: 'Gain', direction: 'input', dataType: 'float', defaultValue: 0.5 },
992
+ ],
993
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'float' }],
994
+ previewable: true,
995
+ },
996
+ {
997
+ type: 'gradient_linear',
998
+ category: 'procedural',
999
+ name: 'Linear Gradient',
1000
+ description: 'Linear gradient',
1001
+ icon: 'arrow-right',
1002
+ inputs: [
1003
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
1004
+ ],
1005
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'float' }],
1006
+ properties: [
1007
+ { id: 'direction', name: 'Direction', type: 'enum', default: 'horizontal',
1008
+ options: [
1009
+ { label: 'Horizontal', value: 'horizontal' },
1010
+ { label: 'Vertical', value: 'vertical' },
1011
+ { label: 'Diagonal', value: 'diagonal' },
1012
+ ] },
1013
+ ],
1014
+ previewable: true,
1015
+ },
1016
+ {
1017
+ type: 'gradient_radial',
1018
+ category: 'procedural',
1019
+ name: 'Radial Gradient',
1020
+ description: 'Radial gradient',
1021
+ icon: 'circle',
1022
+ inputs: [
1023
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
1024
+ { id: 'center', name: 'Center', direction: 'input', dataType: 'vec2', defaultValue: [0.5, 0.5] },
1025
+ { id: 'radius', name: 'Radius', direction: 'input', dataType: 'float', defaultValue: 0.5 },
1026
+ ],
1027
+ outputs: [{ id: 'value', name: 'Value', direction: 'output', dataType: 'float' }],
1028
+ previewable: true,
1029
+ },
1030
+ {
1031
+ type: 'checker',
1032
+ category: 'procedural',
1033
+ name: 'Checker',
1034
+ description: 'Checkerboard pattern',
1035
+ icon: 'grid',
1036
+ inputs: [
1037
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
1038
+ { id: 'scale', name: 'Scale', direction: 'input', dataType: 'float', defaultValue: 8 },
1039
+ { id: 'colorA', name: 'Color A', direction: 'input', dataType: 'vec3', defaultValue: [0, 0, 0] },
1040
+ { id: 'colorB', name: 'Color B', direction: 'input', dataType: 'vec3', defaultValue: [1, 1, 1] },
1041
+ ],
1042
+ outputs: [
1043
+ { id: 'color', name: 'Color', direction: 'output', dataType: 'vec3' },
1044
+ { id: 'value', name: 'Value', direction: 'output', dataType: 'float' },
1045
+ ],
1046
+ previewable: true,
1047
+ },
1048
+ {
1049
+ type: 'brick',
1050
+ category: 'procedural',
1051
+ name: 'Brick',
1052
+ description: 'Brick pattern',
1053
+ icon: 'layout',
1054
+ inputs: [
1055
+ { id: 'uv', name: 'UV', direction: 'input', dataType: 'vec2' },
1056
+ { id: 'brickWidth', name: 'Brick Width', direction: 'input', dataType: 'float', defaultValue: 0.5 },
1057
+ { id: 'brickHeight', name: 'Brick Height', direction: 'input', dataType: 'float', defaultValue: 0.25 },
1058
+ { id: 'mortarSize', name: 'Mortar Size', direction: 'input', dataType: 'float', defaultValue: 0.02 },
1059
+ ],
1060
+ outputs: [
1061
+ { id: 'mask', name: 'Mask', direction: 'output', dataType: 'float' },
1062
+ { id: 'brickId', name: 'Brick ID', direction: 'output', dataType: 'vec2' },
1063
+ ],
1064
+ previewable: true,
1065
+ },
1066
+ ];
1067
+ /* ═══════════════════════════════════════════════════════════════════════════
1068
+ UTILITY NODES
1069
+ ═══════════════════════════════════════════════════════════════════════════ */
1070
+ const utilityNodes = [
1071
+ {
1072
+ type: 'lerp',
1073
+ category: 'utility',
1074
+ name: 'Lerp',
1075
+ description: 'Linear interpolation',
1076
+ icon: 'sliders',
1077
+ inputs: [
1078
+ { id: 'a', name: 'A', direction: 'input', dataType: 'any', defaultValue: 0 },
1079
+ { id: 'b', name: 'B', direction: 'input', dataType: 'any', defaultValue: 1 },
1080
+ { id: 't', name: 'T', direction: 'input', dataType: 'float', defaultValue: 0.5, min: 0, max: 1 },
1081
+ ],
1082
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
1083
+ shaderFunction: '{{typeA}} {{nodeId}}_result = mix({{a}}, {{b}}, {{t}});',
1084
+ },
1085
+ {
1086
+ type: 'clamp',
1087
+ category: 'utility',
1088
+ name: 'Clamp',
1089
+ description: 'Clamp value to range',
1090
+ icon: 'minus-square',
1091
+ inputs: [
1092
+ { id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 },
1093
+ { id: 'min', name: 'Min', direction: 'input', dataType: 'any', defaultValue: 0 },
1094
+ { id: 'max', name: 'Max', direction: 'input', dataType: 'any', defaultValue: 1 },
1095
+ ],
1096
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
1097
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = clamp({{value}}, {{min}}, {{max}});',
1098
+ },
1099
+ {
1100
+ type: 'saturate',
1101
+ category: 'utility',
1102
+ name: 'Saturate',
1103
+ description: 'Clamp to 0-1',
1104
+ icon: 'minimize-2',
1105
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
1106
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
1107
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = clamp({{value}}, 0.0, 1.0);',
1108
+ },
1109
+ {
1110
+ type: 'remap',
1111
+ category: 'utility',
1112
+ name: 'Remap',
1113
+ description: 'Remap value from one range to another',
1114
+ icon: 'repeat',
1115
+ inputs: [
1116
+ { id: 'value', name: 'Value', direction: 'input', dataType: 'float', defaultValue: 0.5 },
1117
+ { id: 'inMin', name: 'In Min', direction: 'input', dataType: 'float', defaultValue: 0 },
1118
+ { id: 'inMax', name: 'In Max', direction: 'input', dataType: 'float', defaultValue: 1 },
1119
+ { id: 'outMin', name: 'Out Min', direction: 'input', dataType: 'float', defaultValue: 0 },
1120
+ { id: 'outMax', name: 'Out Max', direction: 'input', dataType: 'float', defaultValue: 1 },
1121
+ ],
1122
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'float' }],
1123
+ },
1124
+ {
1125
+ type: 'smoothstep',
1126
+ category: 'utility',
1127
+ name: 'Smoothstep',
1128
+ description: 'Smooth Hermite interpolation',
1129
+ icon: 'activity',
1130
+ inputs: [
1131
+ { id: 'edge0', name: 'Edge 0', direction: 'input', dataType: 'float', defaultValue: 0 },
1132
+ { id: 'edge1', name: 'Edge 1', direction: 'input', dataType: 'float', defaultValue: 1 },
1133
+ { id: 'x', name: 'X', direction: 'input', dataType: 'float', defaultValue: 0.5 },
1134
+ ],
1135
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'float' }],
1136
+ shaderFunction: 'float {{nodeId}}_result = smoothstep({{edge0}}, {{edge1}}, {{x}});',
1137
+ },
1138
+ {
1139
+ type: 'step',
1140
+ category: 'utility',
1141
+ name: 'Step',
1142
+ description: 'Step function (threshold)',
1143
+ icon: 'corner-down-right',
1144
+ inputs: [
1145
+ { id: 'edge', name: 'Edge', direction: 'input', dataType: 'any', defaultValue: 0.5 },
1146
+ { id: 'x', name: 'X', direction: 'input', dataType: 'any', defaultValue: 0 },
1147
+ ],
1148
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
1149
+ shaderFunction: '{{typeEdge}} {{nodeId}}_result = step({{edge}}, {{x}});',
1150
+ },
1151
+ {
1152
+ type: 'one_minus',
1153
+ category: 'utility',
1154
+ name: 'One Minus',
1155
+ description: '1 - x',
1156
+ icon: 'minus',
1157
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'any', defaultValue: 0 }],
1158
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
1159
+ shaderFunction: '{{typeValue}} {{nodeId}}_result = 1.0 - {{value}};',
1160
+ },
1161
+ {
1162
+ type: 'fresnel',
1163
+ category: 'utility',
1164
+ name: 'Fresnel',
1165
+ description: 'Fresnel effect',
1166
+ icon: 'circle',
1167
+ inputs: [
1168
+ { id: 'normal', name: 'Normal', direction: 'input', dataType: 'vec3' },
1169
+ { id: 'viewDir', name: 'View Dir', direction: 'input', dataType: 'vec3' },
1170
+ { id: 'power', name: 'Power', direction: 'input', dataType: 'float', defaultValue: 5 },
1171
+ ],
1172
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'float' }],
1173
+ previewable: true,
1174
+ },
1175
+ ];
1176
+ /* ═══════════════════════════════════════════════════════════════════════════
1177
+ LOGIC NODES
1178
+ ═══════════════════════════════════════════════════════════════════════════ */
1179
+ const logicNodes = [
1180
+ {
1181
+ type: 'branch',
1182
+ category: 'logic',
1183
+ name: 'Branch',
1184
+ description: 'Conditional branch (if/else)',
1185
+ icon: 'git-branch',
1186
+ inputs: [
1187
+ { id: 'condition', name: 'Condition', direction: 'input', dataType: 'bool', defaultValue: false },
1188
+ { id: 'true', name: 'True', direction: 'input', dataType: 'any' },
1189
+ { id: 'false', name: 'False', direction: 'input', dataType: 'any' },
1190
+ ],
1191
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'any' }],
1192
+ },
1193
+ {
1194
+ type: 'compare',
1195
+ category: 'logic',
1196
+ name: 'Compare',
1197
+ description: 'Compare two values',
1198
+ icon: 'git-pull-request',
1199
+ inputs: [
1200
+ { id: 'a', name: 'A', direction: 'input', dataType: 'float', defaultValue: 0 },
1201
+ { id: 'b', name: 'B', direction: 'input', dataType: 'float', defaultValue: 0 },
1202
+ ],
1203
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'bool' }],
1204
+ properties: [
1205
+ { id: 'operator', name: 'Operator', type: 'enum', default: 'equal',
1206
+ options: [
1207
+ { label: 'Equal', value: 'equal' },
1208
+ { label: 'Not Equal', value: 'notEqual' },
1209
+ { label: 'Greater', value: 'greater' },
1210
+ { label: 'Less', value: 'less' },
1211
+ { label: 'Greater Equal', value: 'greaterEqual' },
1212
+ { label: 'Less Equal', value: 'lessEqual' },
1213
+ ] },
1214
+ ],
1215
+ },
1216
+ {
1217
+ type: 'and',
1218
+ category: 'logic',
1219
+ name: 'And',
1220
+ description: 'Logical AND',
1221
+ icon: 'check-square',
1222
+ inputs: [
1223
+ { id: 'a', name: 'A', direction: 'input', dataType: 'bool', defaultValue: false },
1224
+ { id: 'b', name: 'B', direction: 'input', dataType: 'bool', defaultValue: false },
1225
+ ],
1226
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'bool' }],
1227
+ },
1228
+ {
1229
+ type: 'or',
1230
+ category: 'logic',
1231
+ name: 'Or',
1232
+ description: 'Logical OR',
1233
+ icon: 'check-square',
1234
+ inputs: [
1235
+ { id: 'a', name: 'A', direction: 'input', dataType: 'bool', defaultValue: false },
1236
+ { id: 'b', name: 'B', direction: 'input', dataType: 'bool', defaultValue: false },
1237
+ ],
1238
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'bool' }],
1239
+ },
1240
+ {
1241
+ type: 'not',
1242
+ category: 'logic',
1243
+ name: 'Not',
1244
+ description: 'Logical NOT',
1245
+ icon: 'x-square',
1246
+ inputs: [{ id: 'value', name: 'Value', direction: 'input', dataType: 'bool', defaultValue: false }],
1247
+ outputs: [{ id: 'result', name: 'Result', direction: 'output', dataType: 'bool' }],
1248
+ },
1249
+ ];
1250
+ /* ═══════════════════════════════════════════════════════════════════════════
1251
+ EXPORTS
1252
+ ═══════════════════════════════════════════════════════════════════════════ */
1253
+ /** All built-in node definitions */
1254
+ const MATERIAL_NODE_DEFINITIONS = [
1255
+ ...inputNodes,
1256
+ ...outputNodes,
1257
+ ...mathNodes,
1258
+ ...vectorNodes,
1259
+ ...colorNodes,
1260
+ ...textureNodes,
1261
+ ...proceduralNodes,
1262
+ ...utilityNodes,
1263
+ ...logicNodes,
1264
+ ];
1265
+ /** Node definitions map by type */
1266
+ const MATERIAL_NODE_MAP = new Map(MATERIAL_NODE_DEFINITIONS.map(def => [def.type, def]));
1267
+ /** Get nodes by category */
1268
+ function getNodesByCategory(category) {
1269
+ return MATERIAL_NODE_DEFINITIONS.filter(def => def.category === category);
1270
+ }
1271
+ /** Search nodes by name/description */
1272
+ function searchNodes(query) {
1273
+ const lowerQuery = query.toLowerCase();
1274
+ return MATERIAL_NODE_DEFINITIONS.filter(def => def.name.toLowerCase().includes(lowerQuery) ||
1275
+ def.description.toLowerCase().includes(lowerQuery) ||
1276
+ def.type.toLowerCase().includes(lowerQuery));
1277
+ }
1278
+
1279
+ export { MATERIAL_NODE_DEFINITIONS, MATERIAL_NODE_MAP, getNodesByCategory, searchNodes };
1280
+ //# sourceMappingURL=materialNodeDefinitions.js.map