| 
									
										
										
										
											2011-02-23 10:52:22 +00:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  |  * 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, | 
					
						
							| 
									
										
										
										
											2012-02-11 04:16:17 +00:00
										 |  |  |  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup edmesh | 
					
						
							| 
									
										
										
										
											2011-02-27 20:29:51 +00:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_blenlib.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-10 20:43:45 +00:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2013-07-03 09:53:06 +00:00
										 |  |  | #include "BLI_bitmap.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "IMB_imbuf_types.h"
 | 
					
						
							|  |  |  | #include "IMB_imbuf.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-22 16:10:29 +02:00
										 |  |  | #include "DNA_meshdata_types.h"
 | 
					
						
							| 
									
										
										
										
											2012-02-19 22:17:30 +00:00
										 |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "DNA_object_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-22 16:10:29 +02:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | #include "BKE_customdata.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | #include "BKE_global.h"
 | 
					
						
							|  |  |  | #include "BKE_mesh.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "ED_mesh.h"
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:06:53 +00:00
										 |  |  | #include "ED_screen.h"
 | 
					
						
							| 
									
										
										
										
											2018-08-14 10:28:41 +10:00
										 |  |  | #include "ED_select_utils.h"
 | 
					
						
							| 
									
										
										
										
											2009-01-05 15:19:31 +00:00
										 |  |  | #include "ED_view3d.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "WM_api.h"
 | 
					
						
							|  |  |  | #include "WM_types.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-06-13 15:26:59 +02:00
										 |  |  | #include "DEG_depsgraph.h"
 | 
					
						
							| 
									
										
										
										
											2018-12-01 15:40:48 +03:00
										 |  |  | #include "DEG_depsgraph_query.h"
 | 
					
						
							| 
									
										
										
										
											2018-06-13 15:26:59 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | /* own include */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-22 23:22:05 +00:00
										 |  |  | /* copy the face flags, most importantly selection from the mesh to the final derived mesh,
 | 
					
						
							|  |  |  |  * use in object mode when selecting faces (while painting) */ | 
					
						
							| 
									
										
										
										
											2018-12-01 15:40:48 +03:00
										 |  |  | void paintface_flush_flags(struct bContext *C, Object *ob, short flag) | 
					
						
							| 
									
										
										
										
											2009-10-22 23:22:05 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Mesh *me = BKE_mesh_from_object(ob); | 
					
						
							|  |  |  |   MPoly *polys, *mp_orig; | 
					
						
							|  |  |  |   const int *index_array = NULL; | 
					
						
							|  |  |  |   int totpoly; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BLI_assert((flag & ~(SELECT | ME_HIDE)) == 0); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (me == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* note, call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* we could call this directly in all areas that change selection,
 | 
					
						
							|  |  |  |    * since this could become slow for realtime updates (circle-select for eg) */ | 
					
						
							|  |  |  |   if (flag & SELECT) { | 
					
						
							|  |  |  |     BKE_mesh_flush_select_from_polys(me); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-25 16:36:22 +02:00
										 |  |  |   Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (ob_eval == NULL) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-28 12:59:18 +01:00
										 |  |  |   Mesh *me_orig = ob_eval->runtime.mesh_orig; | 
					
						
							|  |  |  |   Mesh *me_eval = ob_eval->runtime.mesh_eval; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   bool updated = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (me_orig != NULL && me_eval != NULL && me_orig->totpoly == me->totpoly) { | 
					
						
							|  |  |  |     /* Update the COW copy of the mesh. */ | 
					
						
							|  |  |  |     for (i = 0; i < me->totpoly; i++) { | 
					
						
							|  |  |  |       me_orig->mpoly[i].flag = me->mpoly[i].flag; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* If the mesh has only deform modifiers, the evaluated mesh shares arrays. */ | 
					
						
							|  |  |  |     if (me_eval->mpoly == me_orig->mpoly) { | 
					
						
							|  |  |  |       updated = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     /* Mesh polys => Final derived polys */ | 
					
						
							|  |  |  |     else if ((index_array = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX))) { | 
					
						
							|  |  |  |       polys = me_eval->mpoly; | 
					
						
							|  |  |  |       totpoly = me_eval->totpoly; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       /* loop over final derived polys */ | 
					
						
							|  |  |  |       for (i = 0; i < totpoly; i++) { | 
					
						
							|  |  |  |         if (index_array[i] != ORIGINDEX_NONE) { | 
					
						
							|  |  |  |           /* Copy flags onto the final derived poly from the original mesh poly */ | 
					
						
							|  |  |  |           mp_orig = me->mpoly + index_array[i]; | 
					
						
							|  |  |  |           polys[i].flag = mp_orig->flag; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       updated = true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (updated) { | 
					
						
							|  |  |  |     if (flag & ME_HIDE) { | 
					
						
							|  |  |  |       BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_ALL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2019-04-29 17:52:08 +02:00
										 |  |  |       BKE_mesh_batch_cache_dirty_tag(me_eval, BKE_MESH_BATCH_DIRTY_SELECT_PAINT); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DEG_id_tag_update(ob->data, ID_RECALC_SELECT); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); | 
					
						
							| 
									
										
										
										
											2018-11-23 18:28:36 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-01 15:40:48 +03:00
										 |  |  | void paintface_hide(bContext *C, Object *ob, const bool unselected) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Mesh *me; | 
					
						
							|  |  |  |   MPoly *mpoly; | 
					
						
							|  |  |  |   int a; | 
					
						
							| 
									
										
										
										
											2018-06-04 09:31:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   me = BKE_mesh_from_object(ob); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (me == NULL || me->totpoly == 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2011-02-24 16:04:36 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   mpoly = me->mpoly; | 
					
						
							|  |  |  |   a = me->totpoly; | 
					
						
							|  |  |  |   while (a--) { | 
					
						
							|  |  |  |     if ((mpoly->flag & ME_HIDE) == 0) { | 
					
						
							|  |  |  |       if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) { | 
					
						
							|  |  |  |         mpoly->flag |= ME_HIDE; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-06-26 02:47:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (mpoly->flag & ME_HIDE) { | 
					
						
							|  |  |  |       mpoly->flag &= ~ME_FACE_SEL; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-06-04 09:31:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     mpoly++; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-06-04 09:31:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_mesh_flush_hidden_from_polys(me); | 
					
						
							| 
									
										
										
										
											2013-06-26 02:47:56 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   paintface_flush_flags(C, ob, SELECT | ME_HIDE); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-12-01 15:40:48 +03:00
										 |  |  | void paintface_reveal(bContext *C, Object *ob, const bool select) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Mesh *me; | 
					
						
							|  |  |  |   MPoly *mpoly; | 
					
						
							|  |  |  |   int a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   me = BKE_mesh_from_object(ob); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (me == NULL || me->totpoly == 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   mpoly = me->mpoly; | 
					
						
							|  |  |  |   a = me->totpoly; | 
					
						
							|  |  |  |   while (a--) { | 
					
						
							|  |  |  |     if (mpoly->flag & ME_HIDE) { | 
					
						
							|  |  |  |       SET_FLAG_FROM_TEST(mpoly->flag, select, ME_FACE_SEL); | 
					
						
							|  |  |  |       mpoly->flag &= ~ME_HIDE; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mpoly++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BKE_mesh_flush_hidden_from_polys(me); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   paintface_flush_flags(C, ob, SELECT | ME_HIDE); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-01 00:06:53 +00:00
										 |  |  | /* Set tface seams based on edge data, uses hash table to find seam edges. */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-03 09:53:06 +00:00
										 |  |  | static void select_linked_tfaces_with_seams(Mesh *me, const unsigned int index, const bool select) | 
					
						
							| 
									
										
										
										
											2009-11-01 00:06:53 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MPoly *mp; | 
					
						
							|  |  |  |   MLoop *ml; | 
					
						
							|  |  |  |   int a, b; | 
					
						
							|  |  |  |   bool do_it = true; | 
					
						
							|  |  |  |   bool mark = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__); | 
					
						
							|  |  |  |   BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (index != (unsigned int)-1) { | 
					
						
							|  |  |  |     /* only put face under cursor in array */ | 
					
						
							|  |  |  |     mp = &me->mpoly[index]; | 
					
						
							|  |  |  |     BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart); | 
					
						
							|  |  |  |     BLI_BITMAP_ENABLE(poly_tag, index); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     /* fill array by selection */ | 
					
						
							|  |  |  |     mp = me->mpoly; | 
					
						
							|  |  |  |     for (a = 0; a < me->totpoly; a++, mp++) { | 
					
						
							|  |  |  |       if (mp->flag & ME_HIDE) { | 
					
						
							|  |  |  |         /* pass */ | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else if (mp->flag & ME_FACE_SEL) { | 
					
						
							|  |  |  |         BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart); | 
					
						
							|  |  |  |         BLI_BITMAP_ENABLE(poly_tag, a); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   while (do_it) { | 
					
						
							|  |  |  |     do_it = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /* expand selection */ | 
					
						
							|  |  |  |     mp = me->mpoly; | 
					
						
							|  |  |  |     for (a = 0; a < me->totpoly; a++, mp++) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |       if (mp->flag & ME_HIDE) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         continue; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |       if (!BLI_BITMAP_TEST(poly_tag, a)) { | 
					
						
							|  |  |  |         mark = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ml = me->mloop + mp->loopstart; | 
					
						
							|  |  |  |         for (b = 0; b < mp->totloop; b++, ml++) { | 
					
						
							|  |  |  |           if ((me->medge[ml->e].flag & ME_SEAM) == 0) { | 
					
						
							|  |  |  |             if (BLI_BITMAP_TEST(edge_tag, ml->e)) { | 
					
						
							|  |  |  |               mark = true; | 
					
						
							|  |  |  |               break; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (mark) { | 
					
						
							|  |  |  |           BLI_BITMAP_ENABLE(poly_tag, a); | 
					
						
							|  |  |  |           BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart); | 
					
						
							|  |  |  |           do_it = true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MEM_freeN(edge_tag); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++) { | 
					
						
							|  |  |  |     if (BLI_BITMAP_TEST(poly_tag, a)) { | 
					
						
							|  |  |  |       SET_FLAG_FROM_TEST(mp->flag, select, ME_FACE_SEL); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   MEM_freeN(poly_tag); | 
					
						
							| 
									
										
										
										
											2009-11-01 00:06:53 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-03 09:53:06 +00:00
										 |  |  | void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const bool select) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Mesh *me; | 
					
						
							|  |  |  |   unsigned int index = (unsigned int)-1; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   me = BKE_mesh_from_object(ob); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (me == NULL || me->totpoly == 0) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (mval) { | 
					
						
							|  |  |  |     if (!ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) { | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   select_linked_tfaces_with_seams(me, index, select); | 
					
						
							| 
									
										
										
										
											2009-11-01 00:06:53 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   paintface_flush_flags(C, ob, SELECT); | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-26 18:47:55 +11:00
										 |  |  | bool paintface_deselect_all_visible(bContext *C, Object *ob, int action, bool flush_flags) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Mesh *me; | 
					
						
							|  |  |  |   MPoly *mpoly; | 
					
						
							|  |  |  |   int a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   me = BKE_mesh_from_object(ob); | 
					
						
							|  |  |  |   if (me == NULL) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (action == SEL_TOGGLE) { | 
					
						
							|  |  |  |     action = SEL_SELECT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mpoly = me->mpoly; | 
					
						
							|  |  |  |     a = me->totpoly; | 
					
						
							|  |  |  |     while (a--) { | 
					
						
							|  |  |  |       if ((mpoly->flag & ME_HIDE) == 0 && mpoly->flag & ME_FACE_SEL) { | 
					
						
							|  |  |  |         action = SEL_DESELECT; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       mpoly++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool changed = false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mpoly = me->mpoly; | 
					
						
							|  |  |  |   a = me->totpoly; | 
					
						
							|  |  |  |   while (a--) { | 
					
						
							|  |  |  |     if ((mpoly->flag & ME_HIDE) == 0) { | 
					
						
							|  |  |  |       switch (action) { | 
					
						
							|  |  |  |         case SEL_SELECT: | 
					
						
							|  |  |  |           if ((mpoly->flag & ME_FACE_SEL) == 0) { | 
					
						
							|  |  |  |             mpoly->flag |= ME_FACE_SEL; | 
					
						
							|  |  |  |             changed = true; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case SEL_DESELECT: | 
					
						
							|  |  |  |           if ((mpoly->flag & ME_FACE_SEL) != 0) { | 
					
						
							|  |  |  |             mpoly->flag &= ~ME_FACE_SEL; | 
					
						
							|  |  |  |             changed = true; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case SEL_INVERT: | 
					
						
							|  |  |  |           mpoly->flag ^= ME_FACE_SEL; | 
					
						
							|  |  |  |           changed = true; | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mpoly++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (changed) { | 
					
						
							|  |  |  |     if (flush_flags) { | 
					
						
							|  |  |  |       paintface_flush_flags(C, ob, SELECT); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return changed; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | bool paintface_minmax(Object *ob, float r_min[3], float r_max[3]) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   const Mesh *me; | 
					
						
							|  |  |  |   const MPoly *mp; | 
					
						
							|  |  |  |   const MLoop *ml; | 
					
						
							|  |  |  |   const MVert *mvert; | 
					
						
							|  |  |  |   int a, b; | 
					
						
							|  |  |  |   bool ok = false; | 
					
						
							|  |  |  |   float vec[3], bmat[3][3]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   me = BKE_mesh_from_object(ob); | 
					
						
							|  |  |  |   if (!me || !me->mloopuv) { | 
					
						
							|  |  |  |     return ok; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   copy_m3_m4(bmat, ob->obmat); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mvert = me->mvert; | 
					
						
							|  |  |  |   mp = me->mpoly; | 
					
						
							|  |  |  |   for (a = me->totpoly; a > 0; a--, mp++) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     if (mp->flag & ME_HIDE || !(mp->flag & ME_FACE_SEL)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       continue; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     ml = me->mloop + mp->totloop; | 
					
						
							|  |  |  |     for (b = 0; b < mp->totloop; b++, ml++) { | 
					
						
							|  |  |  |       mul_v3_m3v3(vec, bmat, mvert[ml->v].co); | 
					
						
							|  |  |  |       add_v3_v3v3(vec, vec, ob->obmat[3]); | 
					
						
							|  |  |  |       minmax_v3v3_v3(r_min, r_max, vec); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ok = true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return ok; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | bool paintface_mouse_select( | 
					
						
							|  |  |  |     struct bContext *C, Object *ob, const int mval[2], bool extend, bool deselect, bool toggle) | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Mesh *me; | 
					
						
							|  |  |  |   MPoly *mpoly_sel; | 
					
						
							|  |  |  |   uint index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* Get the face under the cursor */ | 
					
						
							|  |  |  |   me = BKE_mesh_from_object(ob); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!ED_mesh_pick_face(C, ob, mval, ED_MESH_PICK_DEFAULT_FACE_DIST, &index)) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (index >= me->totpoly) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mpoly_sel = me->mpoly + index; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (mpoly_sel->flag & ME_HIDE) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* clear flags */ | 
					
						
							|  |  |  |   if (!extend && !deselect && !toggle) { | 
					
						
							|  |  |  |     paintface_deselect_all_visible(C, ob, SEL_DESELECT, false); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   me->act_face = (int)index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (extend) { | 
					
						
							|  |  |  |     mpoly_sel->flag |= ME_FACE_SEL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (deselect) { | 
					
						
							|  |  |  |     mpoly_sel->flag &= ~ME_FACE_SEL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else if (toggle) { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     if (mpoly_sel->flag & ME_FACE_SEL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       mpoly_sel->flag &= ~ME_FACE_SEL; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       mpoly_sel->flag |= ME_FACE_SEL; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     mpoly_sel->flag |= ME_FACE_SEL; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* image window redraw */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   paintface_flush_flags(C, ob, SELECT); | 
					
						
							|  |  |  |   ED_region_tag_redraw(CTX_wm_region(C));  // XXX - should redraw all 3D views
 | 
					
						
							|  |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2008-12-30 13:16:14 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-22 16:09:27 +00:00
										 |  |  | /*  (similar to void paintface_flush_flags(Object *ob))
 | 
					
						
							|  |  |  |  * copy the vertex flags, most importantly selection from the mesh to the final derived mesh, | 
					
						
							|  |  |  |  * use in object mode when selecting vertices (while painting) */ | 
					
						
							|  |  |  | void paintvert_flush_flags(Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Mesh *me = BKE_mesh_from_object(ob); | 
					
						
							| 
									
										
										
										
											2020-02-28 12:59:18 +01:00
										 |  |  |   Mesh *me_eval = ob->runtime.mesh_eval; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   MVert *mvert_eval, *mv; | 
					
						
							|  |  |  |   const int *index_array = NULL; | 
					
						
							|  |  |  |   int totvert; | 
					
						
							|  |  |  |   int i; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (me == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   /* we could call this directly in all areas that change selection,
 | 
					
						
							|  |  |  |    * since this could become slow for realtime updates (circle-select for eg) */ | 
					
						
							|  |  |  |   BKE_mesh_flush_select_from_verts(me); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (me_eval == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   index_array = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mvert_eval = me_eval->mvert; | 
					
						
							|  |  |  |   totvert = me_eval->totvert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   mv = mvert_eval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (index_array) { | 
					
						
							|  |  |  |     int orig_index; | 
					
						
							|  |  |  |     for (i = 0; i < totvert; i++, mv++) { | 
					
						
							|  |  |  |       orig_index = index_array[i]; | 
					
						
							|  |  |  |       if (orig_index != ORIGINDEX_NONE) { | 
					
						
							|  |  |  |         mv->flag = me->mvert[index_array[i]].flag; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     for (i = 0; i < totvert; i++, mv++) { | 
					
						
							|  |  |  |       mv->flag = me->mvert[i].flag; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BKE_mesh_batch_cache_dirty_tag(me, BKE_MESH_BATCH_DIRTY_ALL); | 
					
						
							| 
									
										
										
										
											2011-09-22 16:09:27 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2018-11-23 18:28:36 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | void paintvert_tag_select_update(struct bContext *C, struct Object *ob) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   DEG_id_tag_update(ob->data, ID_RECALC_COPY_ON_WRITE | ID_RECALC_SELECT); | 
					
						
							|  |  |  |   WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data); | 
					
						
							| 
									
										
										
										
											2018-11-23 18:28:36 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-15 23:24:20 +11:00
										 |  |  | /*  note: if the caller passes false to flush_flags,
 | 
					
						
							|  |  |  |  *  then they will need to run paintvert_flush_flags(ob) themselves */ | 
					
						
							| 
									
										
										
										
											2019-03-26 18:47:55 +11:00
										 |  |  | bool paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags) | 
					
						
							| 
									
										
										
										
											2011-09-22 16:09:27 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Mesh *me; | 
					
						
							|  |  |  |   MVert *mvert; | 
					
						
							|  |  |  |   int a; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   me = BKE_mesh_from_object(ob); | 
					
						
							|  |  |  |   if (me == NULL) { | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (action == SEL_TOGGLE) { | 
					
						
							|  |  |  |     action = SEL_SELECT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     mvert = me->mvert; | 
					
						
							|  |  |  |     a = me->totvert; | 
					
						
							|  |  |  |     while (a--) { | 
					
						
							|  |  |  |       if ((mvert->flag & ME_HIDE) == 0 && mvert->flag & SELECT) { | 
					
						
							|  |  |  |         action = SEL_DESELECT; | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       mvert++; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   bool changed = false; | 
					
						
							|  |  |  |   mvert = me->mvert; | 
					
						
							|  |  |  |   a = me->totvert; | 
					
						
							|  |  |  |   while (a--) { | 
					
						
							|  |  |  |     if ((mvert->flag & ME_HIDE) == 0) { | 
					
						
							|  |  |  |       switch (action) { | 
					
						
							|  |  |  |         case SEL_SELECT: | 
					
						
							|  |  |  |           if ((mvert->flag & SELECT) == 0) { | 
					
						
							|  |  |  |             mvert->flag |= SELECT; | 
					
						
							|  |  |  |             changed = true; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case SEL_DESELECT: | 
					
						
							|  |  |  |           if ((mvert->flag & SELECT) != 0) { | 
					
						
							|  |  |  |             mvert->flag &= ~SELECT; | 
					
						
							|  |  |  |             changed = true; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         case SEL_INVERT: | 
					
						
							|  |  |  |           mvert->flag ^= SELECT; | 
					
						
							|  |  |  |           changed = true; | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     mvert++; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (changed) { | 
					
						
							|  |  |  |     /* handle mselect */ | 
					
						
							|  |  |  |     if (action == SEL_SELECT) { | 
					
						
							|  |  |  |       /* pass */ | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else if (ELEM(action, SEL_DESELECT, SEL_INVERT)) { | 
					
						
							|  |  |  |       BKE_mesh_mselect_clear(me); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     else { | 
					
						
							|  |  |  |       BKE_mesh_mselect_validate(me); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (flush_flags) { | 
					
						
							|  |  |  |       paintvert_flush_flags(ob); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return changed; | 
					
						
							| 
									
										
										
										
											2011-09-22 16:09:27 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2011-12-20 21:28:57 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-19 23:17:44 +00:00
										 |  |  | void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags) | 
					
						
							| 
									
										
										
										
											2013-03-16 16:11:50 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Mesh *me = BKE_mesh_from_object(ob); | 
					
						
							|  |  |  |   MVert *mv; | 
					
						
							|  |  |  |   MDeformVert *dv; | 
					
						
							|  |  |  |   int a, tot; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (me == NULL || me->dvert == NULL) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (!extend) { | 
					
						
							|  |  |  |     paintvert_deselect_all_visible(ob, SEL_DESELECT, false); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   dv = me->dvert; | 
					
						
							|  |  |  |   tot = me->totvert; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (a = 0, mv = me->mvert; a < tot; a++, mv++, dv++) { | 
					
						
							|  |  |  |     if ((mv->flag & ME_HIDE) == 0) { | 
					
						
							|  |  |  |       if (dv->dw == NULL) { | 
					
						
							|  |  |  |         /* if null weight then not grouped */ | 
					
						
							|  |  |  |         mv->flag |= SELECT; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (flush_flags) { | 
					
						
							|  |  |  |     paintvert_flush_flags(ob); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2013-03-16 16:11:50 +00:00
										 |  |  | } |