Files
test/source/blender/makesrna/intern/rna_depsgraph.cc
Hans Goudey da511f5573 Fix: Incorrect freeing in depsgraph RNA objects iterator
Caused by 4d7274b7f4.
The depsgraph iterator was freed twice, and the "custom"
iterator wasn't freed at all. Thanks to Jesse for investigating this.
2023-11-17 00:41:37 +01:00

852 lines
34 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup RNA
*/
#include <array>
#include <cstdlib>
#include "BLI_math_matrix.h"
#include "BLI_math_vector.h"
#include "BLI_path_util.h"
#include "BLI_utildefines.h"
#include "RNA_define.hh"
#include "RNA_enum_types.hh"
#include "rna_internal.h"
#include "DNA_object_types.h"
#include "DEG_depsgraph.hh"
#define STATS_MAX_SIZE 16384
#ifdef RNA_RUNTIME
# ifdef WITH_PYTHON
# include "BPY_extern.h"
# endif
# include "BLI_iterator.h"
# include "RNA_access.hh"
# include "BKE_duplilist.h"
# include "BKE_object.hh"
# include "BKE_scene.h"
# include "DEG_depsgraph_build.hh"
# include "DEG_depsgraph_debug.hh"
# include "DEG_depsgraph_query.hh"
# include "MEM_guardedalloc.h"
/* **************** Object Instance **************** */
struct RNA_DepsgraphIterator {
BLI_Iterator iter;
# ifdef WITH_PYTHON
/**
* Store the Python instance so the #BPy_StructRNA can be set as invalid iteration is completed.
* Otherwise accessing from Python (console auto-complete for e.g.) crashes, see: #100286. */
void *py_instance;
# endif
};
# ifdef WITH_PYTHON
void **rna_DepsgraphIterator_instance(PointerRNA *ptr)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
return &di->py_instance;
}
# endif
/* Temporary hack for Cycles until it is changed to work with the C API directly. */
extern "C" DupliObject *rna_hack_DepsgraphObjectInstance_dupli_object_get(PointerRNA *ptr)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
return deg_iter->dupli_object_current;
}
static PointerRNA rna_DepsgraphObjectInstance_object_get(PointerRNA *ptr)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
return rna_pointer_inherit_refine(ptr, &RNA_Object, di->iter.current);
}
static bool rna_DepsgraphObjectInstance_is_instance_get(PointerRNA *ptr)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
return (deg_iter->dupli_object_current != nullptr);
}
static PointerRNA rna_DepsgraphObjectInstance_instance_object_get(PointerRNA *ptr)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
Object *instance_object = nullptr;
if (deg_iter->dupli_object_current != nullptr) {
instance_object = deg_iter->dupli_object_current->ob;
}
return rna_pointer_inherit_refine(ptr, &RNA_Object, instance_object);
}
static bool rna_DepsgraphObjectInstance_show_self_get(PointerRNA *ptr)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
int ob_visibility = BKE_object_visibility(static_cast<const Object *>(di->iter.current),
deg_iter->eval_mode);
return (ob_visibility & OB_VISIBLE_SELF) != 0;
}
static bool rna_DepsgraphObjectInstance_show_particles_get(PointerRNA *ptr)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
int ob_visibility = BKE_object_visibility(static_cast<const Object *>(di->iter.current),
deg_iter->eval_mode);
return (ob_visibility & OB_VISIBLE_PARTICLES) != 0;
}
static PointerRNA rna_DepsgraphObjectInstance_parent_get(PointerRNA *ptr)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
Object *dupli_parent = nullptr;
if (deg_iter->dupli_object_current != nullptr) {
dupli_parent = deg_iter->dupli_parent;
}
return rna_pointer_inherit_refine(ptr, &RNA_Object, dupli_parent);
}
static PointerRNA rna_DepsgraphObjectInstance_particle_system_get(PointerRNA *ptr)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
ParticleSystem *particle_system = nullptr;
if (deg_iter->dupli_object_current != nullptr) {
particle_system = deg_iter->dupli_object_current->particle_system;
}
return rna_pointer_inherit_refine(ptr, &RNA_ParticleSystem, particle_system);
}
static void rna_DepsgraphObjectInstance_persistent_id_get(PointerRNA *ptr, int *persistent_id)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
if (deg_iter->dupli_object_current != nullptr) {
memcpy(persistent_id,
deg_iter->dupli_object_current->persistent_id,
sizeof(deg_iter->dupli_object_current->persistent_id));
}
else {
memset(persistent_id, 0, sizeof(deg_iter->dupli_object_current->persistent_id));
}
}
static int rna_DepsgraphObjectInstance_random_id_get(PointerRNA *ptr)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
if (deg_iter->dupli_object_current != nullptr) {
return int(deg_iter->dupli_object_current->random_id);
}
else {
return 0;
}
}
static void rna_DepsgraphObjectInstance_matrix_world_get(PointerRNA *ptr, float *mat)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
if (deg_iter->dupli_object_current != nullptr) {
copy_m4_m4((float(*)[4])mat, deg_iter->dupli_object_current->mat);
}
else {
/* We can return actual object's matrix here, no reason to return identity matrix
* when this is not actually an instance... */
Object *ob = (Object *)di->iter.current;
copy_m4_m4((float(*)[4])mat, ob->object_to_world);
}
}
static void rna_DepsgraphObjectInstance_orco_get(PointerRNA *ptr, float *orco)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
if (deg_iter->dupli_object_current != nullptr) {
copy_v3_v3(orco, deg_iter->dupli_object_current->orco);
}
else {
zero_v3(orco);
}
}
static void rna_DepsgraphObjectInstance_uv_get(PointerRNA *ptr, float *uv)
{
RNA_DepsgraphIterator *di = static_cast<RNA_DepsgraphIterator *>(ptr->data);
DEGObjectIterData *deg_iter = (DEGObjectIterData *)di->iter.data;
if (deg_iter->dupli_object_current != nullptr) {
copy_v2_v2(uv, deg_iter->dupli_object_current->uv);
}
else {
zero_v2(uv);
}
}
/* ******************** Sorted ***************** */
static int rna_Depsgraph_mode_get(PointerRNA *ptr)
{
Depsgraph *depsgraph = static_cast<Depsgraph *>(ptr->data);
return DEG_get_mode(depsgraph);
}
/* ******************** Updates ***************** */
static PointerRNA rna_DepsgraphUpdate_id_get(PointerRNA *ptr)
{
return rna_pointer_inherit_refine(ptr, &RNA_ID, ptr->data);
}
static bool rna_DepsgraphUpdate_is_updated_transform_get(PointerRNA *ptr)
{
ID *id = static_cast<ID *>(ptr->data);
return ((id->recalc & ID_RECALC_TRANSFORM) != 0);
}
static bool rna_DepsgraphUpdate_is_updated_shading_get(PointerRNA *ptr)
{
/* Assume any animated parameters can affect shading, we don't have fine
* grained enough updates to distinguish this. */
ID *id = static_cast<ID *>(ptr->data);
return ((id->recalc & (ID_RECALC_SHADING | ID_RECALC_ANIMATION)) != 0);
}
static bool rna_DepsgraphUpdate_is_updated_geometry_get(PointerRNA *ptr)
{
ID *id = static_cast<ID *>(ptr->data);
if (id->recalc & ID_RECALC_GEOMETRY) {
return true;
}
if (GS(id->name) != ID_OB) {
return false;
}
Object *object = (Object *)id;
ID *data = static_cast<ID *>(object->data);
if (data == nullptr) {
return false;
}
return ((data->recalc & ID_RECALC_ALL) != 0);
}
/* **************** Depsgraph **************** */
static void rna_Depsgraph_debug_relations_graphviz(Depsgraph *depsgraph, const char *filepath)
{
FILE *f = fopen(filepath, "w");
if (f == nullptr) {
return;
}
DEG_debug_relations_graphviz(depsgraph, f, "Depsgraph");
fclose(f);
}
static void rna_Depsgraph_debug_stats_gnuplot(Depsgraph *depsgraph,
const char *filepath,
const char *output_filepath)
{
FILE *f = fopen(filepath, "w");
if (f == nullptr) {
return;
}
DEG_debug_stats_gnuplot(depsgraph, f, "Timing Statistics", output_filepath);
fclose(f);
}
static void rna_Depsgraph_debug_tag_update(Depsgraph *depsgraph)
{
DEG_graph_tag_relations_update(depsgraph);
}
static void rna_Depsgraph_debug_stats(Depsgraph *depsgraph, char *result)
{
size_t outer, ops, rels;
DEG_stats_simple(depsgraph, &outer, &ops, &rels);
BLI_snprintf(result,
STATS_MAX_SIZE,
"Approx %zu Operations, %zu Relations, %zu Outer Nodes",
ops,
rels,
outer);
}
static void rna_Depsgraph_update(Depsgraph *depsgraph, Main *bmain, ReportList *reports)
{
if (DEG_is_evaluating(depsgraph)) {
BKE_report(reports, RPT_ERROR, "Dependency graph update requested during evaluation");
return;
}
# ifdef WITH_PYTHON
/* Allow drivers to be evaluated */
BPy_BEGIN_ALLOW_THREADS;
# endif
BKE_scene_graph_update_tagged(depsgraph, bmain);
# ifdef WITH_PYTHON
BPy_END_ALLOW_THREADS;
# endif
}
/* Iteration over objects, simple version */
static void rna_Depsgraph_objects_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
iter->internal.custom = MEM_callocN(sizeof(BLI_Iterator), __func__);
DEGObjectIterData *data = MEM_new<DEGObjectIterData>(__func__);
DEGObjectIterSettings *deg_iter_settings = static_cast<DEGObjectIterSettings *>(
MEM_callocN(sizeof(DEGObjectIterSettings), __func__));
deg_iter_settings->depsgraph = (Depsgraph *)ptr->data;
deg_iter_settings->flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_VISIBLE |
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET;
data->settings = deg_iter_settings;
data->graph = deg_iter_settings->depsgraph;
data->flag = deg_iter_settings->flags;
((BLI_Iterator *)iter->internal.custom)->valid = true;
DEG_iterator_objects_begin(static_cast<BLI_Iterator *>(iter->internal.custom), data);
iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
}
static void rna_Depsgraph_objects_next(CollectionPropertyIterator *iter)
{
DEG_iterator_objects_next(static_cast<BLI_Iterator *>(iter->internal.custom));
iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
}
static void rna_Depsgraph_objects_end(CollectionPropertyIterator *iter)
{
DEGObjectIterData *data = (DEGObjectIterData *)((BLI_Iterator *)iter->internal.custom)->data;
DEG_iterator_objects_end(static_cast<BLI_Iterator *>(iter->internal.custom));
MEM_freeN(data->settings);
MEM_delete(data);
MEM_freeN(iter->internal.custom);
}
static PointerRNA rna_Depsgraph_objects_get(CollectionPropertyIterator *iter)
{
Object *ob = static_cast<Object *>(((BLI_Iterator *)iter->internal.custom)->current);
return rna_pointer_inherit_refine(&iter->parent, &RNA_Object, ob);
}
/* Iteration over objects, extended version
*
* Contains extra information about duplicator and persistent ID.
*/
/* XXX Ugly python seems to query next item of an iterator before using current one (see #57558).
* This forces us to use that nasty ping-pong game between two sets of iterator data,
* so that previous one remains valid memory for python to access to. Yuck.
*/
struct RNA_Depsgraph_Instances_Iterator {
RNA_DepsgraphIterator iterators[2];
DEGObjectIterData deg_data[2];
DupliObject dupli_object_current[2];
int counter;
};
static void rna_Depsgraph_object_instances_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
RNA_Depsgraph_Instances_Iterator *di_it = MEM_new<RNA_Depsgraph_Instances_Iterator>(__func__);
iter->internal.custom = di_it;
DEGObjectIterSettings *deg_iter_settings = static_cast<DEGObjectIterSettings *>(
MEM_callocN(sizeof(DEGObjectIterSettings), __func__));
deg_iter_settings->depsgraph = (Depsgraph *)ptr->data;
deg_iter_settings->flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY |
DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | DEG_ITER_OBJECT_FLAG_VISIBLE |
DEG_ITER_OBJECT_FLAG_DUPLI;
DEGObjectIterData *data = &di_it->deg_data[0];
data->settings = deg_iter_settings;
data->graph = deg_iter_settings->depsgraph;
data->flag = deg_iter_settings->flags;
di_it->iterators[0].iter.valid = true;
DEG_iterator_objects_begin(&di_it->iterators[0].iter, data);
iter->valid = di_it->iterators[0].iter.valid;
}
static void rna_Depsgraph_object_instances_next(CollectionPropertyIterator *iter)
{
RNA_Depsgraph_Instances_Iterator *di_it = (RNA_Depsgraph_Instances_Iterator *)
iter->internal.custom;
/* We need to copy current iterator status to next one being worked on. */
di_it->iterators[(di_it->counter + 1) % 2].iter = di_it->iterators[di_it->counter % 2].iter;
di_it->deg_data[(di_it->counter + 1) % 2] = di_it->deg_data[di_it->counter % 2];
di_it->counter++;
di_it->iterators[di_it->counter % 2].iter.data = &di_it->deg_data[di_it->counter % 2];
DEG_iterator_objects_next(&di_it->iterators[di_it->counter % 2].iter);
/* Dupli_object_current is also temp memory generated during the iterations,
* it may be freed when last item has been iterated,
* so we have same issue as with the iterator itself:
* we need to keep a local copy, which memory remains valid a bit longer,
* for Python accesses to work. */
if (di_it->deg_data[di_it->counter % 2].dupli_object_current != nullptr) {
di_it->dupli_object_current[di_it->counter % 2] =
*di_it->deg_data[di_it->counter % 2].dupli_object_current;
di_it->deg_data[di_it->counter % 2].dupli_object_current =
&di_it->dupli_object_current[di_it->counter % 2];
}
iter->valid = di_it->iterators[di_it->counter % 2].iter.valid;
}
static void rna_Depsgraph_object_instances_end(CollectionPropertyIterator *iter)
{
RNA_Depsgraph_Instances_Iterator *di_it = (RNA_Depsgraph_Instances_Iterator *)
iter->internal.custom;
for (int i = 0; i < ARRAY_SIZE(di_it->iterators); i++) {
RNA_DepsgraphIterator *di = &di_it->iterators[i];
DEGObjectIterData *data = &di_it->deg_data[i];
if (i == 0) {
/* Is shared between both iterators. */
MEM_freeN(data->settings);
}
DEG_iterator_objects_end(&di->iter);
# ifdef WITH_PYTHON
if (di->py_instance) {
BPY_DECREF_RNA_INVALIDATE(di->py_instance);
}
# endif
}
MEM_delete(di_it);
}
static PointerRNA rna_Depsgraph_object_instances_get(CollectionPropertyIterator *iter)
{
RNA_Depsgraph_Instances_Iterator *di_it = (RNA_Depsgraph_Instances_Iterator *)
iter->internal.custom;
RNA_DepsgraphIterator *di = &di_it->iterators[di_it->counter % 2];
return rna_pointer_inherit_refine(&iter->parent, &RNA_DepsgraphObjectInstance, di);
}
/* Iteration over evaluated IDs */
static void rna_Depsgraph_ids_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
iter->internal.custom = MEM_callocN(sizeof(BLI_Iterator), __func__);
DEGIDIterData *data = static_cast<DEGIDIterData *>(MEM_callocN(sizeof(DEGIDIterData), __func__));
data->graph = (Depsgraph *)ptr->data;
((BLI_Iterator *)iter->internal.custom)->valid = true;
DEG_iterator_ids_begin(static_cast<BLI_Iterator *>(iter->internal.custom), data);
iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
}
static void rna_Depsgraph_ids_next(CollectionPropertyIterator *iter)
{
DEG_iterator_ids_next(static_cast<BLI_Iterator *>(iter->internal.custom));
iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
}
static void rna_Depsgraph_ids_end(CollectionPropertyIterator *iter)
{
DEG_iterator_ids_end(static_cast<BLI_Iterator *>(iter->internal.custom));
MEM_freeN(((BLI_Iterator *)iter->internal.custom)->data);
MEM_freeN(iter->internal.custom);
}
static PointerRNA rna_Depsgraph_ids_get(CollectionPropertyIterator *iter)
{
ID *id = static_cast<ID *>(((BLI_Iterator *)iter->internal.custom)->current);
return rna_pointer_inherit_refine(&iter->parent, &RNA_ID, id);
}
static void rna_Depsgraph_updates_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
iter->internal.custom = MEM_callocN(sizeof(BLI_Iterator), __func__);
DEGIDIterData *data = static_cast<DEGIDIterData *>(MEM_callocN(sizeof(DEGIDIterData), __func__));
data->graph = (Depsgraph *)ptr->data;
data->only_updated = true;
((BLI_Iterator *)iter->internal.custom)->valid = true;
DEG_iterator_ids_begin(static_cast<BLI_Iterator *>(iter->internal.custom), data);
iter->valid = ((BLI_Iterator *)iter->internal.custom)->valid;
}
static PointerRNA rna_Depsgraph_updates_get(CollectionPropertyIterator *iter)
{
ID *id = static_cast<ID *>(((BLI_Iterator *)iter->internal.custom)->current);
return rna_pointer_inherit_refine(&iter->parent, &RNA_DepsgraphUpdate, id);
}
static ID *rna_Depsgraph_id_eval_get(Depsgraph *depsgraph, ID *id_orig)
{
return DEG_get_evaluated_id(depsgraph, id_orig);
}
static bool rna_Depsgraph_id_type_updated(Depsgraph *depsgraph, int id_type)
{
return DEG_id_type_updated(depsgraph, id_type);
}
static PointerRNA rna_Depsgraph_scene_get(PointerRNA *ptr)
{
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
Scene *scene = DEG_get_input_scene(depsgraph);
PointerRNA newptr = RNA_pointer_create(&scene->id, &RNA_Scene, scene);
return newptr;
}
static PointerRNA rna_Depsgraph_view_layer_get(PointerRNA *ptr)
{
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
Scene *scene = DEG_get_input_scene(depsgraph);
ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
PointerRNA newptr = RNA_pointer_create(&scene->id, &RNA_ViewLayer, view_layer);
return newptr;
}
static PointerRNA rna_Depsgraph_scene_eval_get(PointerRNA *ptr)
{
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
PointerRNA newptr = RNA_pointer_create(&scene_eval->id, &RNA_Scene, scene_eval);
return newptr;
}
static PointerRNA rna_Depsgraph_view_layer_eval_get(PointerRNA *ptr)
{
Depsgraph *depsgraph = (Depsgraph *)ptr->data;
Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
ViewLayer *view_layer_eval = DEG_get_evaluated_view_layer(depsgraph);
PointerRNA newptr = RNA_pointer_create(&scene_eval->id, &RNA_ViewLayer, view_layer_eval);
return newptr;
}
#else
static void rna_def_depsgraph_instance(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "DepsgraphObjectInstance", nullptr);
RNA_def_struct_ui_text(srna,
"Dependency Graph Object Instance",
"Extended information about dependency graph object iterator "
"(Warning: All data here is 'evaluated' one, not original .blend IDs)");
# ifdef WITH_PYTHON
RNA_def_struct_register_funcs(srna, nullptr, nullptr, "rna_DepsgraphIterator_instance");
# endif
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_ui_text(prop, "Object", "Evaluated object the iterator points to");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_pointer_funcs(
prop, "rna_DepsgraphObjectInstance_object_get", nullptr, nullptr, nullptr);
prop = RNA_def_property(srna, "show_self", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(
prop, "Show Self", "The object geometry itself should be visible in the render");
RNA_def_property_boolean_funcs(prop, "rna_DepsgraphObjectInstance_show_self_get", nullptr);
prop = RNA_def_property(srna, "show_particles", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(
prop, "Show Particles", "Particles part of the object should be visible in the render");
RNA_def_property_boolean_funcs(prop, "rna_DepsgraphObjectInstance_show_particles_get", nullptr);
prop = RNA_def_property(srna, "is_instance", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(
prop, "Is Instance", "Denotes if the object is generated by another object");
RNA_def_property_boolean_funcs(prop, "rna_DepsgraphObjectInstance_is_instance_get", nullptr);
prop = RNA_def_property(srna, "instance_object", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_ui_text(
prop, "Instance Object", "Evaluated object which is being instanced by this iterator");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_pointer_funcs(
prop, "rna_DepsgraphObjectInstance_instance_object_get", nullptr, nullptr, nullptr);
prop = RNA_def_property(srna, "parent", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_ui_text(
prop, "Parent", "If the object is an instance, the parent object that generated it");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_pointer_funcs(
prop, "rna_DepsgraphObjectInstance_parent_get", nullptr, nullptr, nullptr);
prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ParticleSystem");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(
prop, "Particle System", "Evaluated particle system that this object was instanced from");
RNA_def_property_pointer_funcs(
prop, "rna_DepsgraphObjectInstance_particle_system_get", nullptr, nullptr, nullptr);
prop = RNA_def_property(srna, "persistent_id", PROP_INT, PROP_NONE);
RNA_def_property_ui_text(
prop,
"Persistent ID",
"Persistent identifier for inter-frame matching of objects with motion blur");
RNA_def_property_array(prop, MAX_DUPLI_RECUR);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_int_funcs(
prop, "rna_DepsgraphObjectInstance_persistent_id_get", nullptr, nullptr);
prop = RNA_def_property(srna, "random_id", PROP_INT, PROP_UNSIGNED);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(
prop, "Instance Random ID", "Random id for this instance, typically for randomized shading");
RNA_def_property_int_funcs(prop, "rna_DepsgraphObjectInstance_random_id_get", nullptr, nullptr);
prop = RNA_def_property(srna, "matrix_world", PROP_FLOAT, PROP_MATRIX);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4);
RNA_def_property_ui_text(prop, "Generated Matrix", "Generated transform matrix in world space");
RNA_def_property_float_funcs(
prop, "rna_DepsgraphObjectInstance_matrix_world_get", nullptr, nullptr);
prop = RNA_def_property(srna, "orco", PROP_FLOAT, PROP_TRANSLATION);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_array(prop, 3);
RNA_def_property_ui_text(
prop, "Generated Coordinates", "Generated coordinates in parent object space");
RNA_def_property_float_funcs(prop, "rna_DepsgraphObjectInstance_orco_get", nullptr, nullptr);
prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE);
RNA_def_property_ui_text(prop, "UV Coordinates", "UV coordinates in parent object space");
RNA_def_property_array(prop, 2);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_float_funcs(prop, "rna_DepsgraphObjectInstance_uv_get", nullptr, nullptr);
}
static void rna_def_depsgraph_update(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "DepsgraphUpdate", nullptr);
RNA_def_struct_ui_text(srna, "Dependency Graph Update", "Information about ID that was updated");
prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ID");
RNA_def_property_ui_text(prop, "ID", "Updated data-block");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_pointer_funcs(prop, "rna_DepsgraphUpdate_id_get", nullptr, nullptr, nullptr);
/* Use term 'is_updated' instead of 'is_dirty' here because this is a signal
* that users of the depsgraph may want to update their data (render engines for eg). */
prop = RNA_def_property(srna, "is_updated_transform", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Transform", "Object transformation is updated");
RNA_def_property_boolean_funcs(prop, "rna_DepsgraphUpdate_is_updated_transform_get", nullptr);
prop = RNA_def_property(srna, "is_updated_geometry", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Geometry", "Object geometry is updated");
RNA_def_property_boolean_funcs(prop, "rna_DepsgraphUpdate_is_updated_geometry_get", nullptr);
prop = RNA_def_property(srna, "is_updated_shading", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Shading", "Object shading is updated");
RNA_def_property_boolean_funcs(prop, "rna_DepsgraphUpdate_is_updated_shading_get", nullptr);
}
static void rna_def_depsgraph(BlenderRNA *brna)
{
StructRNA *srna;
FunctionRNA *func;
PropertyRNA *parm;
PropertyRNA *prop;
static const EnumPropertyItem enum_depsgraph_mode_items[] = {
{DAG_EVAL_VIEWPORT, "VIEWPORT", 0, "Viewport", "Viewport non-rendered mode"},
{DAG_EVAL_RENDER, "RENDER", 0, "Render", "Render"},
{0, nullptr, 0, nullptr, nullptr},
};
srna = RNA_def_struct(brna, "Depsgraph", nullptr);
RNA_def_struct_ui_text(srna, "Dependency Graph", "");
prop = RNA_def_enum(srna, "mode", enum_depsgraph_mode_items, 0, "Mode", "Evaluation mode");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_funcs(prop, "rna_Depsgraph_mode_get", nullptr, nullptr);
/* Debug helpers. */
func = RNA_def_function(
srna, "debug_relations_graphviz", "rna_Depsgraph_debug_relations_graphviz");
parm = RNA_def_string_file_path(
func, "filepath", nullptr, FILE_MAX, "File Name", "Output path for the graphviz debug file");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
func = RNA_def_function(srna, "debug_stats_gnuplot", "rna_Depsgraph_debug_stats_gnuplot");
parm = RNA_def_string_file_path(
func, "filepath", nullptr, FILE_MAX, "File Name", "Output path for the gnuplot debug file");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_string_file_path(func,
"output_filepath",
nullptr,
FILE_MAX,
"Output File Name",
"File name where gnuplot script will save the result");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
func = RNA_def_function(srna, "debug_tag_update", "rna_Depsgraph_debug_tag_update");
func = RNA_def_function(srna, "debug_stats", "rna_Depsgraph_debug_stats");
RNA_def_function_ui_description(func, "Report the number of elements in the Dependency Graph");
/* weak!, no way to return dynamic string type */
parm = RNA_def_string(func, "result", nullptr, STATS_MAX_SIZE, "result", "");
RNA_def_parameter_flags(
parm, PROP_THICK_WRAP, ParameterFlag(0)); /* needed for string return value */
RNA_def_function_output(func, parm);
/* Updates. */
func = RNA_def_function(srna, "update", "rna_Depsgraph_update");
RNA_def_function_ui_description(
func,
"Re-evaluate any modified data-blocks, for example for animation or modifiers. "
"This invalidates all references to evaluated data-blocks from this dependency graph.");
RNA_def_function_flag(func, FUNC_USE_MAIN | FUNC_USE_REPORTS);
/* Queries for original data-blocks (the ones depsgraph is built for). */
prop = RNA_def_property(srna, "scene", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Scene");
RNA_def_property_pointer_funcs(prop, "rna_Depsgraph_scene_get", nullptr, nullptr, nullptr);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Scene", "Original scene dependency graph is built for");
prop = RNA_def_property(srna, "view_layer", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ViewLayer");
RNA_def_property_pointer_funcs(prop, "rna_Depsgraph_view_layer_get", nullptr, nullptr, nullptr);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(
prop, "View Layer", "Original view layer dependency graph is built for");
/* Queries for evaluated data-blocks (the ones depsgraph is evaluating). */
func = RNA_def_function(srna, "id_eval_get", "rna_Depsgraph_id_eval_get");
parm = RNA_def_pointer(
func, "id", "ID", "", "Original ID to get evaluated complementary part for");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_pointer(func, "id_eval", "ID", "", "Evaluated ID for the given original one");
RNA_def_function_return(func, parm);
func = RNA_def_function(srna, "id_type_updated", "rna_Depsgraph_id_type_updated");
parm = RNA_def_enum(func, "id_type", rna_enum_id_type_items, 0, "ID Type", "");
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
parm = RNA_def_boolean(func,
"updated",
false,
"Updated",
"True if any datablock with this type was added, updated or removed");
RNA_def_function_return(func, parm);
prop = RNA_def_property(srna, "scene_eval", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "Scene");
RNA_def_property_pointer_funcs(prop, "rna_Depsgraph_scene_eval_get", nullptr, nullptr, nullptr);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Scene", "Scene at its evaluated state");
prop = RNA_def_property(srna, "view_layer_eval", PROP_POINTER, PROP_NONE);
RNA_def_property_struct_type(prop, "ViewLayer");
RNA_def_property_pointer_funcs(
prop, "rna_Depsgraph_view_layer_eval_get", nullptr, nullptr, nullptr);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "View Layer", "View layer at its evaluated state");
/* Iterators. */
prop = RNA_def_property(srna, "ids", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "ID");
RNA_def_property_collection_funcs(prop,
"rna_Depsgraph_ids_begin",
"rna_Depsgraph_ids_next",
"rna_Depsgraph_ids_end",
"rna_Depsgraph_ids_get",
nullptr,
nullptr,
nullptr,
nullptr);
RNA_def_property_ui_text(prop, "IDs", "All evaluated data-blocks");
prop = RNA_def_property(srna, "objects", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "Object");
RNA_def_property_collection_funcs(prop,
"rna_Depsgraph_objects_begin",
"rna_Depsgraph_objects_next",
"rna_Depsgraph_objects_end",
"rna_Depsgraph_objects_get",
nullptr,
nullptr,
nullptr,
nullptr);
RNA_def_property_ui_text(prop, "Objects", "Evaluated objects in the dependency graph");
prop = RNA_def_property(srna, "object_instances", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "DepsgraphObjectInstance");
RNA_def_property_collection_funcs(prop,
"rna_Depsgraph_object_instances_begin",
"rna_Depsgraph_object_instances_next",
"rna_Depsgraph_object_instances_end",
"rna_Depsgraph_object_instances_get",
nullptr,
nullptr,
nullptr,
nullptr);
RNA_def_property_ui_text(prop,
"Object Instances",
"All object instances to display or render "
"(Warning: Only use this as an iterator, never as a sequence, "
"and do not keep any references to its items)");
prop = RNA_def_property(srna, "updates", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "DepsgraphUpdate");
RNA_def_property_collection_funcs(prop,
"rna_Depsgraph_updates_begin",
"rna_Depsgraph_ids_next",
"rna_Depsgraph_ids_end",
"rna_Depsgraph_updates_get",
nullptr,
nullptr,
nullptr,
nullptr);
RNA_def_property_ui_text(prop, "Updates", "Updates to data-blocks");
}
void RNA_def_depsgraph(BlenderRNA *brna)
{
rna_def_depsgraph_instance(brna);
rna_def_depsgraph_update(brna);
rna_def_depsgraph(brna);
}
#endif