Files
test2/source/blender/makesrna/intern/rna_depsgraph.cc
Bastien Montagne 45f231141d Core: Add info about chain of ancestors (owner data) of a PointerRNA.
The general idea is to store an array of (type, data) pointers of all
PointerRNA ancestors of the current one.

This will help solving cases in our code where the owner (or sometimes
even the owner of the owner) of a random PointerRNA needs to be
accessed. Current solution mainly relies on linear search from the owner
ID, which is sub-optimal at best, and may not even be possible in case a
same data is shared between different owners.

This lead to refactoring quite a bit of existing PointerRNA creation code.

At a high level (i.e. expected usages outside of RNA internals):
* Add `RNA_pointer_create_with_parent` and
  `RNA_pointer_create_id_subdata` to create RNA pointers with
  ancestors info.
* `RNA_id_pointer_create` and `RNA_main_pointer_create` remain
  unchanged, as they should never have ancestors currently.
* Add `RNA_pointer_create_from_ancestor` to re-create a RNA pointer
  from the nth ancestor of another PointerRNA.
* Add basic python API to access this new ancestors data.
* Update internal RNA/bpy code to handle ancestors generation in most
  common generic cases.
  - The most verbose change here is for collection code, as the owner of the
    collection property is now passed around, to allow collection items to get
    a valid ancestors chain.

Internally:
* `PointerRNA` now has an array of `AncestorPointerRNA` data to store
  the ancestors.
* `PointerRNA` now has constructors that take care of setting its data for
  most usual cases, including handling of the ancestor array data.
* Pointer type refining has been fully factorized into a small utils,
  `rna_pointer_refine`, that is now used from all code doing that operation.
* `rna_pointer_inherit_refine` has been replaced by
  `rna_pointer_create_with_ancestors` as the core function taking care of
  creating pointers with valid ancestors info.
  - Its usage outside of `rna_access` has been essentially reduced to custom
    collection lookup callbacks.

Implements #122431.

--------------

Some notes:
* The goal of this commit is _not_ to fully cover all cases creating
  PointerRNA that should also store the ancestors' chain info. It only
  tackles the most generic code paths (in bpyrna and RNA itself mainly).
  The remaining 'missing cases' can be tackle later, as needs be.
* Performances seem to be only marginally affected currently.
* Currently `AncestorPointerRNA` only stores PointerRNA-like data.
  This will help `StructPathFunc` callbacks to more efficiently generate
  an RNA paths when calling e.g. `RNA_path_from_ID_to_property`, but will
  not be enough info to build these paths without these callbacks. And some
  cases may still remain fuzzy. We'd have to add thinks like a `PropertyRNA`
  pointer, and for RNA collection ones, an index and string identifier, to store
  a complete unambiguous 'RNA path' info. This is probably not needed, nor
  worth the extra processing and memory footprint,  for now.

Pull Request: https://projects.blender.org/blender/blender/pulls/122427
2025-02-05 15:45:04 +01:00

868 lines
34 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup RNA
*/
#include <cstdlib>
#include "BLI_path_utils.hh"
#include "RNA_define.hh"
#include "RNA_enum_types.hh"
#include "rna_internal.hh"
#include "BKE_duplilist.hh"
#include "DEG_depsgraph.hh"
#define STATS_MAX_SIZE 16384
#ifdef RNA_RUNTIME
# ifdef WITH_PYTHON
# include "BPY_extern.hh"
# endif
# include "BLI_iterator.h"
# include "BLI_math_matrix.h"
# include "BLI_math_vector.h"
# include "BLI_string.h"
# include "DNA_scene_types.h"
# include "RNA_access.hh"
# include "BKE_object.hh"
# include "BKE_report.hh"
# include "BKE_scene.hh"
# 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_id_pointer_create(reinterpret_cast<ID *>(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_id_pointer_create(reinterpret_cast<ID *>(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_id_pointer_create(reinterpret_cast<ID *>(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_create_with_parent(*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);
}
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().ptr());
}
}
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_id_pointer_create(reinterpret_cast<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,
const char **r_str,
int *r_len)
{
const std::string dot_str = DEG_debug_graph_to_dot(*depsgraph, "Depsgraph");
*r_len = dot_str.size();
*r_str = BLI_strdup(dot_str.c_str());
if (filepath) {
FILE *f = fopen(filepath, "w");
if (f == nullptr) {
return;
}
fprintf(f, "%s", dot_str.c_str());
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_id_pointer_create(reinterpret_cast<ID *>(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_create_with_parent(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_id_pointer_create(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_create_with_parent(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_id_pointer_create(&scene->id);
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_id_subdata(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_id_pointer_create(&scene_eval->id);
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_id_subdata(
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",
"Optional output path for the graphviz debug file");
parm = RNA_def_string(func, "dot_graph", nullptr, INT32_MAX, "Dot Graph", "Graph in dot format");
RNA_def_parameter_flags(parm, PROP_DYNAMIC, ParameterFlag(0));
RNA_def_parameter_clear_flags(parm, PROP_NEVER_NULL, ParameterFlag(0));
RNA_def_function_output(func, parm);
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