Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/render')
-rw-r--r--intern/cycles/render/graph.cpp32
-rw-r--r--intern/cycles/render/graph.h30
-rw-r--r--intern/cycles/render/nodes.cpp49
-rw-r--r--intern/cycles/render/nodes.h12
-rw-r--r--intern/cycles/render/osl.cpp5
-rw-r--r--intern/cycles/render/osl.h3
-rw-r--r--intern/cycles/render/particles.cpp8
-rw-r--r--intern/cycles/render/particles.h6
-rw-r--r--intern/cycles/render/scene.cpp134
-rw-r--r--intern/cycles/render/scene.h72
-rw-r--r--intern/cycles/render/shader.cpp21
11 files changed, 297 insertions, 75 deletions
diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp
index 1b138455515..684fe6a82c4 100644
--- a/intern/cycles/render/graph.cpp
+++ b/intern/cycles/render/graph.cpp
@@ -221,7 +221,7 @@ ShaderGraph::ShaderGraph()
finalized = false;
simplified = false;
num_node_ids = 0;
- add(new OutputNode());
+ add(create_node<OutputNode>());
}
ShaderGraph::~ShaderGraph()
@@ -272,7 +272,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
ShaderInput *convert_in;
if (to->type() == SocketType::CLOSURE) {
- EmissionNode *emission = new EmissionNode();
+ EmissionNode *emission = create_node<EmissionNode>();
emission->color = make_float3(1.0f, 1.0f, 1.0f);
emission->strength = 1.0f;
convert = add(emission);
@@ -285,7 +285,7 @@ void ShaderGraph::connect(ShaderOutput *from, ShaderInput *to)
}
}
else {
- convert = add(new ConvertNode(from->type(), to->type(), true));
+ convert = add(create_node<ConvertNode>(from->type(), to->type(), true));
convert_in = convert->inputs[0];
}
@@ -416,7 +416,7 @@ void ShaderGraph::find_dependencies(ShaderNodeSet &dependencies, ShaderInput *in
void ShaderGraph::clear_nodes()
{
foreach (ShaderNode *node, nodes) {
- delete node;
+ delete_node(node);
}
nodes.clear();
}
@@ -428,7 +428,7 @@ void ShaderGraph::copy_nodes(ShaderNodeSet &nodes, ShaderNodeMap &nnodemap)
/* copy nodes */
foreach (ShaderNode *node, nodes) {
- ShaderNode *nnode = node->clone();
+ ShaderNode *nnode = node->clone(this);
nnodemap[node] = nnode;
/* create new inputs and outputs to recreate links and ensure
@@ -523,7 +523,7 @@ void ShaderGraph::remove_proxy_nodes()
if (!removed[node->id])
newnodes.push_back(node);
else
- delete node;
+ delete_node(node);
}
nodes = newnodes;
@@ -821,7 +821,7 @@ void ShaderGraph::clean(Scene *scene)
if (visited[node->id])
newnodes.push_back(node);
else
- delete node;
+ delete_node(node);
}
nodes = newnodes;
@@ -848,43 +848,43 @@ void ShaderGraph::default_inputs(bool do_osl)
if (!input->link && (!(input->flags() & SocketType::OSL_INTERNAL) || do_osl)) {
if (input->flags() & SocketType::LINK_TEXTURE_GENERATED) {
if (!texco)
- texco = new TextureCoordinateNode();
+ texco = create_node<TextureCoordinateNode>();
connect(texco->output("Generated"), input);
}
if (input->flags() & SocketType::LINK_TEXTURE_NORMAL) {
if (!texco)
- texco = new TextureCoordinateNode();
+ texco = create_node<TextureCoordinateNode>();
connect(texco->output("Normal"), input);
}
else if (input->flags() & SocketType::LINK_TEXTURE_UV) {
if (!texco)
- texco = new TextureCoordinateNode();
+ texco = create_node<TextureCoordinateNode>();
connect(texco->output("UV"), input);
}
else if (input->flags() & SocketType::LINK_INCOMING) {
if (!geom)
- geom = new GeometryNode();
+ geom = create_node<GeometryNode>();
connect(geom->output("Incoming"), input);
}
else if (input->flags() & SocketType::LINK_NORMAL) {
if (!geom)
- geom = new GeometryNode();
+ geom = create_node<GeometryNode>();
connect(geom->output("Normal"), input);
}
else if (input->flags() & SocketType::LINK_POSITION) {
if (!geom)
- geom = new GeometryNode();
+ geom = create_node<GeometryNode>();
connect(geom->output("Position"), input);
}
else if (input->flags() & SocketType::LINK_TANGENT) {
if (!geom)
- geom = new GeometryNode();
+ geom = create_node<GeometryNode>();
connect(geom->output("Tangent"), input);
}
@@ -1064,7 +1064,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
if (fin) {
/* mix closure: add node to mix closure weights */
- MixClosureWeightNode *mix_node = new MixClosureWeightNode();
+ MixClosureWeightNode *mix_node = create_node<MixClosureWeightNode>();
add(mix_node);
ShaderInput *fac_in = mix_node->input("Fac");
ShaderInput *weight_in = mix_node->input("Weight");
@@ -1101,7 +1101,7 @@ void ShaderGraph::transform_multi_closure(ShaderNode *node, ShaderOutput *weight
/* already has a weight connected to it? add weights */
float weight_value = node->get_float(weight_in->socket_type);
if (weight_in->link || weight_value != 0.0f) {
- MathNode *math_node = new MathNode();
+ MathNode *math_node = create_node<MathNode>();
add(math_node);
if (weight_in->link)
diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h
index febd7a76f03..f6ee708b3f8 100644
--- a/intern/cycles/render/graph.h
+++ b/intern/cycles/render/graph.h
@@ -159,7 +159,7 @@ class ShaderNode : public Node {
ShaderInput *input(ustring name);
ShaderOutput *output(ustring name);
- virtual ShaderNode *clone() const = 0;
+ virtual ShaderNode *clone(ShaderGraph *graph) const = 0;
virtual void attributes(Shader *shader, AttributeRequestSet *attributes);
virtual void compile(SVMCompiler &compiler) = 0;
virtual void compile(OSLCompiler &compiler) = 0;
@@ -275,9 +275,9 @@ class ShaderNode : public Node {
#define SHADER_NODE_CLASS(type) \
NODE_DECLARE \
type(); \
- virtual ShaderNode *clone() const \
+ virtual ShaderNode *clone(ShaderGraph *graph) const \
{ \
- return new type(*this); \
+ return graph->create_node<type>(*this); \
} \
virtual void compile(SVMCompiler &compiler); \
virtual void compile(OSLCompiler &compiler);
@@ -289,9 +289,9 @@ class ShaderNode : public Node {
virtual void compile(OSLCompiler &compiler);
#define SHADER_NODE_BASE_CLASS(type) \
- virtual ShaderNode *clone() const \
+ virtual ShaderNode *clone(ShaderGraph *graph) const \
{ \
- return new type(*this); \
+ return graph->create_node<type>(*this); \
} \
virtual void compile(SVMCompiler &compiler); \
virtual void compile(OSLCompiler &compiler);
@@ -312,7 +312,7 @@ typedef map<ShaderNode *, ShaderNode *, ShaderNodeIDComparator> ShaderNodeMap;
* Shader graph of nodes. Also does graph manipulations for default inputs,
* bump mapping from displacement, and possibly other things in the future. */
-class ShaderGraph {
+class ShaderGraph : public NodeOwner {
public:
list<ShaderNode *> nodes;
size_t num_node_ids;
@@ -345,6 +345,24 @@ class ShaderGraph {
void dump_graph(const char *filename);
+ /* This function is used to create a node of a specified type instead of
+ * calling 'new', and sets the graph as the owner of the node.
+ */
+ template<typename T, typename... Args> T *create_node(Args &&... args)
+ {
+ T *node = new T(args...);
+ node->set_owner(this);
+ return node;
+ }
+
+ /* This function is used to delete a node created and owned by the graph.
+ */
+ template<typename T> void delete_node(T *node)
+ {
+ assert(node->get_owner() == this);
+ delete node;
+ }
+
protected:
typedef pair<ShaderNode *const, ShaderNode *> NodePair;
diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp
index f62d64a7eb3..de32ce53ad7 100644
--- a/intern/cycles/render/nodes.cpp
+++ b/intern/cycles/render/nodes.cpp
@@ -262,9 +262,9 @@ ImageTextureNode::ImageTextureNode() : ImageSlotTextureNode(node_type)
tiles.push_back(1001);
}
-ShaderNode *ImageTextureNode::clone() const
+ShaderNode *ImageTextureNode::clone(ShaderGraph *graph) const
{
- ImageTextureNode *node = new ImageTextureNode(*this);
+ ImageTextureNode *node = graph->create_node<ImageTextureNode>(*this);
node->handle = handle;
return node;
}
@@ -525,9 +525,9 @@ EnvironmentTextureNode::EnvironmentTextureNode() : ImageSlotTextureNode(node_typ
animated = false;
}
-ShaderNode *EnvironmentTextureNode::clone() const
+ShaderNode *EnvironmentTextureNode::clone(ShaderGraph *graph) const
{
- EnvironmentTextureNode *node = new EnvironmentTextureNode(*this);
+ EnvironmentTextureNode *node = graph->create_node<EnvironmentTextureNode>(*this);
node->handle = handle;
return node;
}
@@ -1234,9 +1234,9 @@ IESLightNode::IESLightNode() : TextureNode(node_type)
slot = -1;
}
-ShaderNode *IESLightNode::clone() const
+ShaderNode *IESLightNode::clone(ShaderGraph *graph) const
{
- IESLightNode *node = new IESLightNode(*this);
+ IESLightNode *node = graph->create_node<IESLightNode>(*this);
node->light_manager = NULL;
node->slot = -1;
@@ -1782,12 +1782,12 @@ PointDensityTextureNode::~PointDensityTextureNode()
{
}
-ShaderNode *PointDensityTextureNode::clone() const
+ShaderNode *PointDensityTextureNode::clone(ShaderGraph *graph) const
{
/* Increase image user count for new node. We need to ensure to not call
* add_image again, to work around access of freed data on the Blender
* side. A better solution should be found to avoid this. */
- PointDensityTextureNode *node = new PointDensityTextureNode(*this);
+ PointDensityTextureNode *node = graph->create_node<PointDensityTextureNode>(*this);
node->handle = handle; /* TODO: not needed? */
return node;
}
@@ -2783,8 +2783,8 @@ void PrincipledBsdfNode::expand(ShaderGraph *graph)
ShaderInput *emission_in = input("Emission");
if (emission_in->link || emission != make_float3(0.0f, 0.0f, 0.0f)) {
/* Create add closure and emission. */
- AddClosureNode *add = new AddClosureNode();
- EmissionNode *emission_node = new EmissionNode();
+ AddClosureNode *add = graph->create_node<AddClosureNode>();
+ EmissionNode *emission_node = graph->create_node<EmissionNode>();
ShaderOutput *new_out = add->output("Closure");
graph->add(add);
@@ -2802,8 +2802,8 @@ void PrincipledBsdfNode::expand(ShaderGraph *graph)
ShaderInput *alpha_in = input("Alpha");
if (alpha_in->link || alpha != 1.0f) {
/* Create mix and transparent BSDF for alpha transparency. */
- MixClosureNode *mix = new MixClosureNode();
- TransparentBsdfNode *transparent = new TransparentBsdfNode();
+ MixClosureNode *mix = graph->create_node<MixClosureNode>();
+ TransparentBsdfNode *transparent = graph->create_node<TransparentBsdfNode>();
graph->add(mix);
graph->add(transparent);
@@ -4475,7 +4475,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
{
ShaderOutput *color_out = output("Color");
if (!color_out->links.empty()) {
- AttributeNode *attr = new AttributeNode();
+ AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = "color";
graph->add(attr);
graph->relink(color_out, attr->output("Color"));
@@ -4483,7 +4483,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
ShaderOutput *density_out = output("Density");
if (!density_out->links.empty()) {
- AttributeNode *attr = new AttributeNode();
+ AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = "density";
graph->add(attr);
graph->relink(density_out, attr->output("Fac"));
@@ -4491,7 +4491,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
ShaderOutput *flame_out = output("Flame");
if (!flame_out->links.empty()) {
- AttributeNode *attr = new AttributeNode();
+ AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = "flame";
graph->add(attr);
graph->relink(flame_out, attr->output("Fac"));
@@ -4499,7 +4499,7 @@ void VolumeInfoNode::expand(ShaderGraph *graph)
ShaderOutput *temperature_out = output("Temperature");
if (!temperature_out->links.empty()) {
- AttributeNode *attr = new AttributeNode();
+ AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = "temperature";
graph->add(attr);
graph->relink(temperature_out, attr->output("Fac"));
@@ -5768,7 +5768,7 @@ void MapRangeNode::expand(ShaderGraph *graph)
if (clamp) {
ShaderOutput *result_out = output("Result");
if (!result_out->links.empty()) {
- ClampNode *clamp_node = new ClampNode();
+ ClampNode *clamp_node = graph->create_node<ClampNode>();
clamp_node->type = NODE_CLAMP_RANGE;
graph->add(clamp_node);
graph->relink(result_out, clamp_node->output("Result"));
@@ -6009,7 +6009,7 @@ void MathNode::expand(ShaderGraph *graph)
if (use_clamp) {
ShaderOutput *result_out = output("Value");
if (!result_out->links.empty()) {
- ClampNode *clamp_node = new ClampNode();
+ ClampNode *clamp_node = graph->create_node<ClampNode>();
clamp_node->type = NODE_CLAMP_MINMAX;
clamp_node->min = 0.0f;
clamp_node->max = 1.0f;
@@ -6337,7 +6337,7 @@ void BumpNode::constant_fold(const ConstantFolder &folder)
if (height_in->link == NULL) {
if (normal_in->link == NULL) {
- GeometryNode *geom = new GeometryNode();
+ GeometryNode *geom = folder.graph->create_node<GeometryNode>();
folder.graph->add(geom);
folder.bypass(geom->output("Normal"));
}
@@ -6620,12 +6620,12 @@ OSLNode::~OSLNode()
delete type;
}
-ShaderNode *OSLNode::clone() const
+ShaderNode *OSLNode::clone(ShaderGraph *graph) const
{
- return OSLNode::create(this->inputs.size(), this);
+ return OSLNode::create(graph, this->inputs.size(), this);
}
-OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from)
+OSLNode *OSLNode::create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from)
{
/* allocate space for the node itself and parameters, aligned to 16 bytes
* assuming that's the most parameter types need */
@@ -6636,7 +6636,9 @@ OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from)
memset(node_memory, 0, node_size + inputs_size);
if (!from) {
- return new (node_memory) OSLNode();
+ OSLNode *node = new (node_memory) OSLNode();
+ node->set_owner(graph);
+ return node;
}
else {
/* copy input default values and node type for cloning */
@@ -6644,6 +6646,7 @@ OSLNode *OSLNode::create(size_t num_inputs, const OSLNode *from)
OSLNode *node = new (node_memory) OSLNode(*from);
node->type = new NodeType(*(from->type));
+ node->set_owner(from->owner);
return node;
}
}
diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h
index c21bcacb3ce..59e00231c2c 100644
--- a/intern/cycles/render/nodes.h
+++ b/intern/cycles/render/nodes.h
@@ -92,7 +92,7 @@ class ImageSlotTextureNode : public TextureNode {
class ImageTextureNode : public ImageSlotTextureNode {
public:
SHADER_NODE_NO_CLONE_CLASS(ImageTextureNode)
- ShaderNode *clone() const;
+ ShaderNode *clone(ShaderGraph *graph) const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_attribute_dependency()
{
@@ -126,7 +126,7 @@ class ImageTextureNode : public ImageSlotTextureNode {
class EnvironmentTextureNode : public ImageSlotTextureNode {
public:
SHADER_NODE_NO_CLONE_CLASS(EnvironmentTextureNode)
- ShaderNode *clone() const;
+ ShaderNode *clone(ShaderGraph *graph) const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_attribute_dependency()
{
@@ -364,7 +364,7 @@ class PointDensityTextureNode : public ShaderNode {
}
~PointDensityTextureNode();
- ShaderNode *clone() const;
+ ShaderNode *clone(ShaderGraph *graph) const;
void attributes(Shader *shader, AttributeRequestSet *attributes);
bool has_attribute_dependency()
{
@@ -400,7 +400,7 @@ class IESLightNode : public TextureNode {
SHADER_NODE_NO_CLONE_CLASS(IESLightNode)
~IESLightNode();
- ShaderNode *clone() const;
+ ShaderNode *clone(ShaderGraph *graph) const;
virtual int get_group()
{
return NODE_GROUP_LEVEL_2;
@@ -1501,10 +1501,10 @@ class SetNormalNode : public ShaderNode {
class OSLNode : public ShaderNode {
public:
- static OSLNode *create(size_t num_inputs, const OSLNode *from = NULL);
+ static OSLNode *create(ShaderGraph *graph, size_t num_inputs, const OSLNode *from = NULL);
~OSLNode();
- ShaderNode *clone() const;
+ ShaderNode *clone(ShaderGraph *graph) const;
char *input_default_value();
void add_input(ustring name, SocketType::Type type);
diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp
index 5c62ae73e47..1c54dc2d531 100644
--- a/intern/cycles/render/osl.cpp
+++ b/intern/cycles/render/osl.cpp
@@ -439,7 +439,8 @@ const char *OSLShaderManager::shader_load_bytecode(const string &hash, const str
/* This is a static function to avoid RTTI link errors with only this
* file being compiled without RTTI to match OSL and LLVM libraries. */
-OSLNode *OSLShaderManager::osl_node(ShaderManager *manager,
+OSLNode *OSLShaderManager::osl_node(ShaderGraph *graph,
+ ShaderManager *manager,
const std::string &filepath,
const std::string &bytecode_hash,
const std::string &bytecode)
@@ -482,7 +483,7 @@ OSLNode *OSLShaderManager::osl_node(ShaderManager *manager,
}
/* create node */
- OSLNode *node = OSLNode::create(num_inputs);
+ OSLNode *node = OSLNode::create(graph, num_inputs);
/* add new sockets from parameters */
set<void *> used_sockets;
diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h
index 4dd9f6630f2..ea2d0ca492c 100644
--- a/intern/cycles/render/osl.h
+++ b/intern/cycles/render/osl.h
@@ -93,7 +93,8 @@ class OSLShaderManager : public ShaderManager {
OSLShaderInfo *shader_loaded_info(const string &hash);
/* create OSL node using OSLQuery */
- static OSLNode *osl_node(ShaderManager *manager,
+ static OSLNode *osl_node(ShaderGraph *graph,
+ ShaderManager *manager,
const std::string &filepath,
const std::string &bytecode_hash = "",
const std::string &bytecode = "");
diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp
index ec9276eff86..494f5929df2 100644
--- a/intern/cycles/render/particles.cpp
+++ b/intern/cycles/render/particles.cpp
@@ -29,7 +29,13 @@ CCL_NAMESPACE_BEGIN
/* Particle System */
-ParticleSystem::ParticleSystem()
+NODE_DEFINE(ParticleSystem)
+{
+ NodeType *type = NodeType::add("particle_system", create);
+ return type;
+}
+
+ParticleSystem::ParticleSystem() : Node(node_type)
{
}
diff --git a/intern/cycles/render/particles.h b/intern/cycles/render/particles.h
index 65663c31c37..0b0408184fe 100644
--- a/intern/cycles/render/particles.h
+++ b/intern/cycles/render/particles.h
@@ -20,6 +20,8 @@
#include "util/util_array.h"
#include "util/util_types.h"
+#include "graph/node.h"
+
CCL_NAMESPACE_BEGIN
class Device;
@@ -40,8 +42,10 @@ struct Particle {
float3 angular_velocity;
};
-class ParticleSystem {
+class ParticleSystem : public Node {
public:
+ NODE_DECLARE
+
ParticleSystem();
~ParticleSystem();
diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp
index a8a5b50e6a2..8f863b5d15f 100644
--- a/intern/cycles/render/scene.cpp
+++ b/intern/cycles/render/scene.cpp
@@ -33,6 +33,7 @@
#include "render/shader.h"
#include "render/svm.h"
#include "render/tables.h"
+#include "render/volume.h"
#include "util/util_foreach.h"
#include "util/util_guarded_allocator.h"
@@ -98,15 +99,15 @@ Scene::Scene(const SceneParams &params_, Device *device)
{
memset((void *)&dscene.data, 0, sizeof(dscene.data));
- camera = new Camera();
- dicing_camera = new Camera();
+ camera = create_node<Camera>();
+ dicing_camera = create_node<Camera>();
lookup_tables = new LookupTables();
- film = new Film();
- background = new Background();
+ film = create_node<Film>();
+ background = create_node<Background>();
light_manager = new LightManager();
geometry_manager = new GeometryManager();
object_manager = new ObjectManager();
- integrator = new Integrator();
+ integrator = create_node<Integrator>();
image_manager = new ImageManager(device->info);
particle_system_manager = new ParticleSystemManager();
bake_manager = new BakeManager();
@@ -560,4 +561,127 @@ int Scene::get_max_closure_count()
return max_closure_global;
}
+template<> Light *Scene::create_node<Light>()
+{
+ Light *node = new Light();
+ node->set_owner(this);
+ lights.push_back(node);
+ light_manager->tag_update(this);
+ return node;
+}
+
+template<> Mesh *Scene::create_node<Mesh>()
+{
+ Mesh *node = new Mesh();
+ node->set_owner(this);
+ geometry.push_back(node);
+ geometry_manager->tag_update(this);
+ return node;
+}
+
+template<> Hair *Scene::create_node<Hair>()
+{
+ Hair *node = new Hair();
+ node->set_owner(this);
+ geometry.push_back(node);
+ geometry_manager->tag_update(this);
+ return node;
+}
+
+template<> Volume *Scene::create_node<Volume>()
+{
+ Volume *node = new Volume();
+ node->set_owner(this);
+ geometry.push_back(node);
+ geometry_manager->tag_update(this);
+ return node;
+}
+
+template<> Object *Scene::create_node<Object>()
+{
+ Object *node = new Object();
+ node->set_owner(this);
+ objects.push_back(node);
+ object_manager->tag_update(this);
+ return node;
+}
+
+template<> ParticleSystem *Scene::create_node<ParticleSystem>()
+{
+ ParticleSystem *node = new ParticleSystem();
+ node->set_owner(this);
+ particle_systems.push_back(node);
+ particle_system_manager->tag_update(this);
+ return node;
+}
+
+template<> Shader *Scene::create_node<Shader>()
+{
+ Shader *node = new Shader();
+ node->set_owner(this);
+ shaders.push_back(node);
+ shader_manager->need_update = true;
+ return node;
+}
+
+template<typename T> void delete_node_from_array(vector<T> &nodes, T node)
+{
+ for (size_t i = 0; i < nodes.size(); ++i) {
+ if (nodes[i] == node) {
+ std::swap(nodes[i], nodes[nodes.size() - 1]);
+ break;
+ }
+ }
+
+ nodes.resize(nodes.size() - 1);
+ delete node;
+}
+
+template<> void Scene::delete_node_impl(Light *node)
+{
+ delete_node_from_array(lights, node);
+ light_manager->tag_update(this);
+}
+
+template<> void Scene::delete_node_impl(Mesh *node)
+{
+ delete_node_from_array(geometry, static_cast<Geometry *>(node));
+ geometry_manager->tag_update(this);
+}
+
+template<> void Scene::delete_node_impl(Hair *node)
+{
+ delete_node_from_array(geometry, static_cast<Geometry *>(node));
+ geometry_manager->tag_update(this);
+}
+
+template<> void Scene::delete_node_impl(Volume *node)
+{
+ delete_node_from_array(geometry, static_cast<Geometry *>(node));
+ geometry_manager->tag_update(this);
+}
+
+template<> void Scene::delete_node_impl(Geometry *node)
+{
+ delete_node_from_array(geometry, node);
+ geometry_manager->tag_update(this);
+}
+
+template<> void Scene::delete_node_impl(Object *node)
+{
+ delete_node_from_array(objects, node);
+ object_manager->tag_update(this);
+}
+
+template<> void Scene::delete_node_impl(ParticleSystem *node)
+{
+ delete_node_from_array(particle_systems, node);
+ particle_system_manager->tag_update(this);
+}
+
+template<> void Scene::delete_node_impl(Shader * /*node*/)
+{
+ /* don't delete unused shaders, not supported */
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h
index 25b6b2ef0e4..0e32a70952b 100644
--- a/intern/cycles/render/scene.h
+++ b/intern/cycles/render/scene.h
@@ -59,6 +59,7 @@ class Progress;
class BakeManager;
class BakeData;
class RenderStats;
+class Volume;
/* Scene Device Data */
@@ -212,7 +213,7 @@ class SceneParams {
/* Scene */
-class Scene {
+class Scene : public NodeOwner {
public:
/* Optional name. Is used for logging and reporting. */
string name;
@@ -281,6 +282,40 @@ class Scene {
bool update(Progress &progress, bool &kernel_switch_needed);
+ /* This function is used to create a node of a specified type instead of
+ * calling 'new', and sets the scene as the owner of the node.
+ * The function has overloads that will also add the created node to the right
+ * node array (e.g. Scene::geometry for Geometry nodes) and tag the appropriate
+ * manager for an update.
+ */
+ template<typename T, typename... Args> T *create_node(Args &&... args)
+ {
+ T *node = new T(args...);
+ node->set_owner(this);
+ return node;
+ }
+
+ /* This function is used to delete a node from the scene instead of calling 'delete'
+ * and manually removing the node from the data array. It also tags the
+ * appropriate manager for an update, if any, and checks that the scene is indeed
+ * the owner of the node. Calling this function on a node not owned by the scene
+ * will likely cause a crash which we want in order to detect such cases.
+ */
+ template<typename T> void delete_node(T *node)
+ {
+ assert(node->get_owner() == this);
+ delete_node_impl(node);
+ }
+
+ /* Same as above, but specify the actual owner.
+ */
+ template<typename T> void delete_node(T *node, const NodeOwner *owner)
+ {
+ assert(node->get_owner() == owner);
+ delete_node_impl(node);
+ (void)owner;
+ }
+
protected:
/* Check if some heavy data worth logging was updated.
* Mainly used to suppress extra annoying logging.
@@ -303,8 +338,43 @@ class Scene {
/* Get maximum number of closures to be used in kernel. */
int get_max_closure_count();
+
+ template<typename T> void delete_node_impl(T *node)
+ {
+ delete node;
+ }
};
+template<> Light *Scene::create_node<Light>();
+
+template<> Mesh *Scene::create_node<Mesh>();
+
+template<> Object *Scene::create_node<Object>();
+
+template<> Hair *Scene::create_node<Hair>();
+
+template<> Volume *Scene::create_node<Volume>();
+
+template<> ParticleSystem *Scene::create_node<ParticleSystem>();
+
+template<> Shader *Scene::create_node<Shader>();
+
+template<> void Scene::delete_node_impl(Light *node);
+
+template<> void Scene::delete_node_impl(Mesh *node);
+
+template<> void Scene::delete_node_impl(Volume *node);
+
+template<> void Scene::delete_node_impl(Hair *node);
+
+template<> void Scene::delete_node_impl(Geometry *node);
+
+template<> void Scene::delete_node_impl(Object *node);
+
+template<> void Scene::delete_node_impl(ParticleSystem *node);
+
+template<> void Scene::delete_node_impl(Shader *node);
+
CCL_NAMESPACE_END
#endif /* __SCENE_H__ */
diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp
index 1120d909e98..135d0dc962b 100644
--- a/intern/cycles/render/shader.cpp
+++ b/intern/cycles/render/shader.cpp
@@ -624,16 +624,15 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
- DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
+ DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
diffuse->color = make_float3(0.8f, 0.8f, 0.8f);
graph->add(diffuse);
graph->connect(diffuse->output("BSDF"), graph->output()->input("Surface"));
- Shader *shader = new Shader();
+ Shader *shader = scene->create_node<Shader>();
shader->name = "default_surface";
shader->set_graph(graph);
- scene->shaders.push_back(shader);
scene->default_surface = shader;
shader->tag_update(scene);
}
@@ -642,15 +641,14 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
- PrincipledVolumeNode *principled = new PrincipledVolumeNode();
+ PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>();
graph->add(principled);
graph->connect(principled->output("Volume"), graph->output()->input("Volume"));
- Shader *shader = new Shader();
+ Shader *shader = scene->create_node<Shader>();
shader->name = "default_volume";
shader->set_graph(graph);
- scene->shaders.push_back(shader);
scene->default_volume = shader;
shader->tag_update(scene);
}
@@ -659,17 +657,16 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
- EmissionNode *emission = new EmissionNode();
+ EmissionNode *emission = graph->create_node<EmissionNode>();
emission->color = make_float3(0.8f, 0.8f, 0.8f);
emission->strength = 0.0f;
graph->add(emission);
graph->connect(emission->output("Emission"), graph->output()->input("Surface"));
- Shader *shader = new Shader();
+ Shader *shader = scene->create_node<Shader>();
shader->name = "default_light";
shader->set_graph(graph);
- scene->shaders.push_back(shader);
scene->default_light = shader;
shader->tag_update(scene);
}
@@ -678,10 +675,9 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
- Shader *shader = new Shader();
+ Shader *shader = scene->create_node<Shader>();
shader->name = "default_background";
shader->set_graph(graph);
- scene->shaders.push_back(shader);
scene->default_background = shader;
shader->tag_update(scene);
}
@@ -690,10 +686,9 @@ void ShaderManager::add_default(Scene *scene)
{
ShaderGraph *graph = new ShaderGraph();
- Shader *shader = new Shader();
+ Shader *shader = scene->create_node<Shader>();
shader->name = "default_empty";
shader->set_graph(graph);
- scene->shaders.push_back(shader);
scene->default_empty = shader;
shader->tag_update(scene);
}