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
path: root/intern
diff options
context:
space:
mode:
authorKévin Dietrich <kevin.dietrich@mailoo.org>2020-08-31 00:20:51 +0300
committerKévin Dietrich <kevin.dietrich@mailoo.org>2020-08-31 00:49:38 +0300
commit429afe0c626a6d608385c6bc3a348b3ac8cfa8c0 (patch)
tree3240319bcb09b1737c5b2759a3ecbdd3b45ca59f /intern
parent19363880a6770852a8f94565c162a987850d58e3 (diff)
Cycles: introduce an ownership system to protect nodes from unwanted deletions.
Problem: the Blender synchronization process creates and tags nodes for usage. It does this by directly adding and removing nodes from the scene data. If some node is not tagged as used at the end of a synchronization, it then deletes the node from the scene. This poses a problem when it comes to supporting procedural nodes who can create other nodes not known by the Blender synchonization system, which will remove them. Nodes now have a NodeOwner, which is set after creation. Those owners for now are the Scene for scene level nodes and ShaderGraph for shader nodes. Instead of creating and deleting nodes using `new` and `delete` explicitely, we now use `create_node` and `delete_node` methods found on the owners. `delete_node` will assert that the owner is the right one. Whenever a scene level node is created or deleted, the appropriate node manager is tagged for an update, freeing this responsability from BlenderSync or other software exporters. Concerning BlenderSync, the `id_maps` do not explicitely manipulate scene data anymore, they only keep track of which nodes are used, employing the scene to create and delete them. To achieve this, the ParticleSystem is now a Node, although it does not have any sockets. This is part of T79131. Reviewed By: #cycles, brecht Maniphest Tasks: T79131 Differential Revision: https://developer.blender.org/D8540
Diffstat (limited to 'intern')
-rw-r--r--intern/cycles/blender/blender_geometry.cpp6
-rw-r--r--intern/cycles/blender/blender_id_map.h49
-rw-r--r--intern/cycles/blender/blender_light.cpp6
-rw-r--r--intern/cycles/blender/blender_object.cpp14
-rw-r--r--intern/cycles/blender/blender_particles.cpp3
-rw-r--r--intern/cycles/blender/blender_shader.cpp205
-rw-r--r--intern/cycles/blender/blender_sync.cpp12
-rw-r--r--intern/cycles/graph/node.cpp16
-rw-r--r--intern/cycles/graph/node.h10
-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
20 files changed, 461 insertions, 232 deletions
diff --git a/intern/cycles/blender/blender_geometry.cpp b/intern/cycles/blender/blender_geometry.cpp
index 9a82c5e9371..002f5e0fdb7 100644
--- a/intern/cycles/blender/blender_geometry.cpp
+++ b/intern/cycles/blender/blender_geometry.cpp
@@ -83,13 +83,13 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph,
if (geom == NULL) {
/* Add new geometry if it did not exist yet. */
if (geom_type == Geometry::HAIR) {
- geom = new Hair();
+ geom = scene->create_node<Hair>();
}
else if (geom_type == Geometry::VOLUME) {
- geom = new Volume();
+ geom = scene->create_node<Volume>();
}
else {
- geom = new Mesh();
+ geom = scene->create_node<Mesh>();
}
geometry_map.add(key, geom);
}
diff --git a/intern/cycles/blender/blender_id_map.h b/intern/cycles/blender/blender_id_map.h
index b5f6aaa67a8..f9f201c2e4e 100644
--- a/intern/cycles/blender/blender_id_map.h
+++ b/intern/cycles/blender/blender_id_map.h
@@ -19,6 +19,8 @@
#include <string.h>
+#include "render/scene.h"
+
#include "util/util_map.h"
#include "util/util_set.h"
#include "util/util_vector.h"
@@ -32,9 +34,8 @@ CCL_NAMESPACE_BEGIN
template<typename K, typename T> class id_map {
public:
- id_map(vector<T *> *scene_data_)
+ id_map()
{
- scene_data = scene_data_;
}
T *find(const BL::ID &id)
@@ -76,7 +77,6 @@ template<typename K, typename T> class id_map {
void add(const K &key, T *data)
{
assert(find(key) == NULL);
- scene_data->push_back(data);
b_map[key] = data;
used(data);
}
@@ -97,22 +97,23 @@ template<typename K, typename T> class id_map {
}
/* Combined add and update as needed. */
- bool add_or_update(T **r_data, const BL::ID &id)
+ bool add_or_update(Scene *scene, T **r_data, const BL::ID &id)
{
- return add_or_update(r_data, id, id, id.ptr.owner_id);
+ return add_or_update(scene, r_data, id, id, id.ptr.owner_id);
}
- bool add_or_update(T **r_data, const BL::ID &id, const K &key)
+ bool add_or_update(Scene *scene, T **r_data, const BL::ID &id, const K &key)
{
- return add_or_update(r_data, id, id, key);
+ return add_or_update(scene, r_data, id, id, key);
}
- bool add_or_update(T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
+ bool add_or_update(
+ Scene *scene, T **r_data, const BL::ID &id, const BL::ID &parent, const K &key)
{
T *data = find(key);
bool recalc;
if (!data) {
/* Add data if it didn't exist yet. */
- data = new T();
+ data = scene->create_node<T>();
add(key, data);
recalc = true;
}
@@ -144,27 +145,8 @@ template<typename K, typename T> class id_map {
b_map[NULL] = data;
}
- bool post_sync(bool do_delete = true)
+ void post_sync(Scene *scene, bool do_delete = true)
{
- /* remove unused data */
- vector<T *> new_scene_data;
- typename vector<T *>::iterator it;
- bool deleted = false;
-
- for (it = scene_data->begin(); it != scene_data->end(); it++) {
- T *data = *it;
-
- if (do_delete && used_set.find(data) == used_set.end()) {
- delete data;
- deleted = true;
- }
- else
- new_scene_data.push_back(data);
- }
-
- *scene_data = new_scene_data;
-
- /* update mapping */
map<K, T *> new_map;
typedef pair<const K, T *> TMapPair;
typename map<K, T *>::iterator jt;
@@ -172,15 +154,17 @@ template<typename K, typename T> class id_map {
for (jt = b_map.begin(); jt != b_map.end(); jt++) {
TMapPair &pair = *jt;
- if (used_set.find(pair.second) != used_set.end())
+ if (do_delete && used_set.find(pair.second) == used_set.end()) {
+ scene->delete_node(pair.second);
+ }
+ else {
new_map[pair.first] = pair.second;
+ }
}
used_set.clear();
b_recalc.clear();
b_map = new_map;
-
- return deleted;
}
const map<K, T *> &key_to_scene_data()
@@ -189,7 +173,6 @@ template<typename K, typename T> class id_map {
}
protected:
- vector<T *> *scene_data;
map<K, T *> b_map;
set<T *> used_set;
set<void *> b_recalc;
diff --git a/intern/cycles/blender/blender_light.cpp b/intern/cycles/blender/blender_light.cpp
index 6f95821e31e..117e9214e5a 100644
--- a/intern/cycles/blender/blender_light.cpp
+++ b/intern/cycles/blender/blender_light.cpp
@@ -39,9 +39,9 @@ void BlenderSync::sync_light(BL::Object &b_parent,
BL::Light b_light(b_ob.data());
/* Update if either object or light data changed. */
- if (!light_map.add_or_update(&light, b_ob, b_parent, key)) {
+ if (!light_map.add_or_update(scene, &light, b_ob, b_parent, key)) {
Shader *shader;
- if (!shader_map.add_or_update(&shader, b_light)) {
+ if (!shader_map.add_or_update(scene, &shader, b_light)) {
if (light->is_portal)
*use_portal = true;
return;
@@ -176,7 +176,7 @@ void BlenderSync::sync_background_light(BL::SpaceView3D &b_v3d, bool use_portal)
Light *light;
ObjectKey key(b_world, 0, b_world, false);
- if (light_map.add_or_update(&light, b_world, b_world, key) || world_recalc ||
+ if (light_map.add_or_update(scene, &light, b_world, b_world, key) || world_recalc ||
b_world.ptr.data != world_map) {
light->type = LIGHT_BACKGROUND;
if (sampling_method == SAMPLING_MANUAL) {
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index e0792962b01..212b9cbe103 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -207,7 +207,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
/* test if we need to sync */
bool object_updated = false;
- if (object_map.add_or_update(&object, b_ob, b_parent, key))
+ if (object_map.add_or_update(scene, &object, b_ob, b_parent, key))
object_updated = true;
/* mesh sync */
@@ -405,14 +405,10 @@ void BlenderSync::sync_objects(BL::Depsgraph &b_depsgraph,
sync_background_light(b_v3d, use_portal);
/* handle removed data and modified pointers */
- if (light_map.post_sync())
- scene->light_manager->tag_update(scene);
- if (geometry_map.post_sync())
- scene->geometry_manager->tag_update(scene);
- if (object_map.post_sync())
- scene->object_manager->tag_update(scene);
- if (particle_system_map.post_sync())
- scene->particle_system_manager->tag_update(scene);
+ light_map.post_sync(scene);
+ geometry_map.post_sync(scene);
+ object_map.post_sync(scene);
+ particle_system_map.post_sync(scene);
}
if (motion)
diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp
index e5eab1ae62b..ee14217988b 100644
--- a/intern/cycles/blender/blender_particles.cpp
+++ b/intern/cycles/blender/blender_particles.cpp
@@ -53,7 +53,8 @@ bool BlenderSync::sync_dupli_particle(BL::Object &b_ob,
ParticleSystem *psys;
bool first_use = !particle_system_map.is_used(key);
- bool need_update = particle_system_map.add_or_update(&psys, b_ob, b_instance.object(), key);
+ bool need_update = particle_system_map.add_or_update(
+ scene, &psys, b_ob, b_instance.object(), key);
/* no update needed? */
if (!need_update && !object->geometry->need_update && !scene->object_manager->need_update)
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp
index ae681432a43..03ed88ea9ec 100644
--- a/intern/cycles/blender/blender_shader.cpp
+++ b/intern/cycles/blender/blender_shader.cpp
@@ -224,7 +224,7 @@ static ShaderNode *add_node(Scene *scene,
if (b_node.is_a(&RNA_ShaderNodeRGBCurve)) {
BL::ShaderNodeRGBCurve b_curve_node(b_node);
BL::CurveMapping mapping(b_curve_node.mapping());
- RGBCurvesNode *curves = new RGBCurvesNode();
+ RGBCurvesNode *curves = graph->create_node<RGBCurvesNode>();
curvemapping_color_to_array(mapping, curves->curves, RAMP_TABLE_SIZE, true);
curvemapping_minmax(mapping, true, &curves->min_x, &curves->max_x);
node = curves;
@@ -232,13 +232,13 @@ static ShaderNode *add_node(Scene *scene,
if (b_node.is_a(&RNA_ShaderNodeVectorCurve)) {
BL::ShaderNodeVectorCurve b_curve_node(b_node);
BL::CurveMapping mapping(b_curve_node.mapping());
- VectorCurvesNode *curves = new VectorCurvesNode();
+ VectorCurvesNode *curves = graph->create_node<VectorCurvesNode>();
curvemapping_color_to_array(mapping, curves->curves, RAMP_TABLE_SIZE, false);
curvemapping_minmax(mapping, false, &curves->min_x, &curves->max_x);
node = curves;
}
else if (b_node.is_a(&RNA_ShaderNodeValToRGB)) {
- RGBRampNode *ramp = new RGBRampNode();
+ RGBRampNode *ramp = graph->create_node<RGBRampNode>();
BL::ShaderNodeValToRGB b_ramp_node(b_node);
BL::ColorRamp b_color_ramp(b_ramp_node.color_ramp());
colorramp_to_array(b_color_ramp, ramp->ramp, ramp->ramp_alpha, RAMP_TABLE_SIZE);
@@ -246,94 +246,94 @@ static ShaderNode *add_node(Scene *scene,
node = ramp;
}
else if (b_node.is_a(&RNA_ShaderNodeRGB)) {
- ColorNode *color = new ColorNode();
+ ColorNode *color = graph->create_node<ColorNode>();
color->value = get_node_output_rgba(b_node, "Color");
node = color;
}
else if (b_node.is_a(&RNA_ShaderNodeValue)) {
- ValueNode *value = new ValueNode();
+ ValueNode *value = graph->create_node<ValueNode>();
value->value = get_node_output_value(b_node, "Value");
node = value;
}
else if (b_node.is_a(&RNA_ShaderNodeCameraData)) {
- node = new CameraNode();
+ node = graph->create_node<CameraNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeInvert)) {
- node = new InvertNode();
+ node = graph->create_node<InvertNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeGamma)) {
- node = new GammaNode();
+ node = graph->create_node<GammaNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBrightContrast)) {
- node = new BrightContrastNode();
+ node = graph->create_node<BrightContrastNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeMixRGB)) {
BL::ShaderNodeMixRGB b_mix_node(b_node);
- MixNode *mix = new MixNode();
+ MixNode *mix = graph->create_node<MixNode>();
mix->type = (NodeMix)b_mix_node.blend_type();
mix->use_clamp = b_mix_node.use_clamp();
node = mix;
}
else if (b_node.is_a(&RNA_ShaderNodeSeparateRGB)) {
- node = new SeparateRGBNode();
+ node = graph->create_node<SeparateRGBNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeCombineRGB)) {
- node = new CombineRGBNode();
+ node = graph->create_node<CombineRGBNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeSeparateHSV)) {
- node = new SeparateHSVNode();
+ node = graph->create_node<SeparateHSVNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeCombineHSV)) {
- node = new CombineHSVNode();
+ node = graph->create_node<CombineHSVNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeSeparateXYZ)) {
- node = new SeparateXYZNode();
+ node = graph->create_node<SeparateXYZNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeCombineXYZ)) {
- node = new CombineXYZNode();
+ node = graph->create_node<CombineXYZNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeHueSaturation)) {
- node = new HSVNode();
+ node = graph->create_node<HSVNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeRGBToBW)) {
- node = new RGBToBWNode();
+ node = graph->create_node<RGBToBWNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeMapRange)) {
BL::ShaderNodeMapRange b_map_range_node(b_node);
- MapRangeNode *map_range_node = new MapRangeNode();
+ MapRangeNode *map_range_node = graph->create_node<MapRangeNode>();
map_range_node->clamp = b_map_range_node.clamp();
map_range_node->type = (NodeMapRangeType)b_map_range_node.interpolation_type();
node = map_range_node;
}
else if (b_node.is_a(&RNA_ShaderNodeClamp)) {
BL::ShaderNodeClamp b_clamp_node(b_node);
- ClampNode *clamp_node = new ClampNode();
+ ClampNode *clamp_node = graph->create_node<ClampNode>();
clamp_node->type = (NodeClampType)b_clamp_node.clamp_type();
node = clamp_node;
}
else if (b_node.is_a(&RNA_ShaderNodeMath)) {
BL::ShaderNodeMath b_math_node(b_node);
- MathNode *math_node = new MathNode();
+ MathNode *math_node = graph->create_node<MathNode>();
math_node->type = (NodeMathType)b_math_node.operation();
math_node->use_clamp = b_math_node.use_clamp();
node = math_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorMath)) {
BL::ShaderNodeVectorMath b_vector_math_node(b_node);
- VectorMathNode *vector_math_node = new VectorMathNode();
+ VectorMathNode *vector_math_node = graph->create_node<VectorMathNode>();
vector_math_node->type = (NodeVectorMathType)b_vector_math_node.operation();
node = vector_math_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorRotate)) {
BL::ShaderNodeVectorRotate b_vector_rotate_node(b_node);
- VectorRotateNode *vector_rotate_node = new VectorRotateNode();
+ VectorRotateNode *vector_rotate_node = graph->create_node<VectorRotateNode>();
vector_rotate_node->type = (NodeVectorRotateType)b_vector_rotate_node.rotation_type();
vector_rotate_node->invert = b_vector_rotate_node.invert();
node = vector_rotate_node;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorTransform)) {
BL::ShaderNodeVectorTransform b_vector_transform_node(b_node);
- VectorTransformNode *vtransform = new VectorTransformNode();
+ VectorTransformNode *vtransform = graph->create_node<VectorTransformNode>();
vtransform->type = (NodeVectorTransformType)b_vector_transform_node.vector_type();
vtransform->convert_from = (NodeVectorTransformConvertSpace)
b_vector_transform_node.convert_from();
@@ -344,43 +344,43 @@ static ShaderNode *add_node(Scene *scene,
BL::Node::outputs_iterator out_it;
b_node.outputs.begin(out_it);
- NormalNode *norm = new NormalNode();
+ NormalNode *norm = graph->create_node<NormalNode>();
norm->direction = get_node_output_vector(b_node, "Normal");
node = norm;
}
else if (b_node.is_a(&RNA_ShaderNodeMapping)) {
BL::ShaderNodeMapping b_mapping_node(b_node);
- MappingNode *mapping = new MappingNode();
+ MappingNode *mapping = graph->create_node<MappingNode>();
mapping->type = (NodeMappingType)b_mapping_node.vector_type();
node = mapping;
}
else if (b_node.is_a(&RNA_ShaderNodeFresnel)) {
- node = new FresnelNode();
+ node = graph->create_node<FresnelNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeLayerWeight)) {
- node = new LayerWeightNode();
+ node = graph->create_node<LayerWeightNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeAddShader)) {
- node = new AddClosureNode();
+ node = graph->create_node<AddClosureNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeMixShader)) {
- node = new MixClosureNode();
+ node = graph->create_node<MixClosureNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeAttribute)) {
BL::ShaderNodeAttribute b_attr_node(b_node);
- AttributeNode *attr = new AttributeNode();
+ AttributeNode *attr = graph->create_node<AttributeNode>();
attr->attribute = b_attr_node.attribute_name();
node = attr;
}
else if (b_node.is_a(&RNA_ShaderNodeBackground)) {
- node = new BackgroundNode();
+ node = graph->create_node<BackgroundNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeHoldout)) {
- node = new HoldoutNode();
+ node = graph->create_node<HoldoutNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfAnisotropic)) {
BL::ShaderNodeBsdfAnisotropic b_aniso_node(b_node);
- AnisotropicBsdfNode *aniso = new AnisotropicBsdfNode();
+ AnisotropicBsdfNode *aniso = graph->create_node<AnisotropicBsdfNode>();
switch (b_aniso_node.distribution()) {
case BL::ShaderNodeBsdfAnisotropic::distribution_BECKMANN:
@@ -400,12 +400,12 @@ static ShaderNode *add_node(Scene *scene,
node = aniso;
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) {
- node = new DiffuseBsdfNode();
+ node = graph->create_node<DiffuseBsdfNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) {
BL::ShaderNodeSubsurfaceScattering b_subsurface_node(b_node);
- SubsurfaceScatteringNode *subsurface = new SubsurfaceScatteringNode();
+ SubsurfaceScatteringNode *subsurface = graph->create_node<SubsurfaceScatteringNode>();
switch (b_subsurface_node.falloff()) {
case BL::ShaderNodeSubsurfaceScattering::falloff_CUBIC:
@@ -426,7 +426,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) {
BL::ShaderNodeBsdfGlossy b_glossy_node(b_node);
- GlossyBsdfNode *glossy = new GlossyBsdfNode();
+ GlossyBsdfNode *glossy = graph->create_node<GlossyBsdfNode>();
switch (b_glossy_node.distribution()) {
case BL::ShaderNodeBsdfGlossy::distribution_SHARP:
@@ -449,7 +449,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfGlass)) {
BL::ShaderNodeBsdfGlass b_glass_node(b_node);
- GlassBsdfNode *glass = new GlassBsdfNode();
+ GlassBsdfNode *glass = graph->create_node<GlassBsdfNode>();
switch (b_glass_node.distribution()) {
case BL::ShaderNodeBsdfGlass::distribution_SHARP:
glass->distribution = CLOSURE_BSDF_SHARP_GLASS_ID;
@@ -468,7 +468,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfRefraction)) {
BL::ShaderNodeBsdfRefraction b_refraction_node(b_node);
- RefractionBsdfNode *refraction = new RefractionBsdfNode();
+ RefractionBsdfNode *refraction = graph->create_node<RefractionBsdfNode>();
switch (b_refraction_node.distribution()) {
case BL::ShaderNodeBsdfRefraction::distribution_SHARP:
refraction->distribution = CLOSURE_BSDF_REFRACTION_ID;
@@ -484,7 +484,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfToon)) {
BL::ShaderNodeBsdfToon b_toon_node(b_node);
- ToonBsdfNode *toon = new ToonBsdfNode();
+ ToonBsdfNode *toon = graph->create_node<ToonBsdfNode>();
switch (b_toon_node.component()) {
case BL::ShaderNodeBsdfToon::component_DIFFUSE:
toon->component = CLOSURE_BSDF_DIFFUSE_TOON_ID;
@@ -497,7 +497,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfHair)) {
BL::ShaderNodeBsdfHair b_hair_node(b_node);
- HairBsdfNode *hair = new HairBsdfNode();
+ HairBsdfNode *hair = graph->create_node<HairBsdfNode>();
switch (b_hair_node.component()) {
case BL::ShaderNodeBsdfHair::component_Reflection:
hair->component = CLOSURE_BSDF_HAIR_REFLECTION_ID;
@@ -510,7 +510,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfHairPrincipled)) {
BL::ShaderNodeBsdfHairPrincipled b_principled_hair_node(b_node);
- PrincipledHairBsdfNode *principled_hair = new PrincipledHairBsdfNode();
+ PrincipledHairBsdfNode *principled_hair = graph->create_node<PrincipledHairBsdfNode>();
principled_hair->parametrization = (NodePrincipledHairParametrization)get_enum(
b_principled_hair_node.ptr,
"parametrization",
@@ -520,7 +520,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfPrincipled)) {
BL::ShaderNodeBsdfPrincipled b_principled_node(b_node);
- PrincipledBsdfNode *principled = new PrincipledBsdfNode();
+ PrincipledBsdfNode *principled = graph->create_node<PrincipledBsdfNode>();
switch (b_principled_node.distribution()) {
case BL::ShaderNodeBsdfPrincipled::distribution_GGX:
principled->distribution = CLOSURE_BSDF_MICROFACET_GGX_GLASS_ID;
@@ -540,77 +540,77 @@ static ShaderNode *add_node(Scene *scene,
node = principled;
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfTranslucent)) {
- node = new TranslucentBsdfNode();
+ node = graph->create_node<TranslucentBsdfNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfTransparent)) {
- node = new TransparentBsdfNode();
+ node = graph->create_node<TransparentBsdfNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBsdfVelvet)) {
- node = new VelvetBsdfNode();
+ node = graph->create_node<VelvetBsdfNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeEmission)) {
- node = new EmissionNode();
+ node = graph->create_node<EmissionNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeAmbientOcclusion)) {
BL::ShaderNodeAmbientOcclusion b_ao_node(b_node);
- AmbientOcclusionNode *ao = new AmbientOcclusionNode();
+ AmbientOcclusionNode *ao = graph->create_node<AmbientOcclusionNode>();
ao->samples = b_ao_node.samples();
ao->inside = b_ao_node.inside();
ao->only_local = b_ao_node.only_local();
node = ao;
}
else if (b_node.is_a(&RNA_ShaderNodeVolumeScatter)) {
- node = new ScatterVolumeNode();
+ node = graph->create_node<ScatterVolumeNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeVolumeAbsorption)) {
- node = new AbsorptionVolumeNode();
+ node = graph->create_node<AbsorptionVolumeNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeVolumePrincipled)) {
- PrincipledVolumeNode *principled = new PrincipledVolumeNode();
+ PrincipledVolumeNode *principled = graph->create_node<PrincipledVolumeNode>();
node = principled;
}
else if (b_node.is_a(&RNA_ShaderNodeNewGeometry)) {
- node = new GeometryNode();
+ node = graph->create_node<GeometryNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeWireframe)) {
BL::ShaderNodeWireframe b_wireframe_node(b_node);
- WireframeNode *wire = new WireframeNode();
+ WireframeNode *wire = graph->create_node<WireframeNode>();
wire->use_pixel_size = b_wireframe_node.use_pixel_size();
node = wire;
}
else if (b_node.is_a(&RNA_ShaderNodeWavelength)) {
- node = new WavelengthNode();
+ node = graph->create_node<WavelengthNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeBlackbody)) {
- node = new BlackbodyNode();
+ node = graph->create_node<BlackbodyNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeLightPath)) {
- node = new LightPathNode();
+ node = graph->create_node<LightPathNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeLightFalloff)) {
- node = new LightFalloffNode();
+ node = graph->create_node<LightFalloffNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeObjectInfo)) {
- node = new ObjectInfoNode();
+ node = graph->create_node<ObjectInfoNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeParticleInfo)) {
- node = new ParticleInfoNode();
+ node = graph->create_node<ParticleInfoNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeHairInfo)) {
- node = new HairInfoNode();
+ node = graph->create_node<HairInfoNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeVolumeInfo)) {
- node = new VolumeInfoNode();
+ node = graph->create_node<VolumeInfoNode>();
}
else if (b_node.is_a(&RNA_ShaderNodeVertexColor)) {
BL::ShaderNodeVertexColor b_vertex_color_node(b_node);
- VertexColorNode *vertex_color_node = new VertexColorNode();
+ VertexColorNode *vertex_color_node = graph->create_node<VertexColorNode>();
vertex_color_node->layer_name = b_vertex_color_node.layer_name();
node = vertex_color_node;
}
else if (b_node.is_a(&RNA_ShaderNodeBump)) {
BL::ShaderNodeBump b_bump_node(b_node);
- BumpNode *bump = new BumpNode();
+ BumpNode *bump = graph->create_node<BumpNode>();
bump->invert = b_bump_node.invert();
node = bump;
}
@@ -624,12 +624,13 @@ static ShaderNode *add_node(Scene *scene,
string bytecode_hash = b_script_node.bytecode_hash();
if (!bytecode_hash.empty()) {
- node = OSLShaderManager::osl_node(manager, "", bytecode_hash, b_script_node.bytecode());
+ node = OSLShaderManager::osl_node(
+ graph, manager, "", bytecode_hash, b_script_node.bytecode());
}
else {
string absolute_filepath = blender_absolute_path(
b_data, b_ntree, b_script_node.filepath());
- node = OSLShaderManager::osl_node(manager, absolute_filepath, "");
+ node = OSLShaderManager::osl_node(graph, manager, absolute_filepath, "");
}
}
#else
@@ -641,7 +642,7 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeTexImage b_image_node(b_node);
BL::Image b_image(b_image_node.image());
BL::ImageUser b_image_user(b_image_node.image_user());
- ImageTextureNode *image = new ImageTextureNode();
+ ImageTextureNode *image = graph->create_node<ImageTextureNode>();
image->interpolation = get_image_interpolation(b_image_node);
image->extension = get_image_extension(b_image_node);
@@ -693,7 +694,7 @@ static ShaderNode *add_node(Scene *scene,
BL::ShaderNodeTexEnvironment b_env_node(b_node);
BL::Image b_image(b_env_node.image());
BL::ImageUser b_image_user(b_env_node.image_user());
- EnvironmentTextureNode *env = new EnvironmentTextureNode();
+ EnvironmentTextureNode *env = graph->create_node<EnvironmentTextureNode>();
env->interpolation = get_image_interpolation(b_env_node);
env->projection = (NodeEnvironmentProjection)b_env_node.projection();
@@ -726,7 +727,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexGradient)) {
BL::ShaderNodeTexGradient b_gradient_node(b_node);
- GradientTextureNode *gradient = new GradientTextureNode();
+ GradientTextureNode *gradient = graph->create_node<GradientTextureNode>();
gradient->type = (NodeGradientType)b_gradient_node.gradient_type();
BL::TexMapping b_texture_mapping(b_gradient_node.texture_mapping());
get_tex_mapping(&gradient->tex_mapping, b_texture_mapping);
@@ -734,7 +735,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexVoronoi)) {
BL::ShaderNodeTexVoronoi b_voronoi_node(b_node);
- VoronoiTextureNode *voronoi = new VoronoiTextureNode();
+ VoronoiTextureNode *voronoi = graph->create_node<VoronoiTextureNode>();
voronoi->dimensions = b_voronoi_node.voronoi_dimensions();
voronoi->feature = (NodeVoronoiFeature)b_voronoi_node.feature();
voronoi->metric = (NodeVoronoiDistanceMetric)b_voronoi_node.distance();
@@ -744,7 +745,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexMagic)) {
BL::ShaderNodeTexMagic b_magic_node(b_node);
- MagicTextureNode *magic = new MagicTextureNode();
+ MagicTextureNode *magic = graph->create_node<MagicTextureNode>();
magic->depth = b_magic_node.turbulence_depth();
BL::TexMapping b_texture_mapping(b_magic_node.texture_mapping());
get_tex_mapping(&magic->tex_mapping, b_texture_mapping);
@@ -752,7 +753,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexWave)) {
BL::ShaderNodeTexWave b_wave_node(b_node);
- WaveTextureNode *wave = new WaveTextureNode();
+ WaveTextureNode *wave = graph->create_node<WaveTextureNode>();
wave->type = (NodeWaveType)b_wave_node.wave_type();
wave->bands_direction = (NodeWaveBandsDirection)b_wave_node.bands_direction();
wave->rings_direction = (NodeWaveRingsDirection)b_wave_node.rings_direction();
@@ -763,14 +764,14 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexChecker)) {
BL::ShaderNodeTexChecker b_checker_node(b_node);
- CheckerTextureNode *checker = new CheckerTextureNode();
+ CheckerTextureNode *checker = graph->create_node<CheckerTextureNode>();
BL::TexMapping b_texture_mapping(b_checker_node.texture_mapping());
get_tex_mapping(&checker->tex_mapping, b_texture_mapping);
node = checker;
}
else if (b_node.is_a(&RNA_ShaderNodeTexBrick)) {
BL::ShaderNodeTexBrick b_brick_node(b_node);
- BrickTextureNode *brick = new BrickTextureNode();
+ BrickTextureNode *brick = graph->create_node<BrickTextureNode>();
brick->offset = b_brick_node.offset();
brick->offset_frequency = b_brick_node.offset_frequency();
brick->squash = b_brick_node.squash();
@@ -781,7 +782,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexNoise)) {
BL::ShaderNodeTexNoise b_noise_node(b_node);
- NoiseTextureNode *noise = new NoiseTextureNode();
+ NoiseTextureNode *noise = graph->create_node<NoiseTextureNode>();
noise->dimensions = b_noise_node.noise_dimensions();
BL::TexMapping b_texture_mapping(b_noise_node.texture_mapping());
get_tex_mapping(&noise->tex_mapping, b_texture_mapping);
@@ -789,7 +790,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexMusgrave)) {
BL::ShaderNodeTexMusgrave b_musgrave_node(b_node);
- MusgraveTextureNode *musgrave_node = new MusgraveTextureNode();
+ MusgraveTextureNode *musgrave_node = graph->create_node<MusgraveTextureNode>();
musgrave_node->type = (NodeMusgraveType)b_musgrave_node.musgrave_type();
musgrave_node->dimensions = b_musgrave_node.musgrave_dimensions();
BL::TexMapping b_texture_mapping(b_musgrave_node.texture_mapping());
@@ -798,7 +799,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexCoord)) {
BL::ShaderNodeTexCoord b_tex_coord_node(b_node);
- TextureCoordinateNode *tex_coord = new TextureCoordinateNode();
+ TextureCoordinateNode *tex_coord = graph->create_node<TextureCoordinateNode>();
tex_coord->from_dupli = b_tex_coord_node.from_instancer();
if (b_tex_coord_node.object()) {
tex_coord->use_transform = true;
@@ -808,7 +809,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexSky)) {
BL::ShaderNodeTexSky b_sky_node(b_node);
- SkyTextureNode *sky = new SkyTextureNode();
+ SkyTextureNode *sky = graph->create_node<SkyTextureNode>();
sky->type = (NodeSkyType)b_sky_node.sky_type();
sky->sun_direction = normalize(get_float3(b_sky_node.sun_direction()));
sky->turbidity = b_sky_node.turbidity();
@@ -828,7 +829,7 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexIES)) {
BL::ShaderNodeTexIES b_ies_node(b_node);
- IESLightNode *ies = new IESLightNode();
+ IESLightNode *ies = graph->create_node<IESLightNode>();
switch (b_ies_node.mode()) {
case BL::ShaderNodeTexIES::mode_EXTERNAL:
ies->filename = blender_absolute_path(b_data, b_ntree, b_ies_node.filepath());
@@ -844,20 +845,20 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeTexWhiteNoise)) {
BL::ShaderNodeTexWhiteNoise b_tex_white_noise_node(b_node);
- WhiteNoiseTextureNode *white_noise_node = new WhiteNoiseTextureNode();
+ WhiteNoiseTextureNode *white_noise_node = graph->create_node<WhiteNoiseTextureNode>();
white_noise_node->dimensions = b_tex_white_noise_node.noise_dimensions();
node = white_noise_node;
}
else if (b_node.is_a(&RNA_ShaderNodeNormalMap)) {
BL::ShaderNodeNormalMap b_normal_map_node(b_node);
- NormalMapNode *nmap = new NormalMapNode();
+ NormalMapNode *nmap = graph->create_node<NormalMapNode>();
nmap->space = (NodeNormalMapSpace)b_normal_map_node.space();
nmap->attribute = b_normal_map_node.uv_map();
node = nmap;
}
else if (b_node.is_a(&RNA_ShaderNodeTangent)) {
BL::ShaderNodeTangent b_tangent_node(b_node);
- TangentNode *tangent = new TangentNode();
+ TangentNode *tangent = graph->create_node<TangentNode>();
tangent->direction_type = (NodeTangentDirectionType)b_tangent_node.direction_type();
tangent->axis = (NodeTangentAxis)b_tangent_node.axis();
tangent->attribute = b_tangent_node.uv_map();
@@ -865,14 +866,14 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeUVMap)) {
BL::ShaderNodeUVMap b_uvmap_node(b_node);
- UVMapNode *uvm = new UVMapNode();
+ UVMapNode *uvm = graph->create_node<UVMapNode>();
uvm->attribute = b_uvmap_node.uv_map();
uvm->from_dupli = b_uvmap_node.from_instancer();
node = uvm;
}
else if (b_node.is_a(&RNA_ShaderNodeTexPointDensity)) {
BL::ShaderNodeTexPointDensity b_point_density_node(b_node);
- PointDensityTextureNode *point_density = new PointDensityTextureNode();
+ PointDensityTextureNode *point_density = graph->create_node<PointDensityTextureNode>();
point_density->space = (NodeTexVoxelSpace)b_point_density_node.space();
point_density->interpolation = get_image_interpolation(b_point_density_node);
point_density->handle = scene->image_manager->add_image(
@@ -897,26 +898,26 @@ static ShaderNode *add_node(Scene *scene,
}
else if (b_node.is_a(&RNA_ShaderNodeBevel)) {
BL::ShaderNodeBevel b_bevel_node(b_node);
- BevelNode *bevel = new BevelNode();
+ BevelNode *bevel = graph->create_node<BevelNode>();
bevel->samples = b_bevel_node.samples();
node = bevel;
}
else if (b_node.is_a(&RNA_ShaderNodeDisplacement)) {
BL::ShaderNodeDisplacement b_disp_node(b_node);
- DisplacementNode *disp = new DisplacementNode();
+ DisplacementNode *disp = graph->create_node<DisplacementNode>();
disp->space = (NodeNormalMapSpace)b_disp_node.space();
node = disp;
}
else if (b_node.is_a(&RNA_ShaderNodeVectorDisplacement)) {
BL::ShaderNodeVectorDisplacement b_disp_node(b_node);
- VectorDisplacementNode *disp = new VectorDisplacementNode();
+ VectorDisplacementNode *disp = graph->create_node<VectorDisplacementNode>();
disp->space = (NodeNormalMapSpace)b_disp_node.space();
disp->attribute = "";
node = disp;
}
else if (b_node.is_a(&RNA_ShaderNodeOutputAOV)) {
BL::ShaderNodeOutputAOV b_aov_node(b_node);
- OutputAOVNode *aov = new OutputAOVNode();
+ OutputAOVNode *aov = graph->create_node<OutputAOVNode>();
aov->name = b_aov_node.name();
node = aov;
}
@@ -1038,7 +1039,7 @@ static void add_nodes(Scene *scene,
continue;
}
- ConvertNode *proxy = new ConvertNode(to_socket_type, to_socket_type, true);
+ ConvertNode *proxy = graph->create_node<ConvertNode>(to_socket_type, to_socket_type, true);
input_map[b_link->from_socket().ptr.data] = proxy->inputs[0];
output_map[b_link->to_socket().ptr.data] = proxy->outputs[0];
@@ -1069,7 +1070,7 @@ static void add_nodes(Scene *scene,
continue;
}
- ConvertNode *proxy = new ConvertNode(input_type, input_type, true);
+ ConvertNode *proxy = graph->create_node<ConvertNode>(input_type, input_type, true);
graph->add(proxy);
/* register the proxy node for internal binding */
@@ -1085,7 +1086,7 @@ static void add_nodes(Scene *scene,
continue;
}
- ConvertNode *proxy = new ConvertNode(output_type, output_type, true);
+ ConvertNode *proxy = graph->create_node<ConvertNode>(output_type, output_type, true);
graph->add(proxy);
/* register the proxy node for internal binding */
@@ -1240,7 +1241,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
- if (shader_map.add_or_update(&shader, b_mat) || update_all) {
+ if (shader_map.add_or_update(scene, &shader, b_mat) || update_all) {
ShaderGraph *graph = new ShaderGraph();
shader->name = b_mat.name().c_str();
@@ -1253,7 +1254,7 @@ void BlenderSync::sync_materials(BL::Depsgraph &b_depsgraph, bool update_all)
add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
}
else {
- DiffuseBsdfNode *diffuse = new DiffuseBsdfNode();
+ DiffuseBsdfNode *diffuse = graph->create_node<DiffuseBsdfNode>();
diffuse->color = get_float3(b_mat.diffuse_color());
graph->add(diffuse);
@@ -1336,7 +1337,7 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
shader->volume_step_rate = get_float(cworld, "volume_step_size");
}
else if (new_viewport_parameters.use_scene_world && b_world) {
- BackgroundNode *background = new BackgroundNode();
+ BackgroundNode *background = graph->create_node<BackgroundNode>();
background->color = get_float3(b_world.color());
graph->add(background);
@@ -1352,23 +1353,23 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
world_color = make_float3(0.0f, 0.0f, 0.0f);
}
- BackgroundNode *background = new BackgroundNode();
+ BackgroundNode *background = graph->create_node<BackgroundNode>();
graph->add(background);
- LightPathNode *light_path = new LightPathNode();
+ LightPathNode *light_path = graph->create_node<LightPathNode>();
graph->add(light_path);
- MixNode *mix_scene_with_background = new MixNode();
+ MixNode *mix_scene_with_background = graph->create_node<MixNode>();
mix_scene_with_background->color2 = world_color;
graph->add(mix_scene_with_background);
- EnvironmentTextureNode *texture_environment = new EnvironmentTextureNode();
+ EnvironmentTextureNode *texture_environment = graph->create_node<EnvironmentTextureNode>();
texture_environment->tex_mapping.type = TextureMapping::VECTOR;
texture_environment->tex_mapping.rotation[2] = new_viewport_parameters.studiolight_rotate_z;
texture_environment->filename = new_viewport_parameters.studiolight_path;
graph->add(texture_environment);
- MixNode *mix_intensity = new MixNode();
+ MixNode *mix_intensity = graph->create_node<MixNode>();
mix_intensity->type = NODE_MIX_MUL;
mix_intensity->fac = 1.0f;
mix_intensity->color2 = make_float3(new_viewport_parameters.studiolight_intensity,
@@ -1376,10 +1377,10 @@ void BlenderSync::sync_world(BL::Depsgraph &b_depsgraph, BL::SpaceView3D &b_v3d,
new_viewport_parameters.studiolight_intensity);
graph->add(mix_intensity);
- TextureCoordinateNode *texture_coordinate = new TextureCoordinateNode();
+ TextureCoordinateNode *texture_coordinate = graph->create_node<TextureCoordinateNode>();
graph->add(texture_coordinate);
- MixNode *mix_background_with_environment = new MixNode();
+ MixNode *mix_background_with_environment = graph->create_node<MixNode>();
mix_background_with_environment->fac = new_viewport_parameters.studiolight_background_alpha;
mix_background_with_environment->color1 = world_color;
graph->add(mix_background_with_environment);
@@ -1466,7 +1467,7 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
Shader *shader;
/* test if we need to sync */
- if (shader_map.add_or_update(&shader, b_light) || update_all) {
+ if (shader_map.add_or_update(scene, &shader, b_light) || update_all) {
ShaderGraph *graph = new ShaderGraph();
/* create nodes */
@@ -1478,7 +1479,7 @@ void BlenderSync::sync_lights(BL::Depsgraph &b_depsgraph, bool update_all)
add_nodes(scene, b_engine, b_data, b_depsgraph, b_scene, graph, b_ntree);
}
else {
- EmissionNode *emission = new EmissionNode();
+ EmissionNode *emission = graph->create_node<EmissionNode>();
emission->color = make_float3(1.0f, 1.0f, 1.0f);
emission->strength = 1.0f;
graph->add(emission);
diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp
index f0b5ab087bb..0126e5c8874 100644
--- a/intern/cycles/blender/blender_sync.cpp
+++ b/intern/cycles/blender/blender_sync.cpp
@@ -55,11 +55,11 @@ BlenderSync::BlenderSync(BL::RenderEngine &b_engine,
: b_engine(b_engine),
b_data(b_data),
b_scene(b_scene),
- shader_map(&scene->shaders),
- object_map(&scene->objects),
- geometry_map(&scene->geometry),
- light_map(&scene->lights),
- particle_system_map(&scene->particle_systems),
+ shader_map(),
+ object_map(),
+ geometry_map(),
+ light_map(),
+ particle_system_map(),
world_map(NULL),
world_recalc(false),
scene(scene),
@@ -239,7 +239,7 @@ void BlenderSync::sync_data(BL::RenderSettings &b_render,
/* Shader sync done at the end, since object sync uses it.
* false = don't delete unused shaders, not supported. */
- shader_map.post_sync(false);
+ shader_map.post_sync(scene, false);
free_data_after_sync(b_depsgraph);
}
diff --git a/intern/cycles/graph/node.cpp b/intern/cycles/graph/node.cpp
index c437c6fda1e..14e66959f4f 100644
--- a/intern/cycles/graph/node.cpp
+++ b/intern/cycles/graph/node.cpp
@@ -26,10 +26,16 @@ CCL_NAMESPACE_BEGIN
/* Node Type */
+NodeOwner::~NodeOwner()
+{
+}
+
Node::Node(const NodeType *type_, ustring name_) : name(name_), type(type_)
{
assert(type);
+ owner = nullptr;
+
/* assign non-empty name, convenient for debugging */
if (name.empty()) {
name = type->name;
@@ -679,4 +685,14 @@ bool Node::is_a(const NodeType *type_)
return false;
}
+const NodeOwner *Node::get_owner() const
+{
+ return owner;
+}
+
+void Node::set_owner(const NodeOwner *owner_)
+{
+ owner_ = owner;
+}
+
CCL_NAMESPACE_END
diff --git a/intern/cycles/graph/node.h b/intern/cycles/graph/node.h
index 4473b8aca28..3c84dbdb4a7 100644
--- a/intern/cycles/graph/node.h
+++ b/intern/cycles/graph/node.h
@@ -31,6 +31,10 @@ struct Transform;
/* Node */
+struct NodeOwner {
+ virtual ~NodeOwner();
+};
+
struct Node {
explicit Node(const NodeType *type, ustring name = ustring());
virtual ~Node() = 0;
@@ -99,6 +103,12 @@ struct Node {
ustring name;
const NodeType *type;
+
+ const NodeOwner *get_owner() const;
+ void set_owner(const NodeOwner *owner_);
+
+ protected:
+ const NodeOwner *owner;
};
CCL_NAMESPACE_END
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);
}