Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/depsgraph/intern/depsgraph_query_iter.cc')
-rw-r--r--source/blender/depsgraph/intern/depsgraph_query_iter.cc363
1 files changed, 363 insertions, 0 deletions
diff --git a/source/blender/depsgraph/intern/depsgraph_query_iter.cc b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
new file mode 100644
index 00000000000..1dd6f8b6a0b
--- /dev/null
+++ b/source/blender/depsgraph/intern/depsgraph_query_iter.cc
@@ -0,0 +1,363 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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) 2017 Blender Foundation.
+ * All rights reserved.
+ *
+ * Original Author: Dalai Felinto
+ * Contributor(s): Sergey Sharybin
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/depsgraph/intern/depsgraph_query_iter.cc
+ * \ingroup depsgraph
+ *
+ * Implementation of Querying and Filtering API's
+ */
+
+/* Silence warnings from copying deprecated fields. */
+#define DNA_DEPRECATED_ALLOW
+
+#include "MEM_guardedalloc.h"
+
+extern "C" {
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BKE_anim.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
+#include "BKE_node.h"
+#include "BKE_object.h"
+} /* extern "C" */
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+#include "intern/depsgraph_intern.h"
+#include "util/deg_util_foreach.h"
+
+#include "intern/nodes/deg_node_id.h"
+
+#ifndef NDEBUG
+# include "intern/eval/deg_eval_copy_on_write.h"
+#endif
+
+// If defined, all working data will be set to an invalid state, helping
+// to catch issues when areas accessing data which is considered to be no
+// longer available.
+#undef INVALIDATE_WORK_DATA
+
+#ifndef NDEBUG
+# define INVALIDATE_WORK_DATA
+#endif
+
+/* ************************ DEG ITERATORS ********************* */
+
+namespace {
+
+void deg_invalidate_iterator_work_data(DEGObjectIterData *data)
+{
+#ifdef INVALIDATE_WORK_DATA
+ BLI_assert(data != NULL);
+ memset(&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object));
+#else
+ (void) data;
+#endif
+}
+
+void verify_id_proeprties_freed(DEGObjectIterData *data)
+{
+ if (data->dupli_object_current == NULL) {
+ // We didn't enter duplication yet, so we can't have any dangling
+ // pointers.
+ return;
+ }
+ const Object *dupli_object = data->dupli_object_current->ob;
+ Object *temp_dupli_object = &data->temp_dupli_object;
+ if (temp_dupli_object->id.properties == NULL) {
+ // No ID proeprties in temp datablock -- no leak is possible.
+ return;
+ }
+ if (temp_dupli_object->id.properties == dupli_object->id.properties) {
+ // Temp copy of object did not modify ID properties.
+ return;
+ }
+ // Free memory which is owned by temporary storage which is about to
+ // get overwritten.
+ IDP_FreeProperty(temp_dupli_object->id.properties);
+ MEM_freeN(temp_dupli_object->id.properties);
+ temp_dupli_object->id.properties = NULL;
+}
+
+bool deg_objects_dupli_iterator_next(BLI_Iterator *iter)
+{
+ DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
+ while (data->dupli_object_next != NULL) {
+ DupliObject *dob = data->dupli_object_next;
+ Object *obd = dob->ob;
+
+ data->dupli_object_next = data->dupli_object_next->next;
+
+ /* Group duplis need to set ob matrices correct, for deform. so no_draw
+ * is part handled.
+ */
+ if ((obd->transflag & OB_RENDER_DUPLI) == 0 && dob->no_draw) {
+ continue;
+ }
+
+ if (obd->type == OB_MBALL) {
+ continue;
+ }
+
+ verify_id_proeprties_freed(data);
+
+ data->dupli_object_current = dob;
+
+ /* Temporary object to evaluate. */
+ 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;
+
+ /* Duplicated elements shouldn't care whether their original collection is visible or not. */
+ temp_dupli_object->base_flag |= BASE_VISIBLED;
+
+ if (BKE_object_is_visible(temp_dupli_object, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE) == false) {
+ continue;
+ }
+
+ temp_dupli_object->transflag &= ~OB_DUPLI;
+
+ copy_m4_m4(data->temp_dupli_object.obmat, dob->mat);
+ iter->current = &data->temp_dupli_object;
+ BLI_assert(
+ DEG::deg_validate_copy_on_write_datablock(
+ &data->temp_dupli_object.id));
+ return true;
+ }
+
+ return false;
+}
+
+void deg_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_node)
+{
+ /* Set it early in case we need to exit and we are running from within a loop. */
+ iter->skip = true;
+
+ DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
+ const ID_Type id_type = GS(id_node->id_orig->name);
+
+ if (id_type != ID_OB) {
+ return;
+ }
+
+ switch (id_node->linked_state) {
+ case DEG::DEG_ID_LINKED_DIRECTLY:
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY) == 0) {
+ return;
+ }
+ break;
+ case DEG::DEG_ID_LINKED_VIA_SET:
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) == 0) {
+ return;
+ }
+ break;
+ case DEG::DEG_ID_LINKED_INDIRECTLY:
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY) == 0) {
+ return;
+ }
+ break;
+ }
+
+ Object *object = (Object *)id_node->id_cow;
+ BLI_assert(DEG::deg_validate_copy_on_write_datablock(&object->id));
+
+ if ((BKE_object_is_visible(object, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE) == false) &&
+ ((data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) != 0))
+ {
+ return;
+ }
+
+ if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) &&
+ (object->transflag & OB_DUPLI))
+ {
+ data->dupli_parent = object;
+ data->dupli_list = object_duplilist(data->graph, data->scene, object);
+ data->dupli_object_next = (DupliObject *)data->dupli_list->first;
+ if (BKE_object_is_visible(object, (eObjectVisibilityCheck)data->visibility_check) == false) {
+ return;
+ }
+ }
+
+ iter->current = object;
+ iter->skip = false;
+}
+
+} // namespace
+
+void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data)
+{
+ Depsgraph *depsgraph = data->graph;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ const size_t num_id_nodes = deg_graph->id_nodes.size();
+
+ iter->data = data;
+
+ if (num_id_nodes == 0) {
+ iter->valid = false;
+ return;
+ }
+
+ data->dupli_parent = NULL;
+ data->dupli_list = NULL;
+ data->dupli_object_next = NULL;
+ data->dupli_object_current = NULL;
+ data->scene = DEG_get_evaluated_scene(depsgraph);
+ data->id_node_index = 0;
+ data->num_id_nodes = num_id_nodes;
+ eEvaluationMode eval_mode = DEG_get_mode(depsgraph);
+ data->visibility_check = (eval_mode == DAG_EVAL_RENDER)
+ ? OB_VISIBILITY_CHECK_FOR_RENDER
+ : OB_VISIBILITY_CHECK_FOR_VIEWPORT;
+ deg_invalidate_iterator_work_data(data);
+
+ DEG::IDDepsNode *id_node = deg_graph->id_nodes[data->id_node_index];
+ deg_iterator_objects_step(iter, id_node);
+
+ if (iter->skip) {
+ DEG_iterator_objects_next(iter);
+ }
+}
+
+void DEG_iterator_objects_next(BLI_Iterator *iter)
+{
+ DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
+ Depsgraph *depsgraph = data->graph;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ do {
+ iter->skip = false;
+ if (data->dupli_list) {
+ if (deg_objects_dupli_iterator_next(iter)) {
+ return;
+ }
+ else {
+ verify_id_proeprties_freed(data);
+ free_object_duplilist(data->dupli_list);
+ data->dupli_parent = NULL;
+ data->dupli_list = NULL;
+ data->dupli_object_next = NULL;
+ data->dupli_object_current = NULL;
+ deg_invalidate_iterator_work_data(data);
+ }
+ }
+
+ ++data->id_node_index;
+ if (data->id_node_index == data->num_id_nodes) {
+ iter->valid = false;
+ return;
+ }
+
+ DEG::IDDepsNode *id_node = deg_graph->id_nodes[data->id_node_index];
+ deg_iterator_objects_step(iter, id_node);
+ } while (iter->skip);
+}
+
+void DEG_iterator_objects_end(BLI_Iterator *iter)
+{
+ DEGObjectIterData *data = (DEGObjectIterData *)iter->data;
+ if (data != NULL) {
+ /* Force crash in case the iterator data is referenced and accessed down
+ * the line. (T51718)
+ */
+ deg_invalidate_iterator_work_data(data);
+ }
+}
+
+/* ************************ DEG ID ITERATOR ********************* */
+
+static void DEG_iterator_ids_step(BLI_Iterator *iter, DEG::IDDepsNode *id_node, bool only_updated)
+{
+ ID *id_cow = id_node->id_cow;
+
+ if (only_updated && !(id_cow->recalc & ID_RECALC_ALL)) {
+ bNodeTree *ntree = ntreeFromID(id_cow);
+
+ /* Nodetree is considered part of the datablock. */
+ if (!(ntree && (ntree->id.recalc & ID_RECALC_ALL))) {
+ iter->skip = true;
+ return;
+ }
+ }
+
+ iter->current = id_cow;
+ iter->skip = false;
+}
+
+void DEG_iterator_ids_begin(BLI_Iterator *iter, DEGIDIterData *data)
+{
+ Depsgraph *depsgraph = data->graph;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+ const size_t num_id_nodes = deg_graph->id_nodes.size();
+
+ iter->data = data;
+
+ if ((num_id_nodes == 0) ||
+ (data->only_updated && !DEG_id_type_any_updated(depsgraph)))
+ {
+ iter->valid = false;
+ return;
+ }
+
+ data->id_node_index = 0;
+ data->num_id_nodes = num_id_nodes;
+
+ DEG::IDDepsNode *id_node = deg_graph->id_nodes[data->id_node_index];
+ DEG_iterator_ids_step(iter, id_node, data->only_updated);
+
+ if (iter->skip) {
+ DEG_iterator_ids_next(iter);
+ }
+}
+
+void DEG_iterator_ids_next(BLI_Iterator *iter)
+{
+ DEGIDIterData *data = (DEGIDIterData *)iter->data;
+ Depsgraph *depsgraph = data->graph;
+ DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph);
+
+ do {
+ iter->skip = false;
+
+ ++data->id_node_index;
+ if (data->id_node_index == data->num_id_nodes) {
+ iter->valid = false;
+ return;
+ }
+
+ DEG::IDDepsNode *id_node = deg_graph->id_nodes[data->id_node_index];
+ DEG_iterator_ids_step(iter, id_node, data->only_updated);
+ } while (iter->skip);
+}
+
+void DEG_iterator_ids_end(BLI_Iterator *UNUSED(iter))
+{
+}