From 1b4daf9d2e081562df7898a253d899adf503d402 Mon Sep 17 00:00:00 2001 From: Habib Gahbiche Date: Sun, 14 Sep 2025 17:53:54 +0200 Subject: [PATCH] Nodes: remove "Use Nodes" in Shader Editor for Object Materials "Use Nodes" was removed in the compositor to simplify the compositing workflow. This introduced a slight inconsistency with the Shader Node Editor. This PR removes "Use Nodes" for object materials. For Line Style, no changes are planned (not sure how to preserve compatibility yet). This simplifies the state of objects; either they have a material or they don't. Backward compatibility: - If Use Nodes is turned Off, new nodes are added to the node tree to simulate the same material: - DNA: Only `use_nodes` is marked deprecated - Python API: - `material.use_nodes` is marked deprecated and will be removed in 6.0. Reading it always returns `True` and setting it has no effect. - `material.diffuse_color`, `material.specular` etc.. Are not used by EEVEE anymore but are kept because they are used by Workbench. Forward compatibility: Always enable 'Use Nodes' when writing blend files. Known Issues: Some UI tests are failing on macOS Pull Request: https://projects.blender.org/blender/blender/pulls/141278 --- doc/python_api/examples/bpy.types.USDHook.py | 10 +- intern/cycles/blender/addon/operators.py | 8 +- intern/cycles/blender/addon/ui.py | 5 +- intern/cycles/blender/shader.cpp | 2 +- release/datafiles/blender_icons_geom.py | 2 +- .../addons_core/io_curve_svg/import_svg.py | 7 +- .../addons_core/io_scene_fbx/import_fbx.py | 2 +- .../modules/bpy_extras/node_shader_utils.py | 92 +++++-------- .../startup/bl_operators/image_as_planes.py | 4 +- .../bl_operators/object_quick_effects.py | 19 +-- scripts/startup/bl_operators/world.py | 5 +- scripts/startup/bl_ui/properties_material.py | 18 +-- scripts/startup/bl_ui/space_node.py | 15 +- .../blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/intern/image.cc | 2 +- source/blender/blenkernel/intern/material.cc | 6 +- .../blenloader/intern/versioning_500.cc | 128 ++++++++++++++++++ .../draw/engines/eevee/eevee_material.cc | 54 +------- .../draw/engines/eevee/eevee_material.hh | 29 ---- .../blender/editors/render/render_shading.cc | 2 - .../editors/sculpt_paint/paint_image_proj.cc | 2 - .../blender/editors/space_node/node_edit.cc | 4 +- source/blender/editors/uvedit/uvedit_ops.cc | 4 +- .../BlenderStrokeRenderer.cpp | 1 - .../io/fbx/importer/fbx_import_material.cc | 1 - .../io/usd/intern/usd_reader_material.cc | 14 +- .../io/usd/intern/usd_writer_material.cc | 4 +- .../wavefront_obj/importer/obj_import_mesh.cc | 1 - source/blender/makesdna/DNA_material_types.h | 2 +- .../blender/makesrna/intern/rna_main_api.cc | 9 +- .../blender/makesrna/intern/rna_material.cc | 26 ++-- .../nodes/shader/materialx/material.cc | 31 ++--- .../io_tests/blend_scene/all_objects.blend | 4 +- .../fbx/bl_cube_material_viewport_display.fbx | 3 + .../bl_cube_material_viewport_display.txt | 54 ++++++++ tests/files/io_tests/obj/all_objects.mtl | 14 +- .../io_tests/obj/all_objects_mat_groups.mtl | 14 +- .../io_tests/obj/reference/all_objects.txt | 14 +- .../obj/reference/all_objects_mat_groups.txt | 14 +- tests/python/bl_blendfile_utils.py | 5 +- tests/python/bl_node_group_interface.py | 2 - tests/python/bl_usd_export_test.py | 5 +- tests/python/bl_usd_import_test.py | 9 +- tools/utils_doc/code_layout_diagram.py | 11 +- 44 files changed, 363 insertions(+), 297 deletions(-) create mode 100644 tests/files/io_tests/fbx/bl_cube_material_viewport_display.fbx create mode 100644 tests/files/io_tests/fbx/reference/bl_cube_material_viewport_display.txt diff --git a/doc/python_api/examples/bpy.types.USDHook.py b/doc/python_api/examples/bpy.types.USDHook.py index 2edac15673e..27374ee4d47 100644 --- a/doc/python_api/examples/bpy.types.USDHook.py +++ b/doc/python_api/examples/bpy.types.USDHook.py @@ -320,11 +320,11 @@ class USDHookExample(bpy.types.USDHook): return False # Create the node tree - bl_material.use_nodes = True - node_tree = bl_material.node_tree - nodes = node_tree.nodes - bsdf = nodes.get("Principled BSDF") - assert bsdf + nodes = bl_material.node_tree.nodes + output = nodes.new(type="ShaderNodeOutputMaterial") + bsdf = nodes.new(type="ShaderNodeBsdfPrincipled") + bsdf.location[0] -= 1.5 * bsdf.width + bl_material.node_tree.links.new(output.inputs["Surface"], bsdf.outputs["BSDF"]) bsdf_base_color_input = bsdf.inputs['Base Color'] # Try to set the default color value. diff --git a/intern/cycles/blender/addon/operators.py b/intern/cycles/blender/addon/operators.py index fcedb488b7f..40237380f8a 100644 --- a/intern/cycles/blender/addon/operators.py +++ b/intern/cycles/blender/addon/operators.py @@ -12,18 +12,16 @@ from bpy.app.translations import pgettext_tip as tip_ class CYCLES_OT_use_shading_nodes(Operator): - """Enable nodes on a material or light""" + """Enable nodes on a light""" bl_idname = "cycles.use_shading_nodes" bl_label = "Use Nodes" @classmethod def poll(cls, context): - return (getattr(context, "material", False) or getattr(context, "light", False)) + return getattr(context, "light", False) def execute(self, context): - if context.material: - context.material.use_nodes = True - elif context.light: + if context.light: context.light.use_nodes = True return {'FINISHED'} diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 9362d8f8d34..3549067a5e1 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1475,12 +1475,15 @@ class CYCLES_OBJECT_PT_visibility_culling(CyclesButtonsPanel, Panel): def panel_node_draw(layout, id_data, output_type, input_name): from bpy_extras.node_utils import find_node_input - if output_type != 'OUTPUT_WORLD' and not id_data.use_nodes: + if output_type not in ('OUTPUT_WORLD', 'OUTPUT_MATERIAL') and not id_data.use_nodes: layout.operator("cycles.use_shading_nodes", icon='NODETREE') return False ntree = id_data.node_tree + if ntree is None: + return False + node = ntree.get_output_node('CYCLES') if node: input = find_node_input(node, input_name) diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp index 7ad750ba644..08a45b9f68b 100644 --- a/intern/cycles/blender/shader.cpp +++ b/intern/cycles/blender/shader.cpp @@ -1594,7 +1594,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all) shader->set_pass_id(b_mat.pass_index()); /* create nodes */ - if (b_mat.use_nodes() && b_mat.node_tree()) { + if (b_mat.node_tree()) { BL::ShaderNodeTree b_ntree(b_mat.node_tree()); add_nodes(scene, b_engine, b_data, b_scene, graph.get(), b_ntree); diff --git a/release/datafiles/blender_icons_geom.py b/release/datafiles/blender_icons_geom.py index 8c8a674cab0..b832a40657a 100644 --- a/release/datafiles/blender_icons_geom.py +++ b/release/datafiles/blender_icons_geom.py @@ -94,7 +94,7 @@ def object_material_colors(ob): for slot in ob.material_slots: material = slot.material color = color_default - if material is not None and material.use_nodes: + if material is not None: node_tree = material.node_tree if node_tree is not None: color = next(( diff --git a/scripts/addons_core/io_curve_svg/import_svg.py b/scripts/addons_core/io_curve_svg/import_svg.py index 0b2fe00e1e0..8d475271c93 100644 --- a/scripts/addons_core/io_curve_svg/import_svg.py +++ b/scripts/addons_core/io_curve_svg/import_svg.py @@ -207,7 +207,12 @@ def SVGGetMaterial(color, context): return materials[color] mat = bpy.data.materials.new(name='SVGMat') - mat.diffuse_color = (*diffuse_color, 1.0) + node_tree = mat.node_tree + bsdf = node_tree.nodes.new("ShaderNodeBsdfDiffuse") + output = node_tree.nodes.new("ShaderNodeOutputMaterial") + output.location[0] += bsdf.width + 20.0 + node_tree.links.new(bsdf.outputs["BSDF"], output.inputs["Surface"]) + bsdf.inputs["Color"].default_value = (*diffuse_color, 0.0) materials[color] = mat diff --git a/scripts/addons_core/io_scene_fbx/import_fbx.py b/scripts/addons_core/io_scene_fbx/import_fbx.py index 4525d3790f9..9f688620b37 100644 --- a/scripts/addons_core/io_scene_fbx/import_fbx.py +++ b/scripts/addons_core/io_scene_fbx/import_fbx.py @@ -2064,7 +2064,7 @@ def blen_read_material(fbx_tmpl, fbx_obj, settings): elem_find_first(fbx_tmpl, b'Properties70', fbx_elem_nil)) fbx_props_no_template = (fbx_props[0], fbx_elem_nil) - ma_wrap = node_shader_utils.PrincipledBSDFWrapper(ma, is_readonly=False, use_nodes=True) + ma_wrap = node_shader_utils.PrincipledBSDFWrapper(ma, is_readonly=False) ma_wrap.base_color = elem_props_get_color_rgb(fbx_props, b'DiffuseColor', const_color_white) # No specular color in Principled BSDF shader, assumed to be either white or take some tint from diffuse one... # TODO: add way to handle tint option (guesstimate from spec color + intensity...)? diff --git a/scripts/modules/bpy_extras/node_shader_utils.py b/scripts/modules/bpy_extras/node_shader_utils.py index 5c72f92ea0a..1b2bb309dca 100644 --- a/scripts/modules/bpy_extras/node_shader_utils.py +++ b/scripts/modules/bpy_extras/node_shader_utils.py @@ -102,11 +102,9 @@ class ShaderWrapper: dst_node.width = min(dst_node.width, self._col_size - 20) return loc - def __init__(self, material, is_readonly=True, use_nodes=True): + def __init__(self, material, is_readonly=True): self.is_readonly = is_readonly self.material = material - if not is_readonly: - self.use_nodes = use_nodes self.update() def update(self): # Should be re-implemented by children classes... @@ -115,19 +113,7 @@ class ShaderWrapper: self._textures = {} self._grid_locations = set() - def use_nodes_get(self): - return self.material.use_nodes - - @_set_check - def use_nodes_set(self, val): - self.material.use_nodes = val - self.update() - - use_nodes = property(use_nodes_get, use_nodes_set) - def node_texcoords_get(self): - if not self.use_nodes: - return None if self._node_texcoords is ...: # Running only once, trying to find a valid texcoords node. for n in self.material.node_tree.nodes: @@ -173,17 +159,13 @@ class PrincipledBSDFWrapper(ShaderWrapper): NODES_LIST = ShaderWrapper.NODES_LIST + NODES_LIST - def __init__(self, material, is_readonly=True, use_nodes=True): - super(PrincipledBSDFWrapper, self).__init__(material, is_readonly, use_nodes) + def __init__(self, material, is_readonly=True): + super(PrincipledBSDFWrapper, self).__init__(material, is_readonly) def update(self): super(PrincipledBSDFWrapper, self).update() - if not self.use_nodes: - return - tree = self.material.node_tree - nodes = tree.nodes links = tree.links @@ -237,7 +219,7 @@ class PrincipledBSDFWrapper(ShaderWrapper): self._node_texcoords = ... def node_normalmap_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None node_principled = self.node_principled_bsdf if self._node_normalmap is ...: @@ -268,7 +250,7 @@ class PrincipledBSDFWrapper(ShaderWrapper): # Base Color. def base_color_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return self.material.diffuse_color return rgba_to_rgb(self.node_principled_bsdf.inputs["Base Color"].default_value) @@ -277,13 +259,13 @@ class PrincipledBSDFWrapper(ShaderWrapper): color = values_clamp(color, 0.0, 1.0) color = rgb_to_rgba(color) self.material.diffuse_color = color - if self.use_nodes and self.node_principled_bsdf is not None: + if self.node_principled_bsdf is not None: self.node_principled_bsdf.inputs["Base Color"].default_value = color base_color = property(base_color_get, base_color_set) def base_color_texture_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None return ShaderImageTextureWrapper( self, self.node_principled_bsdf, @@ -297,7 +279,7 @@ class PrincipledBSDFWrapper(ShaderWrapper): # Specular. def specular_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return self.material.specular_intensity return self.node_principled_bsdf.inputs["Specular IOR Level"].default_value @@ -305,14 +287,14 @@ class PrincipledBSDFWrapper(ShaderWrapper): def specular_set(self, value): value = values_clamp(value, 0.0, 1.0) self.material.specular_intensity = value - if self.use_nodes and self.node_principled_bsdf is not None: + if self.node_principled_bsdf is not None: self.node_principled_bsdf.inputs["Specular IOR Level"].default_value = value specular = property(specular_get, specular_set) # Will only be used as gray-scale one... def specular_texture_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None return ShaderImageTextureWrapper( self, self.node_principled_bsdf, @@ -327,7 +309,7 @@ class PrincipledBSDFWrapper(ShaderWrapper): # Specular Tint. def specular_tint_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return Color((0.0, 0.0, 0.0)) return rgba_to_rgb(self.node_principled_bsdf.inputs["Specular Tint"].default_value) @@ -335,13 +317,13 @@ class PrincipledBSDFWrapper(ShaderWrapper): def specular_tint_set(self, color): color = values_clamp(color, 0.0, 1.0) color = rgb_to_rgba(color) - if self.use_nodes and self.node_principled_bsdf is not None: + if self.node_principled_bsdf is not None: self.node_principled_bsdf.inputs["Specular Tint"].default_value = color specular_tint = property(specular_tint_get, specular_tint_set) def specular_tint_texture_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None return ShaderImageTextureWrapper( self, self.node_principled_bsdf, @@ -355,7 +337,7 @@ class PrincipledBSDFWrapper(ShaderWrapper): # Roughness (also sort of inverse of specular hardness...). def roughness_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return self.material.roughness return self.node_principled_bsdf.inputs["Roughness"].default_value @@ -363,14 +345,14 @@ class PrincipledBSDFWrapper(ShaderWrapper): def roughness_set(self, value): value = values_clamp(value, 0.0, 1.0) self.material.roughness = value - if self.use_nodes and self.node_principled_bsdf is not None: + if self.node_principled_bsdf is not None: self.node_principled_bsdf.inputs["Roughness"].default_value = value roughness = property(roughness_get, roughness_set) # Will only be used as gray-scale one... def roughness_texture_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None return ShaderImageTextureWrapper( self, self.node_principled_bsdf, @@ -385,7 +367,7 @@ class PrincipledBSDFWrapper(ShaderWrapper): # Metallic (a.k.a reflection, mirror). def metallic_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return self.material.metallic return self.node_principled_bsdf.inputs["Metallic"].default_value @@ -393,14 +375,14 @@ class PrincipledBSDFWrapper(ShaderWrapper): def metallic_set(self, value): value = values_clamp(value, 0.0, 1.0) self.material.metallic = value - if self.use_nodes and self.node_principled_bsdf is not None: + if self.node_principled_bsdf is not None: self.node_principled_bsdf.inputs["Metallic"].default_value = value metallic = property(metallic_get, metallic_set) # Will only be used as gray-scale one... def metallic_texture_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None return ShaderImageTextureWrapper( self, self.node_principled_bsdf, @@ -415,21 +397,21 @@ class PrincipledBSDFWrapper(ShaderWrapper): # Transparency settings. def ior_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return 1.0 return self.node_principled_bsdf.inputs["IOR"].default_value @_set_check def ior_set(self, value): value = values_clamp(value, 0.0, 1000.0) - if self.use_nodes and self.node_principled_bsdf is not None: + if self.node_principled_bsdf is not None: self.node_principled_bsdf.inputs["IOR"].default_value = value ior = property(ior_get, ior_set) # Will only be used as gray-scale one... def ior_texture_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None return ShaderImageTextureWrapper( self, self.node_principled_bsdf, @@ -441,21 +423,21 @@ class PrincipledBSDFWrapper(ShaderWrapper): ior_texture = property(ior_texture_get) def transmission_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return 0.0 return self.node_principled_bsdf.inputs["Transmission Weight"].default_value @_set_check def transmission_set(self, value): value = values_clamp(value, 0.0, 1.0) - if self.use_nodes and self.node_principled_bsdf is not None: + if self.node_principled_bsdf is not None: self.node_principled_bsdf.inputs["Transmission Weight"].default_value = value transmission = property(transmission_get, transmission_set) # Will only be used as gray-scale one... def transmission_texture_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None return ShaderImageTextureWrapper( self, self.node_principled_bsdf, @@ -467,21 +449,21 @@ class PrincipledBSDFWrapper(ShaderWrapper): transmission_texture = property(transmission_texture_get) def alpha_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return 1.0 return self.node_principled_bsdf.inputs["Alpha"].default_value @_set_check def alpha_set(self, value): value = values_clamp(value, 0.0, 1.0) - if self.use_nodes and self.node_principled_bsdf is not None: + if self.node_principled_bsdf is not None: self.node_principled_bsdf.inputs["Alpha"].default_value = value alpha = property(alpha_get, alpha_set) # Will only be used as gray-scale one... def alpha_texture_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None return ShaderImageTextureWrapper( self, self.node_principled_bsdf, @@ -497,13 +479,13 @@ class PrincipledBSDFWrapper(ShaderWrapper): # Emission color. def emission_color_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return Color((0.0, 0.0, 0.0)) return rgba_to_rgb(self.node_principled_bsdf.inputs["Emission Color"].default_value) @_set_check def emission_color_set(self, color): - if self.use_nodes and self.node_principled_bsdf is not None: + if self.node_principled_bsdf is not None: color = values_clamp(color, 0.0, 1000000.0) color = rgb_to_rgba(color) self.node_principled_bsdf.inputs["Emission Color"].default_value = color @@ -511,7 +493,7 @@ class PrincipledBSDFWrapper(ShaderWrapper): emission_color = property(emission_color_get, emission_color_set) def emission_color_texture_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None return ShaderImageTextureWrapper( self, self.node_principled_bsdf, @@ -522,20 +504,20 @@ class PrincipledBSDFWrapper(ShaderWrapper): emission_color_texture = property(emission_color_texture_get) def emission_strength_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return 1.0 return self.node_principled_bsdf.inputs["Emission Strength"].default_value @_set_check def emission_strength_set(self, value): value = values_clamp(value, 0.0, 1000000.0) - if self.use_nodes and self.node_principled_bsdf is not None: + if self.node_principled_bsdf is not None: self.node_principled_bsdf.inputs["Emission Strength"].default_value = value emission_strength = property(emission_strength_get, emission_strength_set) def emission_strength_texture_get(self): - if not self.use_nodes or self.node_principled_bsdf is None: + if self.node_principled_bsdf is None: return None return ShaderImageTextureWrapper( self, self.node_principled_bsdf, @@ -550,20 +532,20 @@ class PrincipledBSDFWrapper(ShaderWrapper): # Normal map. def normalmap_strength_get(self): - if not self.use_nodes or self.node_normalmap is None: + if self.node_normalmap is None: return 0.0 return self.node_normalmap.inputs["Strength"].default_value @_set_check def normalmap_strength_set(self, value): value = values_clamp(value, 0.0, 10.0) - if self.use_nodes and self.node_normalmap is not None: + if self.node_normalmap is not None: self.node_normalmap.inputs["Strength"].default_value = value normalmap_strength = property(normalmap_strength_get, normalmap_strength_set) def normalmap_texture_get(self): - if not self.use_nodes or self.node_normalmap is None: + if self.node_normalmap is None: return None return ShaderImageTextureWrapper( self, self.node_normalmap, diff --git a/scripts/startup/bl_operators/image_as_planes.py b/scripts/startup/bl_operators/image_as_planes.py index 6c287afd945..b81b57e192a 100644 --- a/scripts/startup/bl_operators/image_as_planes.py +++ b/scripts/startup/bl_operators/image_as_planes.py @@ -425,14 +425,12 @@ def create_cycles_material(self, context, img_spec, name): if material is None: material = bpy.data.materials.new(name=name) - material.use_nodes = True - material.surface_render_method = self.render_method material.use_backface_culling = self.use_backface_culling material.use_transparency_overlap = self.show_transparent_back node_tree = material.node_tree - out_node = clean_node_tree(node_tree) + out_node = node_tree.nodes.new("ShaderNodeOutputMaterial") tex_image = create_cycles_texnode(self, node_tree, img_spec) diff --git a/scripts/startup/bl_operators/object_quick_effects.py b/scripts/startup/bl_operators/object_quick_effects.py index 576d26dc9e4..6cbe88d063b 100644 --- a/scripts/startup/bl_operators/object_quick_effects.py +++ b/scripts/startup/bl_operators/object_quick_effects.py @@ -326,21 +326,18 @@ class QuickExplode(ObjectModeOperator, Operator): mat = object_ensure_material(obj, data_("Explode Fade")) mat.surface_render_method = 'DITHERED' - if not mat.use_nodes: - mat.use_nodes = True nodes = mat.node_tree.nodes - for node in nodes: - if node.type == 'OUTPUT_MATERIAL': - node_out_mat = node - break - - node_surface = node_out_mat.inputs["Surface"].links[0].from_node + node_out_mat = nodes.new("ShaderNodeOutputMaterial") + node_surface = nodes.new("ShaderNodeBsdfPrincipled") + nodes.active = node_out_mat node_x = node_surface.location[0] node_y = node_surface.location[1] - 400 offset_x = 200 + node_out_mat.location[0] = node_x + node_surface.width + offset_x + node_mix = nodes.new('ShaderNodeMixShader') node_mix.location = (node_x - offset_x, node_y) mat.node_tree.links.new(node_surface.outputs[0], node_mix.inputs[1]) @@ -515,9 +512,6 @@ class QuickSmoke(ObjectModeOperator, Operator): mat = bpy.data.materials.new(data_("Smoke Domain Material")) obj.material_slots[0].material = mat - # Make sure we use nodes - mat.use_nodes = True - # Set node variables and clear the default nodes tree = mat.node_tree nodes = tree.nodes @@ -650,9 +644,6 @@ class QuickLiquid(Operator): mat = bpy.data.materials.new(data_("Liquid Domain Material")) obj.material_slots[0].material = mat - # Make sure we use nodes - mat.use_nodes = True - # Set node variables and clear the default nodes tree = mat.node_tree nodes = tree.nodes diff --git a/scripts/startup/bl_operators/world.py b/scripts/startup/bl_operators/world.py index 282df36ff42..d6e48fd8761 100644 --- a/scripts/startup/bl_operators/world.py +++ b/scripts/startup/bl_operators/world.py @@ -53,11 +53,8 @@ class WORLD_OT_convert_volume_to_mesh(bpy.types.Operator): material = bpy.data.materials.new(name) mesh.materials.append(material) - material.use_nodes = True volume_tree = material.node_tree - for node in volume_tree.nodes: - if node.type != 'OUTPUT_MATERIAL': - volume_tree.nodes.remove(node) + volume_tree.nodes.new("ShaderNodeOutputMaterial") volume_output = volume_tree.get_output_node('EEVEE') links_to_add = [] diff --git a/scripts/startup/bl_ui/properties_material.py b/scripts/startup/bl_ui/properties_material.py index 357a1224350..4036aa3a63d 100644 --- a/scripts/startup/bl_ui/properties_material.py +++ b/scripts/startup/bl_ui/properties_material.py @@ -169,16 +169,8 @@ class EEVEE_MATERIAL_PT_surface(MaterialButtonsPanel, Panel): mat = context.material - if mat.use_nodes: - layout.use_property_split = True - panel_node_draw(layout, mat.node_tree, 'OUTPUT_MATERIAL', "Surface") - else: - layout.prop(mat, "use_nodes", icon='NODETREE') - layout.use_property_split = True - layout.prop(mat, "diffuse_color", text="Base Color") - layout.prop(mat, "metallic") - layout.prop(mat, "specular_intensity", text="Specular") - layout.prop(mat, "roughness") + layout.use_property_split = True + panel_node_draw(layout, mat.node_tree, 'OUTPUT_MATERIAL', "Surface") class EEVEE_MATERIAL_PT_volume(MaterialButtonsPanel, Panel): @@ -192,7 +184,7 @@ class EEVEE_MATERIAL_PT_volume(MaterialButtonsPanel, Panel): def poll(cls, context): engine = context.engine mat = context.material - return mat and mat.use_nodes and (engine in cls.COMPAT_ENGINES) and not mat.grease_pencil + return mat and (engine in cls.COMPAT_ENGINES) and not mat.grease_pencil def draw(self, context): layout = self.layout @@ -214,7 +206,7 @@ class EEVEE_MATERIAL_PT_displacement(MaterialButtonsPanel, Panel): def poll(cls, context): engine = context.engine mat = context.material - return mat and mat.use_nodes and (engine in cls.COMPAT_ENGINES) and not mat.grease_pencil + return mat and (engine in cls.COMPAT_ENGINES) and not mat.grease_pencil def draw(self, context): layout = self.layout @@ -237,7 +229,7 @@ class EEVEE_MATERIAL_PT_thickness(MaterialButtonsPanel, Panel): def poll(cls, context): engine = context.engine mat = context.material - return mat and mat.use_nodes and (engine in cls.COMPAT_ENGINES) and not mat.grease_pencil + return mat and (engine in cls.COMPAT_ENGINES) and not mat.grease_pencil def draw(self, context): layout = self.layout diff --git a/scripts/startup/bl_ui/space_node.py b/scripts/startup/bl_ui/space_node.py index b9b07dbbc42..68029878b7f 100644 --- a/scripts/startup/bl_ui/space_node.py +++ b/scripts/startup/bl_ui/space_node.py @@ -65,16 +65,17 @@ class NODE_HT_header(Header): ob_type = ob.type NODE_MT_editor_menus.draw_collapsible(context, layout) - - if snode_id: - row = layout.row() - row.prop(snode_id, "use_nodes") - - layout.separator_spacer() - types_that_support_material = { 'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'GPENCIL', 'VOLUME', 'CURVES', 'POINTCLOUD', } + + if snode_id: + row = layout.row() + if ob_type not in types_that_support_material: + row.prop(snode_id, "use_nodes") + + layout.separator_spacer() + # disable material slot buttons when pinned, cannot find correct slot within id_from (#36589) # disable also when the selected object does not support materials has_material_slots = not snode.pin and ob_type in types_that_support_material diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 6b13f9efbab..37d263003d0 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,7 +27,7 @@ /* Blender file format version. */ #define BLENDER_FILE_VERSION BLENDER_VERSION -#define BLENDER_FILE_SUBVERSION 80 +#define BLENDER_FILE_SUBVERSION 81 /* Minimum Blender version that supports reading file written with the current * version. Older Blender versions will test this and cancel loading the file, showing a warning to diff --git a/source/blender/blenkernel/intern/image.cc b/source/blender/blenkernel/intern/image.cc index 12ad4d6fb45..3703d417f11 100644 --- a/source/blender/blenkernel/intern/image.cc +++ b/source/blender/blenkernel/intern/image.cc @@ -2870,7 +2870,7 @@ static void image_walk_id_all_users( } case ID_MA: { Material *ma = (Material *)id; - if (ma->nodetree && ma->use_nodes && !skip_nested_nodes) { + if (ma->nodetree && !skip_nested_nodes) { image_walk_ntree_all_users(ma->nodetree, &ma->id, customdata, callback); } image_walk_gpu_materials(id, &ma->gpumaterial, customdata, callback); diff --git a/source/blender/blenkernel/intern/material.cc b/source/blender/blenkernel/intern/material.cc index 1d2f0cf4e5b..7048f2776f6 100644 --- a/source/blender/blenkernel/intern/material.cc +++ b/source/blender/blenkernel/intern/material.cc @@ -206,6 +206,9 @@ static void material_blend_write(BlendWriter *writer, ID *id, const void *id_add ma->texpaintslot = nullptr; BLI_listbase_clear(&ma->gpumaterial); + /* Set deprecated #use_nodes for forward compatibility. */ + ma->use_nodes = true; + /* write LibData */ BLO_write_id_struct(writer, Material, id_address, &ma->id); BKE_id_blend_write(writer, &ma->id); @@ -2071,7 +2074,6 @@ static void material_default_surface_init(Material **ma_p) bNodeTree *ntree = blender::bke::node_tree_add_tree_embedded( nullptr, &ma->id, "Shader Nodetree", ntreeType_Shader->idname); - ma->use_nodes = true; bNode *principled = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_BSDF_PRINCIPLED); bNodeSocket *base_color = blender::bke::node_find_socket(*principled, SOCK_IN, "Base Color"); @@ -2099,7 +2101,6 @@ static void material_default_volume_init(Material **ma_p) bNodeTree *ntree = blender::bke::node_tree_add_tree_embedded( nullptr, &ma->id, "Shader Nodetree", ntreeType_Shader->idname); - ma->use_nodes = true; bNode *principled = blender::bke::node_add_static_node( nullptr, *ntree, SH_NODE_VOLUME_PRINCIPLED); @@ -2125,7 +2126,6 @@ static void material_default_holdout_init(Material **ma_p) bNodeTree *ntree = blender::bke::node_tree_add_tree_embedded( nullptr, &ma->id, "Shader Nodetree", ntreeType_Shader->idname); - ma->use_nodes = true; bNode *holdout = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_HOLDOUT); bNode *output = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_OUTPUT_MATERIAL); diff --git a/source/blender/blenloader/intern/versioning_500.cc b/source/blender/blenloader/intern/versioning_500.cc index f080e187de7..284bc189adb 100644 --- a/source/blender/blenloader/intern/versioning_500.cc +++ b/source/blender/blenloader/intern/versioning_500.cc @@ -16,6 +16,7 @@ #include "DNA_brush_types.h" #include "DNA_curves_types.h" #include "DNA_grease_pencil_types.h" +#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_modifier_types.h" #include "DNA_node_types.h" @@ -2010,6 +2011,127 @@ static void initialize_missing_closure_and_bundle_node_storage(bNodeTree &ntree) } } +static void do_version_material_remove_use_nodes(Main *bmain, Material *material) +{ + if (material->use_nodes) { + return; + } + + /* Users defined a material node tree, but deactivated it by disabling "Use Nodes". So we + * simulate the same effect by creating a new Material Output node and setting it to active. */ + bNodeTree *ntree = material->nodetree; + if (ntree == nullptr) { + /* In case the material was created in Python API it might have been missing a node tree. */ + ntree = blender::bke::node_tree_add_tree_embedded( + bmain, &material->id, "Material Node Tree Versioning", "ShaderNodeTree"); + } + + bNode *old_output = nullptr; + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (STREQ(node->idname, "ShaderNodeOutputMaterial") && (node->flag & NODE_DO_OUTPUT)) { + old_output = node; + old_output->flag &= ~NODE_DO_OUTPUT; + } + } + + bNode *frame = blender::bke::node_add_static_node(nullptr, *ntree, NODE_FRAME); + STRNCPY(frame->label, RPT_("Versioning: Use Nodes was removed")); + + { + /* For EEVEE, we use a principled BSDF shader because we need to recreate the metallic, + * specular and roughness properties of the material for use_nodes = false.*/ + bNode &new_output_eevee = version_node_add_empty(*ntree, "ShaderNodeOutputMaterial"); + bNodeSocket &output_surface_input = version_node_add_socket( + *ntree, new_output_eevee, SOCK_IN, "NodeSocketShader", "Surface"); + version_node_add_socket(*ntree, new_output_eevee, SOCK_IN, "NodeSocketShader", "Volume"); + version_node_add_socket(*ntree, new_output_eevee, SOCK_IN, "NodeSocketVector", "Displacement"); + version_node_add_socket(*ntree, new_output_eevee, SOCK_IN, "NodeSocketFloat", "Thickness"); + + version_node_add_socket(*ntree, new_output_eevee, SOCK_IN, "NodeSocketShader", "Volume"); + new_output_eevee.flag |= NODE_DO_OUTPUT; + new_output_eevee.custom1 = SHD_OUTPUT_EEVEE; + + bNode &shader_eevee = *blender::bke::node_add_static_node( + nullptr, *ntree, SH_NODE_BSDF_PRINCIPLED); + bNodeSocket &shader_bsdf_output = *blender::bke::node_find_socket( + shader_eevee, SOCK_OUT, "BSDF"); + bNodeSocket &shader_color_input = *blender::bke::node_find_socket( + shader_eevee, SOCK_IN, "Base Color"); + bNodeSocket &specular_input = *blender::bke::node_find_socket( + shader_eevee, SOCK_IN, "Specular IOR Level"); + bNodeSocket &metallic_input = *blender::bke::node_find_socket( + shader_eevee, SOCK_IN, "Metallic"); + bNodeSocket &roughness_input = *blender::bke::node_find_socket( + shader_eevee, SOCK_IN, "Roughness"); + + version_node_add_link( + *ntree, shader_eevee, shader_bsdf_output, new_output_eevee, output_surface_input); + + bNodeSocketValueRGBA *rgba = shader_color_input.default_value_typed(); + rgba->value[0] = material->r; + rgba->value[1] = material->g; + rgba->value[2] = material->b; + rgba->value[3] = material->a; + roughness_input.default_value_typed()->value = material->roughness; + metallic_input.default_value_typed()->value = material->metallic; + specular_input.default_value_typed()->value = material->spec; + + if (old_output != nullptr) { + /* Position the newly created node after the old output. Assume the old output node is at + * the far right of the node tree. */ + shader_eevee.location[0] = old_output->location[0] + 1.5f * old_output->width; + shader_eevee.location[1] = old_output->location[1]; + } + + new_output_eevee.location[0] = shader_eevee.location[0] + 2.0f * shader_eevee.width; + new_output_eevee.location[1] = shader_eevee.location[1]; + + shader_eevee.parent = frame; + new_output_eevee.parent = frame; + } + + { + /* For Cycles, a simple diffuse BSDF is sufficient. */ + bNode &new_output_cycles = version_node_add_empty(*ntree, "ShaderNodeOutputMaterial"); + bNodeSocket &output_surface_input = version_node_add_socket( + *ntree, new_output_cycles, SOCK_IN, "NodeSocketShader", "Surface"); + version_node_add_socket(*ntree, new_output_cycles, SOCK_IN, "NodeSocketShader", "Volume"); + version_node_add_socket( + *ntree, new_output_cycles, SOCK_IN, "NodeSocketVector", "Displacement"); + version_node_add_socket(*ntree, new_output_cycles, SOCK_IN, "NodeSocketFloat", "Thickness"); + /* We don't activate the output explicitly to avoid having two active outputs. We assume + * `node_tree.get_output_node('Cycles')` will return this node. */ + new_output_cycles.custom1 = SHD_OUTPUT_CYCLES; + + bNode &shader_cycles = *blender::bke::node_add_static_node( + nullptr, *ntree, SH_NODE_BSDF_DIFFUSE); + bNodeSocket &shader_bsdf_output = *blender::bke::node_find_socket( + shader_cycles, SOCK_OUT, "BSDF"); + bNodeSocket &shader_color_input = *blender::bke::node_find_socket( + shader_cycles, SOCK_IN, "Color"); + + version_node_add_link( + *ntree, shader_cycles, shader_bsdf_output, new_output_cycles, output_surface_input); + + bNodeSocketValueRGBA *rgba = shader_color_input.default_value_typed(); + rgba->value[0] = material->r; + rgba->value[1] = material->g; + rgba->value[2] = material->b; + rgba->value[3] = material->a; + + if (old_output != nullptr) { + shader_cycles.location[0] = old_output->location[0] + 1.5f * old_output->width; + shader_cycles.location[1] = old_output->location[1] + 2.0f * old_output->height; + } + + new_output_cycles.location[0] = shader_cycles.location[0] + 3.0f * shader_cycles.width; + new_output_cycles.location[1] = shader_cycles.location[1]; + + shader_cycles.parent = frame; + new_output_cycles.parent = frame; + } +} + void do_versions_after_linking_500(FileData *fd, Main *bmain) { if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 9)) { @@ -3047,6 +3169,12 @@ void blo_do_versions_500(FileData *fd, Library * /*lib*/, Main *bmain) FOREACH_NODETREE_END; } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 81)) { + LISTBASE_FOREACH (Material *, material, &bmain->materials) { + do_version_material_remove_use_nodes(bmain, material); + } + } + /** * Always bump subversion in BKE_blender_version.h when adding versioning * code here, and wrap it inside a MAIN_VERSION_FILE_ATLEAST check. diff --git a/source/blender/draw/engines/eevee/eevee_material.cc b/source/blender/draw/engines/eevee/eevee_material.cc index 5fe2b0f8cfb..c505320c7f1 100644 --- a/source/blender/draw/engines/eevee/eevee_material.cc +++ b/source/blender/draw/engines/eevee/eevee_material.cc @@ -21,52 +21,6 @@ namespace blender::eevee { -/* -------------------------------------------------------------------- */ -/** \name Default Material - * - * \{ */ - -DefaultSurfaceNodeTree::DefaultSurfaceNodeTree() -{ - bNodeTree *ntree = bke::node_tree_add_tree(nullptr, "Shader Nodetree", ntreeType_Shader->idname); - bNode *bsdf = bke::node_add_static_node(nullptr, *ntree, SH_NODE_BSDF_PRINCIPLED); - bNode *output = bke::node_add_static_node(nullptr, *ntree, SH_NODE_OUTPUT_MATERIAL); - bNodeSocket *bsdf_out = bke::node_find_socket(*bsdf, SOCK_OUT, "BSDF"); - bNodeSocket *output_in = bke::node_find_socket(*output, SOCK_IN, "Surface"); - bke::node_add_link(*ntree, *bsdf, *bsdf_out, *output, *output_in); - bke::node_set_active(*ntree, *output); - - color_socket_ = - (bNodeSocketValueRGBA *)bke::node_find_socket(*bsdf, SOCK_IN, "Base Color")->default_value; - metallic_socket_ = - (bNodeSocketValueFloat *)bke::node_find_socket(*bsdf, SOCK_IN, "Metallic")->default_value; - roughness_socket_ = - (bNodeSocketValueFloat *)bke::node_find_socket(*bsdf, SOCK_IN, "Roughness")->default_value; - specular_socket_ = (bNodeSocketValueFloat *)bke::node_find_socket( - *bsdf, SOCK_IN, "Specular IOR Level") - ->default_value; - ntree_ = ntree; -} - -DefaultSurfaceNodeTree::~DefaultSurfaceNodeTree() -{ - bke::node_tree_free_embedded_tree(ntree_); - MEM_SAFE_FREE(ntree_); -} - -bNodeTree *DefaultSurfaceNodeTree::nodetree_get(::Material *ma) -{ - /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */ - copy_v3_fl3(color_socket_->value, ma->r, ma->g, ma->b); - metallic_socket_->value = ma->metallic; - roughness_socket_->value = ma->roughness; - specular_socket_->value = ma->spec; - - return ntree_; -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Material * @@ -78,7 +32,6 @@ MaterialModule::MaterialModule(Instance &inst) : inst_(inst) diffuse_mat = BKE_id_new_nomain<::Material>("EEVEE default diffuse"); bNodeTree *ntree = bke::node_tree_add_tree_embedded( nullptr, &diffuse_mat->id, "Shader Nodetree", ntreeType_Shader->idname); - diffuse_mat->use_nodes = true; diffuse_mat->surface_render_method = MA_SURFACE_METHOD_FORWARD; /* Use 0.18 as it is close to middle gray. Middle gray is typically defined as 18% reflectance @@ -101,7 +54,6 @@ MaterialModule::MaterialModule(Instance &inst) : inst_(inst) metallic_mat = BKE_id_new_nomain<::Material>("EEVEE default metal"); bNodeTree *ntree = bke::node_tree_add_tree_embedded( nullptr, &metallic_mat->id, "Shader Nodetree", ntreeType_Shader->idname); - metallic_mat->use_nodes = true; metallic_mat->surface_render_method = MA_SURFACE_METHOD_FORWARD; bNode *bsdf = bke::node_add_static_node(nullptr, *ntree, SH_NODE_BSDF_GLOSSY); @@ -130,7 +82,6 @@ MaterialModule::MaterialModule(Instance &inst) : inst_(inst) error_mat_ = BKE_id_new_nomain<::Material>("EEVEE default error"); bNodeTree *ntree = bke::node_tree_add_tree_embedded( nullptr, &error_mat_->id, "Shader Nodetree", ntreeType_Shader->idname); - error_mat_->use_nodes = true; /* Use emission and output material to be compatible with both World and Material. */ bNode *bsdf = bke::node_add_static_node(nullptr, *ntree, SH_NODE_EMISSION); @@ -251,9 +202,8 @@ MaterialPass MaterialModule::material_pass_get(Object *ob, eMaterialGeometry geometry_type, eMaterialProbe probe_capture) { - bNodeTree *ntree = (blender_mat->use_nodes && blender_mat->nodetree != nullptr) ? - blender_mat->nodetree : - default_surface_ntree_.nodetree_get(blender_mat); + bNodeTree *ntree = (blender_mat->nodetree != nullptr) ? blender_mat->nodetree : + default_surface->nodetree; /* We can't defer compilation in viewport image render, since we can't re-sync.(See #130235) */ bool use_deferred_compilation = !inst_.is_viewport_image_render; diff --git a/source/blender/draw/engines/eevee/eevee_material.hh b/source/blender/draw/engines/eevee/eevee_material.hh index 6ffbced7265..35ded690462 100644 --- a/source/blender/draw/engines/eevee/eevee_material.hh +++ b/source/blender/draw/engines/eevee/eevee_material.hh @@ -297,33 +297,6 @@ struct ShaderKey { /** \} */ -/* -------------------------------------------------------------------- */ -/** \name Default Material Node-Tree - * - * In order to support materials without nodetree we reuse and configure a standalone nodetree that - * we pass for shader generation. The GPUMaterial is still stored inside the Material even if - * it does not use the same nodetree. - * - * \{ */ - -class DefaultSurfaceNodeTree { - private: - bNodeTree *ntree_; - bNodeSocketValueRGBA *color_socket_; - bNodeSocketValueFloat *metallic_socket_; - bNodeSocketValueFloat *roughness_socket_; - bNodeSocketValueFloat *specular_socket_; - - public: - DefaultSurfaceNodeTree(); - ~DefaultSurfaceNodeTree(); - - /** Configure a default node-tree with the given material. */ - bNodeTree *nodetree_get(::Material *ma); -}; - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name Material * @@ -378,8 +351,6 @@ class MaterialModule { MaterialArray material_array_; - DefaultSurfaceNodeTree default_surface_ntree_; - ::Material *error_mat_; uint64_t gpu_pass_last_update_ = 0; diff --git a/source/blender/editors/render/render_shading.cc b/source/blender/editors/render/render_shading.cc index 24eebda1ddb..ed4099b687e 100644 --- a/source/blender/editors/render/render_shading.cc +++ b/source/blender/editors/render/render_shading.cc @@ -854,7 +854,6 @@ static wmOperatorStatus new_material_exec(bContext *C, wmOperator * /*op*/) ma = BKE_gpencil_material_add(bmain, name); } ED_node_shader_default(C, &ma->id); - ma->use_nodes = true; } if (prop) { @@ -2900,7 +2899,6 @@ static wmOperatorStatus paste_material_exec(bContext *C, wmOperator *op) SWAP_MEMBER(spec); SWAP_MEMBER(roughness); SWAP_MEMBER(metallic); - SWAP_MEMBER(use_nodes); SWAP_MEMBER(index); SWAP_MEMBER(nodetree); SWAP_MEMBER(line_col); diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.cc b/source/blender/editors/sculpt_paint/paint_image_proj.cc index 475f7bb27ce..b2ca2b53655 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.cc +++ b/source/blender/editors/sculpt_paint/paint_image_proj.cc @@ -6751,8 +6751,6 @@ static bool proj_paint_add_slot(bContext *C, wmOperator *op) ntree = ma->nodetree; } - ma->use_nodes = true; - const ePaintCanvasSource slot_type = ob->mode == OB_MODE_SCULPT ? (ePaintCanvasSource)RNA_enum_get(op->ptr, "slot_type") : diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 44297a38764..a71ae180da3 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -785,9 +785,7 @@ void ED_node_set_active( if (node->flag & NODE_ACTIVE_TEXTURE) { /* If active texture changed, free GLSL materials. */ LISTBASE_FOREACH (Material *, ma, &bmain->materials) { - if (ma->nodetree && ma->use_nodes && - blender::bke::node_tree_contains_tree(*ma->nodetree, *ntree)) - { + if (ma->nodetree && blender::bke::node_tree_contains_tree(*ma->nodetree, *ntree)) { GPU_material_free(&ma->gpumaterial); /* Sync to active texpaint slot, otherwise we can end up painting on a different slot diff --git a/source/blender/editors/uvedit/uvedit_ops.cc b/source/blender/editors/uvedit/uvedit_ops.cc index aa2f811626c..a6fe32d6be5 100644 --- a/source/blender/editors/uvedit/uvedit_ops.cc +++ b/source/blender/editors/uvedit/uvedit_ops.cc @@ -124,7 +124,7 @@ bool ED_object_get_active_image(Object *ob, { Material *ma = DEG_is_evaluated(ob) ? BKE_object_material_get_eval(ob, mat_nr) : BKE_object_material_get(ob, mat_nr); - bNodeTree *ntree = (ma && ma->use_nodes) ? ma->nodetree : nullptr; + bNodeTree *ntree = ma ? ma->nodetree : nullptr; bNode *node = (ntree) ? bke::node_get_active_texture(*ntree) : nullptr; if (node && is_image_texture_node(node)) { @@ -170,7 +170,7 @@ bool ED_object_get_active_image(Object *ob, void ED_object_assign_active_image(Main *bmain, Object *ob, int mat_nr, Image *ima) { Material *ma = BKE_object_material_get(ob, mat_nr); - bNode *node = (ma && ma->use_nodes) ? bke::node_get_active_texture(*ma->nodetree) : nullptr; + bNode *node = ma ? bke::node_get_active_texture(*ma->nodetree) : nullptr; if (node && is_image_texture_node(node)) { node->id = &ima->id; diff --git a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp index 46b68b5434b..cbeb288b20f 100644 --- a/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp +++ b/source/blender/freestyle/intern/blender_interface/BlenderStrokeRenderer.cpp @@ -233,7 +233,6 @@ Material *BlenderStrokeRenderer::GetStrokeShader(Main *bmain, ntree = blender::bke::node_tree_add_tree_embedded( nullptr, &ma->id, "stroke_shader", "ShaderNodeTree"); } - ma->use_nodes = true; ma->blend_method = MA_BM_HASHED; bNode *input_attr_color = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_ATTRIBUTE); diff --git a/source/blender/io/fbx/importer/fbx_import_material.cc b/source/blender/io/fbx/importer/fbx_import_material.cc index 03d2dc959ca..1bab63ad16d 100644 --- a/source/blender/io/fbx/importer/fbx_import_material.cc +++ b/source/blender/io/fbx/importer/fbx_import_material.cc @@ -445,7 +445,6 @@ Material *import_material(Main *bmain, const std::string &base_dir, const ufbx_m Material *mat = BKE_material_add(bmain, fmat.name.data); id_us_min(&mat->id); - mat->use_nodes = true; bNodeTree *ntree = blender::bke::node_tree_add_tree_embedded( nullptr, &mat->id, "Shader Nodetree", ntreeType_Shader->idname); bNode *bsdf = add_node(ntree, SH_NODE_BSDF_PRINCIPLED, node_locx_bsdf, node_locy_top); diff --git a/source/blender/io/usd/intern/usd_reader_material.cc b/source/blender/io/usd/intern/usd_reader_material.cc index e821cc70779..d594870f199 100644 --- a/source/blender/io/usd/intern/usd_reader_material.cc +++ b/source/blender/io/usd/intern/usd_reader_material.cc @@ -330,6 +330,8 @@ static void set_viewport_material_props(Material *mtl, const pxr::UsdShadeShader diffuse_color_input.GetAttr().Get(&val) && val.IsHolding()) { pxr::GfVec3f color = val.UncheckedGet(); + /* Note: The material is expected to be rendered by the Workbench render engine (Viewport + * Display), so no need to define a material node tree. */ mtl->r = color[0]; mtl->g = color[1]; mtl->b = color[2]; @@ -454,7 +456,9 @@ Material *USDMaterialReader::add_material(const pxr::UsdShadeMaterial &usd_mater /* Create the material. */ Material *mtl = BKE_material_add(&bmain_, mtl_name.c_str()); - id_us_min(&mtl->id); + mtl->nodetree = blender::bke::node_tree_add_tree_embedded( + &bmain_, &mtl->id, "USD Material Node Tree", "ShaderNodeTree"); + // id_us_min(&mtl->id); if (read_usd_preview) { import_usd_preview(mtl, usd_material); @@ -495,9 +499,11 @@ void USDMaterialReader::import_usd_preview_nodes(Material *mtl, * and output shaders. */ /* Add the node tree. */ - bNodeTree *ntree = blender::bke::node_tree_add_tree_embedded( - nullptr, &mtl->id, "Shader Nodetree", "ShaderNodeTree"); - mtl->use_nodes = true; + bNodeTree *ntree = mtl->nodetree; + if (mtl->nodetree == nullptr) { + ntree = blender::bke::node_tree_add_tree_embedded( + nullptr, &mtl->id, "Shader Nodetree", "ShaderNodeTree"); + } /* Create the Principled BSDF shader node. */ bNode *principled = add_node(ntree, SH_NODE_BSDF_PRINCIPLED, {0.0f, 300.0f}); diff --git a/source/blender/io/usd/intern/usd_writer_material.cc b/source/blender/io/usd/intern/usd_writer_material.cc index 4d5760aba4c..e392a749f40 100644 --- a/source/blender/io/usd/intern/usd_writer_material.cc +++ b/source/blender/io/usd/intern/usd_writer_material.cc @@ -1702,7 +1702,7 @@ pxr::UsdShadeMaterial create_usd_material(const USDExporterContext &usd_export_c pxr::UsdShadeMaterial usd_material = pxr::UsdShadeMaterial::Define(usd_export_context.stage, usd_path); - if (material->use_nodes && usd_export_context.export_params.generate_preview_surface) { + if (usd_export_context.export_params.generate_preview_surface) { create_usd_preview_surface_material( usd_export_context, material, usd_material, active_uvmap_name, reports); } @@ -1711,7 +1711,7 @@ pxr::UsdShadeMaterial create_usd_material(const USDExporterContext &usd_export_c } #ifdef WITH_MATERIALX - if (material->use_nodes && usd_export_context.export_params.generate_materialx_network) { + if (usd_export_context.export_params.generate_materialx_network) { create_usd_materialx_material( usd_export_context, usd_path, material, active_uvmap_name, usd_material); } diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index b6fd5f1ad76..02272090229 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -387,7 +387,6 @@ static Material *get_or_create_material(Main *bmain, Material *mat = BKE_material_add(bmain, name.c_str()); id_us_min(&mat->id); - mat->use_nodes = true; mat->nodetree = create_mtl_node_tree(bmain, mtl, mat, relative_paths); BKE_ntree_update_after_single_tree_change(*bmain, *mat->nodetree); diff --git a/source/blender/makesdna/DNA_material_types.h b/source/blender/makesdna/DNA_material_types.h index 4ab6f048b6b..f1b35849f07 100644 --- a/source/blender/makesdna/DNA_material_types.h +++ b/source/blender/makesdna/DNA_material_types.h @@ -188,7 +188,7 @@ typedef struct Material { float metallic; /** Nodes */ - char use_nodes; + char use_nodes DNA_DEPRECATED; /** Preview render. */ char pr_type; diff --git a/source/blender/makesrna/intern/rna_main_api.cc b/source/blender/makesrna/intern/rna_main_api.cc index f5ce18a070e..395d6d24303 100644 --- a/source/blender/makesrna/intern/rna_main_api.cc +++ b/source/blender/makesrna/intern/rna_main_api.cc @@ -262,12 +262,15 @@ static Material *rna_Main_materials_new(Main *bmain, const char *name) char safe_name[MAX_ID_NAME - 2]; rna_idname_validate(name, safe_name); - ID *id = (ID *)BKE_material_add(bmain, safe_name); - id_us_min(id); + Material *material = BKE_material_add(bmain, safe_name); + id_us_min(&material->id); + + material->nodetree = blender::bke::node_tree_add_tree_embedded( + bmain, &material->id, "Material Node Tree", "ShaderNodeTree"); WM_main_add_notifier(NC_ID | NA_ADDED, nullptr); - return (Material *)id; + return material; } static void rna_Main_materials_gpencil_data(Main * /*bmain*/, PointerRNA *id_ptr) diff --git a/source/blender/makesrna/intern/rna_material.cc b/source/blender/makesrna/intern/rna_material.cc index b39ea78b118..c3bdcc1b352 100644 --- a/source/blender/makesrna/intern/rna_material.cc +++ b/source/blender/makesrna/intern/rna_material.cc @@ -152,7 +152,7 @@ static void rna_Material_active_paint_texture_index_update(bContext *C, PointerR Main *bmain = CTX_data_main(C); Material *ma = (Material *)ptr->owner_id; - if (ma->use_nodes && ma->nodetree) { + if (ma->nodetree) { bNode *node = BKE_texpaint_slot_material_find_node(ma, ma->paint_active_slot); if (node) { @@ -237,18 +237,18 @@ static void rna_Material_transparent_shadow_set(PointerRNA *ptr, bool new_value) material->blend_shadow = new_value ? MA_BS_HASHED : MA_BS_SOLID; } -static void rna_Material_use_nodes_update(bContext *C, PointerRNA *ptr) +static bool rna_Material_use_nodes_get(PointerRNA * /*ptr*/) { - Material *ma = (Material *)ptr->data; - Main *bmain = CTX_data_main(C); + /* #use_nodes is deprecated. All materials now use nodes. */ + return true; +} - if (ma->use_nodes && ma->nodetree == nullptr) { - ED_node_shader_default(C, &ma->id); - } - - DEG_id_tag_update(&ma->id, ID_RECALC_SYNC_TO_EVAL); - DEG_relations_tag_update(bmain); - rna_Material_draw_update(bmain, CTX_data_scene(C), ptr); +static void rna_Material_use_nodes_set(PointerRNA * /*ptr*/, bool /*new_value*/) +{ + /* #use_nodes is deprecated. Setting the property has no effect. + * Note: Users will get a warning through the RNA deprecation warning, so no need to log a + * warning here. */ + return; } MTex *rna_mtex_texture_slots_add(ID *self_id, bContext *C, ReportList *reports) @@ -1108,9 +1108,9 @@ void RNA_def_material(BlenderRNA *brna) prop = RNA_def_property(srna, "use_nodes", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, nullptr, "use_nodes", 1); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); - RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_ui_text(prop, "Use Nodes", "Use shader nodes to render the material"); - RNA_def_property_update(prop, 0, "rna_Material_use_nodes_update"); + RNA_def_property_boolean_funcs(prop, "rna_Material_use_nodes_get", "rna_Material_use_nodes_set"); + RNA_def_property_deprecated(prop, "Unused", 500, 600); /* common */ rna_def_animdata_common(srna); diff --git a/source/blender/nodes/shader/materialx/material.cc b/source/blender/nodes/shader/materialx/material.cc index 0f3abc30f93..60cdb99e958 100644 --- a/source/blender/nodes/shader/materialx/material.cc +++ b/source/blender/nodes/shader/materialx/material.cc @@ -62,31 +62,24 @@ MaterialX::DocumentPtr export_to_materialx(Depsgraph *depsgraph, NodeGraph graph(depsgraph, material, export_params, doc); - if (material->use_nodes) { - bNodeTree *local_tree = bke::node_tree_add_tree( - nullptr, "Inlined Tree", material->nodetree->idname); - BLI_SCOPED_DEFER([&]() { BKE_id_free(nullptr, &local_tree->id); }); + bNodeTree *local_tree = bke::node_tree_add_tree( + nullptr, "Inlined Tree", material->nodetree->idname); + BLI_SCOPED_DEFER([&]() { BKE_id_free(nullptr, &local_tree->id); }); - InlineShaderNodeTreeParams params; - inline_shader_node_tree(*material->nodetree, *local_tree, params); + InlineShaderNodeTreeParams params; + inline_shader_node_tree(*material->nodetree, *local_tree, params); - local_tree->ensure_topology_cache(); - bNode *output_node = ntreeShaderOutputNode(local_tree, SHD_OUTPUT_ALL); - if (output_node && output_node->typeinfo->materialx_fn) { - NodeParserData data = {graph, NodeItem::Type::Material, nullptr, graph.empty_node()}; - output_node->typeinfo->materialx_fn(&data, output_node, nullptr); - output_item = data.result; - } - else { - output_item = DefaultMaterialNodeParser( - graph, nullptr, nullptr, NodeItem::Type::Material, nullptr) - .compute_error(); - } + local_tree->ensure_topology_cache(); + bNode *output_node = ntreeShaderOutputNode(local_tree, SHD_OUTPUT_ALL); + if (output_node && output_node->typeinfo->materialx_fn) { + NodeParserData data = {graph, NodeItem::Type::Material, nullptr, graph.empty_node()}; + output_node->typeinfo->materialx_fn(&data, output_node, nullptr); + output_item = data.result; } else { output_item = DefaultMaterialNodeParser( graph, nullptr, nullptr, NodeItem::Type::Material, nullptr) - .compute(); + .compute_error(); } /* This node is expected to have a specific name to link up to USD. */ diff --git a/tests/files/io_tests/blend_scene/all_objects.blend b/tests/files/io_tests/blend_scene/all_objects.blend index c56ba645eba..30903d81879 100644 --- a/tests/files/io_tests/blend_scene/all_objects.blend +++ b/tests/files/io_tests/blend_scene/all_objects.blend @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:54d20834ac8cb33b06acd999a808de4e69f750217015af1e14047c47dff76b6a -size 134785 +oid sha256:9ece228c56be632b8a51ba79019ed32226a9e49736d371d74cd206cc316995cb +size 157108 diff --git a/tests/files/io_tests/fbx/bl_cube_material_viewport_display.fbx b/tests/files/io_tests/fbx/bl_cube_material_viewport_display.fbx new file mode 100644 index 00000000000..45a8edae903 --- /dev/null +++ b/tests/files/io_tests/fbx/bl_cube_material_viewport_display.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:239d2f0661b8d82bb0cb15ac3059410930a1cd436bed28ef0ea7702a378eeeb8 +size 15052 diff --git a/tests/files/io_tests/fbx/reference/bl_cube_material_viewport_display.txt b/tests/files/io_tests/fbx/reference/bl_cube_material_viewport_display.txt new file mode 100644 index 00000000000..16a373c0578 --- /dev/null +++ b/tests/files/io_tests/fbx/reference/bl_cube_material_viewport_display.txt @@ -0,0 +1,54 @@ +==== Meshes: 1 +- Mesh 'Cube.001' vtx:8 face:6 loop:24 edge:12 + - 0 1 3 2 2 ... 0 7 3 1 5 + - 0/1 1/3 2/3 0/2 3/7 ... 5/7 4/5 4/6 1/5 0/4 + - attr 'position' FLOAT_VECTOR POINT + - (-1.000, -1.000, -1.000) + - (-1.000, -1.000, 1.000) + - (-1.000, 1.000, -1.000) + ... + - (1.000, -1.000, 1.000) + - (1.000, 1.000, -1.000) + - (1.000, 1.000, 1.000) + - attr 'sharp_edge' BOOLEAN EDGE + - 1 1 1 1 1 ... 1 1 1 1 1 + - attr 'material_index' INT FACE + - 0 0 0 0 0 0 + - attr 'custom_normal' INT16_2D CORNER + - (0, 0) + - (0, 0) + - (0, 0) + ... + - (0, 0) + - (0, 0) + - (0, 0) + - attr 'UVMap' FLOAT2 CORNER + - (0.375, 0.000) + - (0.625, 0.000) + - (0.625, 0.250) + ... + - (0.875, 0.500) + - (0.875, 0.750) + - (0.625, 0.750) + - 1 materials + - 'Material.001' + +==== Objects: 1 +- Obj 'Cube' MESH data:'Cube.001' + - pos 0.000, 0.000, 0.000 + - rot 0.000, 0.000, 0.000 (XYZ) + - scl 1.000, 1.000, 1.000 + +==== Materials: 1 +- Mat 'Material.001' + - base color (0.000, 0.042, 0.800) + - specular ior 0.500 + - specular tint (1.000, 1.000, 1.000) + - roughness 0.300 + - metallic 0.700 + - ior 1.500 + - viewport diffuse (0.000, 0.042, 0.800, 1.000) + - viewport specular (1.000, 1.000, 1.000), intensity 0.500 + - viewport metallic 0.700, roughness 0.300 + - backface False probe True shadow False + diff --git a/tests/files/io_tests/obj/all_objects.mtl b/tests/files/io_tests/obj/all_objects.mtl index bd5dc7ab231..6851d4d6f30 100644 --- a/tests/files/io_tests/obj/all_objects.mtl +++ b/tests/files/io_tests/obj/all_objects.mtl @@ -7,7 +7,7 @@ Ka 1.000000 1.000000 1.000000 Kd 0.000000 0.000000 1.000000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -17,7 +17,7 @@ Ka 1.000000 1.000000 1.000000 Kd 0.000000 0.000000 0.500000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -27,7 +27,7 @@ Ka 1.000000 1.000000 1.000000 Kd 0.000000 1.000000 0.000000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -37,7 +37,7 @@ Ka 1.000000 1.000000 1.000000 Kd 0.000000 0.500000 0.000000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -47,7 +47,7 @@ Ka 1.000000 1.000000 1.000000 Kd 0.800000 0.800000 0.800000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -57,7 +57,7 @@ Ka 1.000000 1.000000 1.000000 Kd 1.000000 0.000000 0.000000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -67,6 +67,6 @@ Ka 1.000000 1.000000 1.000000 Kd 0.500000 0.000000 0.000000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 diff --git a/tests/files/io_tests/obj/all_objects_mat_groups.mtl b/tests/files/io_tests/obj/all_objects_mat_groups.mtl index bd5dc7ab231..6851d4d6f30 100644 --- a/tests/files/io_tests/obj/all_objects_mat_groups.mtl +++ b/tests/files/io_tests/obj/all_objects_mat_groups.mtl @@ -7,7 +7,7 @@ Ka 1.000000 1.000000 1.000000 Kd 0.000000 0.000000 1.000000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -17,7 +17,7 @@ Ka 1.000000 1.000000 1.000000 Kd 0.000000 0.000000 0.500000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -27,7 +27,7 @@ Ka 1.000000 1.000000 1.000000 Kd 0.000000 1.000000 0.000000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -37,7 +37,7 @@ Ka 1.000000 1.000000 1.000000 Kd 0.000000 0.500000 0.000000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -47,7 +47,7 @@ Ka 1.000000 1.000000 1.000000 Kd 0.800000 0.800000 0.800000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -57,7 +57,7 @@ Ka 1.000000 1.000000 1.000000 Kd 1.000000 0.000000 0.000000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 @@ -67,6 +67,6 @@ Ka 1.000000 1.000000 1.000000 Kd 0.500000 0.000000 0.000000 Ks 0.500000 0.500000 0.500000 Ke 0.000000 0.000000 0.000000 -Ni 1.000000 +Ni 1.450000 d 1.000000 illum 2 diff --git a/tests/files/io_tests/obj/reference/all_objects.txt b/tests/files/io_tests/obj/reference/all_objects.txt index 61a152c2f11..d9322fca5af 100644 --- a/tests/files/io_tests/obj/reference/all_objects.txt +++ b/tests/files/io_tests/obj/reference/all_objects.txt @@ -590,7 +590,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.000, 0.000, 1.000, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -602,7 +602,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.000, 0.000, 0.500, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -614,7 +614,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.000, 1.000, 0.000, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -626,7 +626,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.000, 0.500, 0.000, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -638,7 +638,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.800, 0.800, 0.800, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -650,7 +650,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (1.000, 0.000, 0.000, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -662,7 +662,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.500, 0.000, 0.000, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 diff --git a/tests/files/io_tests/obj/reference/all_objects_mat_groups.txt b/tests/files/io_tests/obj/reference/all_objects_mat_groups.txt index 4902a3a3675..39d471576e5 100644 --- a/tests/files/io_tests/obj/reference/all_objects_mat_groups.txt +++ b/tests/files/io_tests/obj/reference/all_objects_mat_groups.txt @@ -582,7 +582,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.000, 0.000, 1.000, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -594,7 +594,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.000, 0.000, 0.500, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -606,7 +606,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.000, 1.000, 0.000, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -618,7 +618,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.000, 0.500, 0.000, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -630,7 +630,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.800, 0.800, 0.800, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -642,7 +642,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (1.000, 0.000, 0.000, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 @@ -654,7 +654,7 @@ - specular tint (1.000, 1.000, 1.000) - roughness 0.500 - metallic 0.000 - - ior 1.000 + - ior 1.450 - viewport diffuse (0.500, 0.000, 0.000, 1.000) - viewport specular (1.000, 1.000, 1.000), intensity 0.500 - viewport metallic 0.000, roughness 0.500 diff --git a/tests/python/bl_blendfile_utils.py b/tests/python/bl_blendfile_utils.py index 30a62698443..65bccd54ec9 100644 --- a/tests/python/bl_blendfile_utils.py +++ b/tests/python/bl_blendfile_utils.py @@ -77,10 +77,11 @@ class TestBlendLibLinkHelper(TestHelper): ma = bpy.data.materials.new("LibMaterial") ma.use_fake_user = True - ma.use_nodes = True + out_node = ma.node_tree.nodes.new("ShaderNodeOutputMaterial") + bsdf_node = ma.node_tree.nodes.new("ShaderNodeBsdfPrincipled") + ma.node_tree.links.new(bsdf_node.outputs["BSDF"], out_node.inputs["Surface"]) teximage_node = ma.node_tree.nodes.new("ShaderNodeTexImage") teximage_node.image = im - bsdf_node = ma.node_tree.nodes["Principled BSDF"] ma.node_tree.links.new(bsdf_node.inputs["Base Color"], teximage_node.outputs["Color"]) def gen_library_data_(self): diff --git a/tests/python/bl_node_group_interface.py b/tests/python/bl_node_group_interface.py index af20fb10caa..4e59c552a10 100644 --- a/tests/python/bl_node_group_interface.py +++ b/tests/python/bl_node_group_interface.py @@ -384,7 +384,6 @@ class ShaderNodeGroupInterfaceTest(AbstractNodeGroupInterfaceTest, NodeGroupInte def setUp(self): super().setUp() self.material = bpy.data.materials.new("test") - self.material.use_nodes = True self.main_tree = self.material.node_tree def test_invalid_socket_type(self): @@ -476,7 +475,6 @@ class NodeTreeItemsIteratorTest(AbstractNodeGroupInterfaceTest, NodeGroupInterfa def setUp(self): super().setUp() self.material = bpy.data.materials.new("test") - self.material.use_nodes = True self.main_tree = self.material.node_tree # Regression test for changes while iterating over tree interface items (#143551). diff --git a/tests/python/bl_usd_export_test.py b/tests/python/bl_usd_export_test.py index 72212fb017b..cefc7e75a4a 100644 --- a/tests/python/bl_usd_export_test.py +++ b/tests/python/bl_usd_export_test.py @@ -1257,7 +1257,10 @@ class USDExportTest(AbstractUSDTest): # Create a simple scene with 1 object and 1 material bpy.ops.wm.open_mainfile(filepath=str(self.testdir / "empty.blend")) material = bpy.data.materials.new(name="test_material") - material.use_nodes = True + node_tree = material.node_tree + bsdf = node_tree.nodes.new("ShaderNodeBsdfPrincipled") + output = node_tree.nodes.new("ShaderNodeOutputMaterial") + node_tree.links.new(bsdf.outputs["BSDF"], output.inputs["Surface"]) bpy.ops.mesh.primitive_plane_add() bpy.data.objects[0].data.materials.append(material) diff --git a/tests/python/bl_usd_import_test.py b/tests/python/bl_usd_import_test.py index ba7e53871a3..98a54774640 100644 --- a/tests/python/bl_usd_import_test.py +++ b/tests/python/bl_usd_import_test.py @@ -1937,7 +1937,6 @@ class USDImportTest(AbstractUSDTest): def test_material_import_usd_hook(self): """Test importing color from an mtlx shader.""" - bpy.utils.register_class(ImportMtlxColorUSDHook) bpy.ops.wm.usd_import(filepath=str(self.testdir / "usd_simple_mtlx.usda")) bpy.utils.unregister_class(ImportMtlxColorUSDHook) @@ -1949,7 +1948,6 @@ class USDImportTest(AbstractUSDTest): # Check that a Principled BSDF shader with the expected Base Color input. # was created. mtl = bpy.data.materials["Material"] - self.assertTrue(mtl.use_nodes) bsdf = mtl.node_tree.nodes.get("Principled BSDF") self.assertIsNotNone(bsdf) base_color_input = bsdf.inputs['Base Color'] @@ -2112,11 +2110,12 @@ class ImportMtlxColorUSDHook(bpy.types.USDHook): # Add a Principled BSDF shader and set its 'Base Color' input to # the color we read from mtlx. - bl_material.use_nodes = True node_tree = bl_material.node_tree + assert node_tree nodes = node_tree.nodes - bsdf = nodes.get("Principled BSDF") - assert bsdf + bsdf = nodes.new("ShaderNodeBsdfPrincipled") + output = nodes.new("ShaderNodeOutputMaterial") + node_tree.links.new(bsdf.outputs["BSDF"], output.inputs["Surface"]) color4 = [color[0], color[1], color[2], 1] ImportMtlxColorUSDHook.imported_color = color4 bsdf.inputs['Base Color'].default_value = color4 diff --git a/tools/utils_doc/code_layout_diagram.py b/tools/utils_doc/code_layout_diagram.py index f57fa522ce6..02f1b717591 100644 --- a/tools/utils_doc/code_layout_diagram.py +++ b/tools/utils_doc/code_layout_diagram.py @@ -1080,15 +1080,14 @@ def main(): # Setup materials. material = bpy.data.materials.new("Flat Black") - material.use_nodes = False - material.specular_intensity = 0.0 - material.diffuse_color = (0.0, 0.0, 0.0, 1.0) MATERIAL_FROM_COLOR["black"] = material del material material = bpy.data.materials.new("Flat Grey") - material.use_nodes = False - material.specular_intensity = 0.0 - material.diffuse_color = (0.4, 0.4, 0.4, 1.0) + nodes = material.node_tree.nodes + bsdf = nodes.new("ShaderNodeBsdfPrincipled") + output = nodes.new("ShaderNodeOutputMaterial") + material.node_tree.links.new(bsdf.outputs["BSDF"], output.inputs["Surface"]) + bsdf.inputs['Base Color'].default_value = (0.4, 0.4, 0.4, 1.0) MATERIAL_FROM_COLOR["grey"] = material del material