| 
									
										
										
										
											2017-05-30 17:58:24 +10: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 | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  |  * of the License, or (at your option) any later version. | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  |  * | 
					
						
							|  |  |  |  * 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) 2008 Blender Foundation. | 
					
						
							|  |  |  |  * All rights reserved. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-02-18 08:08:12 +11:00
										 |  |  | /** \file
 | 
					
						
							|  |  |  |  * \ingroup edobj | 
					
						
							| 
									
										
										
										
											2018-08-30 01:56:08 +10:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-20 14:11:45 +11:00
										 |  |  | #include <string.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "BLI_listbase.h"
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  | #include "BLI_math.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "BLI_utildefines.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_mesh_types.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "DNA_object_types.h"
 | 
					
						
							| 
									
										
										
										
											2018-02-09 22:14:17 +11:00
										 |  |  | #include "DNA_workspace_types.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | #include "BKE_customdata.h"
 | 
					
						
							|  |  |  | #include "BKE_editmesh.h"
 | 
					
						
							|  |  |  | #include "BKE_object.h"
 | 
					
						
							|  |  |  | #include "BKE_object_deform.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "BKE_object_facemap.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-08 10:14:53 +02:00
										 |  |  | #include "DEG_depsgraph.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-20 14:11:45 +11:00
										 |  |  | #include "RNA_access.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "RNA_define.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-20 14:11:45 +11:00
										 |  |  | #include "WM_api.h"
 | 
					
						
							| 
									
										
										
										
											2020-03-19 09:33:03 +01:00
										 |  |  | #include "WM_types.h"
 | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "ED_mesh.h"
 | 
					
						
							|  |  |  | #include "ED_object.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "object_intern.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called while not in editmode */ | 
					
						
							|  |  |  | void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int fmap_nr; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (GS(((ID *)ob->data)->name) != ID_ME) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* get the face map number, exit if it can't be found */ | 
					
						
							|  |  |  |   fmap_nr = BLI_findindex(&ob->fmaps, fmap); | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (fmap_nr != -1) { | 
					
						
							|  |  |  |     int *facemap; | 
					
						
							|  |  |  |     Mesh *me = ob->data; | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     /* if there's is no facemap layer then create one */ | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     facemap[facenum] = fmap_nr; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* called while not in editmode */ | 
					
						
							|  |  |  | void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   int fmap_nr; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (GS(((ID *)ob->data)->name) != ID_ME) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* get the face map number, exit if it can't be found */ | 
					
						
							|  |  |  |   fmap_nr = BLI_findindex(&ob->fmaps, fmap); | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (fmap_nr != -1) { | 
					
						
							|  |  |  |     int *facemap; | 
					
						
							|  |  |  |     Mesh *me = ob->data; | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       return; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     facemap[facenum] = -1; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  | static void object_fmap_remap_edit_mode(Object *ob, const int *remap) | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |   if (ob->type != OB_MESH) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Mesh *me = ob->data; | 
					
						
							|  |  |  |   if (me->edit_mesh) { | 
					
						
							|  |  |  |     BMEditMesh *em = me->edit_mesh; | 
					
						
							|  |  |  |     const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |     if (cd_fmap_offset != -1) { | 
					
						
							|  |  |  |       BMFace *efa; | 
					
						
							|  |  |  |       BMIter iter; | 
					
						
							|  |  |  |       int *map; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | 
					
						
							|  |  |  |         map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (map && *map != -1) { | 
					
						
							|  |  |  |           *map = remap[*map]; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  | static void object_fmap_remap_object_mode(Object *ob, const int *remap) | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |   if (ob->type != OB_MESH) { | 
					
						
							|  |  |  |     return; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |   Mesh *me = ob->data; | 
					
						
							|  |  |  |   if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) { | 
					
						
							|  |  |  |     int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP); | 
					
						
							|  |  |  |     if (map) { | 
					
						
							| 
									
										
										
										
											2020-09-09 18:41:07 +02:00
										 |  |  |       for (int i = 0; i < me->totpoly; i++) { | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |         if (map[i] != -1) { | 
					
						
							|  |  |  |           map[i] = remap[map[i]]; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  | static void object_facemap_remap(Object *ob, const int *remap) | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (BKE_object_is_in_editmode(ob)) { | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |     object_fmap_remap_edit_mode(ob, remap); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |     object_fmap_remap_object_mode(ob, remap); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 12:03:56 +02:00
										 |  |  | static bool face_map_supported_poll(bContext *C) | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Object *ob = ED_object_context(C); | 
					
						
							|  |  |  |   ID *data = (ob) ? ob->data : NULL; | 
					
						
							| 
									
										
										
										
											2020-06-30 17:51:41 +02:00
										 |  |  |   return (ob && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && ob->type == OB_MESH && data && | 
					
						
							|  |  |  |           !ID_IS_LINKED(data) && !ID_IS_OVERRIDE_LIBRARY(data)); | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-07-02 12:03:56 +02:00
										 |  |  | static bool face_map_supported_edit_mode_poll(bContext *C) | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Object *ob = ED_object_context(C); | 
					
						
							| 
									
										
										
										
											2020-06-30 17:51:41 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   if (face_map_supported_poll(C)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     if (ob->mode == OB_MODE_EDIT) { | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int face_map_add_exec(bContext *C, wmOperator *UNUSED(op)) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Object *ob = ED_object_context(C); | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   BKE_object_facemap_add(ob); | 
					
						
							|  |  |  |   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); | 
					
						
							|  |  |  |   WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); | 
					
						
							|  |  |  |   WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void OBJECT_OT_face_map_add(struct wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* identifiers */ | 
					
						
							|  |  |  |   ot->name = "Add Face Map"; | 
					
						
							|  |  |  |   ot->idname = "OBJECT_OT_face_map_add"; | 
					
						
							|  |  |  |   ot->description = "Add a new face map to the active object"; | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* api callbacks */ | 
					
						
							|  |  |  |   ot->poll = face_map_supported_poll; | 
					
						
							|  |  |  |   ot->exec = face_map_add_exec; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* flags */ | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int face_map_remove_exec(bContext *C, wmOperator *UNUSED(op)) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Object *ob = ED_object_context(C); | 
					
						
							|  |  |  |   bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (fmap) { | 
					
						
							|  |  |  |     BKE_object_facemap_remove(ob, fmap); | 
					
						
							|  |  |  |     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); | 
					
						
							|  |  |  |     WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); | 
					
						
							|  |  |  |     WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void OBJECT_OT_face_map_remove(struct wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* identifiers */ | 
					
						
							|  |  |  |   ot->name = "Remove Face Map"; | 
					
						
							|  |  |  |   ot->idname = "OBJECT_OT_face_map_remove"; | 
					
						
							|  |  |  |   ot->description = "Remove a face map from the active object"; | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* api callbacks */ | 
					
						
							|  |  |  |   ot->poll = face_map_supported_poll; | 
					
						
							|  |  |  |   ot->exec = face_map_remove_exec; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* flags */ | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int face_map_assign_exec(bContext *C, wmOperator *UNUSED(op)) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Object *ob = ED_object_context(C); | 
					
						
							|  |  |  |   bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (fmap) { | 
					
						
							|  |  |  |     Mesh *me = ob->data; | 
					
						
							|  |  |  |     BMEditMesh *em = me->edit_mesh; | 
					
						
							|  |  |  |     BMFace *efa; | 
					
						
							|  |  |  |     BMIter iter; | 
					
						
							|  |  |  |     int *map; | 
					
						
							|  |  |  |     int cd_fmap_offset; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | 
					
						
							|  |  |  |       map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { | 
					
						
							|  |  |  |         *map = ob->actfmap - 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); | 
					
						
							|  |  |  |     WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); | 
					
						
							|  |  |  |     WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void OBJECT_OT_face_map_assign(struct wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* identifiers */ | 
					
						
							|  |  |  |   ot->name = "Assign Face Map"; | 
					
						
							|  |  |  |   ot->idname = "OBJECT_OT_face_map_assign"; | 
					
						
							|  |  |  |   ot->description = "Assign faces to a face map"; | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* api callbacks */ | 
					
						
							|  |  |  |   ot->poll = face_map_supported_edit_mode_poll; | 
					
						
							|  |  |  |   ot->exec = face_map_assign_exec; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* flags */ | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int face_map_remove_from_exec(bContext *C, wmOperator *UNUSED(op)) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Object *ob = ED_object_context(C); | 
					
						
							|  |  |  |   bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (fmap) { | 
					
						
							|  |  |  |     Mesh *me = ob->data; | 
					
						
							|  |  |  |     BMEditMesh *em = me->edit_mesh; | 
					
						
							|  |  |  |     BMFace *efa; | 
					
						
							|  |  |  |     BMIter iter; | 
					
						
							|  |  |  |     int *map; | 
					
						
							|  |  |  |     int cd_fmap_offset; | 
					
						
							|  |  |  |     int mapindex = ob->actfmap - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |       return OPERATOR_CANCELLED; | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | 
					
						
							|  |  |  |       map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) { | 
					
						
							|  |  |  |         *map = -1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); | 
					
						
							|  |  |  |     WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); | 
					
						
							|  |  |  |     WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* identifiers */ | 
					
						
							|  |  |  |   ot->name = "Remove From Face Map"; | 
					
						
							|  |  |  |   ot->idname = "OBJECT_OT_face_map_remove_from"; | 
					
						
							|  |  |  |   ot->description = "Remove faces from a face map"; | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* api callbacks */ | 
					
						
							|  |  |  |   ot->poll = face_map_supported_edit_mode_poll; | 
					
						
							|  |  |  |   ot->exec = face_map_remove_from_exec; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* flags */ | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void fmap_select(Object *ob, bool select) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Mesh *me = ob->data; | 
					
						
							|  |  |  |   BMEditMesh *em = me->edit_mesh; | 
					
						
							|  |  |  |   BMFace *efa; | 
					
						
							|  |  |  |   BMIter iter; | 
					
						
							|  |  |  |   int *map; | 
					
						
							|  |  |  |   int cd_fmap_offset; | 
					
						
							|  |  |  |   int mapindex = ob->actfmap - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP); | 
					
						
							| 
									
										
										
										
											2019-04-22 09:19:45 +10:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { | 
					
						
							|  |  |  |     map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (*map == mapindex) { | 
					
						
							|  |  |  |       BM_face_select_set(em->bm, efa, select); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int face_map_select_exec(bContext *C, wmOperator *UNUSED(op)) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Object *ob = ED_object_context(C); | 
					
						
							|  |  |  |   bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (fmap) { | 
					
						
							|  |  |  |     fmap_select(ob, true); | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); | 
					
						
							|  |  |  |     WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); | 
					
						
							|  |  |  |     WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void OBJECT_OT_face_map_select(struct wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* identifiers */ | 
					
						
							|  |  |  |   ot->name = "Select Face Map Faces"; | 
					
						
							|  |  |  |   ot->idname = "OBJECT_OT_face_map_select"; | 
					
						
							|  |  |  |   ot->description = "Select faces belonging to a face map"; | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* api callbacks */ | 
					
						
							|  |  |  |   ot->poll = face_map_supported_edit_mode_poll; | 
					
						
							|  |  |  |   ot->exec = face_map_select_exec; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* flags */ | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int face_map_deselect_exec(bContext *C, wmOperator *UNUSED(op)) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Object *ob = ED_object_context(C); | 
					
						
							|  |  |  |   bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   if (fmap) { | 
					
						
							|  |  |  |     fmap_select(ob, false); | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); | 
					
						
							|  |  |  |     WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data); | 
					
						
							|  |  |  |     WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* identifiers */ | 
					
						
							|  |  |  |   ot->name = "Deselect Face Map Faces"; | 
					
						
							|  |  |  |   ot->idname = "OBJECT_OT_face_map_deselect"; | 
					
						
							|  |  |  |   ot->description = "Deselect faces belonging to a face map"; | 
					
						
							| 
									
										
										
										
											2018-04-22 08:44:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* api callbacks */ | 
					
						
							|  |  |  |   ot->poll = face_map_supported_edit_mode_poll; | 
					
						
							|  |  |  |   ot->exec = face_map_deselect_exec; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   /* flags */ | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int face_map_move_exec(bContext *C, wmOperator *op) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   Object *ob = ED_object_context(C); | 
					
						
							|  |  |  |   bFaceMap *fmap; | 
					
						
							|  |  |  |   int dir = RNA_enum_get(op->ptr, "direction"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1); | 
					
						
							|  |  |  |   if (!fmap) { | 
					
						
							|  |  |  |     return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |   if (!fmap->prev && !fmap->next) { | 
					
						
							|  |  |  |     return OPERATOR_CANCELLED; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |   int pos1 = BLI_findindex(&ob->fmaps, fmap); | 
					
						
							|  |  |  |   int pos2 = pos1 - dir; | 
					
						
							|  |  |  |   int len = BLI_listbase_count(&ob->fmaps); | 
					
						
							|  |  |  |   int *map = MEM_mallocN(len * sizeof(*map), __func__); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |   if (!IN_RANGE(pos2, -1, len)) { | 
					
						
							|  |  |  |     const int offset = len - dir; | 
					
						
							|  |  |  |     for (int i = 0; i < len; i++) { | 
					
						
							|  |  |  |       map[i] = (i + offset) % len; | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |     pos2 = map[pos1]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { | 
					
						
							|  |  |  |     range_vn_i(map, len, 0); | 
					
						
							|  |  |  |     SWAP(int, map[pos1], map[pos2]); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |   void *prev = fmap->prev; | 
					
						
							|  |  |  |   void *next = fmap->next; | 
					
						
							|  |  |  |   BLI_remlink(&ob->fmaps, fmap); | 
					
						
							|  |  |  |   if (dir == 1) { /*up*/ | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |     BLI_insertlinkbefore(&ob->fmaps, prev, fmap); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   else { /*down*/ | 
					
						
							|  |  |  |     BLI_insertlinkafter(&ob->fmaps, next, fmap); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-31 08:40:54 -03:00
										 |  |  |   /* Iterate through mesh and substitute the indices as necessary. */ | 
					
						
							|  |  |  |   object_facemap_remap(ob, map); | 
					
						
							|  |  |  |   MEM_freeN(map); | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ob->actfmap = pos2 + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); | 
					
						
							|  |  |  |   WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return OPERATOR_FINISHED; | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void OBJECT_OT_face_map_move(wmOperatorType *ot) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-04-17 06:17:24 +02:00
										 |  |  |   static EnumPropertyItem fmap_slot_move[] = { | 
					
						
							|  |  |  |       {1, "UP", 0, "Up", ""}, | 
					
						
							|  |  |  |       {-1, "DOWN", 0, "Down", ""}, | 
					
						
							|  |  |  |       {0, NULL, 0, NULL, NULL}, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* identifiers */ | 
					
						
							|  |  |  |   ot->name = "Move Face Map"; | 
					
						
							|  |  |  |   ot->idname = "OBJECT_OT_face_map_move"; | 
					
						
							|  |  |  |   ot->description = "Move the active face map up/down in the list"; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* api callbacks */ | 
					
						
							|  |  |  |   ot->poll = face_map_supported_poll; | 
					
						
							|  |  |  |   ot->exec = face_map_move_exec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   /* flags */ | 
					
						
							|  |  |  |   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   RNA_def_enum( | 
					
						
							|  |  |  |       ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, UP or DOWN"); | 
					
						
							| 
									
										
										
										
											2017-05-30 17:58:24 +10:00
										 |  |  | } |