Depsgraph: Flush flags from base to object as an evaluation step

Previously it was done during depsgraph iteration, which is not good at all,
since after evaluation nobody should really modify how object was evaluated.
This commit is contained in:
Sergey Sharybin 2017-11-24 10:18:16 +01:00
parent 93f6a9d652
commit 87c821ff26
8 changed files with 69 additions and 67 deletions

View File

@ -35,6 +35,7 @@ extern "C" {
#include "BLI_compiler_attrs.h"
struct Base;
struct EvaluationContext;
struct Scene;
struct ViewLayer;
@ -209,6 +210,9 @@ void BKE_object_eval_update_shading(const struct EvaluationContext *eval_ctx,
void BKE_object_data_select_update(const struct EvaluationContext *eval_ctx,
struct ID *object_data);
void BKE_object_eval_flush_base_flags(const struct EvaluationContext *eval_ctx,
struct Object *object, struct Base *base);
void BKE_object_handle_data_update(
const struct EvaluationContext *eval_ctx,
struct Scene *scene,

View File

@ -383,13 +383,16 @@ void BKE_object_eval_uber_data(const EvaluationContext *eval_ctx,
ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME);
}
void BKE_object_eval_cloth(const EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *object)
void BKE_object_eval_cloth(const EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *object)
{
DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH);
}
void BKE_object_eval_update_shading(const EvaluationContext *UNUSED(eval_ctx), Object *object)
void BKE_object_eval_update_shading(const EvaluationContext *UNUSED(eval_ctx),
Object *object)
{
DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
if (object->type == OB_MESH) {
@ -418,3 +421,15 @@ void BKE_object_data_select_update(const EvaluationContext *UNUSED(eval_ctx),
break;
}
}
void BKE_object_eval_flush_base_flags(const EvaluationContext *UNUSED(eval_ctx),
Object *object, Base *base)
{
/* Make sure we have the base collection settings is already populated.
* This will fail when BKE_layer_eval_layer_collection_pre hasn't run yet
* Which usually means a missing call to DEG_id_tag_update(). */
BLI_assert(!BLI_listbase_is_empty(&base->collection_properties->data.group));
/* Copy flags and settings from base. */
object->base_flag = base->flag;
object->base_collection_properties = base->collection_properties;
}

View File

@ -404,10 +404,15 @@ void DepsgraphNodeBuilder::build_object(Base *base,
Object *object,
eDepsNode_LinkedState_Type linked_state)
{
(void)base;
/* Skip rest of components if the ID node was already there. */
if (object->id.tag & LIB_TAG_DOIT) {
IDDepsNode *id_node = find_id_node(&object->id);
/* We need to build some extra stuff if object becomes linked
* directly.
*/
if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) {
build_object_flags(base, object);
}
id_node->linked_state = max(id_node->linked_state, linked_state);
return;
}
@ -416,6 +421,8 @@ void DepsgraphNodeBuilder::build_object(Base *base,
IDDepsNode *id_node = add_id_node(&object->id);
id_node->linked_state = linked_state;
object->customdata_mask = 0;
/* Various flags, flushing from bases/collections. */
build_object_flags(base, object);
/* Transform. */
build_object_transform(object);
/* Parent. */
@ -462,6 +469,20 @@ void DepsgraphNodeBuilder::build_object(Base *base,
}
}
void DepsgraphNodeBuilder::build_object_flags(Base *base, Object *object)
{
if (base == NULL) {
return;
}
/* TODO(sergey): Is this really best component to be used? */
Object *object_cow = get_cow_datablock(object);
add_operation_node(&object->id,
DEG_NODE_TYPE_LAYER_COLLECTIONS,
function_bind(BKE_object_eval_flush_base_flags,
_1, object_cow, base),
DEG_OPCODE_OBJECT_BASE_FLAGS);
}
void DepsgraphNodeBuilder::build_object_data(Object *object)
{
if (object->data == NULL) {

View File

@ -165,6 +165,7 @@ struct DepsgraphNodeBuilder {
void build_object(Base *base,
Object *object,
eDepsNode_LinkedState_Type linked_state);
void build_object_flags(Base *base, Object *object);
void build_object_data(Object *object);
void build_object_transform(Object *object);
void build_object_constraints(Object *object);

View File

@ -455,6 +455,8 @@ void DepsgraphRelationBuilder::build_object(Object *object)
OperationKey ob_ubereval_key(&object->id,
DEG_NODE_TYPE_TRANSFORM,
DEG_OPCODE_TRANSFORM_OBJECT_UBEREVAL);
/* Various flags, flushing from bases/collections. */
build_object_flags(object);
/* Parenting. */
if (object->parent != NULL) {
/* Parent relationship. */
@ -541,6 +543,17 @@ void DepsgraphRelationBuilder::build_object(Object *object)
}
}
void DepsgraphRelationBuilder::build_object_flags(Object *object)
{
OperationKey view_layer_done_key(&scene_->id,
DEG_NODE_TYPE_LAYER_COLLECTIONS,
DEG_OPCODE_VIEW_LAYER_DONE);
OperationKey object_flags_key(&object->id,
DEG_NODE_TYPE_LAYER_COLLECTIONS,
DEG_OPCODE_OBJECT_BASE_FLAGS);
add_relation(view_layer_done_key, object_flags_key, "Base flags flush");
}
void DepsgraphRelationBuilder::build_object_data(Object *object)
{
if (object->data == NULL) {

View File

@ -190,6 +190,7 @@ struct DepsgraphRelationBuilder
void build_group(Object *object, Group *group);
void build_object(Object *object);
void build_object_data(Object *object);
void build_object_flags(Object *object);
void build_object_parent(Object *object);
void build_constraints(ID *id,
eDepsNode_Type component_type,

View File

@ -124,57 +124,6 @@ ID *DEG_get_evaluated_id(struct Depsgraph *depsgraph, ID *id)
/* ************************ DEG ITERATORS ********************* */
/**
* XXX (dfelinto/sergey) big hack, waiting for:
* "Reshuffle collections base flags evaluation, make it so object is gathering its base flags from collections."
*
* Returns false if object shouldn't be found (which should never happen in the final implementation
* and instead we should have a tag to the objects that were not directly part of the depsgraph).
*
* That means that the object is not in a collection but it's part of depsgraph, or the object is simply
* not in the current ViewLayer - Depsgraph at the moment includes all the ViewLayer in the Scene.
*/
static bool deg_flush_base_flags_and_settings(
DEGObjectsIteratorData *data, Object *ob_dst, Object *ob_src, const bool is_dupli)
{
Base *base;
Depsgraph *graph = data->graph;
ViewLayer *view_layer = data->eval_ctx.view_layer;
int flag = is_dupli ? BASE_FROMDUPLI : 0;
/* First attempt, see if object is in the current ViewLayer. */
base = (Base *)BLI_findptr(&view_layer->object_bases, ob_src, offsetof(Base, object));
/* Next attempt, see if object is in one of the sets. */
if (base == NULL) {
Scene *scene_iter, *scene = DEG_get_evaluated_scene(graph);
scene_iter = scene;
while ((scene_iter = (scene_iter)->set)) {
ViewLayer *view_layer_set = BKE_view_layer_from_scene_get(scene_iter);
base = (Base *)BLI_findptr(&view_layer_set->object_bases, ob_src, offsetof(Base, object));
if (base != NULL) {
flag |= BASE_FROM_SET;
flag &= ~(BASE_SELECTED | BASE_SELECTABLED);
break;
}
}
}
if (base == NULL) {
return false;
}
/* Make sure we have the base collection settings is already populated.
* This will fail when BKE_layer_eval_layer_collection_pre hasn't run yet
* Which usually means a missing call to DEG_id_tag_update(). */
BLI_assert(!BLI_listbase_is_empty(&base->collection_properties->data.group));
ob_dst->base_flag = base->flag | flag;
ob_dst->base_collection_properties = base->collection_properties;
return true;
}
static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
{
DEGObjectsIteratorData *data = (DEGObjectsIteratorData *)iter->data;
@ -198,16 +147,19 @@ static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
data->dupli_object_current = dob;
/* Temporary object to evaluate. */
data->temp_dupli_object = *dob->ob;
data->temp_dupli_object.select_color = data->dupli_parent->select_color;
Object *dupli_parent = data->dupli_parent;
Object *temp_dupli_object = &data->temp_dupli_object;
*temp_dupli_object = *dob->ob;
temp_dupli_object->select_color = dupli_parent->select_color;
temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROMDUPLI;
temp_dupli_object->base_collection_properties =
dupli_parent->base_collection_properties;
copy_m4_m4(data->temp_dupli_object.obmat, dob->mat);
deg_flush_base_flags_and_settings(data,
&data->temp_dupli_object,
data->dupli_parent,
true);
iter->current = &data->temp_dupli_object;
BLI_assert(DEG::deg_validate_copy_on_write_datablock(&data->temp_dupli_object.id));
BLI_assert(
DEG::deg_validate_copy_on_write_datablock(
&data->temp_dupli_object.id));
return true;
}
@ -245,11 +197,6 @@ static void deg_objects_iterator_step(BLI_Iterator *iter, DEG::IDDepsNode *id_no
Object *object = (Object *)id_node->id_cow;
BLI_assert(DEG::deg_validate_copy_on_write_datablock(&object->id));
if (deg_flush_base_flags_and_settings(data, object, object, false) == false) {
iter->skip = true;
return;
}
if ((data->flag & DEG_OBJECT_ITER_FLAG_DUPLI) && (object->transflag & OB_DUPLI)) {
data->dupli_parent = object;
data->dupli_list = object_duplilist(&data->eval_ctx, data->scene, object);

View File

@ -860,7 +860,7 @@ static void view3d_main_region_listener(
break;
case ND_OB_ACTIVE:
case ND_OB_SELECT:
DEG_id_tag_update((ID *)&scene->id, DEG_TAG_COPY_ON_WRITE);
DEG_id_tag_update((ID *)&scene->id, DEG_TAG_SELECT_UPDATE);
ATTR_FALLTHROUGH;
case ND_FRAME:
case ND_TRANSFORM: