From 445eceb02a3a3aa9ee38c3e2c05c2eff5db77f7e Mon Sep 17 00:00:00 2001 From: Habib Gahbiche Date: Mon, 28 Jul 2025 14:06:08 +0200 Subject: [PATCH] Nodes: Remove "Use Nodes" in Shader Editor for World Part of https://projects.blender.org/blender/blender/pulls/141278 Blend files compatibility: If a World exists and "Use Nodes" is disabled, we add new nodes to the existing node tree (or create one if it doesn't) that emulates the behavior of a world without a node tree. This ensures backward and forward compatibility. Python API compatibility: - `world.use_nodes` was removed from Python API => **Breaking change** - `world.color` is still being used by Workbench, so it stays there, although it has no effect anymore when using Cycles or EEVEE. Python API changes: Creating a World using `bpy.data.worlds.new()` now creates a World with an empty (embedded) node tree. This was necessary to enable Python scripts to add nodes without having to create a node tree (which is currently not possible, because World node trees are embedded). Pull Request: https://projects.blender.org/blender/blender/pulls/142342 --- intern/cycles/blender/addon/operators.py | 7 +- intern/cycles/blender/addon/ui.py | 2 +- intern/cycles/blender/shader.cpp | 4 +- scripts/startup/bl_operators/world.py | 2 +- scripts/startup/bl_ui/properties_world.py | 22 ++--- scripts/startup/bl_ui/space_node.py | 3 +- .../blender/blenkernel/BKE_blender_version.h | 2 +- source/blender/blenkernel/intern/image.cc | 2 +- .../blenloader/intern/versioning_500.cc | 60 +++++++++++++ .../draw/engines/eevee/eevee_lookdev.cc | 1 - .../blender/draw/engines/eevee/eevee_world.cc | 47 ++-------- .../blender/draw/engines/eevee/eevee_world.hh | 23 ----- source/blender/editors/include/ED_render.hh | 2 + .../blender/editors/render/render_preview.cc | 54 +++++++++--- .../blender/editors/render/render_shading.cc | 1 - .../blender/editors/space_node/node_edit.cc | 7 +- .../editors/space_node/node_shader_preview.cc | 8 +- source/blender/io/usd/hydra/world.cc | 85 +++++++++---------- .../io/usd/intern/usd_light_convert.cc | 10 +-- source/blender/makesdna/DNA_world_types.h | 3 +- .../blender/makesrna/intern/rna_main_api.cc | 3 + source/blender/makesrna/intern/rna_world.cc | 22 ----- tools/utils_doc/code_layout_diagram.py | 6 +- 23 files changed, 184 insertions(+), 192 deletions(-) diff --git a/intern/cycles/blender/addon/operators.py b/intern/cycles/blender/addon/operators.py index 25dbce0fb98..fcedb488b7f 100644 --- a/intern/cycles/blender/addon/operators.py +++ b/intern/cycles/blender/addon/operators.py @@ -12,20 +12,17 @@ from bpy.app.translations import pgettext_tip as tip_ class CYCLES_OT_use_shading_nodes(Operator): - """Enable nodes on a material, world or light""" + """Enable nodes on a material or light""" bl_idname = "cycles.use_shading_nodes" bl_label = "Use Nodes" @classmethod def poll(cls, context): - return (getattr(context, "material", False) or getattr(context, "world", False) or - getattr(context, "light", False)) + return (getattr(context, "material", False) or getattr(context, "light", False)) def execute(self, context): if context.material: context.material.use_nodes = True - elif context.world: - context.world.use_nodes = True elif context.light: context.light.use_nodes = True diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 1f5ed5c43e7..fde2d6aa610 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1456,7 +1456,7 @@ 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 not id_data.use_nodes: + if not isinstance(id_data, bpy.types.World) and not id_data.use_nodes: layout.operator("cycles.use_shading_nodes", icon='NODETREE') return False diff --git a/intern/cycles/blender/shader.cpp b/intern/cycles/blender/shader.cpp index 35ec99d04bb..f77558cc6a2 100644 --- a/intern/cycles/blender/shader.cpp +++ b/intern/cycles/blender/shader.cpp @@ -1639,9 +1639,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d, unique_ptr graph = make_unique(); /* create nodes */ - if (new_viewport_parameters.use_scene_world && b_world && b_world.use_nodes() && - b_world.node_tree()) - { + if (new_viewport_parameters.use_scene_world && b_world && b_world.node_tree()) { BL::ShaderNodeTree b_ntree(b_world.node_tree()); add_nodes(scene, b_engine, b_data, b_scene, graph.get(), b_ntree); diff --git a/scripts/startup/bl_operators/world.py b/scripts/startup/bl_operators/world.py index 48528dff2a8..282df36ff42 100644 --- a/scripts/startup/bl_operators/world.py +++ b/scripts/startup/bl_operators/world.py @@ -16,7 +16,7 @@ class WORLD_OT_convert_volume_to_mesh(bpy.types.Operator): @classmethod def poll(cls, context): world = cls._world_get(context) - if not world or not world.use_nodes: + if not world: return False ntree = world.node_tree diff --git a/scripts/startup/bl_ui/properties_world.py b/scripts/startup/bl_ui/properties_world.py index 8449f96eb39..e9ef89d841e 100644 --- a/scripts/startup/bl_ui/properties_world.py +++ b/scripts/startup/bl_ui/properties_world.py @@ -120,25 +120,21 @@ class EEVEE_WORLD_PT_surface(WorldButtonsPanel, Panel): world = context.world - layout.prop(world, "use_nodes", icon='NODETREE') layout.separator() layout.use_property_split = True - if world.use_nodes: - ntree = world.node_tree - node = ntree.get_output_node('EEVEE') + ntree = world.node_tree + node = ntree.get_output_node('EEVEE') - if node: - input = find_node_input(node, "Surface") - if input: - layout.template_node_view(ntree, node, input) - else: - layout.label(text="Incompatible output node") + if node: + input = find_node_input(node, "Surface") + if input: + layout.template_node_view(ntree, node, input) else: - layout.label(text="No output node") + layout.label(text="Incompatible output node") else: - layout.prop(world, "color") + layout.label(text="No output node") class EEVEE_WORLD_PT_volume(WorldButtonsPanel, Panel): @@ -151,7 +147,7 @@ class EEVEE_WORLD_PT_volume(WorldButtonsPanel, Panel): def poll(cls, context): engine = context.engine world = context.world - return world and world.use_nodes and (engine in cls.COMPAT_ENGINES) + return world and (engine in cls.COMPAT_ENGINES) 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 83e703914bb..c26819b8879 100644 --- a/scripts/startup/bl_ui/space_node.py +++ b/scripts/startup/bl_ui/space_node.py @@ -99,7 +99,8 @@ class NODE_HT_header(Header): if snode_id: row = layout.row() - row.prop(snode_id, "use_nodes") + if snode.shader_type != 'WORLD': + row.prop(snode_id, "use_nodes") if world and world.use_eevee_finite_volume: row.operator("world.convert_volume_to_mesh", emboss=False, icon='WORLD', text="Convert Volume") diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index 6acfd32bf7b..2e57bb4bd07 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 42 +#define BLENDER_FILE_SUBVERSION 43 /* 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 b2d90155927..f6aded56ff8 100644 --- a/source/blender/blenkernel/intern/image.cc +++ b/source/blender/blenkernel/intern/image.cc @@ -2951,7 +2951,7 @@ static void image_walk_id_all_users( } case ID_WO: { World *world = (World *)id; - if (world->nodetree && world->use_nodes && !skip_nested_nodes) { + if (world->nodetree && !skip_nested_nodes) { image_walk_ntree_all_users(world->nodetree, &world->id, customdata, callback); } image_walk_gpu_materials(id, &world->gpumaterial, customdata, callback); diff --git a/source/blender/blenloader/intern/versioning_500.cc b/source/blender/blenloader/intern/versioning_500.cc index 87f8815b907..df6a31ad47b 100644 --- a/source/blender/blenloader/intern/versioning_500.cc +++ b/source/blender/blenloader/intern/versioning_500.cc @@ -19,6 +19,7 @@ #include "DNA_rigidbody_types.h" #include "DNA_screen_types.h" #include "DNA_sequence_types.h" +#include "DNA_world_types.h" #include "BLI_listbase.h" #include "BLI_math_numbers.hh" @@ -1236,6 +1237,59 @@ static void update_format_media_type(ImageFormatData *format) } } +static void do_version_world_remove_use_nodes(Main *bmain, World *world) +{ + if (world->use_nodes == true) { + return; + } + + /* Users defined a world node tree, but deactivated it by disabling "Use Nodes". So we + * simulate the same effect by creating a new World Output node and setting it to active. */ + bNodeTree *ntree = world->nodetree; + if (ntree == nullptr) { + /* In case the world was defined through Python API it might have been missing a node tree. */ + ntree = blender::bke::node_tree_add_tree_embedded( + bmain, &world->id, "World Node Tree Versioning", "ShaderNodeTree"); + } + + bNode *old_output = nullptr; + LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { + if (STREQ(node->idname, "ShaderNodeOutputWorld") && (node->flag & NODE_DO_OUTPUT)) { + old_output = node; + old_output->flag &= ~NODE_DO_OUTPUT; + } + } + + bNode *new_output = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_OUTPUT_WORLD); + new_output->flag |= NODE_DO_OUTPUT; + bNode *background = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_BACKGROUND); + version_node_add_link(*ntree, + *background, + *blender::bke::node_find_socket(*background, SOCK_OUT, "Background"), + *new_output, + *blender::bke::node_find_socket(*new_output, SOCK_IN, "Surface")); + + bNodeSocket *color_sock = blender::bke::node_find_socket(*background, SOCK_IN, "Color"); + color_sock->default_value_typed()->value[0] = world->horr; + color_sock->default_value_typed()->value[1] = world->horg; + color_sock->default_value_typed()->value[2] = world->horb; + color_sock->default_value_typed()->value[3] = 1.0f; + + 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. */ + background->location[0] = old_output->location[0] + 1.5f * old_output->width; + background->location[1] = old_output->location[1]; + } + + new_output->location[0] = background->location[0] + 2.0f * background->width; + new_output->location[1] = background->location[1]; + + bNode *frame = blender::bke::node_add_static_node(nullptr, *ntree, NODE_FRAME); + background->parent = frame; + new_output->parent = frame; +} + void do_versions_after_linking_500(FileData *fd, Main *bmain) { if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 9)) { @@ -1692,6 +1746,12 @@ void blo_do_versions_500(FileData * /*fd*/, Library * /*lib*/, Main *bmain) FOREACH_NODETREE_END; } + if (!MAIN_VERSION_FILE_ATLEAST(bmain, 500, 43)) { + LISTBASE_FOREACH (World *, world, &bmain->worlds) { + do_version_world_remove_use_nodes(bmain, world); + } + } + /** * 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_lookdev.cc b/source/blender/draw/engines/eevee/eevee_lookdev.cc index 18c9bd75b53..2bc41980b31 100644 --- a/source/blender/draw/engines/eevee/eevee_lookdev.cc +++ b/source/blender/draw/engines/eevee/eevee_lookdev.cc @@ -68,7 +68,6 @@ LookdevWorld::LookdevWorld() bke::node_add_link(*ntree, *background, *background_out, *output, *output_in); bke::node_set_active(*ntree, *output); - world->use_nodes = true; world->nodetree = ntree; /* Create a dummy image data block to hold GPU textures generated by studio-lights. */ diff --git a/source/blender/draw/engines/eevee/eevee_world.cc b/source/blender/draw/engines/eevee/eevee_world.cc index 3b64de054df..c87af23b4e0 100644 --- a/source/blender/draw/engines/eevee/eevee_world.cc +++ b/source/blender/draw/engines/eevee/eevee_world.cc @@ -16,41 +16,6 @@ namespace blender::eevee { -/* -------------------------------------------------------------------- */ -/** \name Default Material - * - * \{ */ - -DefaultWorldNodeTree::DefaultWorldNodeTree() -{ - bNodeTree *ntree = bke::node_tree_add_tree(nullptr, "World Nodetree", ntreeType_Shader->idname); - bNode *background = bke::node_add_static_node(nullptr, *ntree, SH_NODE_BACKGROUND); - bNode *output = bke::node_add_static_node(nullptr, *ntree, SH_NODE_OUTPUT_WORLD); - bNodeSocket *background_out = bke::node_find_socket(*background, SOCK_OUT, "Background"); - bNodeSocket *output_in = bke::node_find_socket(*output, SOCK_IN, "Surface"); - bke::node_add_link(*ntree, *background, *background_out, *output, *output_in); - bke::node_set_active(*ntree, *output); - - color_socket_ = - (bNodeSocketValueRGBA *)bke::node_find_socket(*background, SOCK_IN, "Color")->default_value; - ntree_ = ntree; -} - -DefaultWorldNodeTree::~DefaultWorldNodeTree() -{ - bke::node_tree_free_embedded_tree(ntree_); - MEM_SAFE_FREE(ntree_); -} - -bNodeTree *DefaultWorldNodeTree::nodetree_get(::World *wo) -{ - /* WARNING: This function is not thread-safe. Which is not a problem for the moment. */ - copy_v3_fl3(color_socket_->value, wo->horr, wo->horg, wo->horb); - return ntree_; -} - -/** \} */ - /* -------------------------------------------------------------------- */ /** \name World * @@ -67,9 +32,9 @@ World::~World() { if (default_world_ == nullptr) { default_world_ = BKE_id_new_nomain<::World>("EEVEE default world"); - default_world_->horr = default_world_->horg = default_world_->horb = 0.0f; - default_world_->use_nodes = 0; - default_world_->nodetree = nullptr; + default_world_->nodetree = bke::node_tree_add_tree_embedded( + nullptr, &default_world_->id, "World Nodetree", ntreeType_Shader->idname); + BLI_listbase_clear(&default_world_->gpumaterial); } return default_world_; @@ -131,9 +96,7 @@ void World::sync() bl_world = world_override; } - bNodeTree *ntree = (bl_world->nodetree && bl_world->use_nodes) ? - bl_world->nodetree : - default_tree.nodetree_get(bl_world); + bNodeTree *ntree = (bl_world->nodetree) ? bl_world->nodetree : default_world_get()->nodetree; { if (has_volume_absorption_) { @@ -181,7 +144,7 @@ void World::sync_volume(const WorldHandle &world_handle, bool wait_ready) GPUMaterial *gpumat = nullptr; /* Only the scene world nodetree can have volume shader. */ - if (world && world->nodetree && world->use_nodes) { + if (world && world->nodetree) { gpumat = inst_.shaders.world_shader_get( world, world->nodetree, MAT_PIPE_VOLUME_MATERIAL, !wait_ready); } diff --git a/source/blender/draw/engines/eevee/eevee_world.hh b/source/blender/draw/engines/eevee/eevee_world.hh index 61efe4d6b28..b3f967c2ec0 100644 --- a/source/blender/draw/engines/eevee/eevee_world.hh +++ b/source/blender/draw/engines/eevee/eevee_world.hh @@ -24,27 +24,6 @@ namespace blender::eevee { class Instance; -/* -------------------------------------------------------------------- */ -/** \name Default World Node-Tree - * - * In order to support worlds without node-tree we reuse and configure a standalone node-tree that - * we pass for shader generation. The GPUMaterial is still stored inside the World even if - * it does not use a node-tree. - * \{ */ - -class DefaultWorldNodeTree { - private: - bNodeTree *ntree_; - bNodeSocketValueRGBA *color_socket_; - - public: - DefaultWorldNodeTree(); - ~DefaultWorldNodeTree(); - - /** Configure a default node-tree with the given world. */ - bNodeTree *nodetree_get(::World *world); -}; - /** \} */ /* -------------------------------------------------------------------- */ @@ -63,8 +42,6 @@ class World { private: Instance &inst_; - DefaultWorldNodeTree default_tree; - /* Used to detect if world change. */ ::World *prev_original_world = nullptr; diff --git a/source/blender/editors/include/ED_render.hh b/source/blender/editors/include/ED_render.hh index 2b986b1f25b..6af9f747c2b 100644 --- a/source/blender/editors/include/ED_render.hh +++ b/source/blender/editors/include/ED_render.hh @@ -94,6 +94,8 @@ World *ED_preview_prepare_world(Main *pr_main, const World *world, ID_Type id_type, ePreviewRenderMethod pr_method); +World *ED_preview_prepare_world_simple(Main *bmain); +void ED_preview_world_simple_set_rgb(World *world, const float color[4]); void ED_preview_shader_job(const bContext *C, void *owner, diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index 1b6c5055b5f..99509b9fbd7 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -370,6 +370,40 @@ static World *preview_get_localized_world(ShaderPreview *sp, World *world) return sp->worldcopy; } +World *ED_preview_prepare_world_simple(Main *pr_main) +{ + using namespace blender::bke; + + World *world = BKE_world_add(pr_main, "SimpleWorld"); + bNodeTree *ntree = world->nodetree; + ntree = blender::bke::node_tree_add_tree_embedded( + nullptr, &world->id, "World Nodetree", "ShaderNodeTree"); + + bNode *background = node_add_node(nullptr, *ntree, "ShaderNodeBackground"); + bNode *output = node_add_node(nullptr, *ntree, "ShaderNodeOutputWorld"); + node_add_link(*world->nodetree, + *background, + *node_find_socket(*background, SOCK_OUT, "Background"), + *output, + *node_find_socket(*output, SOCK_IN, "Surface")); + node_set_active(*ntree, *output); + + world->nodetree = ntree; + return world; +} + +void ED_preview_world_simple_set_rgb(World *world, const float color[4]) +{ + BLI_assert(world != nullptr); + + bNode *background = blender::bke::node_find_node_by_name(*world->nodetree, "Background"); + BLI_assert(background != nullptr); + + auto color_socket = static_cast( + blender::bke::node_find_socket(*background, SOCK_IN, "Color")->default_value); + copy_v4_v4(color_socket->value, color); +} + static ID *duplicate_ids(ID *id, const bool allow_failure) { if (id == nullptr) { @@ -534,17 +568,16 @@ static Scene *preview_prepare_scene( else if (sce->world && sp->pr_method != PR_ICON_RENDER) { /* Use a default world color. Using the current * scene world can be slow if it has big textures. */ - sce->world->use_nodes = false; + sce->world = ED_preview_prepare_world_simple(sp->bmain); + /* Use brighter world color for grease pencil. */ if (sp->pr_main == G_pr_main_grease_pencil) { - sce->world->horr = 1.0f; - sce->world->horg = 1.0f; - sce->world->horb = 1.0f; + const float white[4] = {1.0f, 1.0f, 1.0f, 1.0f}; + ED_preview_world_simple_set_rgb(sce->world, white); } else { - sce->world->horr = 0.05f; - sce->world->horg = 0.05f; - sce->world->horb = 0.05f; + const float dark[4] = {0.05f, 0.05f, 0.05f, 0.05f}; + ED_preview_world_simple_set_rgb(sce->world, dark); } } @@ -601,10 +634,9 @@ static Scene *preview_prepare_scene( if (sce->world) { /* Only use lighting from the light. */ - sce->world->use_nodes = false; - sce->world->horr = 0.0f; - sce->world->horg = 0.0f; - sce->world->horb = 0.0f; + sce->world = ED_preview_prepare_world_simple(pr_main); + const float black[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + ED_preview_world_simple_set_rgb(sce->world, black); } BKE_view_layer_synced_ensure(sce, view_layer); diff --git a/source/blender/editors/render/render_shading.cc b/source/blender/editors/render/render_shading.cc index a934166f7a6..36031b5c56e 100644 --- a/source/blender/editors/render/render_shading.cc +++ b/source/blender/editors/render/render_shading.cc @@ -983,7 +983,6 @@ static wmOperatorStatus new_world_exec(bContext *C, wmOperator * /*op*/) else { wo = BKE_world_add(bmain, CTX_DATA_(BLT_I18NCONTEXT_ID_WORLD, "World")); ED_node_shader_default(C, &wo->id); - wo->use_nodes = true; } /* hook into UI */ diff --git a/source/blender/editors/space_node/node_edit.cc b/source/blender/editors/space_node/node_edit.cc index 9e35c616471..b9546ce3a8c 100644 --- a/source/blender/editors/space_node/node_edit.cc +++ b/source/blender/editors/space_node/node_edit.cc @@ -538,12 +538,13 @@ void ED_node_shader_default(const bContext *C, ID *id) } else if (ELEM(GS(id->name), ID_WO, ID_LA)) { /* Emission */ + bNode *shader, *output; bNodeTree *ntree = blender::bke::node_tree_add_tree_embedded( nullptr, id, "Shader Nodetree", ntreeType_Shader->idname); - bNode *shader, *output; if (GS(id->name) == ID_WO) { World *world = (World *)id; + ntree = world->nodetree; shader = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_BACKGROUND); output = blender::bke::node_add_static_node(nullptr, *ntree, SH_NODE_OUTPUT_WORLD); @@ -799,9 +800,7 @@ void ED_node_set_active( } LISTBASE_FOREACH (World *, wo, &bmain->worlds) { - if (wo->nodetree && wo->use_nodes && - blender::bke::node_tree_contains_tree(*wo->nodetree, *ntree)) - { + if (wo->nodetree && blender::bke::node_tree_contains_tree(*wo->nodetree, *ntree)) { GPU_material_free(&wo->gpumaterial); } } diff --git a/source/blender/editors/space_node/node_shader_preview.cc b/source/blender/editors/space_node/node_shader_preview.cc index 388f910039a..2c2e7022de6 100644 --- a/source/blender/editors/space_node/node_shader_preview.cc +++ b/source/blender/editors/space_node/node_shader_preview.cc @@ -212,14 +212,10 @@ static Scene *preview_prepare_scene(const Main *bmain, scene_preview->r.cfra = scene_orig->r.cfra; /* Setup the world. */ - scene_preview->world = ED_preview_prepare_world( - pr_main, scene_preview, scene_orig->world, ID_MA, PR_BUTS_RENDER); + scene_preview->world = ED_preview_prepare_world_simple(pr_main); + ED_preview_world_simple_set_rgb(scene_preview->world, float4{0.05f, 0.05f, 0.05f, 0.05f}); BLI_addtail(&pr_main->materials, mat_copy); - scene_preview->world->use_nodes = false; - scene_preview->world->horr = 0.05f; - scene_preview->world->horg = 0.05f; - scene_preview->world->horb = 0.05f; ED_preview_set_visibility(pr_main, scene_preview, view_layer, preview_type, PR_BUTS_RENDER); diff --git a/source/blender/io/usd/hydra/world.cc b/source/blender/io/usd/hydra/world.cc index 3c297042935..fe6014b5c21 100644 --- a/source/blender/io/usd/hydra/world.cc +++ b/source/blender/io/usd/hydra/world.cc @@ -53,62 +53,55 @@ void WorldData::init() pxr::GfVec3f color(1.0f, 1.0f, 1.0f); ID_LOG("%s", world->id.name); - if (world->use_nodes) { - /* TODO: Create nodes parsing system */ + /* TODO: Create nodes parsing system */ + bNode *output_node = ntreeShaderOutputNode(world->nodetree, SHD_OUTPUT_ALL); + if (!output_node) { + return; + } + const Span input_sockets = output_node->input_sockets(); + bNodeSocket *input_socket = nullptr; - bNode *output_node = ntreeShaderOutputNode(world->nodetree, SHD_OUTPUT_ALL); - if (!output_node) { - return; + for (auto *socket : input_sockets) { + if (STREQ(socket->name, "Surface")) { + input_socket = socket; + break; } - const Span input_sockets = output_node->input_sockets(); - bNodeSocket *input_socket = nullptr; + } + if (!input_socket) { + return; + } + if (input_socket->directly_linked_links().is_empty()) { + return; + } + bNodeLink const *link = input_socket->directly_linked_links()[0]; - for (auto *socket : input_sockets) { - if (STREQ(socket->name, "Surface")) { - input_socket = socket; - break; - } - } - if (!input_socket) { - return; - } - if (input_socket->directly_linked_links().is_empty()) { - return; - } - bNodeLink const *link = input_socket->directly_linked_links()[0]; + bNode *input_node = link->fromnode; + if (input_node->type_legacy != SH_NODE_BACKGROUND) { + return; + } - bNode *input_node = link->fromnode; - if (input_node->type_legacy != SH_NODE_BACKGROUND) { - return; - } + const bNodeSocket &color_input = input_node->input_by_identifier("Color"); + const bNodeSocket &strength_input = input_node->input_by_identifier("Strength"); - const bNodeSocket &color_input = input_node->input_by_identifier("Color"); - const bNodeSocket &strength_input = input_node->input_by_identifier("Strength"); + float const *strength = strength_input.default_value_typed(); + float const *input_color = color_input.default_value_typed(); + intensity = strength[1]; + color = pxr::GfVec3f(input_color[0], input_color[1], input_color[2]); - float const *strength = strength_input.default_value_typed(); - float const *input_color = color_input.default_value_typed(); - intensity = strength[1]; - color = pxr::GfVec3f(input_color[0], input_color[1], input_color[2]); - - if (!color_input.directly_linked_links().is_empty()) { - bNode *color_input_node = color_input.directly_linked_links()[0]->fromnode; - if (ELEM(color_input_node->type_legacy, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) { - NodeTexImage *tex = static_cast(color_input_node->storage); - Image *image = (Image *)color_input_node->id; - if (image) { - std::string image_path = cache_or_get_image_file( - scene_delegate_->bmain, scene_delegate_->scene, image, &tex->iuser); - if (!image_path.empty()) { - texture_file = pxr::SdfAssetPath(image_path, image_path); - } + if (!color_input.directly_linked_links().is_empty()) { + bNode *color_input_node = color_input.directly_linked_links()[0]->fromnode; + if (ELEM(color_input_node->type_legacy, SH_NODE_TEX_IMAGE, SH_NODE_TEX_ENVIRONMENT)) { + NodeTexImage *tex = static_cast(color_input_node->storage); + Image *image = (Image *)color_input_node->id; + if (image) { + std::string image_path = cache_or_get_image_file( + scene_delegate_->bmain, scene_delegate_->scene, image, &tex->iuser); + if (!image_path.empty()) { + texture_file = pxr::SdfAssetPath(image_path, image_path); } } } } - else { - intensity = 1.0f; - color = pxr::GfVec3f(world->horr, world->horg, world->horb); - } if (texture_file.GetAssetPath().empty()) { float fill_color[4] = {color[0], color[1], color[2], 1.0f}; diff --git a/source/blender/io/usd/intern/usd_light_convert.cc b/source/blender/io/usd/intern/usd_light_convert.cc index 91a84c38a1f..7a0d872d0b4 100644 --- a/source/blender/io/usd/intern/usd_light_convert.cc +++ b/source/blender/io/usd/intern/usd_light_convert.cc @@ -233,7 +233,7 @@ void world_material_to_dome_light(const USDExportParams ¶ms, WorldNtreeSearchResults res(params, stage); - if (scene->world->use_nodes && scene->world->nodetree) { + if (scene->world->nodetree) { /* Find the world output. */ bNode *output = nullptr; const bNodeTree *ntree = scene->world->nodetree; @@ -255,8 +255,8 @@ void world_material_to_dome_light(const USDExportParams ¶ms, } else { res.world_intensity = 1.0f; - copy_v3_v3(res.world_color, &scene->world->horr); - res.background_found = !is_zero_v3(res.world_color); + zero_v3(res.world_color); + res.background_found = false; } if (!(res.background_found || res.env_tex_found)) { @@ -356,10 +356,6 @@ void dome_light_to_world_material(const USDImportParams ¶ms, return; } - if (!scene->world->use_nodes) { - scene->world->use_nodes = true; - } - if (!scene->world->nodetree) { scene->world->nodetree = bke::node_tree_add_tree_embedded( nullptr, &scene->world->id, "Shader Nodetree", "ShaderNodeTree"); diff --git a/source/blender/makesdna/DNA_world_types.h b/source/blender/makesdna/DNA_world_types.h index 34b382517cf..87ec6e63a4c 100644 --- a/source/blender/makesdna/DNA_world_types.h +++ b/source/blender/makesdna/DNA_world_types.h @@ -78,7 +78,8 @@ typedef struct World { /** Old animation system, deprecated for 2.5. */ struct Ipo *ipo DNA_DEPRECATED; - short pr_texture, use_nodes; + short pr_texture; + short use_nodes DNA_DEPRECATED; char _pad[4]; /* previews */ diff --git a/source/blender/makesrna/intern/rna_main_api.cc b/source/blender/makesrna/intern/rna_main_api.cc index 4d4e18539a4..1cea5eed10e 100644 --- a/source/blender/makesrna/intern/rna_main_api.cc +++ b/source/blender/makesrna/intern/rna_main_api.cc @@ -522,6 +522,9 @@ static World *rna_Main_worlds_new(Main *bmain, const char *name) World *world = BKE_world_add(bmain, safe_name); id_us_min(&world->id); + world->nodetree = blender::bke::node_tree_add_tree_embedded( + bmain, &world->id, "World Node Tree", "ShaderNodeTree"); + WM_main_add_notifier(NC_ID | NA_ADDED, nullptr); return world; diff --git a/source/blender/makesrna/intern/rna_world.cc b/source/blender/makesrna/intern/rna_world.cc index 5b725b11277..d6ae7731ea2 100644 --- a/source/blender/makesrna/intern/rna_world.cc +++ b/source/blender/makesrna/intern/rna_world.cc @@ -70,21 +70,6 @@ static void rna_World_draw_update(Main * /*bmain*/, Scene * /*scene*/, PointerRN WM_main_add_notifier(NC_OBJECT | ND_DRAW, nullptr); } -static void rna_World_use_nodes_update(bContext *C, PointerRNA *ptr) -{ - World *wrld = (World *)ptr->data; - Main *bmain = CTX_data_main(C); - Scene *scene = CTX_data_scene(C); - - if (wrld->use_nodes && wrld->nodetree == nullptr) { - ED_node_shader_default(C, &wrld->id); - } - - DEG_relations_tag_update(bmain); - rna_World_update(bmain, scene, ptr); - rna_World_draw_update(bmain, scene, ptr); -} - void rna_World_lightgroup_get(PointerRNA *ptr, char *value) { LightgroupMembership *lgm = ((World *)ptr->owner_id)->lightgroup; @@ -258,13 +243,6 @@ void RNA_def_world(BlenderRNA *brna) RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY); RNA_def_property_ui_text(prop, "Node Tree", "Node tree for node based worlds"); - 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 world"); - RNA_def_property_update(prop, 0, "rna_World_use_nodes_update"); - /* Lightgroup Membership */ prop = RNA_def_property(srna, "lightgroup", PROP_STRING, PROP_NONE); RNA_def_property_string_funcs( diff --git a/tools/utils_doc/code_layout_diagram.py b/tools/utils_doc/code_layout_diagram.py index 73c01229f0e..f57fa522ce6 100644 --- a/tools/utils_doc/code_layout_diagram.py +++ b/tools/utils_doc/code_layout_diagram.py @@ -934,8 +934,10 @@ def render_output(scene, bounds, filepath): scene.render.filepath = filepath world = bpy.data.worlds.new(name_gen) - world.color = 1.0, 1.0, 1.0 - world.use_nodes = False + output = world.node_tree.nodes.new("ShaderNodeOutputWorld") + background = world.node_tree.nodes.new("ShaderNodeBackground") + world.node_tree.links.new(output.outputs["Surface"], background.outputs["Surface"]) + background.inputs["Color"].default_value = 1.0, 1.0, 1.0, 1.0 scene.world = world # Some space around the edges.