Blender  V2.93
object_facemap_ops.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2008 Blender Foundation.
17  * All rights reserved.
18  */
19 
24 #include <string.h>
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "BLI_listbase.h"
29 #include "BLI_math.h"
30 #include "BLI_utildefines.h"
31 
32 #include "DNA_mesh_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_workspace_types.h"
35 
36 #include "BKE_context.h"
37 #include "BKE_customdata.h"
38 #include "BKE_editmesh.h"
39 #include "BKE_object.h"
40 #include "BKE_object_deform.h"
41 #include "BKE_object_facemap.h"
42 
43 #include "DEG_depsgraph.h"
44 
45 #include "RNA_access.h"
46 #include "RNA_define.h"
47 
48 #include "WM_api.h"
49 #include "WM_types.h"
50 
51 #include "ED_mesh.h"
52 #include "ED_object.h"
53 
54 #include "object_intern.h"
55 
56 /* called while not in editmode */
57 void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum)
58 {
59  int fmap_nr;
60  if (GS(((ID *)ob->data)->name) != ID_ME) {
61  return;
62  }
63 
64  /* get the face map number, exit if it can't be found */
65  fmap_nr = BLI_findindex(&ob->fmaps, fmap);
66 
67  if (fmap_nr != -1) {
68  int *facemap;
69  Mesh *me = ob->data;
70 
71  /* if there's is no facemap layer then create one */
72  if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL) {
74  }
75 
76  facemap[facenum] = fmap_nr;
77  }
78 }
79 
80 /* called while not in editmode */
81 void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
82 {
83  int fmap_nr;
84  if (GS(((ID *)ob->data)->name) != ID_ME) {
85  return;
86  }
87 
88  /* get the face map number, exit if it can't be found */
89  fmap_nr = BLI_findindex(&ob->fmaps, fmap);
90 
91  if (fmap_nr != -1) {
92  int *facemap;
93  Mesh *me = ob->data;
94 
95  if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL) {
96  return;
97  }
98 
99  facemap[facenum] = -1;
100  }
101 }
102 
103 static void object_fmap_remap_edit_mode(Object *ob, const int *remap)
104 {
105  if (ob->type != OB_MESH) {
106  return;
107  }
108 
109  Mesh *me = ob->data;
110  if (me->edit_mesh) {
111  BMEditMesh *em = me->edit_mesh;
112  const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
113 
114  if (cd_fmap_offset != -1) {
115  BMFace *efa;
116  BMIter iter;
117  int *map;
118 
119  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
120  map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
121 
122  if (map && *map != -1) {
123  *map = remap[*map];
124  }
125  }
126  }
127  }
128 }
129 
130 static void object_fmap_remap_object_mode(Object *ob, const int *remap)
131 {
132  if (ob->type != OB_MESH) {
133  return;
134  }
135 
136  Mesh *me = ob->data;
137  if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
138  int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
139  if (map) {
140  for (int i = 0; i < me->totpoly; i++) {
141  if (map[i] != -1) {
142  map[i] = remap[map[i]];
143  }
144  }
145  }
146  }
147 }
148 
149 static void object_facemap_remap(Object *ob, const int *remap)
150 {
151  if (BKE_object_is_in_editmode(ob)) {
152  object_fmap_remap_edit_mode(ob, remap);
153  }
154  else {
156  }
157 }
158 
160 {
161  Object *ob = ED_object_context(C);
162  ID *data = (ob) ? ob->data : NULL;
163  return (ob && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && ob->type == OB_MESH && data &&
165 }
166 
168 {
169  Object *ob = ED_object_context(C);
170 
171  if (face_map_supported_poll(C)) {
172  if (ob->mode == OB_MODE_EDIT) {
173  return true;
174  }
175  }
176  return false;
177 }
178 
180 {
181  Object *ob = ED_object_context(C);
182 
187 
188  return OPERATOR_FINISHED;
189 }
190 
192 {
193  /* identifiers */
194  ot->name = "Add Face Map";
195  ot->idname = "OBJECT_OT_face_map_add";
196  ot->description = "Add a new face map to the active object";
197 
198  /* api callbacks */
201 
202  /* flags */
204 }
205 
207 {
208  Object *ob = ED_object_context(C);
209  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
210 
211  if (fmap) {
212  BKE_object_facemap_remove(ob, fmap);
216  }
217  return OPERATOR_FINISHED;
218 }
219 
221 {
222  /* identifiers */
223  ot->name = "Remove Face Map";
224  ot->idname = "OBJECT_OT_face_map_remove";
225  ot->description = "Remove a face map from the active object";
226 
227  /* api callbacks */
230 
231  /* flags */
233 }
234 
236 {
237  Object *ob = ED_object_context(C);
238  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
239 
240  if (fmap) {
241  Mesh *me = ob->data;
242  BMEditMesh *em = me->edit_mesh;
243  BMFace *efa;
244  BMIter iter;
245  int *map;
246  int cd_fmap_offset;
247 
248  if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
249  BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
250  }
251 
252  cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
253 
254  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
255  map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
256 
257  if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
258  *map = ob->actfmap - 1;
259  }
260  }
261 
265  }
266  return OPERATOR_FINISHED;
267 }
268 
270 {
271  /* identifiers */
272  ot->name = "Assign Face Map";
273  ot->idname = "OBJECT_OT_face_map_assign";
274  ot->description = "Assign faces to a face map";
275 
276  /* api callbacks */
279 
280  /* flags */
282 }
283 
285 {
286  Object *ob = ED_object_context(C);
287  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
288 
289  if (fmap) {
290  Mesh *me = ob->data;
291  BMEditMesh *em = me->edit_mesh;
292  BMFace *efa;
293  BMIter iter;
294  int *map;
295  int cd_fmap_offset;
296  int mapindex = ob->actfmap - 1;
297 
298  if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
299  return OPERATOR_CANCELLED;
300  }
301 
302  cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
303 
304  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
305  map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
306 
307  if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) {
308  *map = -1;
309  }
310  }
311 
315  }
316  return OPERATOR_FINISHED;
317 }
318 
320 {
321  /* identifiers */
322  ot->name = "Remove from Face Map";
323  ot->idname = "OBJECT_OT_face_map_remove_from";
324  ot->description = "Remove faces from a face map";
325 
326  /* api callbacks */
329 
330  /* flags */
332 }
333 
334 static void fmap_select(Object *ob, bool select)
335 {
336  Mesh *me = ob->data;
337  BMEditMesh *em = me->edit_mesh;
338  BMFace *efa;
339  BMIter iter;
340  int *map;
341  int cd_fmap_offset;
342  int mapindex = ob->actfmap - 1;
343 
344  if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
345  BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
346  }
347 
348  cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
349 
350  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
351  map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
352 
353  if (*map == mapindex) {
354  BM_face_select_set(em->bm, efa, select);
355  }
356  }
357 }
358 
360 {
361  Object *ob = ED_object_context(C);
362  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
363 
364  if (fmap) {
365  fmap_select(ob, true);
366 
370  }
371  return OPERATOR_FINISHED;
372 }
373 
375 {
376  /* identifiers */
377  ot->name = "Select Face Map Faces";
378  ot->idname = "OBJECT_OT_face_map_select";
379  ot->description = "Select faces belonging to a face map";
380 
381  /* api callbacks */
384 
385  /* flags */
387 }
388 
390 {
391  Object *ob = ED_object_context(C);
392  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
393 
394  if (fmap) {
395  fmap_select(ob, false);
396 
400  }
401  return OPERATOR_FINISHED;
402 }
403 
405 {
406  /* identifiers */
407  ot->name = "Deselect Face Map Faces";
408  ot->idname = "OBJECT_OT_face_map_deselect";
409  ot->description = "Deselect faces belonging to a face map";
410 
411  /* api callbacks */
414 
415  /* flags */
417 }
418 
420 {
421  Object *ob = ED_object_context(C);
422  bFaceMap *fmap;
423  int dir = RNA_enum_get(op->ptr, "direction");
424 
425  fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
426  if (!fmap) {
427  return OPERATOR_CANCELLED;
428  }
429 
430  if (!fmap->prev && !fmap->next) {
431  return OPERATOR_CANCELLED;
432  }
433 
434  int pos1 = BLI_findindex(&ob->fmaps, fmap);
435  int pos2 = pos1 - dir;
436  int len = BLI_listbase_count(&ob->fmaps);
437  int *map = MEM_mallocN(len * sizeof(*map), __func__);
438 
439  if (!IN_RANGE(pos2, -1, len)) {
440  const int offset = len - dir;
441  for (int i = 0; i < len; i++) {
442  map[i] = (i + offset) % len;
443  }
444  pos2 = map[pos1];
445  }
446  else {
447  range_vn_i(map, len, 0);
448  SWAP(int, map[pos1], map[pos2]);
449  }
450 
451  void *prev = fmap->prev;
452  void *next = fmap->next;
453  BLI_remlink(&ob->fmaps, fmap);
454  if (dir == 1) { /*up*/
455  BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
456  }
457  else { /*down*/
458  BLI_insertlinkafter(&ob->fmaps, next, fmap);
459  }
460 
461  /* Iterate through mesh and substitute the indices as necessary. */
462  object_facemap_remap(ob, map);
463  MEM_freeN(map);
464 
465  ob->actfmap = pos2 + 1;
466 
469 
470  return OPERATOR_FINISHED;
471 }
472 
474 {
475  static EnumPropertyItem fmap_slot_move[] = {
476  {1, "UP", 0, "Up", ""},
477  {-1, "DOWN", 0, "Down", ""},
478  {0, NULL, 0, NULL, NULL},
479  };
480 
481  /* identifiers */
482  ot->name = "Move Face Map";
483  ot->idname = "OBJECT_OT_face_map_move";
484  ot->description = "Move the active face map up/down in the list";
485 
486  /* api callbacks */
489 
490  /* flags */
492 
493  RNA_def_enum(
494  ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, up or down");
495 }
CustomData interface, see also DNA_customdata_types.h.
@ CD_DEFAULT
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_get_layer(const struct CustomData *data, int type)
void * CustomData_add_layer(struct CustomData *data, int type, eCDAllocType alloctype, void *layer, int totelem)
Definition: customdata.c:2620
int CustomData_get_offset(const struct CustomData *data, int type)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const struct Object *ob)
Functions for dealing with objects and deform verts, used by painting and tools.
Functions for dealing with object face-maps.
void BKE_object_facemap_remove(struct Object *ob, struct bFaceMap *fmap)
struct bFaceMap * BKE_object_facemap_add(struct Object *ob)
void BLI_insertlinkafter(struct ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:352
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void BLI_insertlinkbefore(struct ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition: listbase.c:395
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void range_vn_i(int *array_tar, const int size, const int start)
Definition: math_vector.c:1172
#define SWAP(type, a, b)
#define IN_RANGE(a, b, c)
#define UNUSED(x)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:445
@ ID_ME
Definition: DNA_ID_enums.h:60
@ CD_FACEMAP
@ OB_MODE_EDIT
Object is a sort of wrapper for general info.
@ OB_MESH
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
struct Object * ED_object_context(const struct bContext *C)
Read Guarded memory(de)allocation.
const int facemap[6][4]
Definition: Projections.cpp:57
#define C
Definition: RandGen.cpp:39
#define NC_GEOM
Definition: WM_types.h:294
#define ND_DRAW
Definition: WM_types.h:362
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
#define ND_VERTEX_GROUP
Definition: WM_types.h:409
#define NC_OBJECT
Definition: WM_types.h:280
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:530
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:26
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:894
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
void BM_face_select_set(BMesh *bm, BMFace *f, const bool select)
Select Face.
return(oflags[bm->toolflag_index].f &oflag) !=0
#define GS(x)
Definition: iris.c:241
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static ulong * next
void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot)
void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
static int face_map_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
void OBJECT_OT_face_map_remove(struct wmOperatorType *ot)
void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum)
void OBJECT_OT_face_map_move(wmOperatorType *ot)
static void fmap_select(Object *ob, bool select)
static void object_fmap_remap_edit_mode(Object *ob, const int *remap)
static bool face_map_supported_poll(bContext *C)
static int face_map_select_exec(bContext *C, wmOperator *UNUSED(op))
void OBJECT_OT_face_map_select(struct wmOperatorType *ot)
static int face_map_remove_exec(bContext *C, wmOperator *UNUSED(op))
static int face_map_deselect_exec(bContext *C, wmOperator *UNUSED(op))
static int face_map_assign_exec(bContext *C, wmOperator *UNUSED(op))
static void object_fmap_remap_object_mode(Object *ob, const int *remap)
static int face_map_move_exec(bContext *C, wmOperator *op)
void OBJECT_OT_face_map_add(struct wmOperatorType *ot)
static void object_facemap_remap(Object *ob, const int *remap)
static int face_map_add_exec(bContext *C, wmOperator *UNUSED(op))
static bool face_map_supported_edit_mode_poll(bContext *C)
void OBJECT_OT_face_map_assign(struct wmOperatorType *ot)
void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot)
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
struct BMesh * bm
Definition: BKE_editmesh.h:52
CustomData pdata
Definition: bmesh_class.h:337
Definition: DNA_ID.h:273
struct BMEditMesh * edit_mesh
int totpoly
unsigned short actfmap
void * data
ListBase fmaps
struct bFaceMap * next
struct bFaceMap * prev
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct PointerRNA * ptr
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: util_avxb.h:167
uint len
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3156