| 
									
										
										
										
											2013-06-04 01:23:51 +00: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) 2004 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * The Original Code is: all of this file. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Contributor(s): none yet. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * ***** END GPL LICENSE BLOCK ***** | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** \file blender/editors/mesh/editmesh_path.c
 | 
					
						
							|  |  |  |  *  \ingroup edmesh | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_scene_types.h"
 | 
					
						
							|  |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							|  |  |  | #include "DNA_windowmanager_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-28 15:50:43 +01:00
										 |  |  | #ifdef WITH_FREESTYLE
 | 
					
						
							|  |  |  | #  include "DNA_meshdata_types.h"
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							|  |  |  | #include "BLI_linklist.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | #include "BKE_editmesh.h"
 | 
					
						
							|  |  |  | #include "BKE_report.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ED_mesh.h"
 | 
					
						
							|  |  |  | #include "ED_screen.h"
 | 
					
						
							|  |  |  | #include "ED_uvedit.h"
 | 
					
						
							|  |  |  | #include "ED_view3d.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "RNA_access.h"
 | 
					
						
							|  |  |  | #include "RNA_define.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | #include "WM_api.h"
 | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | #include "WM_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-08-23 04:22:07 +00:00
										 |  |  | #include "bmesh.h"
 | 
					
						
							|  |  |  | #include "bmesh_tools.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | #include "mesh_intern.h"  /* own include */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | struct PathSelectParams { | 
					
						
							|  |  |  | 	bool track_active;  /* ensure the active element is the last selected item (handy for picking) */ | 
					
						
							|  |  |  | 	bool topology_distance; | 
					
						
							|  |  |  | 	char edge_mode; | 
					
						
							|  |  |  | 	struct CheckerIntervalParams interval_params; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void path_select_properties(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	RNA_def_boolean( | 
					
						
							|  |  |  | 	        ot->srna, "topology_distance", false, "Topology Distance", | 
					
						
							|  |  |  | 	        "Find the minimum number of steps, ignoring spatial distance"); | 
					
						
							|  |  |  | 	WM_operator_properties_checker_interval(ot, true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void path_select_params_from_op(wmOperator *op, struct PathSelectParams *op_params) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	op_params->edge_mode = EDGE_MODE_SELECT; | 
					
						
							|  |  |  | 	op_params->track_active = false; | 
					
						
							|  |  |  | 	op_params->topology_distance = RNA_boolean_get(op->ptr, "topology_distance"); | 
					
						
							|  |  |  | 	WM_operator_properties_checker_interval_from_op(op, &op_params->interval_params); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | struct UserData { | 
					
						
							|  |  |  | 	BMesh *bm; | 
					
						
							|  |  |  | 	Mesh  *me; | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	const struct PathSelectParams *op_params; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* Vert Path */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* callbacks */ | 
					
						
							|  |  |  | static bool verttag_filter_cb(BMVert *v, void *UNUSED(user_data_v)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return !BM_elem_flag_test(v, BM_ELEM_HIDDEN); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static bool verttag_test_cb(BMVert *v, void *UNUSED(user_data_v)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return BM_elem_flag_test_bool(v, BM_ELEM_SELECT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static void verttag_set_cb(BMVert *v, bool val, void *user_data_v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct UserData *user_data = user_data_v; | 
					
						
							|  |  |  | 	BM_vert_select_set(user_data->bm, v, val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | static void mouse_mesh_shortest_path_vert( | 
					
						
							|  |  |  |         Scene *scene, const struct PathSelectParams *op_params, | 
					
						
							|  |  |  |         BMVert *v_act, BMVert *v_dst) | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	Object *obedit = scene->obedit; | 
					
						
							|  |  |  | 	BMEditMesh *em = BKE_editmesh_from_object(obedit); | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 	BMesh *bm = em->bm; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	struct UserData user_data = {bm, obedit->data, op_params}; | 
					
						
							|  |  |  | 	LinkNode *path = NULL; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if (v_act && (v_act != v_dst)) { | 
					
						
							|  |  |  | 		if ((path = BM_mesh_calc_path_vert( | 
					
						
							|  |  |  | 		         bm, v_act, v_dst, !op_params->topology_distance, | 
					
						
							|  |  |  | 		         verttag_filter_cb, &user_data))) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (op_params->track_active) { | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 				BM_select_history_remove(bm, v_act); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	BMVert *v_dst_last = v_dst; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if (path) { | 
					
						
							|  |  |  | 		/* toggle the flag */ | 
					
						
							|  |  |  | 		bool all_set = true; | 
					
						
							|  |  |  | 		LinkNode *node; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		node = path; | 
					
						
							|  |  |  | 		do { | 
					
						
							|  |  |  | 			if (!verttag_test_cb((BMVert *)node->link, &user_data)) { | 
					
						
							|  |  |  | 				all_set = false; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} while ((node = node->next)); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		int depth = 1; | 
					
						
							|  |  |  | 		node = path; | 
					
						
							|  |  |  | 		do { | 
					
						
							|  |  |  | 			if (WM_operator_properties_checker_interval_test(&op_params->interval_params, depth)) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 				verttag_set_cb((BMVert *)node->link, !all_set, &user_data); | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 				v_dst_last = node->link; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} while (depth++, (node = node->next)); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		BLI_linklist_free(path, NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		const bool is_act = !verttag_test_cb(v_dst, &user_data); | 
					
						
							|  |  |  | 		verttag_set_cb(v_dst, is_act, &user_data); /* switch the face option */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	EDBM_selectmode_flush(em); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if (op_params->track_active) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 		/* even if this is selected it may not be in the selection list */ | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		if (BM_elem_flag_test(v_dst_last, BM_ELEM_SELECT) == 0) { | 
					
						
							|  |  |  | 			BM_select_history_remove(bm, v_dst_last); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							|  |  |  | 			BM_select_history_store(bm, v_dst_last); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	EDBM_update_generic(em, false, false); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* Edge Path */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* callbacks */ | 
					
						
							|  |  |  | static bool edgetag_filter_cb(BMEdge *e, void *UNUSED(user_data_v)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return !BM_elem_flag_test(e, BM_ELEM_HIDDEN); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static bool edgetag_test_cb(BMEdge *e, void *user_data_v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct UserData *user_data = user_data_v; | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	const char edge_mode = user_data->op_params->edge_mode; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	BMesh *bm = user_data->bm; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	switch (edge_mode) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 		case EDGE_MODE_SELECT: | 
					
						
							|  |  |  | 			return BM_elem_flag_test(e, BM_ELEM_SELECT) ? true : false; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_SEAM: | 
					
						
							| 
									
										
										
										
											2013-06-24 05:26:42 +00:00
										 |  |  | 			return BM_elem_flag_test(e, BM_ELEM_SEAM) ? true : false; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 		case EDGE_MODE_TAG_SHARP: | 
					
						
							|  |  |  | 			return BM_elem_flag_test(e, BM_ELEM_SMOOTH) ? false : true; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_CREASE: | 
					
						
							|  |  |  | 			return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? true : false; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_BEVEL: | 
					
						
							|  |  |  | 			return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? true : false; | 
					
						
							|  |  |  | #ifdef WITH_FREESTYLE
 | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_FREESTYLE: | 
					
						
							| 
									
										
										
										
											2014-03-19 12:46:33 +11:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			FreestyleEdge *fed = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE); | 
					
						
							| 
									
										
										
										
											2014-04-01 11:34:00 +11:00
										 |  |  | 			return (!fed) ? false : (fed->flag & FREESTYLE_EDGE_MARK) ? true : false; | 
					
						
							| 
									
										
										
										
											2014-03-19 12:46:33 +11:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | static void edgetag_set_cb(BMEdge *e, bool val, void *user_data_v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct UserData *user_data = user_data_v; | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	const char edge_mode = user_data->op_params->edge_mode; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	BMesh *bm = user_data->bm; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	switch (edge_mode) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 		case EDGE_MODE_SELECT: | 
					
						
							|  |  |  | 			BM_edge_select_set(bm, e, val); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_SEAM: | 
					
						
							|  |  |  | 			BM_elem_flag_set(e, BM_ELEM_SEAM, val); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_SHARP: | 
					
						
							|  |  |  | 			BM_elem_flag_set(e, BM_ELEM_SMOOTH, !val); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_CREASE: | 
					
						
							|  |  |  | 			BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (val) ? 1.0f : 0.0f); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_BEVEL: | 
					
						
							|  |  |  | 			BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (val) ? 1.0f : 0.0f); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | #ifdef WITH_FREESTYLE
 | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_FREESTYLE: | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			FreestyleEdge *fed; | 
					
						
							|  |  |  | 			fed = CustomData_bmesh_get(&bm->edata, e->head.data, CD_FREESTYLE_EDGE); | 
					
						
							|  |  |  | 			if (!val) | 
					
						
							|  |  |  | 				fed->flag &= ~FREESTYLE_EDGE_MARK; | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				fed->flag |= FREESTYLE_EDGE_MARK; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void edgetag_ensure_cd_flag(Scene *scene, Mesh *me) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BMesh *bm = me->edit_btmesh->bm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	switch (scene->toolsettings->edge_mode) { | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_CREASE: | 
					
						
							|  |  |  | 			BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_BEVEL: | 
					
						
							|  |  |  | 			BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | #ifdef WITH_FREESTYLE
 | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_FREESTYLE: | 
					
						
							|  |  |  | 			if (!CustomData_has_layer(&bm->edata, CD_FREESTYLE_EDGE)) { | 
					
						
							|  |  |  | 				BM_data_layer_add(bm, &bm->edata, CD_FREESTYLE_EDGE); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* mesh shortest path select, uses prev-selected edge */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* since you want to create paths with multiple selects, it doesn't have extend option */ | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | static void mouse_mesh_shortest_path_edge( | 
					
						
							|  |  |  |         Scene *scene, const struct PathSelectParams *op_params, | 
					
						
							|  |  |  |         BMEdge *e_act, BMEdge *e_dst) | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	Object *obedit = scene->obedit; | 
					
						
							|  |  |  | 	BMEditMesh *em = BKE_editmesh_from_object(obedit); | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 	BMesh *bm = em->bm; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	struct UserData user_data = {bm, obedit->data, op_params}; | 
					
						
							|  |  |  | 	LinkNode *path = NULL; | 
					
						
							|  |  |  | 	Mesh *me = obedit->data; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	edgetag_ensure_cd_flag(scene, obedit->data); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if (e_act && (e_act != e_dst)) { | 
					
						
							|  |  |  | 		if ((path = BM_mesh_calc_path_edge( | 
					
						
							|  |  |  | 		         bm, e_act, e_dst, !op_params->topology_distance, | 
					
						
							|  |  |  | 		         edgetag_filter_cb, &user_data))) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			if (op_params->track_active) { | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 				BM_select_history_remove(bm, e_act); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	BMEdge *e_dst_last = e_dst; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if (path) { | 
					
						
							|  |  |  | 		/* toggle the flag */ | 
					
						
							|  |  |  | 		bool all_set = true; | 
					
						
							|  |  |  | 		LinkNode *node; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		node = path; | 
					
						
							|  |  |  | 		do { | 
					
						
							|  |  |  | 			if (!edgetag_test_cb((BMEdge *)node->link, &user_data)) { | 
					
						
							|  |  |  | 				all_set = false; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} while ((node = node->next)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int depth = 1; | 
					
						
							|  |  |  | 		node = path; | 
					
						
							|  |  |  | 		do { | 
					
						
							|  |  |  | 			if (WM_operator_properties_checker_interval_test(&op_params->interval_params, depth)) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 				edgetag_set_cb((BMEdge *)node->link, !all_set, &user_data); | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 				e_dst_last = node->link; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} while (depth++, (node = node->next)); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		BLI_linklist_free(path, NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		const bool is_act = !edgetag_test_cb(e_dst, &user_data); | 
					
						
							|  |  |  | 		edgetag_ensure_cd_flag(scene, obedit->data); | 
					
						
							|  |  |  | 		edgetag_set_cb(e_dst, is_act, &user_data); /* switch the edge option */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if (op_params->edge_mode != EDGE_MODE_SELECT) { | 
					
						
							|  |  |  | 		if (op_params->track_active) { | 
					
						
							| 
									
										
										
										
											2013-06-24 05:24:27 +00:00
										 |  |  | 			/* simple rules - last edge is _always_ active and selected */ | 
					
						
							|  |  |  | 			if (e_act) | 
					
						
							|  |  |  | 				BM_edge_select_set(bm, e_act, false); | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 			BM_edge_select_set(bm, e_dst_last, true); | 
					
						
							|  |  |  | 			BM_select_history_store(bm, e_dst_last); | 
					
						
							| 
									
										
										
										
											2013-06-24 05:24:27 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-24 05:24:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	EDBM_selectmode_flush(em); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if (op_params->track_active) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 		/* even if this is selected it may not be in the selection list */ | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		if (op_params->edge_mode == EDGE_MODE_SELECT) { | 
					
						
							|  |  |  | 			if (edgetag_test_cb(e_dst_last, &user_data) == 0) | 
					
						
							|  |  |  | 				BM_select_history_remove(bm, e_dst_last); | 
					
						
							| 
									
										
										
										
											2013-06-24 05:24:27 +00:00
										 |  |  | 			else | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 				BM_select_history_store(bm, e_dst_last); | 
					
						
							| 
									
										
										
										
											2013-06-24 05:24:27 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	/* force drawmode for mesh */ | 
					
						
							|  |  |  | 	switch (op_params->edge_mode) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		case EDGE_MODE_TAG_SEAM: | 
					
						
							|  |  |  | 			me->drawflag |= ME_DRAWSEAMS; | 
					
						
							|  |  |  | 			ED_uvedit_live_unwrap(scene, obedit); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_SHARP: | 
					
						
							|  |  |  | 			me->drawflag |= ME_DRAWSHARP; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_CREASE: | 
					
						
							|  |  |  | 			me->drawflag |= ME_DRAWCREASES; | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case EDGE_MODE_TAG_BEVEL: | 
					
						
							|  |  |  | 			me->drawflag |= ME_DRAWBWEIGHTS; | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | #ifdef WITH_FREESTYLE
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		case EDGE_MODE_TAG_FREESTYLE: | 
					
						
							|  |  |  | 			me->drawflag |= ME_DRAW_FREESTYLE_EDGE; | 
					
						
							|  |  |  | 			break; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	EDBM_update_generic(em, false, false); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* Face Path */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* callbacks */ | 
					
						
							|  |  |  | static bool facetag_filter_cb(BMFace *f, void *UNUSED(user_data_v)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return !BM_elem_flag_test(f, BM_ELEM_HIDDEN); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | //static bool facetag_test_cb(Scene *UNUSED(scene), BMesh *UNUSED(bm), BMFace *f)
 | 
					
						
							|  |  |  | static bool facetag_test_cb(BMFace *f, void *UNUSED(user_data_v)) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return BM_elem_flag_test_bool(f, BM_ELEM_SELECT); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | //static void facetag_set_cb(BMesh *bm, Scene *UNUSED(scene), BMFace *f, const bool val)
 | 
					
						
							|  |  |  | static void facetag_set_cb(BMFace *f, bool val, void *user_data_v) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	struct UserData *user_data = user_data_v; | 
					
						
							|  |  |  | 	BM_face_select_set(user_data->bm, f, val); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | static void mouse_mesh_shortest_path_face( | 
					
						
							|  |  |  |         Scene *scene, const struct PathSelectParams *op_params, | 
					
						
							|  |  |  |         BMFace *f_act, BMFace *f_dst) | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	Object *obedit = scene->obedit; | 
					
						
							|  |  |  | 	BMEditMesh *em = BKE_editmesh_from_object(obedit); | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 	BMesh *bm = em->bm; | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	struct UserData user_data = {bm, obedit->data, op_params}; | 
					
						
							|  |  |  | 	LinkNode *path = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (f_act) { | 
					
						
							|  |  |  | 		if (f_act != f_dst) { | 
					
						
							|  |  |  | 			if ((path = BM_mesh_calc_path_face( | 
					
						
							|  |  |  | 			         bm, f_act, f_dst, !op_params->topology_distance, | 
					
						
							|  |  |  | 			         facetag_filter_cb, &user_data))) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (op_params->track_active) { | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 					BM_select_history_remove(bm, f_act); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	BMFace *f_dst_last = f_dst; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if (path) { | 
					
						
							|  |  |  | 		/* toggle the flag */ | 
					
						
							|  |  |  | 		bool all_set = true; | 
					
						
							|  |  |  | 		LinkNode *node; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		node = path; | 
					
						
							|  |  |  | 		do { | 
					
						
							|  |  |  | 			if (!facetag_test_cb((BMFace *)node->link, &user_data)) { | 
					
						
							|  |  |  | 				all_set = false; | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} while ((node = node->next)); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		int depth = 1; | 
					
						
							|  |  |  | 		node = path; | 
					
						
							|  |  |  | 		do { | 
					
						
							|  |  |  | 			if (WM_operator_properties_checker_interval_test(&op_params->interval_params, depth)) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 				facetag_set_cb((BMFace *)node->link, !all_set, &user_data); | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 				f_dst_last = node->link; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} while (depth++, (node = node->next)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		BLI_linklist_free(path, NULL); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		const bool is_act = !facetag_test_cb(f_dst, &user_data); | 
					
						
							|  |  |  | 		facetag_set_cb(f_dst, is_act, &user_data); /* switch the face option */ | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	EDBM_selectmode_flush(em); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (op_params->track_active) { | 
					
						
							|  |  |  | 		/* even if this is selected it may not be in the selection list */ | 
					
						
							|  |  |  | 		if (facetag_test_cb(f_dst_last, &user_data) == 0) { | 
					
						
							|  |  |  | 			BM_select_history_remove(bm, f_dst_last); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 			BM_select_history_store(bm, f_dst_last); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		BM_mesh_active_face_set(bm, f_dst_last); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	EDBM_update_generic(em, false, false); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* Main Operator for vert/edge/face tag */ | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | static bool edbm_shortest_path_pick_ex( | 
					
						
							|  |  |  |         Scene *scene, const struct PathSelectParams *op_params, | 
					
						
							|  |  |  |         BMElem *ele_src, BMElem *ele_dst) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ELEM(NULL, ele_src, ele_dst) && (ele_src->head.htype != ele_dst->head.htype)) { | 
					
						
							|  |  |  | 		/* pass */ | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if (ele_src->head.htype == BM_VERT) { | 
					
						
							|  |  |  | 		mouse_mesh_shortest_path_vert(scene, op_params, (BMVert *)ele_src, (BMVert *)ele_dst); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	else if (ele_src->head.htype == BM_EDGE) { | 
					
						
							|  |  |  | 		mouse_mesh_shortest_path_edge(scene, op_params, (BMEdge *)ele_src, (BMEdge *)ele_dst); | 
					
						
							|  |  |  | 		return true; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	else if (ele_src->head.htype == BM_FACE) { | 
					
						
							|  |  |  | 		mouse_mesh_shortest_path_face(scene, op_params, (BMFace *)ele_src, (BMFace *)ele_dst); | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | static BMElem *edbm_elem_find_nearest(ViewContext *vc, const char htype) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	BMEditMesh *em = vc->em; | 
					
						
							|  |  |  | 	float dist = ED_view3d_select_dist_px(); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if ((em->selectmode & SCE_SELECT_VERTEX) && (htype == BM_VERT)) { | 
					
						
							|  |  |  | 		return (BMElem *)EDBM_vert_find_nearest(vc, &dist); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if ((em->selectmode & SCE_SELECT_EDGE) && (htype == BM_EDGE)) { | 
					
						
							|  |  |  | 		return (BMElem *)EDBM_edge_find_nearest(vc, &dist); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else if ((em->selectmode & SCE_SELECT_FACE) && (htype == BM_FACE)) { | 
					
						
							|  |  |  | 		return (BMElem *)EDBM_face_find_nearest(vc, &dist); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return NULL; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | static int edbm_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event) | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if (RNA_struct_property_is_set(op->ptr, "index")) { | 
					
						
							|  |  |  | 		return edbm_shortest_path_pick_exec(C, op); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	ViewContext vc; | 
					
						
							|  |  |  | 	BMEditMesh *em; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	em_setup_viewcontext(C, &vc); | 
					
						
							|  |  |  | 	copy_v2_v2_int(vc.mval, event->mval); | 
					
						
							|  |  |  | 	em = vc.em; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	view3d_operator_needs_opengl(C); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	BMElem *ele_src, *ele_dst; | 
					
						
							|  |  |  | 	if (!(ele_src = BM_mesh_active_elem_get(em->bm)) || | 
					
						
							|  |  |  | 	    !(ele_dst = edbm_elem_find_nearest(&vc, ele_src->head.htype))) | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2014-02-18 08:21:19 +11:00
										 |  |  | 		return OPERATOR_PASS_THROUGH; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	struct PathSelectParams op_params; | 
					
						
							|  |  |  | 	path_select_params_from_op(op, &op_params); | 
					
						
							|  |  |  | 	op_params.track_active = true; | 
					
						
							|  |  |  | 	op_params.edge_mode = vc.scene->toolsettings->edge_mode; | 
					
						
							| 
									
										
										
										
											2014-02-18 08:21:19 +11:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	if (!edbm_shortest_path_pick_ex(vc.scene, &op_params, ele_src, ele_dst)) { | 
					
						
							|  |  |  | 		return OPERATOR_PASS_THROUGH; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* to support redo */ | 
					
						
							|  |  |  | 	int index = EDBM_elem_to_index_any(em, ele_dst); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	RNA_int_set(op->ptr, "index", index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return OPERATOR_FINISHED; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int edbm_shortest_path_pick_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							|  |  |  | 	Object *obedit = CTX_data_edit_object(C); | 
					
						
							|  |  |  | 	BMEditMesh *em = BKE_editmesh_from_object(obedit); | 
					
						
							|  |  |  | 	BMesh *bm = em->bm; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const int index = RNA_int_get(op->ptr, "index"); | 
					
						
							|  |  |  | 	if (index < 0 || index >= (bm->totvert + bm->totedge + bm->totface)) { | 
					
						
							|  |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	BMElem *ele_src, *ele_dst; | 
					
						
							|  |  |  | 	if (!(ele_src = BM_mesh_active_elem_get(em->bm)) || | 
					
						
							|  |  |  | 	    !(ele_dst = EDBM_elem_from_index_any(em, index))) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct PathSelectParams op_params; | 
					
						
							|  |  |  | 	path_select_params_from_op(op, &op_params); | 
					
						
							|  |  |  | 	op_params.track_active = true; | 
					
						
							|  |  |  | 	op_params.edge_mode = scene->toolsettings->edge_mode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!edbm_shortest_path_pick_ex(scene, &op_params, ele_src, ele_dst)) { | 
					
						
							|  |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_shortest_path_pick(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	PropertyRNA *prop; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name = "Pick Shortest Path"; | 
					
						
							|  |  |  | 	ot->idname = "MESH_OT_shortest_path_pick"; | 
					
						
							|  |  |  | 	ot->description = "Select shortest path between two selections"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->invoke = edbm_shortest_path_pick_invoke; | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	ot->exec = edbm_shortest_path_pick_exec; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	ot->poll = ED_operator_editmesh_region_view3d; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* properties */ | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	path_select_properties(ot); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	/* use for redo */ | 
					
						
							|  |  |  | 	prop = RNA_def_int(ot->srna, "index", -1, -1, INT_MAX, "", "", 0, INT_MAX); | 
					
						
							|  |  |  | 	RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* -------------------------------------------------------------------- */ | 
					
						
							|  |  |  | /* Select path between existing selection */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int edbm_shortest_path_select_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	Scene *scene = CTX_data_scene(C); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	Object *ob = CTX_data_edit_object(C); | 
					
						
							|  |  |  | 	BMEditMesh *em = BKE_editmesh_from_object(ob); | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 	BMesh *bm = em->bm; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	BMIter iter; | 
					
						
							|  |  |  | 	BMEditSelection *ese_src, *ese_dst; | 
					
						
							|  |  |  | 	BMElem *ele_src = NULL, *ele_dst = NULL, *ele; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* first try to find vertices in edit selection */ | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 	ese_src = bm->selected.last; | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 	if (ese_src && (ese_dst = ese_src->prev) && (ese_src->htype  == ese_dst->htype)) { | 
					
						
							|  |  |  | 		ele_src = ese_src->ele; | 
					
						
							|  |  |  | 		ele_dst = ese_dst->ele; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		/* if selection history isn't available, find two selected elements */ | 
					
						
							| 
									
										
										
										
											2013-06-04 05:03:36 +00:00
										 |  |  | 		ele_src = ele_dst = NULL; | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 		if ((em->selectmode & SCE_SELECT_VERTEX) && (bm->totvertsel >= 2)) { | 
					
						
							|  |  |  | 			BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 				if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { | 
					
						
							|  |  |  | 					if      (ele_src == NULL) ele_src = ele; | 
					
						
							|  |  |  | 					else if (ele_dst == NULL) ele_dst = ele; | 
					
						
							|  |  |  | 					else                      break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 		if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_EDGE) && (bm->totedgesel >= 2)) { | 
					
						
							| 
									
										
										
										
											2013-06-04 05:03:36 +00:00
										 |  |  | 			ele_src = NULL; | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 			BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 				if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { | 
					
						
							|  |  |  | 					if      (ele_src == NULL) ele_src = ele; | 
					
						
							|  |  |  | 					else if (ele_dst == NULL) ele_dst = ele; | 
					
						
							|  |  |  | 					else                      break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 		if ((ele_dst == NULL) && (em->selectmode & SCE_SELECT_FACE) && (bm->totfacesel >= 2)) { | 
					
						
							| 
									
										
										
										
											2013-06-04 05:03:36 +00:00
										 |  |  | 			ele_src = NULL; | 
					
						
							| 
									
										
										
										
											2013-06-24 04:51:56 +00:00
										 |  |  | 			BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) { | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 				if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { | 
					
						
							|  |  |  | 					if      (ele_src == NULL) ele_src = ele; | 
					
						
							|  |  |  | 					else if (ele_dst == NULL) ele_dst = ele; | 
					
						
							|  |  |  | 					else                      break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ele_src && ele_dst) { | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		struct PathSelectParams op_params; | 
					
						
							|  |  |  | 		path_select_params_from_op(op, &op_params); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 		edbm_shortest_path_pick_ex(scene, &op_params, ele_src, ele_dst); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return OPERATOR_FINISHED; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		BKE_report(op->reports, RPT_WARNING, "Path selection requires two matching elements to be selected"); | 
					
						
							|  |  |  | 		return OPERATOR_CANCELLED; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void MESH_OT_shortest_path_select(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* identifiers */ | 
					
						
							|  |  |  | 	ot->name = "Select Shortest Path"; | 
					
						
							|  |  |  | 	ot->idname = "MESH_OT_shortest_path_select"; | 
					
						
							|  |  |  | 	ot->description = "Selected vertex path between two vertices"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* api callbacks */ | 
					
						
							|  |  |  | 	ot->exec = edbm_shortest_path_select_exec; | 
					
						
							|  |  |  | 	ot->poll = ED_operator_editmesh; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* flags */ | 
					
						
							|  |  |  | 	ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* properties */ | 
					
						
							| 
									
										
										
										
											2015-12-27 18:05:53 +11:00
										 |  |  | 	path_select_properties(ot); | 
					
						
							| 
									
										
										
										
											2013-06-04 01:23:51 +00:00
										 |  |  | } |