This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/depsgraph/intern/depsgraph_build.cc
Jacques Lucke ba5b4d1bd6 Fix T88250: crash when instancing object in disabled collection
This issue was that `BKE_object_eval_uber_data` was not called for
the text object, because its geometry was not dependent upon
and its `is_directly_visible` tag was `false`. The crash happens in
rendering code, because the evaluated data is missing.

This not only affects text objects, but all object types that have a
geometry component that geometry nodes does not support yet.

The solution is to just add the missing dependencies.

Differential Revision: https://developer.blender.org/D11385
2021-05-26 16:06:01 +02:00

323 lines
12 KiB
C++

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2013 Blender Foundation.
* All rights reserved.
*/
/** \file
* \ingroup depsgraph
*
* Methods for constructing depsgraph.
*/
#include "MEM_guardedalloc.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "PIL_time.h"
#include "PIL_time_utildefines.h"
#include "DNA_cachefile_types.h"
#include "DNA_collection_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_simulation_types.h"
#include "BKE_collection.h"
#include "BKE_main.h"
#include "BKE_scene.h"
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_debug.h"
#include "builder/deg_builder_relations.h"
#include "builder/pipeline_all_objects.h"
#include "builder/pipeline_compositor.h"
#include "builder/pipeline_from_ids.h"
#include "builder/pipeline_render.h"
#include "builder/pipeline_view_layer.h"
#include "intern/debug/deg_debug.h"
#include "intern/node/deg_node.h"
#include "intern/node/deg_node_component.h"
#include "intern/node/deg_node_id.h"
#include "intern/node/deg_node_operation.h"
#include "intern/depsgraph_registry.h"
#include "intern/depsgraph_relation.h"
#include "intern/depsgraph_tag.h"
#include "intern/depsgraph_type.h"
/* ****************** */
/* External Build API */
namespace deg = blender::deg;
static deg::NodeType deg_build_scene_component_type(eDepsSceneComponentType component)
{
switch (component) {
case DEG_SCENE_COMP_PARAMETERS:
return deg::NodeType::PARAMETERS;
case DEG_SCENE_COMP_ANIMATION:
return deg::NodeType::ANIMATION;
case DEG_SCENE_COMP_SEQUENCER:
return deg::NodeType::SEQUENCER;
}
return deg::NodeType::UNDEFINED;
}
static deg::DepsNodeHandle *get_node_handle(DepsNodeHandle *node_handle)
{
return reinterpret_cast<deg::DepsNodeHandle *>(node_handle);
}
void DEG_add_scene_relation(DepsNodeHandle *node_handle,
Scene *scene,
eDepsSceneComponentType component,
const char *description)
{
deg::NodeType type = deg_build_scene_component_type(component);
deg::ComponentKey comp_key(&scene->id, type);
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
}
void DEG_add_object_relation(DepsNodeHandle *node_handle,
Object *object,
eDepsObjectComponentType component,
const char *description)
{
deg::NodeType type = deg::nodeTypeFromObjectComponent(component);
deg::ComponentKey comp_key(&object->id, type);
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
}
bool DEG_object_has_geometry_component(Object *object)
{
return deg::geometry_tag_to_component(&object->id) != deg::NodeType::UNDEFINED;
}
void DEG_add_collection_geometry_relation(DepsNodeHandle *node_handle,
Collection *collection,
const char *description)
{
deg::OperationKey operation_key{
&collection->id, deg::NodeType::GEOMETRY, deg::OperationCode::GEOMETRY_EVAL_DONE};
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(operation_key, deg_node_handle, description);
}
void DEG_add_collection_geometry_customdata_mask(DepsNodeHandle *node_handle,
Collection *collection,
const CustomData_MeshMasks *masks)
{
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (collection, ob) {
DEG_add_customdata_mask(node_handle, ob, masks);
if (ob->type == OB_EMPTY && ob->instance_collection != nullptr) {
DEG_add_collection_geometry_customdata_mask(node_handle, ob->instance_collection, masks);
}
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
}
void DEG_add_simulation_relation(DepsNodeHandle *node_handle,
Simulation *simulation,
const char *description)
{
deg::OperationKey operation_key(
&simulation->id, deg::NodeType::SIMULATION, deg::OperationCode::SIMULATION_EVAL);
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(operation_key, deg_node_handle, description);
}
void DEG_add_node_tree_relation(DepsNodeHandle *node_handle,
bNodeTree *node_tree,
const char *description)
{
/* Using shading key, because that's the one that exists right now. Should use something else in
* the future. */
deg::ComponentKey shading_key(&node_tree->id, deg::NodeType::SHADING);
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(shading_key, deg_node_handle, description);
}
void DEG_add_object_cache_relation(DepsNodeHandle *node_handle,
CacheFile *cache_file,
eDepsObjectComponentType component,
const char *description)
{
deg::NodeType type = deg::nodeTypeFromObjectComponent(component);
deg::ComponentKey comp_key(&cache_file->id, type);
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
}
void DEG_add_bone_relation(DepsNodeHandle *node_handle,
Object *object,
const char *bone_name,
eDepsObjectComponentType component,
const char *description)
{
deg::NodeType type = deg::nodeTypeFromObjectComponent(component);
deg::ComponentKey comp_key(&object->id, type, bone_name);
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(comp_key, deg_node_handle, description);
}
void DEG_add_object_pointcache_relation(struct DepsNodeHandle *node_handle,
struct Object *object,
eDepsObjectComponentType component,
const char *description)
{
deg::NodeType type = deg::nodeTypeFromObjectComponent(component);
deg::ComponentKey comp_key(&object->id, type);
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg::DepsgraphRelationBuilder *relation_builder = deg_node_handle->builder;
/* Add relation from source to the node handle. */
relation_builder->add_node_handle_relation(comp_key, deg_node_handle, description);
/* Node deduct point cache component and connect source to it. */
ID *id = DEG_get_id_from_handle(node_handle);
deg::ComponentKey point_cache_key(id, deg::NodeType::POINT_CACHE);
deg::Relation *rel = relation_builder->add_relation(comp_key, point_cache_key, "Point Cache");
if (rel != nullptr) {
rel->flag |= deg::RELATION_FLAG_FLUSH_USER_EDIT_ONLY;
}
else {
fprintf(stderr, "Error in point cache relation from %s to ^%s.\n", object->id.name, id->name);
}
}
void DEG_add_generic_id_relation(struct DepsNodeHandle *node_handle,
struct ID *id,
const char *description)
{
deg::OperationKey operation_key(
id, deg::NodeType::GENERIC_DATABLOCK, deg::OperationCode::GENERIC_DATABLOCK_UPDATE);
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_node_handle_relation(operation_key, deg_node_handle, description);
}
void DEG_add_modifier_to_transform_relation(struct DepsNodeHandle *node_handle,
const char *description)
{
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_modifier_to_transform_relation(deg_node_handle, description);
}
void DEG_add_special_eval_flag(struct DepsNodeHandle *node_handle, ID *id, uint32_t flag)
{
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_special_eval_flag(id, flag);
}
void DEG_add_customdata_mask(struct DepsNodeHandle *node_handle,
struct Object *object,
const CustomData_MeshMasks *masks)
{
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg_node_handle->builder->add_customdata_mask(object, deg::DEGCustomDataMeshMasks(masks));
}
struct ID *DEG_get_id_from_handle(struct DepsNodeHandle *node_handle)
{
deg::DepsNodeHandle *deg_handle = get_node_handle(node_handle);
return deg_handle->node->owner->owner->id_orig;
}
struct Depsgraph *DEG_get_graph_from_handle(struct DepsNodeHandle *node_handle)
{
deg::DepsNodeHandle *deg_node_handle = get_node_handle(node_handle);
deg::DepsgraphRelationBuilder *relation_builder = deg_node_handle->builder;
return reinterpret_cast<Depsgraph *>(relation_builder->getGraph());
}
/* ******************** */
/* Graph Building API's */
/* Build depsgraph for the given scene layer, and dump results in given graph container. */
void DEG_graph_build_from_view_layer(Depsgraph *graph)
{
deg::ViewLayerBuilderPipeline builder(graph);
builder.build();
}
void DEG_graph_build_for_all_objects(struct Depsgraph *graph)
{
deg::AllObjectsBuilderPipeline builder(graph);
builder.build();
}
void DEG_graph_build_for_render_pipeline(Depsgraph *graph)
{
deg::RenderBuilderPipeline builder(graph);
builder.build();
}
void DEG_graph_build_for_compositor_preview(Depsgraph *graph, bNodeTree *nodetree)
{
deg::CompositorBuilderPipeline builder(graph, nodetree);
builder.build();
}
void DEG_graph_build_from_ids(Depsgraph *graph, ID **ids, const int num_ids)
{
deg::FromIDsBuilderPipeline builder(graph, blender::Span(ids, num_ids));
builder.build();
}
/* Tag graph relations for update. */
void DEG_graph_tag_relations_update(Depsgraph *graph)
{
DEG_DEBUG_PRINTF(graph, TAG, "%s: Tagging relations for update.\n", __func__);
deg::Depsgraph *deg_graph = reinterpret_cast<deg::Depsgraph *>(graph);
deg_graph->need_update = true;
/* NOTE: When relations are updated, it's quite possible that
* we've got new bases in the scene. This means, we need to
* re-create flat array of bases in view layer.
*
* TODO(sergey): Try to make it so we don't flush updates
* to the whole depsgraph. */
deg::IDNode *id_node = deg_graph->find_id_node(&deg_graph->scene->id);
if (id_node != nullptr) {
id_node->tag_update(deg_graph, deg::DEG_UPDATE_SOURCE_RELATIONS);
}
}
/* Create or update relations in the specified graph. */
void DEG_graph_relations_update(Depsgraph *graph)
{
deg::Depsgraph *deg_graph = (deg::Depsgraph *)graph;
if (!deg_graph->need_update) {
/* Graph is up to date, nothing to do. */
return;
}
DEG_graph_build_from_view_layer(graph);
}
/* Tag all relations for update. */
void DEG_relations_tag_update(Main *bmain)
{
DEG_GLOBAL_DEBUG_PRINTF(TAG, "%s: Tagging relations for update.\n", __func__);
for (deg::Depsgraph *depsgraph : deg::get_all_registered_graphs(bmain)) {
DEG_graph_tag_relations_update(reinterpret_cast<Depsgraph *>(depsgraph));
}
}