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