Blender  V3.3
object_facemap.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 "DNA_mesh_types.h"
11 #include "DNA_object_types.h"
12 
13 #include "BLI_listbase.h"
14 #include "BLI_string.h"
15 #include "BLI_string_utils.h"
16 #include "BLI_utildefines.h"
17 
18 #include "BKE_customdata.h"
19 #include "BKE_editmesh.h"
20 #include "BKE_object.h"
21 #include "BKE_object_deform.h"
22 #include "BKE_object_facemap.h" /* own include */
23 
24 #include "BLT_translation.h"
25 
26 #include "MEM_guardedalloc.h"
27 
28 #include "RNA_access.h"
29 #include "RNA_define.h"
30 
31 static bool fmap_unique_check(void *arg, const char *name)
32 {
33  struct {
34  Object *ob;
35  void *fm;
36  } *data = arg;
37 
38  bFaceMap *fmap;
39 
40  for (fmap = data->ob->fmaps.first; fmap; fmap = fmap->next) {
41  if (data->fm != fmap) {
42  if (STREQ(fmap->name, name)) {
43  return true;
44  }
45  }
46  }
47 
48  return false;
49 }
50 
52 {
53  bFaceMap *outfmap;
54 
55  if (!infmap) {
56  return NULL;
57  }
58 
59  outfmap = MEM_callocN(sizeof(bFaceMap), "copy facemap");
60 
61  /* For now, just copy everything over. */
62  memcpy(outfmap, infmap, sizeof(bFaceMap));
63 
64  outfmap->next = outfmap->prev = NULL;
65 
66  return outfmap;
67 }
68 
69 void BKE_object_facemap_copy_list(ListBase *outbase, const ListBase *inbase)
70 {
71  bFaceMap *fmap, *fmapn;
72 
73  BLI_listbase_clear(outbase);
74 
75  for (fmap = inbase->first; fmap; fmap = fmap->next) {
76  fmapn = fmap_duplicate(fmap);
77  BLI_addtail(outbase, fmapn);
78  }
79 }
80 
82 {
83  struct {
84  Object *ob;
85  void *fmap;
86  } data;
87  data.ob = ob;
88  data.fmap = fmap;
89 
90  BLI_uniquename_cb(fmap_unique_check, &data, DATA_("Group"), '.', fmap->name, sizeof(fmap->name));
91 }
92 
94 {
95  bFaceMap *fmap;
96 
97  if (!ob || ob->type != OB_MESH) {
98  return NULL;
99  }
100 
101  fmap = MEM_callocN(sizeof(bFaceMap), __func__);
102 
103  BLI_strncpy(fmap->name, name, sizeof(fmap->name));
104 
105  BLI_addtail(&ob->fmaps, fmap);
106 
107  ob->actfmap = BLI_listbase_count(&ob->fmaps);
108 
110 
111  return fmap;
112 }
113 
115 {
116  return BKE_object_facemap_add_name(ob, DATA_("FaceMap"));
117 }
118 
119 static void object_fmap_remove_edit_mode(Object *ob, bFaceMap *fmap, bool do_selected, bool purge)
120 {
121  const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
122 
123  if (ob->type == OB_MESH) {
124  Mesh *me = ob->data;
125 
126  if (me->edit_mesh) {
127  BMEditMesh *em = me->edit_mesh;
128  const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
129 
130  if (cd_fmap_offset != -1) {
131  BMFace *efa;
132  BMIter iter;
133  int *map;
134 
135  if (purge) {
136  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
137  map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
138 
139  if (map) {
140  if (*map == fmap_nr) {
141  *map = -1;
142  }
143  else if (*map > fmap_nr) {
144  *map -= 1;
145  }
146  }
147  }
148  }
149  else {
150  BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
151  map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
152 
153  if (map && *map == fmap_nr &&
154  (!do_selected || BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
155  *map = -1;
156  }
157  }
158  }
159  }
160 
161  if (ob->actfmap == BLI_listbase_count(&ob->fmaps)) {
162  ob->actfmap--;
163  }
164 
165  BLI_remlink(&ob->fmaps, fmap);
166  MEM_freeN(fmap);
167  }
168  }
169 }
170 
171 static void object_fmap_remove_object_mode(Object *ob, bFaceMap *fmap, bool purge)
172 {
173  const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
174 
175  if (ob->type == OB_MESH) {
176  Mesh *me = ob->data;
177 
180  int i;
181 
182  if (map) {
183  for (i = 0; i < me->totpoly; i++) {
184  if (map[i] == fmap_nr) {
185  map[i] = -1;
186  }
187  else if (purge && map[i] > fmap_nr) {
188  map[i]--;
189  }
190  }
191  }
192  }
193 
194  if (ob->actfmap == BLI_listbase_count(&ob->fmaps)) {
195  ob->actfmap--;
196  }
197 
198  BLI_remlink(&ob->fmaps, fmap);
199  MEM_freeN(fmap);
200  }
201 }
202 
203 static void fmap_remove_exec(Object *ob, bFaceMap *fmap, const bool is_edit_mode, const bool purge)
204 {
205  if (is_edit_mode) {
206  object_fmap_remove_edit_mode(ob, fmap, false, purge);
207  }
208  else {
209  object_fmap_remove_object_mode(ob, fmap, purge);
210  }
211 }
212 
214 {
215  fmap_remove_exec(ob, fmap, BKE_object_is_in_editmode(ob), true);
216 }
217 
219 {
220  bFaceMap *fmap = (bFaceMap *)ob->fmaps.first;
221 
222  if (fmap) {
223  const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
224 
225  while (fmap) {
226  bFaceMap *next_fmap = fmap->next;
227  fmap_remove_exec(ob, fmap, edit_mode, false);
228  fmap = next_fmap;
229  }
230  }
231  /* remove all face-maps */
232  if (ob->type == OB_MESH) {
233  Mesh *me = ob->data;
235  }
236  ob->actfmap = 0;
237 }
238 
239 int BKE_object_facemap_name_index(Object *ob, const char *name)
240 {
241  return (name) ? BLI_findstringindex(&ob->fmaps, name, offsetof(bFaceMap, name)) : -1;
242 }
243 
245 {
246  return BLI_findstring(&ob->fmaps, name, offsetof(bFaceMap, name));
247 }
248 
249 int *BKE_object_facemap_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
250 {
251  /* Build src to merged mapping of facemap indices. */
252  if (BLI_listbase_is_empty(&ob_src->fmaps) || BLI_listbase_is_empty(&ob_dst->fmaps)) {
253  *r_map_len = 0;
254  return NULL;
255  }
256 
257  *r_map_len = BLI_listbase_count(&ob_src->fmaps);
258  int *fmap_index_map = MEM_malloc_arrayN(
259  *r_map_len, sizeof(*fmap_index_map), "defgroup index map create");
260  bool is_fmap_remap_needed = false;
261 
262  int i = 0;
263  for (bFaceMap *fmap_src = ob_src->fmaps.first; fmap_src; fmap_src = fmap_src->next, i++) {
264  fmap_index_map[i] = BKE_object_facemap_name_index(ob_dst, fmap_src->name);
265  is_fmap_remap_needed = is_fmap_remap_needed || (fmap_index_map[i] != i);
266  }
267 
268  if (!is_fmap_remap_needed) {
269  MEM_freeN(fmap_index_map);
270  fmap_index_map = NULL;
271  *r_map_len = 0;
272  }
273 
274  return fmap_index_map;
275 }
276 
277 void BKE_object_facemap_index_map_apply(int *fmap, int fmap_len, const int *map, int map_len)
278 {
279  if (map == NULL || map_len == 0) {
280  return;
281  }
282  for (int i = 0; i < fmap_len; i++, fmap++) {
283  *fmap = (*fmap < map_len && *fmap != -1) ? map[*fmap] : -1;
284  }
285 }
CustomData interface, see also DNA_customdata_types.h.
bool CustomData_free_layer(struct CustomData *data, int type, int totelem, int index)
Definition: customdata.cc:2831
bool CustomData_has_layer(const struct CustomData *data, int type)
void * CustomData_get_layer(const struct CustomData *data, int type)
int CustomData_get_offset(const struct CustomData *data, int type)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode_vgroup(const struct Object *ob)
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.
BLI_INLINE bool BLI_listbase_is_empty(const struct ListBase *lb)
Definition: BLI_listbase.h:269
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
Definition: BLI_listbase.h:273
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
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)
int BLI_findstringindex(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findstring(const struct ListBase *listbase, const char *id, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
bool BLI_uniquename_cb(UniquenameCheckCallback unique_check, void *arg, const char *defname, char delim, char *name, size_t name_len)
Definition: string_utils.c:233
#define STREQ(a, b)
#define DATA_(msgid)
@ CD_FACEMAP
Object is a sort of wrapper for general info.
@ OB_MESH
Read Guarded memory(de)allocation.
@ 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
#define BM_ITER_MESH(ele, iter, bm, itype)
@ BM_FACES_OF_MESH
void *(* MEM_malloc_arrayN)(size_t len, size_t size, const char *str)
Definition: mallocn.c:34
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
SocketIndexByIdentifierMap * map
bFaceMap * BKE_object_facemap_add(Object *ob)
int BKE_object_facemap_name_index(Object *ob, const char *name)
void BKE_object_facemap_clear(Object *ob)
bFaceMap * BKE_object_facemap_find_name(Object *ob, const char *name)
bFaceMap * BKE_object_facemap_add_name(Object *ob, const char *name)
void BKE_object_facemap_copy_list(ListBase *outbase, const ListBase *inbase)
static bool fmap_unique_check(void *arg, const char *name)
void BKE_object_facemap_remove(Object *ob, bFaceMap *fmap)
static void fmap_remove_exec(Object *ob, bFaceMap *fmap, const bool is_edit_mode, const bool purge)
static void object_fmap_remove_object_mode(Object *ob, bFaceMap *fmap, bool purge)
void BKE_object_facemap_index_map_apply(int *fmap, int fmap_len, const int *map, int map_len)
int * BKE_object_facemap_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
static bFaceMap * fmap_duplicate(bFaceMap *infmap)
static void object_fmap_remove_edit_mode(Object *ob, bFaceMap *fmap, bool do_selected, bool purge)
void BKE_object_facemap_unique_name(Object *ob, bFaceMap *fmap)
struct BMesh * bm
Definition: BKE_editmesh.h:40
CustomData pdata
Definition: bmesh_class.h:337
void * first
Definition: DNA_listBase.h:31
struct BMEditMesh * edit_mesh
CustomData pdata
int totpoly
ustring name
Definition: graph/node.h:174
unsigned short actfmap
void * data
ListBase fmaps
struct bFaceMap * next
struct bFaceMap * prev
char name[64]