Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2017-05-30 10:58:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2017-05-30 11:05:59 +0300
commitd88845324430c4d5d98a828af5cef991f56bcb3f (patch)
tree0298db193281e9e1ebc16dd49054f509fb06ccdc /source/blender
parentd321ed62b8a5d0e9f82c2d7a3229b35a42c49e6d (diff)
Face Maps: custom-data, UI and RNA API
Add face maps, needed for face-map widgets, only data structure, widgets will be separate commit. This comes from 'custom-manipulator' branch with only minor changes.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_object_facemap.h53
-rw-r--r--source/blender/blenkernel/CMakeLists.txt2
-rw-r--r--source/blender/blenkernel/intern/object.c7
-rw-r--r--source/blender/blenkernel/intern/object_facemap.c259
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/blenloader/intern/writefile.c12
-rw-r--r--source/blender/editors/include/ED_mesh.h5
-rw-r--r--source/blender/editors/object/CMakeLists.txt1
-rw-r--r--source/blender/editors/object/object_facemap_ops.c493
-rw-r--r--source/blender/editors/object/object_intern.h9
-rw-r--r--source/blender/editors/object/object_ops.c8
-rw-r--r--source/blender/makesdna/DNA_customdata_types.h4
-rw-r--r--source/blender/makesdna/DNA_object_types.h13
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_object.c240
15 files changed, 1103 insertions, 5 deletions
diff --git a/source/blender/blenkernel/BKE_object_facemap.h b/source/blender/blenkernel/BKE_object_facemap.h
new file mode 100644
index 00000000000..332b2851e85
--- /dev/null
+++ b/source/blender/blenkernel/BKE_object_facemap.h
@@ -0,0 +1,53 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Antony Riakiotakis
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_OBJECT_FACEMAP_H__
+#define __BKE_OBJECT_FACEMAP_H__
+
+/** \file BKE_object_facemap.h
+ * \ingroup bke
+ * \brief Functions for dealing with object face-maps.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bFaceMap;
+struct ListBase;
+struct Object;
+
+struct bFaceMap *BKE_object_facemap_add(struct Object *ob);
+struct bFaceMap *BKE_object_facemap_add_name(struct Object *ob, const char *name);
+void BKE_object_facemap_remove(struct Object *ob, struct bFaceMap *fmap);
+void BKE_object_facemap_clear(struct Object *ob);
+
+int BKE_object_facemap_name_index(struct Object *ob, const char *name);
+void BKE_object_facemap_unique_name(struct Object *ob, struct bFaceMap *fmap);
+struct bFaceMap *BKE_object_facemap_find_name(struct Object *ob, const char *name);
+void BKE_object_facemap_copy_list(struct ListBase *outbase, struct ListBase *inbase);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_OBJECT_FACEMAP_H__ */
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 7af0b5d092a..1ddc6fce818 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -145,6 +145,7 @@ set(SRC
intern/nla.c
intern/node.c
intern/object.c
+ intern/object_facemap.c
intern/object_deform.c
intern/object_dupli.c
intern/object_update.c
@@ -271,6 +272,7 @@ set(SRC
BKE_nla.h
BKE_node.h
BKE_object.h
+ BKE_object_facemap.h
BKE_object_deform.h
BKE_ocean.h
BKE_outliner_treehash.h
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 8776e341b84..dd23b61f148 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -103,6 +103,7 @@
#include "BKE_multires.h"
#include "BKE_node.h"
#include "BKE_object.h"
+#include "BKE_object_facemap.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
@@ -422,6 +423,7 @@ void BKE_object_free(Object *ob)
MEM_SAFE_FREE(ob->bb);
BLI_freelistN(&ob->defbase);
+ BLI_freelistN(&ob->fmaps);
if (ob->pose) {
BKE_pose_free_ex(ob->pose, false);
ob->pose = NULL;
@@ -1151,6 +1153,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches)
BKE_pose_rebuild(obn, obn->data);
}
defgroup_copy_list(&obn->defbase, &ob->defbase);
+ BKE_object_facemap_copy_list(&obn->fmaps, &ob->fmaps);
BKE_constraints_copy(&obn->constraints, &ob->constraints, true);
obn->mode = OB_MODE_OBJECT;
@@ -1279,10 +1282,10 @@ static void armature_set_id_extern(Object *ob)
unsigned int lay = arm->layer_protected;
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- if (!(pchan->bone->layer & lay))
+ if (!(pchan->bone->layer & lay)) {
id_lib_extern((ID *)pchan->custom);
+ }
}
-
}
void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
diff --git a/source/blender/blenkernel/intern/object_facemap.c b/source/blender/blenkernel/intern/object_facemap.c
new file mode 100644
index 00000000000..02dedc10026
--- /dev/null
+++ b/source/blender/blenkernel/intern/object_facemap.c
@@ -0,0 +1,259 @@
+
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/object_facemap.c
+ * \ingroup bke
+ */
+
+#include <string.h>
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_editmesh.h"
+#include "BKE_object.h"
+#include "BKE_object_facemap.h" /* own include */
+#include "BKE_object_deform.h"
+
+#include "BKE_depsgraph.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
+#include "BLI_listbase.h"
+
+#include "BLT_translation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+static bool fmap_unique_check(void *arg, const char *name)
+{
+ struct {Object *ob; void *fm; } *data = arg;
+
+ bFaceMap *fmap;
+
+ for (fmap = data->ob->fmaps.first; fmap; fmap = fmap->next) {
+ if (data->fm != fmap) {
+ if (!strcmp(fmap->name, name)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static bFaceMap *fmap_duplicate(bFaceMap *infmap)
+{
+ bFaceMap *outfmap;
+
+ if (!infmap)
+ return NULL;
+
+ outfmap = MEM_callocN(sizeof(bFaceMap), "copy facemap");
+
+ /* For now, just copy everything over. */
+ memcpy(outfmap, infmap, sizeof(bFaceMap));
+
+ outfmap->next = outfmap->prev = NULL;
+
+ return outfmap;
+}
+
+void BKE_object_facemap_copy_list(ListBase *outbase, ListBase *inbase)
+{
+ bFaceMap *fmap, *fmapn;
+
+ BLI_listbase_clear(outbase);
+
+ for (fmap = inbase->first; fmap; fmap = fmap->next) {
+ fmapn = fmap_duplicate(fmap);
+ BLI_addtail(outbase, fmapn);
+ }
+}
+
+void BKE_object_facemap_unique_name(Object *ob, bFaceMap *fmap)
+{
+ struct {Object *ob; void *fmap; } data;
+ data.ob = ob;
+ data.fmap = fmap;
+
+ BLI_uniquename_cb(fmap_unique_check, &data, DATA_("Group"), '.', fmap->name, sizeof(fmap->name));
+}
+
+bFaceMap *BKE_object_facemap_add_name(Object *ob, const char *name)
+{
+ bFaceMap *fmap;
+
+ if (!ob || ob->type != OB_MESH)
+ return NULL;
+
+ fmap = MEM_callocN(sizeof(bFaceMap), __func__);
+
+ BLI_strncpy(fmap->name, name, sizeof(fmap->name));
+
+ BLI_addtail(&ob->fmaps, fmap);
+
+ ob->actfmap = BLI_listbase_count(&ob->fmaps);
+
+ BKE_object_facemap_unique_name(ob, fmap);
+
+ return fmap;
+}
+
+bFaceMap *BKE_object_facemap_add(Object *ob)
+{
+ return BKE_object_facemap_add_name(ob, DATA_("FaceMap"));
+}
+
+
+static void object_fmap_remove_edit_mode(Object *ob, bFaceMap *fmap, bool do_selected, bool purge)
+{
+ const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ if (cd_fmap_offset != -1) {
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+
+ if (purge) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (map) {
+ if (*map == fmap_nr)
+ *map = -1;
+ else if (*map > fmap_nr)
+ *map -= 1;
+ }
+ }
+ }
+ else {
+ 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 == fmap_nr && (!do_selected || BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
+ *map = -1;
+ }
+ }
+ }
+ }
+
+ if (ob->actfmap == BLI_listbase_count(&ob->fmaps))
+ ob->actfmap--;
+
+ BLI_remlink(&ob->fmaps, fmap);
+ MEM_freeN(fmap);
+ }
+ }
+}
+
+static void object_fmap_remove_object_mode(Object *ob, bFaceMap *fmap, bool purge)
+{
+ const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ int i;
+
+ if (map) {
+ for (i = 0; i < me->totpoly; i++) {
+ if (map[i] == fmap_nr)
+ map[i] = -1;
+ else if (purge && map[i] > fmap_nr)
+ map[i]--;
+ }
+ }
+ }
+
+ if (ob->actfmap == BLI_listbase_count(&ob->fmaps))
+ ob->actfmap--;
+
+ BLI_remlink(&ob->fmaps, fmap);
+ MEM_freeN(fmap);
+ }
+}
+
+static void fmap_remove_exec(Object *ob, bFaceMap *fmap, const bool is_edit_mode, const bool purge)
+{
+ if (is_edit_mode)
+ object_fmap_remove_edit_mode(ob, fmap, false, purge);
+ else
+ object_fmap_remove_object_mode(ob, fmap, purge);
+}
+
+void BKE_object_facemap_remove(Object *ob, bFaceMap *fmap)
+{
+ fmap_remove_exec(ob, fmap, BKE_object_is_in_editmode(ob), true);
+}
+
+void BKE_object_facemap_clear(Object *ob)
+{
+ bFaceMap *fmap = (bFaceMap *)ob->fmaps.first;
+
+ if (fmap) {
+ const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
+
+ while (fmap) {
+ bFaceMap *next_fmap = fmap->next;
+ fmap_remove_exec(ob, fmap, edit_mode, false);
+ fmap = next_fmap;
+ }
+ }
+ /* remove all face-maps */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ CustomData_free_layer(&me->pdata, CD_FACEMAP, me->totpoly, 0);
+ }
+ ob->actfmap = 0;
+}
+
+int BKE_object_facemap_name_index(Object *ob, const char *name)
+{
+ return (name) ? BLI_findstringindex(&ob->fmaps, name, offsetof(bFaceMap, name)) : -1;
+}
+
+bFaceMap *BKE_object_facemap_find_name(Object *ob, const char *name)
+{
+ return BLI_findstring(&ob->fmaps, name, offsetof(bFaceMap, name));
+}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index c387f4669dc..2b27148a3a8 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5392,6 +5392,7 @@ static void direct_link_object(FileData *fd, Object *ob)
direct_link_motionpath(fd, ob->mpath);
link_list(fd, &ob->defbase);
+ link_list(fd, &ob->fmaps);
// XXX deprecated - old animation system <<<
direct_link_nlastrips(fd, &ob->nlastrips);
link_list(fd, &ob->constraintChannels);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 12e5685df9d..19f6b9f370d 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1688,6 +1688,13 @@ static void write_defgroups(WriteData *wd, ListBase *defbase)
}
}
+static void write_fmaps(WriteData *wd, ListBase *fbase)
+{
+ for (bFaceMap *fmap = fbase->first; fmap; fmap = fmap->next) {
+ writestruct(wd, DATA, bFaceMap, 1, fmap);
+ }
+}
+
static void write_modifiers(WriteData *wd, ListBase *modbase)
{
ModifierData *md;
@@ -1891,6 +1898,7 @@ static void write_object(WriteData *wd, Object *ob)
write_pose(wd, ob->pose);
write_defgroups(wd, &ob->defbase);
+ write_fmaps(wd, &ob->fmaps);
write_constraints(wd, &ob->constraints);
write_motionpath(wd, ob->mpath);
@@ -2123,6 +2131,10 @@ static void write_customdata(
else if (layer->type == CD_GRID_PAINT_MASK) {
write_grid_paint_mask(wd, count, layer->data);
}
+ else if (layer->type == CD_FACEMAP) {
+ const int *layer_data = layer->data;
+ writedata(wd, DATA, sizeof(*layer_data) * count, layer_data);
+ }
else {
CustomData_file_write_info(layer->type, &structname, &structnum);
if (structnum) {
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index d069241defd..f9eae703bcc 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -39,6 +39,7 @@ struct ID;
struct View3D;
struct ARegion;
struct bContext;
+struct bFaceMap;
struct wmOperator;
struct wmKeyConfig;
struct ReportList;
@@ -260,6 +261,10 @@ float ED_vgroup_vert_weight(struct Object *ob, struct bDeformGrou
void ED_vgroup_vert_active_mirror(struct Object *ob, int def_nr);
+/* object_facemap_ops.c */
+void ED_object_facemap_face_add(struct Object *ob, struct bFaceMap *fmap, int facenum);
+void ED_object_facemap_face_remove(struct Object *ob, struct bFaceMap *fmap, int facenum);
+
/* mesh_data.c */
// void ED_mesh_geometry_add(struct Mesh *mesh, struct ReportList *reports, int verts, int edges, int faces);
void ED_mesh_polys_add(struct Mesh *mesh, struct ReportList *reports, int count);
diff --git a/source/blender/editors/object/CMakeLists.txt b/source/blender/editors/object/CMakeLists.txt
index 8a880e470c7..8050508983b 100644
--- a/source/blender/editors/object/CMakeLists.txt
+++ b/source/blender/editors/object/CMakeLists.txt
@@ -47,6 +47,7 @@ set(SRC
object_bake_api.c
object_constraint.c
object_edit.c
+ object_facemap_ops.c
object_group.c
object_hook.c
object_lattice.c
diff --git a/source/blender/editors/object/object_facemap_ops.c b/source/blender/editors/object/object_facemap_ops.c
new file mode 100644
index 00000000000..b8666fc7a65
--- /dev/null
+++ b/source/blender/editors/object/object_facemap_ops.c
@@ -0,0 +1,493 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * 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,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
+#include "WM_types.h"
+#include "WM_api.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_editmesh.h"
+#include "BKE_object.h"
+#include "BKE_object_facemap.h"
+#include "BKE_object_deform.h"
+
+#include "BKE_depsgraph.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_listbase.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "ED_mesh.h"
+#include "ED_object.h"
+
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+#include <string.h>
+
+#include "object_intern.h"
+
+/* called while not in editmode */
+void ED_object_facemap_face_add(Object *ob, bFaceMap *fmap, int facenum)
+{
+ int fmap_nr;
+ if (GS(((ID *)ob->data)->name) != ID_ME)
+ return;
+
+ /* get the face map number, exit if it can't be found */
+ fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+
+ if (fmap_nr != -1) {
+ int *facemap;
+ Mesh *me = ob->data;
+
+ /* if there's is no facemap layer then create one */
+ if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
+ facemap = CustomData_add_layer(&me->pdata, CD_FACEMAP, CD_DEFAULT, NULL, me->totpoly);
+
+ facemap[facenum] = fmap_nr;
+ }
+}
+
+/* called while not in editmode */
+void ED_object_facemap_face_remove(Object *ob, bFaceMap *fmap, int facenum)
+{
+ int fmap_nr;
+ if (GS(((ID *)ob->data)->name) != ID_ME)
+ return;
+
+ /* get the face map number, exit if it can't be found */
+ fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+
+ if (fmap_nr != -1) {
+ int *facemap;
+ Mesh *me = ob->data;
+
+ /* if there's is no facemap layer then create one */
+ if ((facemap = CustomData_get_layer(&me->pdata, CD_FACEMAP)) == NULL)
+ return;
+
+ facemap[facenum] = -1;
+ }
+}
+
+static void object_fmap_swap_edit_mode(Object *ob, int num1, int num2)
+{
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ 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) {
+ if (num1 != -1) {
+ if (*map == num1)
+ *map = num2;
+ else if (*map == num2)
+ *map = num1;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+static void object_fmap_swap_object_mode(Object *ob, int num1, int num2)
+{
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ int i;
+
+ if (map) {
+ for (i = 0; i < me->totpoly; i++) {
+ if (num1 != -1) {
+ if (map[i] == num1)
+ map[i] = num2;
+ else if (map[i]== num2)
+ map[i] = num1;
+ }
+ }
+ }
+ }
+ }
+}
+
+static void object_facemap_swap(Object *ob, int num1, int num2)
+{
+ if (BKE_object_is_in_editmode(ob))
+ object_fmap_swap_edit_mode(ob, num1, num2);
+ else
+ object_fmap_swap_object_mode(ob, num1, num2);
+}
+
+static int face_map_supported_poll(bContext *C)
+{
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib);
+}
+
+static int face_map_supported_edit_mode_poll(bContext *C)
+{
+ Object *ob = ED_object_context(C);
+ ID *data = (ob) ? ob->data : NULL;
+ return (ob && !ob->id.lib && ob->type == OB_MESH && data && !data->lib && ob->mode == OB_MODE_EDIT);
+}
+
+static int face_map_add_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+
+ BKE_object_facemap_add(ob);
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_add(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Add Face Map";
+ ot->idname = "OBJECT_OT_face_map_add";
+ ot->description = "Add a new face map to the active object";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_add_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int face_map_remove_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ BKE_object_facemap_remove(ob, fmap);
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_remove(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove Face Map";
+ ot->idname = "OBJECT_OT_face_map_remove";
+ ot->description = "Remove a face map from the active object";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_poll;
+ ot->exec = face_map_remove_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int face_map_assign_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ 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_btmesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
+
+ 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;
+ }
+ }
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_assign(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Assign Face Map";
+ ot->idname = "OBJECT_OT_face_map_assign";
+ ot->description = "Assign faces to a face map";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_assign_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int face_map_remove_from_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ 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_btmesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+ int mapindex = ob->actfmap - 1;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ return OPERATOR_CANCELLED;
+
+ 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;
+ }
+ }
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Remove From Face Map";
+ ot->idname = "OBJECT_OT_face_map_remove_from";
+ ot->description = "Remove faces from a face map";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_remove_from_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static void fmap_select(Object *ob, bool select)
+{
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+ int cd_fmap_offset;
+ int mapindex = ob->actfmap - 1;
+
+ if (!CustomData_has_layer(&em->bm->pdata, CD_FACEMAP))
+ BM_data_layer_add(em->bm, &em->bm->pdata, CD_FACEMAP);
+
+ 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);
+ }
+ }
+}
+
+static int face_map_select_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ fmap_select(ob, true);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_select(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Select Face Map Faces";
+ ot->idname = "OBJECT_OT_face_map_select";
+ ot->description = "Select faces belonging to a face map";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_select_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+static int face_map_deselect_exec(bContext *C, wmOperator *UNUSED(op))
+{
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+
+ if (fmap) {
+ fmap_select(ob, false);
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
+ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
+ }
+ return OPERATOR_FINISHED;
+}
+
+void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Deselect Face Map Faces";
+ ot->idname = "OBJECT_OT_face_map_deselect";
+ ot->description = "Deselect faces belonging to a face map";
+
+ /* api callbacks */
+ ot->poll = face_map_supported_edit_mode_poll;
+ ot->exec = face_map_deselect_exec;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+
+static int face_map_move_exec(bContext *C, wmOperator *op)
+{
+ Object *ob = ED_object_context(C);
+ bFaceMap *fmap;
+ int dir = RNA_enum_get(op->ptr, "direction");
+ int pos1, pos2 = -1, count;
+
+ fmap = BLI_findlink(&ob->fmaps, ob->actfmap - 1);
+ if (!fmap) {
+ return OPERATOR_CANCELLED;
+ }
+
+ count = BLI_listbase_count(&ob->fmaps);
+ pos1 = BLI_findindex(&ob->fmaps, fmap);
+
+ if (dir == 1) { /*up*/
+ void *prev = fmap->prev;
+
+ if (prev) {
+ pos2 = pos1 - 1;
+ }
+ else {
+ pos2 = count - 1;
+ }
+
+ BLI_remlink(&ob->fmaps, fmap);
+ BLI_insertlinkbefore(&ob->fmaps, prev, fmap);
+ }
+ else { /*down*/
+ void *next = fmap->next;
+
+ if (next) {
+ pos2 = pos1 + 1;
+ }
+ else {
+ pos2 = 0;
+ }
+
+ BLI_remlink(&ob->fmaps, fmap);
+ BLI_insertlinkafter(&ob->fmaps, next, fmap);
+ }
+
+ /* iterate through mesh and substitute the indices as necessary */
+ object_facemap_swap(ob, pos2, pos1);
+
+ ob->actfmap = pos2 + 1;
+
+ DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_GEOM | ND_VERTEX_GROUP, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+
+void OBJECT_OT_face_map_move(wmOperatorType *ot)
+{
+ 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");
+}
diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h
index 854ea9709f2..ed64f1c8ec1 100644
--- a/source/blender/editors/object/object_intern.h
+++ b/source/blender/editors/object/object_intern.h
@@ -242,6 +242,15 @@ void OBJECT_OT_vertex_weight_set_active(struct wmOperatorType *ot);
void OBJECT_OT_vertex_weight_normalize_active_vertex(struct wmOperatorType *ot);
void OBJECT_OT_vertex_weight_copy(struct wmOperatorType *ot);
+/* object_facemap_ops.c */
+void OBJECT_OT_face_map_add(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_remove(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_assign(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_remove_from(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_select(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_deselect(struct wmOperatorType *ot);
+void OBJECT_OT_face_map_move(struct wmOperatorType *ot);
+
/* object_warp.c */
void TRANSFORM_OT_vertex_warp(struct wmOperatorType *ot);
diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c
index 91950872a3d..5641f62ec7a 100644
--- a/source/blender/editors/object/object_ops.c
+++ b/source/blender/editors/object/object_ops.c
@@ -196,6 +196,14 @@ void ED_operatortypes_object(void)
WM_operatortype_append(OBJECT_OT_vertex_weight_normalize_active_vertex);
WM_operatortype_append(OBJECT_OT_vertex_weight_copy);
+ WM_operatortype_append(OBJECT_OT_face_map_add);
+ WM_operatortype_append(OBJECT_OT_face_map_remove);
+ WM_operatortype_append(OBJECT_OT_face_map_assign);
+ WM_operatortype_append(OBJECT_OT_face_map_remove_from);
+ WM_operatortype_append(OBJECT_OT_face_map_select);
+ WM_operatortype_append(OBJECT_OT_face_map_deselect);
+ WM_operatortype_append(OBJECT_OT_face_map_move);
+
WM_operatortype_append(TRANSFORM_OT_vertex_warp);
WM_operatortype_append(OBJECT_OT_game_property_new);
diff --git a/source/blender/makesdna/DNA_customdata_types.h b/source/blender/makesdna/DNA_customdata_types.h
index 0e8573c8d46..0e0b1d669d9 100644
--- a/source/blender/makesdna/DNA_customdata_types.h
+++ b/source/blender/makesdna/DNA_customdata_types.h
@@ -92,7 +92,7 @@ typedef enum CustomDataType {
CD_MCOL = 6,
CD_ORIGINDEX = 7,
CD_NORMAL = 8,
-/* CD_POLYINDEX = 9, */
+ CD_FACEMAP = 9, /* exclusive face group, each face can only be part of one */
CD_PROP_FLT = 10,
CD_PROP_INT = 11,
CD_PROP_STR = 12,
@@ -143,7 +143,7 @@ typedef enum CustomDataType {
#define CD_MASK_MCOL (1 << CD_MCOL)
#define CD_MASK_ORIGINDEX (1 << CD_ORIGINDEX)
#define CD_MASK_NORMAL (1 << CD_NORMAL)
-// #define CD_MASK_POLYINDEX (1 << CD_POLYINDEX)
+#define CD_MASK_FACEMAP (1 << CD_FACEMAP)
#define CD_MASK_PROP_FLT (1 << CD_PROP_FLT)
#define CD_MASK_PROP_INT (1 << CD_PROP_INT)
#define CD_MASK_PROP_STR (1 << CD_PROP_STR)
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 31fc1c0a5c0..ba42f403a30 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -65,6 +65,14 @@ typedef struct bDeformGroup {
/* need this flag for locking weights */
char flag, pad[7];
} bDeformGroup;
+
+/* Face Maps*/
+typedef struct bFaceMap {
+ struct bFaceMap *next, *prev;
+ char name[64]; /* MAX_VGROUP_NAME */
+} bFaceMap;
+
+
#define MAX_VGROUP_NAME 64
/* bDeformGroup->flag */
@@ -142,7 +150,8 @@ typedef struct Object {
ListBase effect DNA_DEPRECATED; // XXX deprecated... keep for readfile
ListBase defbase; /* list of bDeformGroup (vertex groups) names and flag only */
ListBase modifiers; /* list of ModifierData structures */
-
+ ListBase fmaps; /* list of facemaps */
+
int mode; /* Local object mode */
int restore_mode; /* Keep track of what mode to return to after toggling a mode */
@@ -251,6 +260,8 @@ typedef struct Object {
short index; /* custom index, for renderpasses */
unsigned short actdef; /* current deformation group, note: index starts at 1 */
+ unsigned short actfmap; /* current face map, note: index starts at 1 */
+ unsigned char pad5[6];
float col[4]; /* object color */
int gameflag;
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 7f919ef058a..127977c23bb 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -231,6 +231,7 @@ extern StructRNA RNA_EnvironmentMapTexture;
extern StructRNA RNA_Event;
extern StructRNA RNA_ExplodeModifier;
extern StructRNA RNA_ExpressionController;
+extern StructRNA RNA_FaceMap;
extern StructRNA RNA_FCurve;
extern StructRNA RNA_FCurveSample;
extern StructRNA RNA_FFmpegSettings;
diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c
index 7eb9c77d76a..8de706008ad 100644
--- a/source/blender/makesrna/intern/rna_object.c
+++ b/source/blender/makesrna/intern/rna_object.c
@@ -47,6 +47,7 @@
#include "BKE_editmesh.h"
#include "BKE_group.h" /* needed for BKE_group_object_exists() */
#include "BKE_object_deform.h"
+#include "BKE_object_facemap.h"
#include "RNA_access.h"
#include "RNA_define.h"
@@ -608,6 +609,87 @@ void rna_object_vgroup_name_set(PointerRNA *ptr, const char *value, char *result
result[0] = '\0';
}
+static void rna_FaceMap_name_set(PointerRNA *ptr, const char *value)
+{
+ Object *ob = (Object *)ptr->id.data;
+ bFaceMap *fmap = (bFaceMap *)ptr->data;
+ BLI_strncpy_utf8(fmap->name, value, sizeof(fmap->name));
+ BKE_object_facemap_unique_name(ob, fmap);
+}
+
+static int rna_FaceMap_index_get(PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->id.data;
+
+ return BLI_findindex(&ob->fmaps, ptr->data);
+}
+
+static PointerRNA rna_Object_active_face_map_get(PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->id.data;
+ return rna_pointer_inherit_refine(ptr, &RNA_FaceMap, BLI_findlink(&ob->fmaps, ob->actfmap - 1));
+}
+
+static int rna_Object_active_face_map_index_get(PointerRNA *ptr)
+{
+ Object *ob = (Object *)ptr->id.data;
+ return ob->actfmap - 1;
+}
+
+static void rna_Object_active_face_map_index_set(PointerRNA *ptr, int value)
+{
+ Object *ob = (Object *)ptr->id.data;
+ ob->actfmap = value + 1;
+}
+
+static void rna_Object_active_face_map_index_range(PointerRNA *ptr, int *min, int *max,
+ int *UNUSED(softmin), int *UNUSED(softmax))
+{
+ Object *ob = (Object *)ptr->id.data;
+
+ *min = 0;
+ *max = max_ii(0, BLI_listbase_count(&ob->fmaps) - 1);
+}
+
+void rna_object_BKE_object_facemap_name_index_get(PointerRNA *ptr, char *value, int index)
+{
+ Object *ob = (Object *)ptr->id.data;
+ bFaceMap *fmap;
+
+ fmap = BLI_findlink(&ob->fmaps, index - 1);
+
+ if (fmap) BLI_strncpy(value, fmap->name, sizeof(fmap->name));
+ else value[0] = '\0';
+}
+
+int rna_object_BKE_object_facemap_name_index_length(PointerRNA *ptr, int index)
+{
+ Object *ob = (Object *)ptr->id.data;
+ bFaceMap *fmap;
+
+ fmap = BLI_findlink(&ob->fmaps, index - 1);
+ return (fmap) ? strlen(fmap->name) : 0;
+}
+
+void rna_object_BKE_object_facemap_name_index_set(PointerRNA *ptr, const char *value, short *index)
+{
+ Object *ob = (Object *)ptr->id.data;
+ *index = BKE_object_facemap_name_index(ob, value) + 1;
+}
+
+void rna_object_fmap_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen)
+{
+ Object *ob = (Object *)ptr->id.data;
+ bFaceMap *fmap = BKE_object_facemap_find_name(ob, value);
+ if (fmap) {
+ BLI_strncpy(result, value, maxlen); /* no need for BLI_strncpy_utf8, since this matches an existing group */
+ return;
+ }
+
+ result[0] = '\0';
+}
+
+
void rna_object_uvlayer_name_set(PointerRNA *ptr, const char *value, char *result, int maxlen)
{
Object *ob = (Object *)ptr->id.data;
@@ -1452,6 +1534,69 @@ static float rna_VertexGroup_weight(ID *id, bDeformGroup *dg, ReportList *report
return weight;
}
+static bFaceMap *rna_Object_fmap_new(Object *ob, const char *name)
+{
+ bFaceMap *fmap = BKE_object_facemap_add_name(ob, name);
+
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+
+ return fmap;
+}
+
+static void rna_Object_fmap_remove(Object *ob, ReportList *reports, PointerRNA *fmap_ptr)
+{
+ bFaceMap *fmap = fmap_ptr->data;
+ if (BLI_findindex(&ob->fmaps, fmap) == -1) {
+ BKE_reportf(reports, RPT_ERROR, "FaceMap '%s' not in object '%s'", fmap->name, ob->id.name + 2);
+ return;
+ }
+
+ BKE_object_facemap_remove(ob, fmap);
+ RNA_POINTER_INVALIDATE(fmap_ptr);
+
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+}
+
+
+static void rna_Object_fmap_clear(Object *ob)
+{
+ BKE_object_facemap_clear(ob);
+
+ WM_main_add_notifier(NC_OBJECT | ND_DRAW, ob);
+}
+
+
+static void rna_FaceMap_face_add(ID *id, bFaceMap *fmap, ReportList *reports, int index_len,
+ int *index)
+{
+ Object *ob = (Object *)id;
+
+ if (BKE_object_is_in_editmode(ob)) {
+ BKE_report(reports, RPT_ERROR, "FaceMap.add(): cannot be called while object is in edit mode");
+ return;
+ }
+
+ while (index_len--)
+ ED_object_facemap_face_add(ob, fmap, *index++);
+
+ WM_main_add_notifier(NC_GEOM | ND_DATA, (ID *)ob->data);
+}
+
+static void rna_FaceMap_face_remove(ID *id, bFaceMap *fmap, ReportList *reports, int index_len, int *index)
+{
+ Object *ob = (Object *)id;
+
+ if (BKE_object_is_in_editmode(ob)) {
+ BKE_report(reports, RPT_ERROR, "FaceMap.add(): cannot be called while object is in edit mode");
+ return;
+ }
+
+ while (index_len--)
+ ED_object_facemap_face_remove(ob, fmap, *index++);
+
+ WM_main_add_notifier(NC_GEOM | ND_DATA, (ID *)ob->data);
+}
+
/* generic poll functions */
int rna_Lattice_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value)
{
@@ -1571,6 +1716,44 @@ static void rna_def_vertex_group(BlenderRNA *brna)
RNA_def_function_return(func, parm);
}
+static void rna_def_face_map(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ FunctionRNA *func;
+
+ srna = RNA_def_struct(brna, "FaceMap", NULL);
+ RNA_def_struct_sdna(srna, "bFaceMap");
+ RNA_def_struct_ui_text(srna, "Face Map", "Group of faces, each face can only be part of one map");
+ RNA_def_struct_ui_icon(srna, ICON_MOD_TRIANGULATE);
+
+ prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Face map name");
+ RNA_def_struct_name_property(srna, prop);
+ RNA_def_property_string_funcs(prop, NULL, NULL, "rna_FaceMap_name_set");
+ /* update data because modifiers may use [#24761] */
+ RNA_def_property_update(prop, NC_GEOM | ND_DATA | NA_RENAME, "rna_Object_internal_update_data");
+
+ prop = RNA_def_property(srna, "index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_property_int_funcs(prop, "rna_FaceMap_index_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Index", "Index number of the face map");
+
+ func = RNA_def_function(srna, "add", "rna_FaceMap_face_add");
+ RNA_def_function_ui_description(func, "Add vertices to the group");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
+ /* TODO, see how array size of 0 works, this shouldnt be used */
+ prop = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "Index List", 0, 0);
+ RNA_def_parameter_flags(prop, PROP_DYNAMIC, PARM_REQUIRED);
+
+ func = RNA_def_function(srna, "remove", "rna_FaceMap_face_remove");
+ RNA_def_function_ui_description(func, "Remove a vertex from the group");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_SELF_ID);
+ /* TODO, see how array size of 0 works, this shouldnt be used */
+ prop = RNA_def_int_array(func, "index", 1, NULL, 0, 0, "", "Index List", 0, 0);
+ RNA_def_parameter_flags(prop, PROP_DYNAMIC, PARM_REQUIRED);
+}
+
static void rna_def_material_slot(BlenderRNA *brna)
{
StructRNA *srna;
@@ -2098,6 +2281,54 @@ static void rna_def_object_vertex_groups(BlenderRNA *brna, PropertyRNA *cprop)
RNA_def_function_ui_description(func, "Delete all vertex groups from object");
}
+/* object.face_maps */
+static void rna_def_object_face_maps(BlenderRNA *brna, PropertyRNA *cprop)
+{
+ StructRNA *srna;
+
+ PropertyRNA *prop;
+
+ FunctionRNA *func;
+ PropertyRNA *parm;
+
+ RNA_def_property_srna(cprop, "FaceMaps");
+ srna = RNA_def_struct(brna, "FaceMaps", NULL);
+ RNA_def_struct_sdna(srna, "Object");
+ RNA_def_struct_ui_text(srna, "Face Maps", "Collection of face maps");
+
+ prop = RNA_def_property(srna, "active", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "FaceMap");
+ RNA_def_property_pointer_funcs(prop, "rna_Object_active_face_map_get",
+ "rna_Object_active_face_map_set", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Active Face Map", "Face maps of the object");
+ RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Object_internal_update_data");
+
+ prop = RNA_def_property(srna, "active_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
+ RNA_def_property_int_sdna(prop, NULL, "actfmap");
+ RNA_def_property_int_funcs(prop, "rna_Object_active_face_map_index_get",
+ "rna_Object_active_face_map_index_set",
+ "rna_Object_active_face_map_index_range");
+ RNA_def_property_ui_text(prop, "Active Face Map Index", "Active index in face map array");
+ RNA_def_property_update(prop, NC_GEOM | ND_DATA, "rna_Object_internal_update_data");
+
+ /* face maps */ /* add_face_map */
+ func = RNA_def_function(srna, "new", "rna_Object_fmap_new");
+ RNA_def_function_ui_description(func, "Add face map to object");
+ RNA_def_string(func, "name", "Map", 0, "", "face map name"); /* optional */
+ parm = RNA_def_pointer(func, "fmap", "FaceMap", "", "New face map");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "remove", "rna_Object_fmap_remove");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ RNA_def_function_ui_description(func, "Delete vertex group from object");
+ parm = RNA_def_pointer(func, "group", "FaceMap", "", "Face map to remove");
+ RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_REQUIRED | PARM_RNAPTR);
+ RNA_def_property_clear_flag(parm, PROP_THICK_WRAP);
+
+ func = RNA_def_function(srna, "clear", "rna_Object_fmap_clear");
+ RNA_def_function_ui_description(func, "Delete all vertex groups from object");
+}
static void rna_def_object_lodlevel(BlenderRNA *brna)
{
@@ -2515,6 +2746,14 @@ static void rna_def_object(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertex Groups", "Vertex groups of the object");
rna_def_object_vertex_groups(brna, prop);
+
+ /* face maps */
+ prop = RNA_def_property(srna, "face_maps", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "fmaps", NULL);
+ RNA_def_property_struct_type(prop, "FaceMap");
+ RNA_def_property_ui_text(prop, "Face Maps", "Maps of faces of the object");
+ rna_def_object_face_maps(brna, prop);
+
/* empty */
prop = RNA_def_property(srna, "empty_draw_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "empty_drawtype");
@@ -2935,6 +3174,7 @@ void RNA_def_object(BlenderRNA *brna)
rna_def_object_game_settings(brna);
rna_def_object_base_legacy(brna);
rna_def_vertex_group(brna);
+ rna_def_face_map(brna);
rna_def_material_slot(brna);
rna_def_dupli_object(brna);
RNA_define_animate_sdna(true);