Skip to content

Commit 25a9b6e

Browse files
committed
Blender 4.0 Support
1 parent ae47b8b commit 25a9b6e

File tree

4 files changed

+145
-61
lines changed

4 files changed

+145
-61
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import bpy
2+
3+
4+
def GetNodeTreeInputs(node_tree):
5+
# Blen 3
6+
if bpy.app.version[0] == 3:
7+
return node_tree.inputs.items()
8+
9+
# Blen 4
10+
else:
11+
inputs = []
12+
13+
for item in node_tree.interface.items_tree:
14+
if item.item_type == 'SOCKET':
15+
if item.in_out == 'INPUT':
16+
inputs.append(item)
17+
18+
return inputs
19+
20+
21+
def GetInputIdentifier(input):
22+
# Blen 3
23+
if bpy.app.version[0] == 3:
24+
return input[1].identifier
25+
26+
# Blen 4
27+
return input.identifier
28+
29+
30+
def GetInputType(input):
31+
# Blen 3
32+
if bpy.app.version[0] == 3:
33+
return input[1].type
34+
35+
# Blen 4
36+
else:
37+
input_class = str(type(input))
38+
39+
if "NodeTreeInterfaceSocketFloat" in str(type(input)):
40+
return "VALUE"
41+
elif isinstance(input, bpy.types.NodeTreeInterfaceSocketBool):
42+
return "BOOLEAN"
43+
elif isinstance(input, bpy.types.NodeTreeInterfaceSocketObject):
44+
return "OBJECT"
45+
elif isinstance(input, bpy.types.NodeTreeInterfaceSocketCollection):
46+
return "COLLECTION"
47+
elif isinstance(input, bpy.types.NodeTreeInterfaceSocketColor):
48+
return "RGBA"
49+
elif isinstance(input, bpy.types.NodeTreeInterfaceSocketImage):
50+
return "IMAGE"
51+
elif "NodeTreeInterfaceSocketInt" in str(type(input)):
52+
return "INT"
53+
elif isinstance(input, bpy.types.NodeTreeInterfaceSocketMaterial):
54+
return "MATERIAL"
55+
elif isinstance(input, bpy.types.NodeTreeInterfaceSocketString):
56+
return "STRING"
57+
elif "NodeTreeInterfaceSocketVector" in str(type(input)):
58+
return "VECTOR"
59+
60+
return "UNSUPPORTED_TYPE"
61+
62+
63+
def GetInputName(input):
64+
# Blen 3
65+
if bpy.app.version[0] == 3:
66+
return input[1].name
67+
68+
# Blen 4
69+
return input.name

BEngine-Py/bengine/Utils/BEUtils.py

Lines changed: 75 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414
from ..BESettings import BaseStuff, EngineType
1515
# from ..BEStartParams import StartParams
1616

17-
from . import BEGeoUtils
17+
from . import BEUtilsGeo
18+
from . import BEGNInputs
1819

1920

2021
def LoadJSON(bengineInputs_path: str):
@@ -43,58 +44,66 @@ def SaveJSON(gn_js_path, js_data):
4344
# Set GN/SV Default/Min/Max Values
4445
# input is either GNNodeInputs or SVNode
4546
def SetBaseInputValues(input_data, input, is_GN: bool):
47+
input_obj = input
48+
49+
# If Blen 3
50+
if bpy.app.version[0] == 3:
51+
if is_GN:
52+
input_obj = input[1]
53+
54+
4655
match input_data['Type']:
4756
case 'VALUE':
4857
if is_GN:
49-
input_data['DefaultValue'] = input[1].default_value
50-
# input_data['DefaultValue'] = numpy.float32(input[1].default_value)
58+
input_data['DefaultValue'] = input_obj.default_value
59+
# input_data['DefaultValue'] = numpy.float32(input_obj.default_value)
5160

52-
input_data['MinValue'] = input[1].min_value
53-
input_data['MaxValue'] = input[1].max_value
61+
input_data['MinValue'] = input_obj.min_value
62+
input_data['MaxValue'] = input_obj.max_value
5463

55-
# input_data['Value'] = geom_mod[input[1].identifier]
64+
# input_data['Value'] = geom_mod[input_obj.identifier]
5665
else:
57-
input_data['DefaultValue'] = input['BEFloatDefault']
58-
input_data['MinValue'] = input['BEFloatMin']
59-
input_data['MaxValue'] = input['BEFloatMax']
66+
input_data['DefaultValue'] = input_obj['BEFloatDefault']
67+
input_data['MinValue'] = input_obj['BEFloatMin']
68+
input_data['MaxValue'] = input_obj['BEFloatMax']
6069

6170
case 'INT':
6271
if is_GN:
63-
input_data['DefaultValue'] = input[1].default_value
64-
input_data['MinValue'] = input[1].min_value
65-
input_data['MaxValue'] = input[1].max_value
72+
input_data['DefaultValue'] = input_obj.default_value
73+
input_data['MinValue'] = input_obj.min_value
74+
input_data['MaxValue'] = input_obj.max_value
6675
else:
67-
input_data['DefaultValue'] = input['BEIntegerDefault']
68-
input_data['MinValue'] = input['BEIntegerMin']
69-
input_data['MaxValue'] = input['BEIntegerMax']
76+
input_data['DefaultValue'] = input_obj['BEIntegerDefault']
77+
input_data['MinValue'] = input_obj['BEIntegerMin']
78+
input_data['MaxValue'] = input_obj['BEIntegerMax']
7079

7180
case 'BOOLEAN':
7281
if is_GN:
73-
input_data['DefaultValue'] = input[1].default_value
82+
input_data['DefaultValue'] = input_obj.default_value
7483
else:
75-
input_data['DefaultValue'] = input['BEBooleanDefault']
84+
input_data['DefaultValue'] = input_obj['BEBooleanDefault']
7685

7786
case 'STRING':
7887
if is_GN:
79-
input_data['DefaultValue'] = input[1].default_value
88+
input_data['DefaultValue'] = input_obj.default_value
8089
else:
81-
input_data['DefaultValue'] = input['BEStringDefault']
90+
input_data['DefaultValue'] = input_obj['BEStringDefault']
8291

8392
case 'RGBA':
8493
if is_GN:
85-
input_data['DefaultValue'] = list(input[1].default_value)
94+
input_data['DefaultValue'] = list(input_obj.default_value)
8695
else:
87-
input_data['DefaultValue'] = list(input['BEColorDefault'])
96+
input_data['DefaultValue'] = list(input_obj['BEColorDefault'])
8897

8998
case 'VECTOR':
9099
if is_GN:
91-
input_data['DefaultValue'] = list(input[1].default_value)
92-
input_data['MinValue'] = input[1].min_value
93-
input_data['MaxValue'] = input[1].max_value
100+
input_data['DefaultValue'] = list(input_obj.default_value)
101+
input_data['MinValue'] = input_obj.min_value
102+
input_data['MaxValue'] = input_obj.max_value
94103
else:
95-
input_data['DefaultValue'] = list(input['BEVectorDefault'])
96-
input_data['DefaultValue'] = input['BEVectorMin']
97-
input_data['DefaultValue'] = input['BEVectorMax']
104+
input_data['DefaultValue'] = list(input_obj['BEVectorDefault'])
105+
input_data['DefaultValue'] = input_obj['BEVectorMin']
106+
input_data['DefaultValue'] = input_obj['BEVectorMax']
98107

99108

100109
def GetSVOutputObjects(node_tree):
@@ -180,11 +189,11 @@ def GetSVInputsData(node_group): # ADD IMAGE AND MATERIAL!!!!!!!!!!!!!!!!!!!!!
180189
def GetGNInputsData(node_group):
181190
gn_inputs_data = []
182191

183-
for input in node_group.inputs.items():
192+
for input in BEGNInputs.GetNodeTreeInputs(node_group):
184193
input_data = {}
185-
input_data['Type'] = input[1].type
186-
input_data['Name'] = input[1].name
187-
input_data['Identifier'] = input[1].identifier
194+
input_data['Type'] = BEGNInputs.GetInputType(input)
195+
input_data['Name'] = BEGNInputs.GetInputName(input)
196+
input_data['Identifier'] = BEGNInputs.GetInputIdentifier(input)
188197

189198
# Set Default/Min/Max Values
190199
SetBaseInputValues(input_data, input, True)
@@ -243,7 +252,7 @@ def SetupInputsFromJSON(context, node_tree, GN_mod, js_input_data,
243252
# GN - Inputs
244253
# SV - SVInputNodes
245254
if is_GN:
246-
input_items = node_tree.inputs.items()
255+
input_items = BEGNInputs.GetNodeTreeInputs(node_tree)
247256
else:
248257
input_items = GetSVInputNodes(node_tree)
249258

@@ -252,18 +261,22 @@ def SetupInputsFromJSON(context, node_tree, GN_mod, js_input_data,
252261
for input in input_items:
253262

254263
if is_GN:
255-
node_id = input[1].identifier
264+
node_id = BEGNInputs.GetInputIdentifier(input)
256265
else:
257266
node_id = input[1].node_id
258267

268+
# NEED TO DO THE SAME FOR SVERCHOK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
269+
input_name = BEGNInputs.GetInputName(input)
270+
input_type = BEGNInputs.GetInputType(input)
271+
259272
if node_id in js_inputs.keys():
260273

261274
# Check if the same type
262275
if is_GN:
263-
is_same_type = (input[1].type == js_inputs[node_id]["Type"])
276+
is_same_type = (input_type == js_inputs[node_id]["Type"])
264277

265278
if not is_same_type:
266-
print("!Input " + input[1].name + " is not the same type! " + input[1].type + " " + js_inputs[node_id]["Type"])
279+
print("!Input " + input_name + " is not the same type! " + input_type + " " + js_inputs[node_id]["Type"])
267280
continue
268281

269282
else:
@@ -281,10 +294,10 @@ def SetupInputsFromJSON(context, node_tree, GN_mod, js_input_data,
281294
match js_prop["Type"]:
282295
case "RGBA":
283296
if is_GN:
284-
GN_mod[input[1].identifier][0] = js_prop["Value"][0]
285-
GN_mod[input[1].identifier][1] = js_prop["Value"][1]
286-
GN_mod[input[1].identifier][2] = js_prop["Value"][2]
287-
GN_mod[input[1].identifier][3] = js_prop["Value"][3]
297+
GN_mod[node_id][0] = js_prop["Value"][0]
298+
GN_mod[node_id][1] = js_prop["Value"][1]
299+
GN_mod[node_id][2] = js_prop["Value"][2]
300+
GN_mod[node_id][3] = js_prop["Value"][3]
288301
else:
289302
input[1]['BEColor'][0] = js_prop["Value"][0]
290303
input[1]['BEColor'][1] = js_prop["Value"][1]
@@ -293,9 +306,9 @@ def SetupInputsFromJSON(context, node_tree, GN_mod, js_input_data,
293306

294307
case "VECTOR":
295308
if is_GN:
296-
GN_mod[input[1].identifier][0] = js_prop["Value"][0]
297-
GN_mod[input[1].identifier][1] = js_prop["Value"][1]
298-
GN_mod[input[1].identifier][2] = js_prop["Value"][2]
309+
GN_mod[node_id][0] = js_prop["Value"][0]
310+
GN_mod[node_id][1] = js_prop["Value"][1]
311+
GN_mod[node_id][2] = js_prop["Value"][2]
299312
else:
300313
input[1]['BEVector'][0] = js_prop["Value"][0]
301314
input[1]['BEVector'][1] = js_prop["Value"][1]
@@ -305,7 +318,7 @@ def SetupInputsFromJSON(context, node_tree, GN_mod, js_input_data,
305318
new_img = bpy.data.images.load(js_prop["Value"])
306319

307320
if is_GN:
308-
GN_mod[input[1].identifier] = new_img
321+
GN_mod[node_id] = new_img
309322

310323
# case "TEXTURE":
311324
# pass
@@ -314,7 +327,7 @@ def SetupInputsFromJSON(context, node_tree, GN_mod, js_input_data,
314327
mat = bpy.data.materials.new(name="BEMaterial")
315328

316329
if is_GN:
317-
GN_mod[input[1].identifier] = mat
330+
GN_mod[node_id] = mat
318331

319332
case "OBJECT":
320333
js_obj_val = js_prop["Value"]
@@ -343,7 +356,7 @@ def SetupInputsFromJSON(context, node_tree, GN_mod, js_input_data,
343356
context.collection.objects.link(be_objs[0])
344357

345358
if is_GN:
346-
GN_mod[input[1].identifier] = be_obj
359+
GN_mod[node_id] = be_obj
347360
else:
348361
input[1]['BEObject'] = be_obj.name
349362

@@ -361,42 +374,42 @@ def SetupInputsFromJSON(context, node_tree, GN_mod, js_input_data,
361374
be_coll.objects.link(obj)
362375

363376
if is_GN:
364-
GN_mod[input[1].identifier] = be_coll
377+
GN_mod[node_id] = be_coll
365378
else:
366379
input[1]['BECollection'] = be_coll.name
367380

368381
coll_idx += 1
369382

370383
case "VALUE":
371384
if is_GN:
372-
GN_mod[input[1].identifier] = float(js_prop["Value"])
385+
GN_mod[node_id] = float(js_prop["Value"])
373386
else:
374387
input[1]['BEFloat'] = float(js_prop["Value"])
375388

376389
case "INT":
377390
if is_GN:
378-
GN_mod[input[1].identifier] = js_prop["Value"]
391+
GN_mod[node_id] = js_prop["Value"]
379392
else:
380393
input[1]['BEInteger'] = js_prop["Value"]
381394

382395
case "STRING":
383396
if is_GN:
384-
GN_mod[input[1].identifier] = js_prop["Value"]
397+
GN_mod[node_id] = js_prop["Value"]
385398
else:
386399
input[1]['BEString'] = js_prop["Value"]
387400

388401
case "BOOLEAN":
389402
if is_GN:
390-
GN_mod[input[1].identifier] = js_prop["Value"]
403+
GN_mod[node_id] = js_prop["Value"]
391404
else:
392405
input[1]['BEBoolean'] = js_prop["Value"]
393406

394407
case default:
395408
if is_GN:
396-
GN_mod[input[1].identifier] = js_prop["Value"]
409+
GN_mod[node_id] = js_prop["Value"]
397410

398411
# else:
399-
# GN_mod[input[1].identifier] = prop_value
412+
# GN_mod[node_id] = prop_value
400413

401414

402415
def ParseObjectFromJSON(js_obj_val, js_input_data, instanced_meshes,
@@ -422,7 +435,7 @@ def ParseObjectFromJSON(js_obj_val, js_input_data, instanced_meshes,
422435
if "Mesh" in js_obj:
423436
if js_obj["Mesh"] not in instanced_meshes.keys():
424437
js_mesh = js_input_data["Meshes"][js_obj["Mesh"]]
425-
be_mesh = BEGeoUtils.MeshFromJSON(js_mesh, engine_type)
438+
be_mesh = BEUtilsGeo.MeshFromJSON(js_mesh, engine_type)
426439

427440
instanced_meshes[js_obj["Mesh"]] = be_mesh
428441
else:
@@ -435,17 +448,17 @@ def ParseObjectFromJSON(js_obj_val, js_input_data, instanced_meshes,
435448
# Import Curves
436449
if "Curves" in js_obj:
437450
if (convert_to_meshes):
438-
be_curves_data = BEGeoUtils.CurvesFromJSON(js_obj, engine_type, bool(1 - has_mesh))
451+
be_curves_data = BEUtilsGeo.CurvesFromJSON(js_obj, engine_type, bool(1 - has_mesh))
439452
else:
440-
be_curves_data = BEGeoUtils.CurvesFromJSON(js_obj, engine_type, True)
453+
be_curves_data = BEUtilsGeo.CurvesFromJSON(js_obj, engine_type, True)
441454

442455
be_curves_obj = ObjectFromJSON(js_obj, be_curves_data, engine_type, True)
443456

444457
be_objs.append(be_curves_obj)
445458

446459
# Import Terrain
447460
if "Terrain" in js_obj:
448-
be_terr_mesh = BEGeoUtils.TerrainMeshFromJSON(js_obj, engine_type)
461+
be_terr_mesh = BEUtilsGeo.TerrainMeshFromJSON(js_obj, engine_type)
449462
be_terr_obj = ObjectFromJSON(js_obj, be_terr_mesh, engine_type, False)
450463

451464
be_objs.append(be_terr_obj)
@@ -464,7 +477,7 @@ def ParseObjectFromJSON(js_obj_val, js_input_data, instanced_meshes,
464477

465478
if len(js_obj_val) > 1:
466479
if has_mesh:
467-
empty_mesh_data = BEGeoUtils.CreateEmptyMesh()
480+
empty_mesh_data = BEUtilsGeo.CreateEmptyMesh()
468481

469482
be_append_obj = bpy.data.objects.new(js_obj["Name"], empty_mesh_data)
470483
else:
@@ -542,7 +555,7 @@ def RecordObjectOutputToJSON(objects_sets_dict, the_object, is_instance: bool,
542555
# Get Mesh to JSON
543556
elif "Mesh" not in js_object_data.keys():
544557
if mesh not in meshes_tmp_set:
545-
js_mesh = BEGeoUtils.MeshToJSONData(mesh, engine_type)
558+
js_mesh = BEUtilsGeo.MeshToJSONData(mesh, engine_type)
546559
js_meshes.append(js_mesh)
547560

548561
js_object_data["Mesh"] = len(meshes_tmp_list)
@@ -572,7 +585,7 @@ def GetBlenderOutputs(context, process_objs: list, engine_type: EngineType, is_G
572585
# # GET MAIN MESH
573586
# if is_GN:
574587
# # GET MAIN MESH (FOR GN ONLY)!!!
575-
# main_mesh_dict = BEGeoUtils.MeshToJSONData(process_objs[0])
588+
# main_mesh_dict = BEUtilsGeo.MeshToJSONData(process_objs[0])
576589

577590
# # If the main mesh has Verts/Polygons
578591
# # Only one mesh at the moment
@@ -626,4 +639,6 @@ def SetRotationFromJSON(obj, js_euler, engine_type: EngineType):
626639
obj.rotation_euler = rot_XYZ
627640

628641
else:
629-
obj.rotation_euler = Euler(js_euler, 'XYZ')
642+
obj.rotation_euler = Euler(js_euler, 'XYZ')
643+
644+

0 commit comments

Comments
 (0)