Blender  V3.3
object_facemap_ops.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2008 Blender Foundation. All rights reserved. */
3 
8 #include <string.h>
9 
10 #include "MEM_guardedalloc.h"
11 
12 #include "BLI_listbase.h"
13 #include "BLI_math.h"
14 #include "BLI_utildefines.h"
15 
16 #include "DNA_mesh_types.h"
17 #include "DNA_object_types.h"
18 #include "DNA_workspace_types.h"
19 
20 #include "BKE_context.h"
21 #include "BKE_customdata.h"
22 #include "BKE_editmesh.h"
23 #include "BKE_object.h"
24 #include "BKE_object_deform.h"
25 #include "BKE_object_facemap.h"
26 
27 #include "DEG_depsgraph.h"
28 
29 #include "RNA_access.h"
30 #include "RNA_define.h"
31 
32 #include "WM_api.h"
33 #include "WM_types.h"
34 
35 #include "ED_mesh.h"
36 #include "ED_object.h"
37 
38 #include "object_intern.h"
39 
40 void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum)
41 {
42  int fmap_nr;
43  if (GS(((ID *)ob->data)->name) != ID_ME) {
44  return;
45  }
46 
47  /* get the face map number, exit if it can't be found */
48  fmap_nr = BLI_findindex(&ob->fmaps, fmap);
49 
50  if (fmap_nr != -1) {
51  int *facemap;
52  Mesh *me = ob->data;
53 
54  /* if there's is no facemap layer then create one */
55  if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL) {
57  }
58 
59  facemap[facenum] = fmap_nr;
60  }
61 }
62 
63 void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
64 {
65  int fmap_nr;
66  if (GS(((ID *)ob->data)->name) != ID_ME) {
67  return;
68  }
69 
70  /* get the face map number, exit if it can't be found */
71  fmap_nr = BLI_findindex(&ob->fmaps, fmap);
72 
73  if (fmap_nr != -1) {
74  int *facemap;
75  Mesh *me = ob->data;
76 
77  if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL) {
78  return;
79  }
80 
81  facemap[facenum] = -1;
82  }
83 }
84 
85 static void object_fmap_remap_edit_mode(Object *ob, const int *remap)
86 {
87  if (ob->type != OB_MESH) {
88  return;
89  }
90 
91  Mesh *me = ob->data;
92  if (me->edit_mesh) {
93  BMEditMesh *em = me->edit_mesh;
94  const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
95 
96  if (cd_fmap_offset != -1) {
97  BMFace *efa;
98  BMIter iter;
99  int *map;
100 
101  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
102  map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
103 
104  if (map && *map != -1) {
105  *map = remap[*map];
106  }
107  }
108  }
109  }
110 }
111 
112 static void object_fmap_remap_object_mode(Object *ob, const int *remap)
113 {
114  if (ob->type != OB_MESH) {
115  return;
116  }
117 
118  Mesh *me = ob->data;
121  if (map) {
122  for (int i = 0; i < me->totpoly; i++) {
123  if (map[i] != -1) {
124  map[i] = remap[map[i]];
125  }
126  }
127  }
128  }
129 }
130 
131 static void object_facemap_remap(Object *ob, const int *remap)
132 {
133  if (BKE_object_is_in_editmode(ob)) {
134  object_fmap_remap_edit_mode(ob, remap);
135  }
136  else {
138  }
139 }
140 
142 {
143  Object *ob = ED_object_context(C);
144  ID *data = (ob) ? ob->data : NULL;
145  return (ob && !ID_IS_LINKED(ob) && !ID_IS_OVERRIDE_LIBRARY(ob) && ob->type == OB_MESH && data &&
147 }
148 
150 {
151  Object *ob = ED_object_context(C);
152 
153  if (face_map_supported_poll(C)) {
154  if (ob->mode == OB_MODE_EDIT) {
155  return true;
156  }
157  }
158  return false;
159 }
160 
162 {
163  if (!face_map_supported_poll(C)) {
164  return false;
165  }
166 
167  Object *ob = ED_object_context(C);
168  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
169  if (fmap) {
170  return true;
171  }
172 
173  return false;
174 }
175 
177 {
178  Object *ob = ED_object_context(C);
179 
184 
185  return OPERATOR_FINISHED;
186 }
187 
189 {
190  /* identifiers */
191  ot->name = "Add Face Map";
192  ot->idname = "OBJECT_OT_face_map_add";
193  ot->description = "Add a new face map to the active object";
194 
195  /* api callbacks */
198 
199  /* flags */
201 }
202 
204 {
205  Object *ob = ED_object_context(C);
206  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
207 
208  if (fmap) {
209  BKE_object_facemap_remove(ob, fmap);
213  }
214  return OPERATOR_FINISHED;
215 }
216 
218 {
219  /* identifiers */
220  ot->name = "Remove Face Map";
221  ot->idname = "OBJECT_OT_face_map_remove";
222  ot->description = "Remove a face map from the active object";
223 
224  /* api callbacks */
227 
228  /* flags */
230 }
231 
233 {
234  Object *ob = ED_object_context(C);
235  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
236 
237  if (fmap) {
238  Mesh *me = ob->data;
239  BMEditMesh *em = me->edit_mesh;
240  BMFace *efa;
241  BMIter iter;
242  int *map;
243  int cd_fmap_offset;
244 
245  if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
246  BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
247  }
248 
249  cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
250 
251  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
252  map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
253 
254  if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) {
255  *map = ob->actfmap - 1;
256  }
257  }
258 
262  }
263  return OPERATOR_FINISHED;
264 }
265 
267 {
268  /* identifiers */
269  ot->name = "Assign Face Map";
270  ot->idname = "OBJECT_OT_face_map_assign";
271  ot->description = "Assign faces to a face map";
272 
273  /* api callbacks */
276 
277  /* flags */
279 }
280 
282 {
283  Object *ob = ED_object_context(C);
284  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
285 
286  if (fmap) {
287  Mesh *me = ob->data;
288  BMEditMesh *em = me->edit_mesh;
289  BMFace *efa;
290  BMIter iter;
291  int *map;
292  int cd_fmap_offset;
293  int mapindex = ob->actfmap - 1;
294 
295  if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
296  return OPERATOR_CANCELLED;
297  }
298 
299  cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
300 
301  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
302  map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
303 
304  if (BM_elem_flag_test(efa, BM_ELEM_SELECT) && *map == mapindex) {
305  *map = -1;
306  }
307  }
308 
312  }
313  return OPERATOR_FINISHED;
314 }
315 
317 {
318  /* identifiers */
319  ot->name = "Remove from Face Map";
320  ot->idname = "OBJECT_OT_face_map_remove_from";
321  ot->description = "Remove faces from a face map";
322 
323  /* api callbacks */
326 
327  /* flags */
329 }
330 
331 static void fmap_select(Object *ob, bool select)
332 {
333  Mesh *me = ob->data;
334  BMEditMesh *em = me->edit_mesh;
335  BMFace *efa;
336  BMIter iter;
337  int *map;
338  int cd_fmap_offset;
339  int mapindex = ob->actfmap - 1;
340 
341  if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP)) {
342  BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
343  }
344 
345  cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
346 
347  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
348  map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
349 
350  if (*map == mapindex) {
351  BM_face_select_set(em->bm, efa, select);
352  }
353  }
354 }
355 
357 {
358  Object *ob = ED_object_context(C);
359  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
360 
361  if (fmap) {
362  fmap_select(ob, true);
363 
367  }
368  return OPERATOR_FINISHED;
369 }
370 
372 {
373  /* identifiers */
374  ot->name = "Select Face Map Faces";
375  ot->idname = "OBJECT_OT_face_map_select";
376  ot->description = "Select faces belonging to a face map";
377 
378  /* api callbacks */
381 
382  /* flags */
384 }
385 
387 {
388  Object *ob = ED_object_context(C);
389  bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
390 
391  if (fmap) {
392  fmap_select(ob, false);
393 
397  }
398  return OPERATOR_FINISHED;
399 }
400 
402 {
403  /* identifiers */
404  ot->name = "Deselect Face Map Faces";
405  ot->idname = "OBJECT_OT_face_map_deselect";
406  ot->description = "Deselect faces belonging to a face map";
407 
408  /* api callbacks */
411 
412  /* flags */
414 }
415 
417 {
418  Object *ob = ED_object_context(C);
419  bFaceMap *fmap;
420  int dir = RNA_enum_get(op->ptr, "direction");
421 
422  fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
423  if (!fmap) {
424  return OPERATOR_CANCELLED;
425  }
426 
427  if (!fmap->prev && !fmap->next) {
428  return OPERATOR_CANCELLED;
429  }
430 
431  int pos1 = BLI_findindex(&ob->fmaps, fmap);
432  int pos2 = pos1 - dir;
433  int len = BLI_listbase_count(&ob->fmaps);
434  int *map = MEM_mallocN(len * sizeof(*map), __func__);
435 
436  if (!IN_RANGE(pos2, -1, len)) {
437  const int offset = len - dir;
438  for (int i = 0; i < len; i++) {
439  map[i] = (i + offset) % len;
440  }
441  pos2 = map[pos1];
442  }
443  else {
444  range_vn_i(map, len, 0);
445  SWAP(int, map[pos1], map[pos2]);
446  }
447 
448  void *prev = fmap->prev;
449  void *next = fmap->next;
450  BLI_remlink(&ob->fmaps, fmap);
451  if (dir == 1) { /*up*/
452  BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
453  }
454  else { /*down*/
455  BLI_insertlinkafter(&ob->fmaps, next, fmap);
456  }
457 
458  /* Iterate through mesh and substitute the indices as necessary. */
460  MEM_freeN(map);
461 
462  ob->actfmap = pos2 + 1;
463 
466 
467  return OPERATOR_FINISHED;
468 }
469 
471 {
472  static EnumPropertyItem fmap_slot_move[] = {
473  {1, "UP", 0, "Up", ""},
474  {-1, "DOWN", 0, "Down", ""},
475  {0, NULL, 0, NULL, NULL},
476  };
477 
478  /* identifiers */
479  ot->name = "Move Face Map";
480  ot->idname = "OBJECT_OT_face_map_move";
481  ot->description = "Move the active face map up/down in the list";
482 
483  /* api callbacks */
486 
487  /* flags */
489 
490  RNA_def_enum(
491  ot->srna, "direction", fmap_slot_move, 0, "Direction", "Direction to move, up or down");
492 }
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.cc:2776
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:301
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:100
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:340
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, int size, int start)
Definition: math_vector.c:1021
#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:791
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:566
#define ID_IS_OVERRIDE_LIBRARY(_id)
Definition: DNA_ID.h:588
@ ID_ME
Definition: DNA_ID_enums.h:48
@ 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:43
#define C
Definition: RandGen.cpp:25
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_GEOM
Definition: WM_types.h:343
#define ND_DRAW
Definition: WM_types.h:410
#define ND_DATA
Definition: WM_types.h:456
#define ND_VERTEX_GROUP
Definition: WM_types.h:457
#define NC_OBJECT
Definition: WM_types.h:329
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: avxb.h:154
@ BM_ELEM_SELECT
Definition: bmesh_class.h:471
#define BM_ELEM_CD_GET_VOID_P(ele, offset)
Definition: bmesh_class.h:541
#define BM_elem_flag_test(ele, hflag)
Definition: bmesh_inline.h:12
void BM_data_layer_add(BMesh *bm, CustomData *data, int type)
Definition: bmesh_interp.c:839
#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
int len
Definition: draw_manager.c:108
#define GS(x)
Definition: iris.c:225
ccl_gpu_kernel_postfix ccl_global float int int int int float bool int offset
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
static ulong * next
SymEdge< T > * prev(const SymEdge< T > *se)
Definition: delaunay_2d.cc:105
SocketIndexByIdentifierMap * map
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)
static bool face_map_supported_remove_poll(bContext *C)
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:5004
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:3783
struct BMesh * bm
Definition: BKE_editmesh.h:40
CustomData pdata
Definition: bmesh_class.h:337
Definition: DNA_ID.h:368
struct BMEditMesh * edit_mesh
CustomData pdata
int totpoly
unsigned short actfmap
void * data
ListBase fmaps
struct bFaceMap * next
struct bFaceMap * prev
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479