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
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -1639,9 +1639,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
|
||||
unique_ptr<ShaderGraph> graph = make_unique<ShaderGraph>();
|
||||
|
||||
/* 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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<bNodeSocketValueRGBA>()->value[0] = world->horr;
|
||||
color_sock->default_value_typed<bNodeSocketValueRGBA>()->value[1] = world->horg;
|
||||
color_sock->default_value_typed<bNodeSocketValueRGBA>()->value[2] = world->horb;
|
||||
color_sock->default_value_typed<bNodeSocketValueRGBA>()->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.
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<bNodeSocketValueRGBA *>(
|
||||
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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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<bNodeSocket *> 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<bNodeSocket *> 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>();
|
||||
float const *input_color = color_input.default_value_typed<float>();
|
||||
intensity = strength[1];
|
||||
color = pxr::GfVec3f(input_color[0], input_color[1], input_color[2]);
|
||||
|
||||
float const *strength = strength_input.default_value_typed<float>();
|
||||
float const *input_color = color_input.default_value_typed<float>();
|
||||
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<NodeTexImage *>(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<NodeTexImage *>(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};
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user