| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * ***** 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 | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | extern "C" { | 
					
						
							|  |  |  | #include "BLI_utildefines.h"
 | 
					
						
							|  |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | #include "BKE_anim.h"
 | 
					
						
							| 
									
										
										
										
											2017-12-01 11:24:21 -02:00
										 |  |  | #include "BKE_idprop.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | #include "BKE_layer.h"
 | 
					
						
							| 
									
										
										
										
											2017-12-15 07:51:16 -02:00
										 |  |  | #include "BKE_object.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | } /* 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"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-20 16:40:49 +01:00
										 |  |  | #include "intern/nodes/deg_node_id.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | #ifndef NDEBUG
 | 
					
						
							|  |  |  | #  include "intern/eval/deg_eval_copy_on_write.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************ DEG ITERATORS ********************* */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 15:46:34 +01:00
										 |  |  | static 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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | static bool deg_objects_dupli_iterator_next(BLI_Iterator *iter) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-12-15 08:11:19 -02:00
										 |  |  | 	DEGObjectIterData *data = (DEGObjectIterData *)iter->data; | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 	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; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 15:46:34 +01:00
										 |  |  | 		verify_id_proeprties_freed(data); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2017-12-21 13:29:14 -02:00
										 |  |  | 		temp_dupli_object->transflag &= ~OB_DUPLI; | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 		temp_dupli_object->select_color = dupli_parent->select_color; | 
					
						
							|  |  |  | 		temp_dupli_object->base_flag = dupli_parent->base_flag | BASE_FROMDUPLI; | 
					
						
							| 
									
										
										
										
											2017-12-15 07:05:50 -02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (dob->collection_properties != NULL) { | 
					
						
							|  |  |  | 			temp_dupli_object->base_collection_properties = dob->collection_properties; | 
					
						
							| 
									
										
										
										
											2018-01-24 15:34:33 +01:00
										 |  |  | 			IDP_MergeGroup(temp_dupli_object->base_collection_properties, | 
					
						
							|  |  |  | 			               dupli_parent->base_collection_properties, | 
					
						
							|  |  |  | 			               false); | 
					
						
							| 
									
										
										
										
											2017-12-15 07:05:50 -02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2018-01-24 15:34:33 +01:00
										 |  |  | 			temp_dupli_object->base_collection_properties = | 
					
						
							|  |  |  | 			        dupli_parent->base_collection_properties; | 
					
						
							| 
									
										
										
										
											2017-12-15 07:05:50 -02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 		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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void DEG_iterator_objects_step(BLI_Iterator *iter, DEG::IDDepsNode *id_node) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-12-15 07:51:16 -02:00
										 |  |  | 	/* Set it early in case we need to exit and we are running from within a loop. */ | 
					
						
							|  |  |  | 	iter->skip = true; | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-15 08:11:19 -02:00
										 |  |  | 	DEGObjectIterData *data = (DEGObjectIterData *)iter->data; | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 	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: | 
					
						
							| 
									
										
										
										
											2017-12-15 07:51:16 -02:00
										 |  |  | 			if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY) == 0) { | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		case DEG::DEG_ID_LINKED_VIA_SET: | 
					
						
							| 
									
										
										
										
											2017-12-15 07:51:16 -02:00
										 |  |  | 			if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET) == 0) { | 
					
						
							|  |  |  | 				return; | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-12-15 07:51:16 -02:00
										 |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 		case DEG::DEG_ID_LINKED_INDIRECTLY: | 
					
						
							| 
									
										
										
										
											2017-12-15 07:51:16 -02:00
										 |  |  | 			if ((data->flag & DEG_ITER_OBJECT_FLAG_LINKED_INDIRECTLY) == 0) { | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Object *object = (Object *)id_node->id_cow; | 
					
						
							|  |  |  | 	BLI_assert(DEG::deg_validate_copy_on_write_datablock(&object->id)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-21 13:29:14 -02:00
										 |  |  | 	if ((BKE_object_is_visible(object, OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE) == false) && | 
					
						
							| 
									
										
										
										
											2017-12-15 07:51:16 -02:00
										 |  |  | 	    ((data->flag & DEG_ITER_OBJECT_FLAG_VISIBLE) != 0)) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-24 15:34:33 +01:00
										 |  |  | 	if ((data->flag & DEG_ITER_OBJECT_FLAG_DUPLI) && | 
					
						
							|  |  |  | 	    (object->transflag & OB_DUPLI)) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 		data->dupli_parent = object; | 
					
						
							|  |  |  | 		data->dupli_list = object_duplilist(&data->eval_ctx, data->scene, object); | 
					
						
							|  |  |  | 		data->dupli_object_next = (DupliObject *)data->dupli_list->first; | 
					
						
							| 
									
										
										
										
											2018-01-24 15:34:33 +01:00
										 |  |  | 		const eObjectVisibilityCheck mode = | 
					
						
							|  |  |  | 		        (data->mode == DEG_ITER_OBJECT_MODE_RENDER) | 
					
						
							|  |  |  | 		                ? OB_VISIBILITY_CHECK_FOR_RENDER | 
					
						
							|  |  |  | 		                : OB_VISIBILITY_CHECK_FOR_VIEWPORT; | 
					
						
							| 
									
										
										
										
											2017-12-21 13:29:14 -02:00
										 |  |  | 		if (BKE_object_is_visible(object, mode) == false) { | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	iter->current = object; | 
					
						
							| 
									
										
										
										
											2017-12-15 07:51:16 -02:00
										 |  |  | 	iter->skip = false; | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-15 08:11:19 -02:00
										 |  |  | void DEG_iterator_objects_begin(BLI_Iterator *iter, DEGObjectIterData *data) | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | { | 
					
						
							|  |  |  | 	Depsgraph *depsgraph = data->graph; | 
					
						
							|  |  |  | 	DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph); | 
					
						
							|  |  |  | 	const size_t num_id_nodes = deg_graph->id_nodes.size(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (num_id_nodes == 0) { | 
					
						
							|  |  |  | 		iter->valid = false; | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* TODO(sergey): What evaluation type we want here? */ | 
					
						
							| 
									
										
										
										
											2017-12-21 13:29:14 -02:00
										 |  |  | 	/* TODO(dfelinto): Get rid of evaluation context here, it's only used to do
 | 
					
						
							|  |  |  | 	 * direct dupli-objects update in group.c. Which is terribly bad, and all | 
					
						
							|  |  |  | 	 * objects are expected to be evaluated already. */ | 
					
						
							|  |  |  | 	DEG_evaluation_context_init(&data->eval_ctx, DAG_EVAL_VIEWPORT); | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 	data->eval_ctx.view_layer = DEG_get_evaluated_view_layer(depsgraph); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	iter->data = data; | 
					
						
							|  |  |  | 	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; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-12-15 08:11:19 -02:00
										 |  |  | 	DEGObjectIterData *data = (DEGObjectIterData *)iter->data; | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 	Depsgraph *depsgraph = data->graph; | 
					
						
							|  |  |  | 	DEG::Depsgraph *deg_graph = reinterpret_cast<DEG::Depsgraph *>(depsgraph); | 
					
						
							|  |  |  | 	do { | 
					
						
							| 
									
										
										
										
											2017-12-21 13:29:14 -02:00
										 |  |  | 		iter->skip = false; | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 		if (data->dupli_list) { | 
					
						
							|  |  |  | 			if (deg_objects_dupli_iterator_next(iter)) { | 
					
						
							|  |  |  | 				return; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							| 
									
										
										
										
											2018-01-24 15:46:34 +01:00
										 |  |  | 				verify_id_proeprties_freed(data); | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 				free_object_duplilist(data->dupli_list); | 
					
						
							|  |  |  | 				data->dupli_parent = NULL; | 
					
						
							|  |  |  | 				data->dupli_list = NULL; | 
					
						
							|  |  |  | 				data->dupli_object_next = NULL; | 
					
						
							|  |  |  | 				data->dupli_object_current = NULL; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		++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) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifndef NDEBUG
 | 
					
						
							| 
									
										
										
										
											2017-12-15 08:11:19 -02:00
										 |  |  | 	DEGObjectIterData *data = (DEGObjectIterData *)iter->data; | 
					
						
							| 
									
										
										
										
											2018-01-24 15:34:33 +01:00
										 |  |  | 	/* Force crash in case the iterator data is referenced and accessed down
 | 
					
						
							|  |  |  | 	 * the line. (T51718) | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											2017-11-30 16:49:32 +01:00
										 |  |  | 	memset(&data->temp_dupli_object, 0xff, sizeof(data->temp_dupli_object)); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 	(void) iter; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } |