Blender 5.0 - avoid using deprecated use_nodes

This commit is contained in:
Andrej730
2025-11-04 14:23:55 +05:00
parent 3bdfbebc02
commit d2126e5929
12 changed files with 58 additions and 30 deletions
@@ -455,7 +455,7 @@ class ActivateExternalStyle(bpy.types.Operator):
return {"CANCELLED"} return {"CANCELLED"}
self.copy_material_attributes(db["data_block"], material) self.copy_material_attributes(db["data_block"], material)
if material.use_nodes: if tool.Style.get_use_nodes(material):
tool.Blender.copy_node_graph(material, db["data_block"]) tool.Blender.copy_node_graph(material, db["data_block"])
bpy.data.materials.remove(db["data_block"]) bpy.data.materials.remove(db["data_block"])
return {"FINISHED"} return {"FINISHED"}
+2 -2
View File
@@ -786,7 +786,7 @@ class BIM_OT_add_section_plane(bpy.types.Operator):
material = bpy.data.materials.get("Section Override") material = bpy.data.materials.get("Section Override")
if not material: if not material:
material = bpy.data.materials.new("Section Override") material = bpy.data.materials.new("Section Override")
material.use_nodes = True tool.Style.set_use_nodes(material, True)
props = tool.Blender.get_bim_props() props = tool.Blender.get_bim_props()
if props.should_section_selected_objects: if props.should_section_selected_objects:
@@ -809,7 +809,7 @@ class BIM_OT_add_section_plane(bpy.types.Operator):
def override_materials(self): def override_materials(self):
override = bpy.data.node_groups.get("Section Override") override = bpy.data.node_groups.get("Section Override")
for material in bpy.data.materials: for material in bpy.data.materials:
material.use_nodes = True tool.Style.set_use_nodes(material, True)
if material.node_tree.nodes.get("Section Override"): if material.node_tree.nodes.get("Section Override"):
continue continue
# In EEVEE rendering engine, `blend_mode` is deprecated and replaced by `surface_render_method` # In EEVEE rendering engine, `blend_mode` is deprecated and replaced by `surface_render_method`
+2 -1
View File
@@ -100,6 +100,7 @@ class Blender(bonsai.core.tool.Blender):
- (identifier, name, description, icon, number) - (identifier, name, description, icon, number)
""" """
BLENDER_ENUM_ITEMS = Iterable[BLENDER_ENUM_ITEM] BLENDER_ENUM_ITEMS = Iterable[BLENDER_ENUM_ITEM]
BLENDER_5 = bpy.app.version >= (5, 0, 0)
@classmethod @classmethod
def activate_camera(cls, obj: bpy.types.Object) -> None: def activate_camera(cls, obj: bpy.types.Object) -> None:
@@ -416,7 +417,7 @@ class Blender(bonsai.core.tool.Blender):
cls, blender_material: bpy.types.Material, node_type: str, kwargs: Optional[dict] = {} cls, blender_material: bpy.types.Material, node_type: str, kwargs: Optional[dict] = {}
) -> Union[bpy.types.ShaderNode, None]: ) -> Union[bpy.types.ShaderNode, None]:
"""returns first node from the `blender_material` shader graph with type `node_type`""" """returns first node from the `blender_material` shader graph with type `node_type`"""
if not blender_material.use_nodes: if not tool.Style.get_use_nodes(blender_material):
return return
nodes = blender_material.node_tree.nodes nodes = blender_material.node_tree.nodes
for node in nodes: for node in nodes:
+2 -2
View File
@@ -1262,7 +1262,7 @@ class Geometry(bonsai.core.tool.Geometry):
if tool.Ifc.get().schema == "IFC2X3": if tool.Ifc.get().schema == "IFC2X3":
return False return False
for slot in obj.material_slots: for slot in obj.material_slots:
if slot.material and slot.material.use_nodes: if slot.material and tool.Style.get_use_nodes(slot.material):
for node in slot.material.node_tree.nodes: for node in slot.material.node_tree.nodes:
if node.type == "TEX_COORD" and node.outputs["UV"].links: if node.type == "TEX_COORD" and node.outputs["UV"].links:
return True return True
@@ -2021,7 +2021,7 @@ class Geometry(bonsai.core.tool.Geometry):
continue continue
if not (style := tool.Ifc.get_entity(material)): if not (style := tool.Ifc.get_entity(material)):
style = ifcopenshell.api.style.add_style(ifc_file, name=material.name) style = ifcopenshell.api.style.add_style(ifc_file, name=material.name)
if material.use_nodes: if tool.Style.get_use_nodes(material):
ifc_class = "IfcSurfaceStyleRendering" ifc_class = "IfcSurfaceStyleRendering"
attributes = tool.Style.get_surface_rendering_attributes(material) attributes = tool.Style.get_surface_rendering_attributes(material)
else: else:
+3 -3
View File
@@ -116,7 +116,7 @@ class Loader(bonsai.core.tool.Loader):
if transparency := surface_style.get("Transparency", None): if transparency := surface_style.get("Transparency", None):
alpha = 1 - transparency alpha = 1 - transparency
blender_material.diffuse_color = surface_style["SurfaceColour"] + (alpha,) blender_material.diffuse_color = surface_style["SurfaceColour"] + (alpha,)
blender_material.use_nodes = False tool.Style.set_use_nodes(blender_material, False)
@classmethod @classmethod
def restart_material_node_tree(cls, blender_material: bpy.types.Material) -> None: def restart_material_node_tree(cls, blender_material: bpy.types.Material) -> None:
@@ -204,7 +204,7 @@ class Loader(bonsai.core.tool.Loader):
# TODO: reset pins to default values if no values passed # TODO: reset pins to default values if no values passed
if reflectance_method in ["PHYSICAL", "NOTDEFINED"]: if reflectance_method in ["PHYSICAL", "NOTDEFINED"]:
blender_material.use_nodes = True tool.Style.set_use_nodes(blender_material, True)
cls.restart_material_node_tree(blender_material) cls.restart_material_node_tree(blender_material)
bsdf = tool.Blender.get_material_node(blender_material, "BSDF_PRINCIPLED") bsdf = tool.Blender.get_material_node(blender_material, "BSDF_PRINCIPLED")
assert bsdf assert bsdf
@@ -231,7 +231,7 @@ class Loader(bonsai.core.tool.Loader):
blender_material.blend_method = "BLEND" blender_material.blend_method = "BLEND"
elif reflectance_method == "FLAT": elif reflectance_method == "FLAT":
blender_material.use_nodes = True tool.Style.set_use_nodes(blender_material, True)
cls.restart_material_node_tree(blender_material) cls.restart_material_node_tree(blender_material)
output = tool.Blender.get_material_node(blender_material, "OUTPUT_MATERIAL") output = tool.Blender.get_material_node(blender_material, "OUTPUT_MATERIAL")
+1 -1
View File
@@ -1020,7 +1020,7 @@ class Sequence(bonsai.core.tool.Sequence):
def set_material(name, r, g, b): def set_material(name, r, g, b):
material = bpy.data.materials.new(name) material = bpy.data.materials.new(name)
material.use_nodes = True tool.Style.set_use_nodes(material, True)
tool.Blender.get_material_node(material, "BSDF_PRINCIPLED").inputs[0].default_value = (r, g, b, 1.0) tool.Blender.get_material_node(material, "BSDF_PRINCIPLED").inputs[0].default_value = (r, g, b, 1.0)
return material return material
+15 -1
View File
@@ -63,9 +63,23 @@ class Style(bonsai.core.tool.Style):
def get_material_style_props(cls, material: bpy.types.Material) -> BIMStyleProperties: def get_material_style_props(cls, material: bpy.types.Material) -> BIMStyleProperties:
return material.BIMStyleProperties return material.BIMStyleProperties
@classmethod
def get_use_nodes(cls, obj: bpy.types.Material) -> bool:
"""Since Blender 5.0 ``use_nodes`` are always ``True`` and considered deprecated."""
if tool.Blender.BLENDER_5:
return True
return obj.use_nodes
@classmethod
def set_use_nodes(cls, obj: bpy.types.Material, use_nodes: bool) -> None:
"""Since Blender 5.0 ``use_nodes`` are always ``True`` and considered deprecated."""
if tool.Blender.BLENDER_5:
return
obj.use_nodes = use_nodes
@classmethod @classmethod
def can_support_rendering_style(cls, obj: bpy.types.Material) -> bool: def can_support_rendering_style(cls, obj: bpy.types.Material) -> bool:
return obj.use_nodes and hasattr(obj.node_tree, "nodes") return tool.Blender.BLENDER_5 or (obj.use_nodes and hasattr(obj.node_tree, "nodes"))
@classmethod @classmethod
def delete_object(cls, obj: bpy.types.Material) -> None: def delete_object(cls, obj: bpy.types.Material) -> None:
@@ -89,10 +89,17 @@ class SectionCutawayManager:
SectionCutawayManager.offset_previous_nodes(previous_section_compare, offset_x, offset_y) SectionCutawayManager.offset_previous_nodes(previous_section_compare, offset_x, offset_y)
@staticmethod @staticmethod
def override_materials(): def set_use_nodes(obj: bpy.types.Material, use_nodes: bool) -> None:
if bpy.app.version >= (5, 0, 0):
# Since Blender 5.0 `use_nodes` are always `True` and considered deprecated.
return
obj.use_nodes = use_nodes
@classmethod
def override_materials(cls):
override = SectionCutawayManager.get_section_tree() override = SectionCutawayManager.get_section_tree()
for material in bpy.data.materials: for material in bpy.data.materials:
material.use_nodes = True cls.set_use_nodes(material, True)
if material.node_tree.nodes.get(override.name): if material.node_tree.nodes.get(override.name):
continue continue
material.blend_method = "HASHED" material.blend_method = "HASHED"
@@ -261,12 +268,12 @@ class SectionCutawayManager:
section_compare.name = "Last Section Compare" section_compare.name = "Last Section Compare"
@staticmethod @classmethod
def add_default_material_if_none_exists(context): def add_default_material_if_none_exists(cls, context):
material = bpy.data.materials.get("Section Override") material = bpy.data.materials.get("Section Override")
if not material: if not material:
material = bpy.data.materials.new("Section Override") material = bpy.data.materials.new("Section Override")
material.use_nodes = True cls.set_use_nodes(material, True)
if context.scene.SectionProperties.should_section_selected_objects: if context.scene.SectionProperties.should_section_selected_objects:
objects = list(context.selected_objects) objects = list(context.selected_objects)
+2 -2
View File
@@ -37,7 +37,7 @@ class TestImplementsTool(NewFile):
class TestCopyNodeGraph(NewFile): class TestCopyNodeGraph(NewFile):
def test_run(self): def test_run(self):
material_to = bpy.data.materials.new("material_to") material_to = bpy.data.materials.new("material_to")
material_to.use_nodes = True tool.Style.set_use_nodes(material_to, True)
assert material_to.node_tree assert material_to.node_tree
material_to_nodes = material_to.node_tree.nodes material_to_nodes = material_to.node_tree.nodes
assert len(material_to_nodes) == 2 assert len(material_to_nodes) == 2
@@ -46,7 +46,7 @@ class TestCopyNodeGraph(NewFile):
assert len(material_to_nodes) == 0 assert len(material_to_nodes) == 0
material_from = bpy.data.materials.new("material_from") material_from = bpy.data.materials.new("material_from")
material_from.use_nodes = True tool.Style.set_use_nodes(material_from, True)
subject.copy_node_graph(material_to, material_from) subject.copy_node_graph(material_to, material_from)
assert len(material_to_nodes) == 2 assert len(material_to_nodes) == 2
+3 -3
View File
@@ -488,7 +488,7 @@ class TestShouldGenerateUVs(NewFile):
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh")) obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
material = bpy.data.materials.new("Material") material = bpy.data.materials.new("Material")
obj.data.materials.append(material) obj.data.materials.append(material)
material.use_nodes = False tool.Style.set_use_nodes(material, False)
assert subject.should_generate_uvs(obj) is False assert subject.should_generate_uvs(obj) is False
def test_needs_texture_coordinates_with_a_uv_output(self): def test_needs_texture_coordinates_with_a_uv_output(self):
@@ -497,7 +497,7 @@ class TestShouldGenerateUVs(NewFile):
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh")) obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
material = bpy.data.materials.new("Material") material = bpy.data.materials.new("Material")
obj.data.materials.append(material) obj.data.materials.append(material)
material.use_nodes = True tool.Style.set_use_nodes(material, True)
bsdf = tool.Blender.get_material_node(material, "BSDF_PRINCIPLED") bsdf = tool.Blender.get_material_node(material, "BSDF_PRINCIPLED")
node = material.node_tree.nodes.new(type="ShaderNodeTexImage") node = material.node_tree.nodes.new(type="ShaderNodeTexImage")
@@ -513,7 +513,7 @@ class TestShouldGenerateUVs(NewFile):
obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh")) obj = bpy.data.objects.new("Object", bpy.data.meshes.new("Mesh"))
material = bpy.data.materials.new("Material") material = bpy.data.materials.new("Material")
obj.data.materials.append(material) obj.data.materials.append(material)
material.use_nodes = True tool.Style.set_use_nodes(material, True)
bsdf = tool.Blender.get_material_node(material, "BSDF_PRINCIPLED") bsdf = tool.Blender.get_material_node(material, "BSDF_PRINCIPLED")
node = material.node_tree.nodes.new(type="ShaderNodeTexImage") node = material.node_tree.nodes.new(type="ShaderNodeTexImage")
+13 -8
View File
@@ -22,6 +22,7 @@ import ifcopenshell
import ifcopenshell.api import ifcopenshell.api
import ifcopenshell.api.root import ifcopenshell.api.root
import ifcopenshell.util.representation import ifcopenshell.util.representation
import pytest
import bonsai.core.tool import bonsai.core.tool
import bonsai.tool as tool import bonsai.tool as tool
from test.bim.bootstrap import NewFile from test.bim.bootstrap import NewFile
@@ -37,12 +38,16 @@ class TestImplementsTool(NewFile):
class TestCanSupportRenderingStyle(NewFile): class TestCanSupportRenderingStyle(NewFile):
def test_anything_with_nodes_can_support_a_rendering_style(self): def test_anything_with_nodes_can_support_a_rendering_style(self):
obj = bpy.data.materials.new("Material") obj = bpy.data.materials.new("Material")
obj.use_nodes = True tool.Style.set_use_nodes(obj, True)
assert subject.can_support_rendering_style(obj) is True assert subject.can_support_rendering_style(obj) is True
@pytest.mark.skipif(
tool.Blender.BLENDER_5,
reason="Since Blender 5.0 `use_nodes` are always `True` and deprecated.",
)
def test_without_nodes_we_do_not_support_rendering(self): def test_without_nodes_we_do_not_support_rendering(self):
obj = bpy.data.materials.new("Material") obj = bpy.data.materials.new("Material")
obj.use_nodes = False tool.Style.set_use_nodes(obj, False)
assert subject.can_support_rendering_style(obj) is False assert subject.can_support_rendering_style(obj) is False
@@ -125,7 +130,7 @@ class TestGetSurfaceRenderingAttributes(NewFile):
def test_get_different_surface_and_diffuse_colours_from_a_principled_bsdf(self): def test_get_different_surface_and_diffuse_colours_from_a_principled_bsdf(self):
obj = bpy.data.materials.new("Material") obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1] obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True tool.Style.set_use_nodes(obj, True)
node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED") node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED")
assert node assert node
node.inputs["Alpha"].default_value = 0.8 node.inputs["Alpha"].default_value = 0.8
@@ -153,7 +158,7 @@ class TestGetSurfaceRenderingAttributes(NewFile):
def test_get_rendering_styles_from_a_glossy_bsdf(self): def test_get_rendering_styles_from_a_glossy_bsdf(self):
obj = bpy.data.materials.new("Material") obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1] obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True tool.Style.set_use_nodes(obj, True)
output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL") output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL")
node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED") node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED")
assert obj.node_tree and node assert obj.node_tree and node
@@ -185,7 +190,7 @@ class TestGetSurfaceRenderingAttributes(NewFile):
def test_get_rendering_styles_from_a_diffuse_bsdf(self): def test_get_rendering_styles_from_a_diffuse_bsdf(self):
obj = bpy.data.materials.new("Material") obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1] obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True tool.Style.set_use_nodes(obj, True)
output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL") output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL")
node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED") node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED")
assert obj.node_tree and node and output assert obj.node_tree and node and output
@@ -217,7 +222,7 @@ class TestGetSurfaceRenderingAttributes(NewFile):
def test_get_rendering_styles_from_a_glass_bsdf(self): def test_get_rendering_styles_from_a_glass_bsdf(self):
obj = bpy.data.materials.new("Material") obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1] obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True tool.Style.set_use_nodes(obj, True)
output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL") output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL")
node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED") node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED")
assert obj.node_tree and node and output assert obj.node_tree and node and output
@@ -249,7 +254,7 @@ class TestGetSurfaceRenderingAttributes(NewFile):
def test_get_rendering_styles_from_a_emission_bsdf(self): def test_get_rendering_styles_from_a_emission_bsdf(self):
obj = bpy.data.materials.new("Material") obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1] obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True tool.Style.set_use_nodes(obj, True)
output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL") output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL")
node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED") node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED")
assert obj.node_tree and node and output assert obj.node_tree and node and output
@@ -280,7 +285,7 @@ class TestGetSurfaceRenderingAttributes(NewFile):
def test_other_unsupported_bsdfs_copy_the_rendering_style_from_the_shading_colours_as_a_fallback(self): def test_other_unsupported_bsdfs_copy_the_rendering_style_from_the_shading_colours_as_a_fallback(self):
obj = bpy.data.materials.new("Material") obj = bpy.data.materials.new("Material")
obj.diffuse_color = [1, 1, 1, 1] obj.diffuse_color = [1, 1, 1, 1]
obj.use_nodes = True tool.Style.set_use_nodes(obj, True)
output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL") output = tool.Blender.get_material_node(obj, "OUTPUT_MATERIAL")
node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED") node = tool.Blender.get_material_node(obj, "BSDF_PRINCIPLED")
assert obj.node_tree and node and output assert obj.node_tree and node and output
@@ -176,7 +176,8 @@ def import_ifc(filename, use_names, process_relations, blender_booleans):
mat.blend_method = "HASHED" mat.blend_method = "HASHED"
mat.use_screen_refraction = True mat.use_screen_refraction = True
mat.refraction_depth = 0.1 mat.refraction_depth = 0.1
mat.use_nodes = True if bpy.app.version >= (5, 0, 0):
mat.use_nodes = True
bsdf = next(n for n in mat.node_tree.nodes if n.type == "BSDF_PRINCIPLED") bsdf = next(n for n in mat.node_tree.nodes if n.type == "BSDF_PRINCIPLED")
bsdf.inputs[15].default_value = v bsdf.inputs[15].default_value = v
else: else: