3131 'NodeSocketTexture' ,
3232 'NodeSocketVirtual' }
3333
34+ node_settings = {
35+ #attribute
36+ "GeometryNodeAttributeStatistic" : ["data_type" , "domain" ],
37+ "GeometryNodeCaptureAttribute" : ["data_type" , "domain" ],
38+ "GeometryNodeAttributeDomainSize" : ["component" ],
39+ "GeometryNodeStoreNamedAttribute" : ["data_type" , "domain" ],
40+ "GeometryNodeAttributeTransfer" : ["data_type" , "mapping" ],
41+
42+ #color
43+ "ShaderNodeMixRGB" : ["blend_type" , "use_clamp" ],
44+
45+ #curve
46+ "GeometryNodeCurveToPoints" : ["mode" ],
47+ "GeometryNodeFillCurve" : ["mode" ],
48+ "GeometryNodeFilletCurve" : ["mode" ],
49+ "GeometryNodeResampleCurve" : ["mode" ],
50+ "GeometryNodeSampleCurve" : ["mode" ],
51+ "GeometryNodeTrimCurve" : ["mode" ],
52+ "GeometryNodeCurveHandleTypeSelection" : ["mode" , "handle_type" ],
53+ "GeometryNodeSetCurveHandlePositions" : ["mode" ],
54+ "GeometryNodeCurveSetHandles" : ["mode" , "handle_type" ],
55+ "GeometryNodeCurveSplineType" : ["spline_type" ],
56+
57+ #curve primitives
58+ "GeometryNodeCurveArc" : ["mode" ],
59+ "GeometryNodeCurvePrimitiveBezierSegment" : ["mode" ],
60+ "GeometryNodeCurvePrimitiveCircle" : ["mode" ],
61+ "GeometryNodeCurvePrimitiveLine" : ["mode" ],
62+ "GeometryNodeCurvePrimitiveQuadrilateral" : ["mode" ],
63+
64+ #geometry
65+ "GeometryNodeDeleteGeometry" : ["domain" , "mode" ],
66+ "GeometryNodeDuplicateElements" : ["domain" ],
67+ "GeometryNodeProximity" : ["target_element" ],
68+ "GeometryNodeMergeByDistance" : ["mode" ],
69+ "GeometryNodeRaycast" : ["data_type" , "mapping" ],
70+ "GeometryNodeSeparateGeometry" : ["domain" ],
71+
72+ #input
73+ "GeometryNodeCollectionInfo" : ["transform_space" ],
74+ "GeometryNodeObjectInfo" : ["transform_space" ],
75+ "GeometryNodeInputNamedAttribute" : ["data_type" ],
76+
77+ #mesh
78+ "GeometryNodeExtrudeMesh" : ["mode" ],
79+ "GeometryNodeMeshBoolean" : ["operation" ],
80+ "GeometryNodeMeshToPoints" : ["mode" ],
81+ "GeometryNodeSubdivisionSurface" : ["uv_smooth" , "boundary_smooth" ],
82+ "GeometryNodeTriangulate" : ["quad_method" , "ngon_method" ],
83+ "GeometryNodeScaleElements" : ["domain" , "scale_mode" ],
84+
85+ #mesh primitives
86+ "GeometryNodeMeshCone" : ["fill_type" ],
87+ "GeometryNodeMeshCylinder" : ["fill_type" ],
88+ "GeometryNodeMeshCircle" : ["fill_type" ],
89+ "GeometryNodeMeshLine" : ["mode" ],
90+
91+ #point
92+ "GeometryNodeDistributePointsOnFaces" : ["distribute_method" ],
93+ "GeometryNodePointsToVolume" : ["resolution_mode" ],
94+
95+ #text
96+ "GeometryNodeStringToCurves" : ["overflow" , "align_x" , "align_y" ,
97+ "pivot_mode" ],
98+
99+ #texture
100+ "ShaderNodeTexBrick" : ["offset" , "offset_frequency" , "squash" ,
101+ "squash_frequency" ],
102+ "ShaderNodeTexGradient" : ["gradient_type" ],
103+ "GeometryNodeImageTexture" : ["interpolation" , "extension" ],
104+ "ShaderNodeTexMagic" : ["turbulence_depth" ],
105+ "ShaderNodeTexNoise" : ["noise_dimensions" ],
106+ "ShaderNodeTexVoronoi" : ["voronoi_dimensions" , "feature" , "distance" ],
107+ "ShaderNodeTexWave" : ["wave_type" , "bands_direction" , "wave_profile" ],
108+ "ShaderNodeTexWhiteNoise" : ["noise_dimensions" ],
109+
110+ #utilities
111+ "GeometryNodeAccumulateField" : ["data_type" , "domain" ],
112+ "FunctionNodeAlignEulerToVector" : ["axis" , "pivot_axis" ],
113+ "FunctionNodeBooleanMath" : ["operation" ],
114+ "ShaderNodeClamp" : ["clamp_type" ],
115+ "FunctionNodeCompare" : ["data_type" , "operation" , "mode" ],
116+ "GeometryNodeFieldAtIndex" : ["data_type" , "domain" ],
117+ "FunctionNodeFloatToInt" : ["rounding_mode" ],
118+ "ShaderNodeMapRange" : ["data_type" , "interpolation_type" , "clamp" ],
119+ "ShaderNodeMath" : ["operation" , "use_clamp" ],
120+ "FunctionNodeRandomValue" : ["data_type" ],
121+ "FunctionNodeRotateEuler" : ["type" , "space" ],
122+ "GeometryNodeSwitch" : ["input_type" ],
123+
124+ #vector
125+ "ShaderNodeVectorMath" : ["operation" ],
126+ "ShaderNodeVectorRotate" : ["rotation_type" , "invert" ],
127+
128+ #volume
129+ "GeometryNodeVolumeToMesh" : ["resolution_mode" ]
130+ }
131+
34132class NodeToPython (bpy .types .Operator ):
35133 bl_idname = "object.node_to_python"
36134 bl_label = "Node to Python"
@@ -82,10 +180,10 @@ def process_node_group(node_group, level):
82180 #initialize node group
83181 file .write (f"{ outer } #initialize { ng_name } node group\n " )
84182 file .write (f"{ outer } def { ng_name } _node_group():\n " )
85- file .write (f"{ inner } { ng_name } " +
86- f"= bpy.data.node_groups.new(" +
87- f"type = \" GeometryNodeTree\" ," +
88- f"name = \" { node_group .name } \" )\n " )
183+ file .write (( f"{ inner } { ng_name } "
184+ f"= bpy.data.node_groups.new("
185+ f"type = \" GeometryNodeTree\" , "
186+ f"name = \" { node_group .name } \" )\n " ) )
89187 file .write ("\n " )
90188
91189 #initialize nodes
@@ -98,8 +196,9 @@ def process_node_group(node_group, level):
98196 for input in node .outputs :
99197 if input .bl_idname != "NodeSocketVirtual" :
100198 file .write (f"{ inner } #input { input .name } \n " )
101- file .write (f"{ inner } { ng_name } .inputs.new" +
102- f"(\" { input .bl_idname } \" , \" { input .name } \" )\n " )
199+ file .write ((f"{ inner } { ng_name } .inputs.new"
200+ f"(\" { input .bl_idname } \" , "
201+ f"\" { input .name } \" )\n " ))
103202 if input .bl_idname in default_sockets :
104203 socket = node_group .inputs [input .name ]
105204 if input .bl_idname == 'NodeSocketColor' :
@@ -113,76 +212,79 @@ def process_node_group(node_group, level):
113212 dv = socket .default_value
114213
115214 #default value
116- file .write (f"{ inner } { ng_name } " +
117- f".inputs[\" { input .name } \" ]" +
118- f".default_value = { dv } \n " )
215+ file .write (( f"{ inner } { ng_name } "
216+ f".inputs[\" { input .name } \" ]"
217+ f".default_value = { dv } \n " ) )
119218 if input .bl_idname in value_sockets :
120219 #min value
121- file .write (f"{ inner } { ng_name } " +
122- f".inputs[\" { input .name } \" ]" +
123- f".min_value = " +
124- f"{ socket .min_value } \n " )
220+ file .write (( f"{ inner } { ng_name } "
221+ f".inputs[\" { input .name } \" ]"
222+ f".min_value = "
223+ f"{ socket .min_value } \n " ) )
125224 #max value
126- file .write (f"{ inner } { ng_name } " +
127- f".inputs[\" { input .name } \" ]" +
128- f".max_value = " +
129- f"{ socket .max_value } \n " )
225+ file .write (( f"{ inner } { ng_name } "
226+ f".inputs[\" { input .name } \" ]"
227+ f".max_value = "
228+ f"{ socket .max_value } \n " ) )
130229 file .write ("\n " )
131230 file .write ("\n " )
132231 elif node .bl_idname == 'NodeGroupOutput' :
133232 file .write (f"{ inner } #{ ng_name } outputs\n " )
134233 for output in node .inputs :
135234 if output .bl_idname != 'NodeSocketVirtual' :
136- file .write (f"{ inner } { ng_name } .outputs" +
137- f".new(\" { output .bl_idname } \" , " +
138- f"\" { output .name } \" )\n " )
235+ file .write (( f"{ inner } { ng_name } .outputs"
236+ f".new(\" { output .bl_idname } \" , "
237+ f"\" { output .name } \" )\n " ) )
139238 file .write ("\n " )
140239
141240 #create node
142241 node_name = node .name .lower ()
143242 node_name = node_name .replace (' ' , '_' ).replace ('.' , '_' )
144243 file .write (f"{ inner } #node { node .name } \n " )
145- file .write (f"{ inner } { node_name } " +
146- f"= { ng_name } .nodes.new(\" { node .bl_idname } \" )\n " )
147- file .write (f"{ inner } { node_name } .location " +
148- f"= ({ node .location .x } , { node .location .y } )\n " )
149- file .write (f"{ inner } { node_name } .width, { node_name } .height " +
150- f"= { node .width } , { node .height } \n " )
244+ file .write (( f"{ inner } { node_name } "
245+ f"= { ng_name } .nodes.new(\" { node .bl_idname } \" )\n " ) )
246+ file .write (( f"{ inner } { node_name } .location "
247+ f"= ({ node .location .x } , { node .location .y } )\n " ) )
248+ file .write (( f"{ inner } { node_name } .width, { node_name } .height "
249+ f"= { node .width } , { node .height } \n " ) )
151250 if node .label :
152251 file .write (f"{ inner } { node_name } .label = \" { node .label } \" \n " )
153252
154253 #special nodes
155- """
156- NTS: these aren't special
157- pretty much every node has something similar
158- you're gonna need to make some sort of dictionary with all
159- the different quirky features for each node.
160- """
161- if node .bl_idname == 'GeometryNodeGroup' :
162- file .write (f"{ inner } { node_name } .node_tree = " +
163- f"bpy.data.node_groups" +
164- f"[\" { node .node_tree .name } \" ]\n " )
254+ print (node .bl_idname )
255+ if node .bl_idname in node_settings :
256+ for setting in node_settings [node .bl_idname ]:
257+ print (type (getattr (node , setting )))
258+ attr = getattr (node , setting )
259+ if type (attr ) == str :
260+ attr = f"\' { attr } \' "
261+ file .write ((f"{ inner } { node_name } .{ setting } = "
262+ f"{ attr } \n " ))
263+ elif node .bl_idname == 'GeometryNodeGroup' :
264+ file .write ((f"{ inner } { node_name } .node_tree = "
265+ f"bpy.data.node_groups"
266+ f"[\" { node .node_tree .name } \" ]\n " ))
165267 elif node .bl_idname == 'ShaderNodeValToRGB' :
166268 color_ramp = node .color_ramp
167269 file .write ("\n " )
168- file .write (f"{ inner } { node_name } .color_ramp.color_mode = " +
169- f"\' { color_ramp .color_mode } \' \n " )
170- file .write (f"{ inner } { node_name } .color_ramp" +
171- f".hue_interpolation = " +
172- f"\' { color_ramp .hue_interpolation } \' \n " )
173- file .write (f"{ inner } { node_name } .color_ramp.interpolation" +
174- f" = '{ color_ramp .interpolation } '\n " )
270+ file .write (( f"{ inner } { node_name } .color_ramp.color_mode = "
271+ f"\' { color_ramp .color_mode } \' \n " ) )
272+ file .write (( f"{ inner } { node_name } .color_ramp"
273+ f".hue_interpolation = "
274+ f"\' { color_ramp .hue_interpolation } \' \n " ) )
275+ file .write (( f"{ inner } { node_name } .color_ramp.interpolation "
276+ f" = '{ color_ramp .interpolation } '\n ") )
175277 file .write ("\n " )
176278 for i , element in enumerate (color_ramp .elements ):
177- file .write (f"{ inner } { node_name } _cre_{ i } = " +
178- f"{ node_name } .color_ramp.elements" +
179- f".new({ element .position } )\n " )
180- file .write (f"{ inner } { node_name } _cre_{ i } .alpha = " +
181- f"{ element .alpha } \n " )
279+ file .write (( f"{ inner } { node_name } _cre_{ i } = "
280+ f"{ node_name } .color_ramp.elements"
281+ f".new({ element .position } )\n " ) )
282+ file .write (( f"{ inner } { node_name } _cre_{ i } .alpha = "
283+ f"{ element .alpha } \n " ) )
182284 col = element .color
183285 r , g , b , a = col [0 ], col [1 ], col [2 ], col [3 ]
184- file .write (f"{ inner } { node_name } _cre_{ i } .color = " +
185- f"({ r } , { g } , { b } , { a } )\n \n " )
286+ file .write (( f"{ inner } { node_name } _cre_{ i } .color = "
287+ f"({ r } , { g } , { b } , { a } )\n \n " ) )
186288
187289 for input in node .inputs :
188290 if input .bl_idname not in dont_set_defaults :
@@ -197,13 +299,11 @@ def process_node_group(node_group, level):
197299 else :
198300 dv = input .default_value
199301 if dv is not None :
200- file .write (f"{ inner } { node_name } " +
201- f".inputs[\" { input .name } \" ]" +
202- f".default_value = { dv } \n " )
203-
302+ file .write ((f"{ inner } { node_name } "
303+ f".inputs[\" { input .name } \" ]"
304+ f".default_value = { dv } \n " ))
204305 file .write ("\n " )
205306
206-
207307 #initialize links
208308 if node_group .links :
209309 file .write (f"{ inner } #initialize { ng_name } links\n " )
@@ -214,9 +314,9 @@ def process_node_group(node_group, level):
214314 output_node = link .to_node .name .lower ().replace (' ' , '_' )
215315 output_socket = link .to_socket .name
216316
217- file .write (f"{ inner } { ng_name } .links.new({ input_node } " +
218- f".outputs[\" { input_socket } \" ], " +
219- f"{ output_node } .inputs[\" { output_socket } \" ])\n " )
317+ file .write (( f"{ inner } { ng_name } .links.new({ input_node } "
318+ f".outputs[\" { input_socket } \" ], "
319+ f"{ output_node } .inputs[\" { output_socket } \" ])\n " ) )
220320
221321 #create node group
222322 file .write ("\n " )
0 commit comments