Transform: Use new DEG query API to see what's being affected by a changing object

This avoids us from directly calling object update, and doing other type of
update flushing.

Prepares us to get rid of Object->recalc flags.
This commit is contained in:
Sergey Sharybin
2017-12-01 11:39:42 +01:00
parent 0591fb17e9
commit 2ae709d282

View File

@@ -119,6 +119,7 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "DEG_depsgraph_query.h"
#include "transform.h"
#include "bmesh.h"
@@ -5528,6 +5529,37 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob)
}
}
static void trans_object_base_deps_flag_prepare(ViewLayer *view_layer)
{
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
base->object->id.tag &= ~LIB_TAG_DOIT;
}
}
static void set_trans_object_base_deps_flag_cb(ID *id, void *UNUSED(user_data))
{
/* Here we only handle object IDs. */
if (GS(id->name) != ID_OB) {
return;
}
id->tag |= LIB_TAG_DOIT;
}
static void flush_trans_object_base_deps_flag(Depsgraph *depsgraph, Object *object)
{
object->id.tag |= LIB_TAG_DOIT;
DEG_foreach_dependent_ID(depsgraph, &object->id,
set_trans_object_base_deps_flag_cb, NULL);
}
static void trans_object_base_deps_flag_finish(ViewLayer *view_layer)
{
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
if (base->object->id.tag & LIB_TAG_DOIT) {
base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
}
}
}
/* sets flags in Bases to define whether they take part in transform */
/* it deselects Bases, so we have to call the clear function always after */
@@ -5538,47 +5570,30 @@ static void set_trans_object_base_flags(TransInfo *t)
ViewLayer *view_layer = t->view_layer;
Scene *scene = t->scene;
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
/*
* if Base selected and has parent selected:
* base->flag_legacy = BA_WAS_SEL
/* NOTE: if Base selected and has parent selected:
* base->flag_legacy = BA_WAS_SEL
*/
Base *base;
/* don't do it if we're not actually going to recalculate anything */
if (t->mode == TFM_DUMMY)
/* Don't do it if we're not actually going to recalculate anything. */
if (t->mode == TFM_DUMMY) {
return;
/* makes sure base flags and object flags are identical */
}
/* Makes sure base flags and object flags are identical. */
BKE_scene_base_flag_to_objects(t->view_layer);
/* Make sure depsgraph is here. */
DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
/* handle pending update events, otherwise they got copied below */
EvaluationContext eval_ctx;
DEG_evaluation_context_init_from_scene(&eval_ctx,
t->scene, t->view_layer, t->engine_type,
DAG_EVAL_VIEWPORT);
for (base = view_layer->object_bases.first; base; base = base->next) {
if (base->object->recalc & OB_RECALC_ALL) {
/* TODO(sergey): Ideally, it's not needed. */
BKE_object_handle_update(&eval_ctx, t->scene, base->object);
}
}
for (base = view_layer->object_bases.first; base; base = base->next) {
/* Clear all flags we need. It will be used to detect dependencies. */
trans_object_base_deps_flag_prepare(view_layer);
/* Traverse all bases and set all possible flags. */
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
base->flag_legacy &= ~BA_WAS_SEL;
if (TESTBASELIB_BGMODE(base)) {
Object *ob = base->object;
Object *parsel = ob->parent;
/* if parent selected, deselect */
while (parsel) {
/* If parent selected, deselect. */
while (parsel != NULL) {
if (parsel->base_flag & BASE_SELECTED) {
Base *parbase = BKE_view_layer_base_find(view_layer, parsel);
if (parbase) { /* in rare cases this can fail */
if (parbase != NULL) { /* in rare cases this can fail */
if (TESTBASELIB_BGMODE(parbase)) {
break;
}
@@ -5586,9 +5601,8 @@ static void set_trans_object_base_flags(TransInfo *t)
}
parsel = parsel->parent;
}
if (parsel) {
/* rotation around local centers are allowed to propagate */
if (parsel != NULL) {
/* Rotation around local centers are allowed to propagate. */
if ((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
(t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL))
{
@@ -5599,20 +5613,13 @@ static void set_trans_object_base_flags(TransInfo *t)
base->flag_legacy |= BA_WAS_SEL;
}
}
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
}
}
/* all recalc flags get flushed to all layers, so a layer flip later on works fine */
DEG_graph_flush_update(bmain, depsgraph);
/* and we store them temporal in base (only used for transform code) */
/* this because after doing updates, the object->recalc is cleared */
for (base = view_layer->object_bases.first; base; base = base->next) {
if (base->object->recalc & (OB_RECALC_OB | OB_RECALC_DATA)) {
base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
flush_trans_object_base_deps_flag(depsgraph, ob);
}
}
/* Store temporary bits in base indicating that base is being modified
* (directly or indirectly) by transforming objects.
*/
trans_object_base_deps_flag_finish(view_layer);
}
static bool mark_children(Object *ob)
@@ -5633,32 +5640,28 @@ static bool mark_children(Object *ob)
static int count_proportional_objects(TransInfo *t)
{
int total = 0;
/* TODO(sergey): Get rid of global, use explicit main. */
Main *bmain = G.main;
ViewLayer *view_layer = t->view_layer;
Scene *scene = t->scene;
Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
Base *base;
/* rotations around local centers are allowed to propagate, so we take all objects */
/* Clear all flags we need. It will be used to detect dependencies. */
trans_object_base_deps_flag_prepare(view_layer);
/* Rotations around local centers are allowed to propagate, so we take all objects. */
if (!((t->around == V3D_AROUND_LOCAL_ORIGINS) &&
(t->mode == TFM_ROTATION || t->mode == TFM_TRACKBALL)))
{
/* mark all parents */
for (base = view_layer->object_bases.first; base; base = base->next) {
/* Mark all parents. */
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
if (TESTBASELIB_BGMODE(base)) {
Object *parent = base->object->parent;
/* flag all parents */
while (parent) {
while (parent != NULL) {
parent->flag |= BA_TRANSFORM_PARENT;
parent = parent->parent;
}
}
}
/* mark all children */
for (base = view_layer->object_bases.first; base; base = base->next) {
/* Mark all children. */
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
/* all base not already selected or marked that is editable */
if ((base->object->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
(base->flag & BASE_SELECTED) == 0 &&
@@ -5668,35 +5671,24 @@ static int count_proportional_objects(TransInfo *t)
}
}
}
for (base = view_layer->object_bases.first; base; base = base->next) {
/* Flush changed flags to all dependencies. */
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
Object *ob = base->object;
/* if base is not selected, not a parent of selection or not a child of selection and it is editable */
/* If base is not selected, not a parent of selection or not a child of
* selection and it is editable.
*/
if ((ob->flag & (BA_TRANSFORM_CHILD | BA_TRANSFORM_PARENT)) == 0 &&
(base->flag & BASE_SELECTED) == 0 &&
(BASE_EDITABLE_BGMODE(base)))
{
DEG_id_tag_update(&ob->id, OB_RECALC_OB);
flush_trans_object_base_deps_flag(depsgraph, ob);
total += 1;
}
}
/* all recalc flags get flushed to all layers, so a layer flip later on works fine */
DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
DEG_graph_flush_update(bmain, depsgraph);
/* and we store them temporal in base (only used for transform code) */
/* this because after doing updates, the object->recalc is cleared */
for (base = view_layer->object_bases.first; base; base = base->next) {
if (base->object->recalc & (OB_RECALC_OB | OB_RECALC_DATA)) {
base->flag_legacy |= BA_SNAP_FIX_DEPS_FIASCO;
}
}
/* Store temporary bits in base indicating that base is being modified
* (directly or indirectly) by transforming objects.
*/
trans_object_base_deps_flag_finish(view_layer);
return total;
}
@@ -8286,7 +8278,7 @@ void createTransData(bContext *C, TransInfo *t)
RegionView3D *rv3d = t->ar->regiondata;
if ((rv3d->persp == RV3D_CAMOB) && v3d->camera) {
/* we could have a flag to easily check an object is being transformed */
if (v3d->camera->recalc) {
if (v3d->camera->id.tag & LIB_TAG_DOIT) {
t->flag |= T_CAMERA;
}
}