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>2018-04-16 17:27:55 +0300
committerCampbell Barton <ideasman42@gmail.com>2018-04-16 18:56:50 +0300
commitbfc9d426bb95e2bc0dd4541d6b4c5f802909149c (patch)
tree37702887bc3185309a13612613efd2752ebe0639 /source/blender/blenkernel
parent80bb4254c6fb638cee0d33868c81c76c104817bf (diff)
Multi-Object Editing
This adds initial multi-object editing support. - Selected objects are used when entering edit & pose modes. - Selection & tools work on all objects however many tools need porting See: T54641 for remaining tasks. Indentation will be done separately. See patch: D3101
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_layer.h111
-rw-r--r--source/blender/blenkernel/BKE_object.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/editmesh.c2
-rw-r--r--source/blender/blenkernel/intern/layer.c57
-rw-r--r--source/blender/blenkernel/intern/layer_utils.c125
-rw-r--r--source/blender/blenkernel/intern/object.c39
-rw-r--r--source/blender/blenkernel/intern/object_update.c8
8 files changed, 345 insertions, 0 deletions
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
index 9c06ae4f40d..75fb4962bef 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -187,10 +187,20 @@ void BKE_visible_objects_iterator_begin(BLI_Iterator *iter, void *data_in);
void BKE_visible_objects_iterator_next(BLI_Iterator *iter);
void BKE_visible_objects_iterator_end(BLI_Iterator *iter);
+struct ObjectsInModeIteratorData {
+ int object_mode;
+ struct ViewLayer *view_layer;
+ struct Base *base_active;
+};
+
void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in);
void BKE_renderable_objects_iterator_next(BLI_Iterator *iter);
void BKE_renderable_objects_iterator_end(BLI_Iterator *iter);
+void BKE_view_layer_objects_in_mode_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_view_layer_objects_in_mode_iterator_next(BLI_Iterator *iter);
+void BKE_view_layer_objects_in_mode_iterator_end(BLI_Iterator *iter);
+
void BKE_selected_bases_iterator_begin(BLI_Iterator *iter, void *data_in);
void BKE_selected_bases_iterator_next(BLI_Iterator *iter);
void BKE_selected_bases_iterator_end(BLI_Iterator *iter);
@@ -217,6 +227,43 @@ void BKE_visible_bases_iterator_end(BLI_Iterator *iter);
#define FOREACH_VISIBLE_OBJECT_END \
ITER_END
+
+#define FOREACH_BASE_IN_MODE_BEGIN(_view_layer, _object_mode, _instance) \
+{ \
+ struct ObjectsInModeIteratorData data_ = { \
+ .object_mode = _object_mode, \
+ .view_layer = _view_layer, \
+ .base_active = _view_layer->basact, \
+ }; \
+ ITER_BEGIN(BKE_view_layer_objects_in_mode_iterator_begin, \
+ BKE_view_layer_objects_in_mode_iterator_next, \
+ BKE_view_layer_objects_in_mode_iterator_end, \
+ &data_, Base *, _instance)
+
+#define FOREACH_BASE_IN_MODE_END \
+ ITER_END; \
+} ((void)0)
+
+#define FOREACH_BASE_IN_EDIT_MODE_BEGIN(_view_layer, _instance) \
+ FOREACH_BASE_IN_MODE_BEGIN(_view_layer, OB_MODE_EDIT, _instance)
+
+#define FOREACH_BASE_IN_EDIT_MODE_END \
+ FOREACH_BASE_IN_MODE_END
+
+#define FOREACH_OBJECT_IN_MODE_BEGIN(_view_layer, _object_mode, _instance) \
+ FOREACH_BASE_IN_MODE_BEGIN(_view_layer, _object_mode, _base) { \
+ Object *_instance = _base->object;
+
+#define FOREACH_OBJECT_IN_MODE_END \
+ } FOREACH_BASE_IN_MODE_END
+
+#define FOREACH_OBJECT_IN_EDIT_MODE_BEGIN(_view_layer, _instance) \
+ FOREACH_BASE_IN_EDIT_MODE_BEGIN(_view_layer, _base) { \
+ Object *_instance = _base->object;
+
+#define FOREACH_OBJECT_IN_EDIT_MODE_END \
+ } FOREACH_BASE_IN_EDIT_MODE_END
+
#define FOREACH_SELECTED_BASE_BEGIN(view_layer, _instance) \
ITER_BEGIN(BKE_selected_bases_iterator_begin, \
BKE_selected_bases_iterator_next, \
@@ -299,6 +346,70 @@ struct ObjectsRenderableIteratorData {
ITER_END; \
} ((void)0)
+
+/* layer_utils.c */
+
+struct ObjectsInModeParams {
+ int object_mode;
+ uint no_dup_data : 1;
+
+ bool (*filter_fn)(struct Object *ob, void *user_data);
+ void *filter_userdata;
+};
+
+Base **BKE_view_layer_array_from_bases_in_mode_params(
+ struct ViewLayer *view_layer, uint *r_len,
+ const struct ObjectsInModeParams *params);
+
+struct Object **BKE_view_layer_array_from_objects_in_mode_params(
+ struct ViewLayer *view_layer, uint *len,
+ const struct ObjectsInModeParams *params);
+
+#define BKE_view_layer_array_from_objects_in_mode(view_layer, r_len, ...) \
+ BKE_view_layer_array_from_objects_in_mode_params( \
+ view_layer, r_len, \
+ &(const struct ObjectsInModeParams)__VA_ARGS__)
+
+#define BKE_view_layer_array_from_bases_in_mode(view_layer, r_len, ...) \
+ BKE_view_layer_array_from_bases_in_mode_params( \
+ view_layer, r_len, \
+ &(const struct ObjectsInModeParams)__VA_ARGS__)
+
+bool BKE_view_layer_filter_edit_mesh_has_uvs(struct Object *ob, void *user_data);
+bool BKE_view_layer_filter_edit_mesh_has_edges(struct Object *ob, void *user_data);
+
+/* Utility macros that wrap common args (add more as needed). */
+
+#define BKE_view_layer_array_from_objects_in_edit_mode(view_layer, r_len) \
+ BKE_view_layer_array_from_objects_in_mode( \
+ view_layer, r_len, { \
+ .object_mode = OB_MODE_EDIT});
+
+#define BKE_view_layer_array_from_bases_in_edit_mode(view_layer, r_len) \
+ BKE_view_layer_array_from_bases_in_mode( \
+ view_layer, r_len, { \
+ .object_mode = OB_MODE_EDIT});
+
+#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, r_len) \
+ BKE_view_layer_array_from_objects_in_mode( \
+ view_layer, r_len, { \
+ .object_mode = OB_MODE_EDIT, \
+ .no_dup_data = true});
+
+#define BKE_view_layer_array_from_bases_in_edit_mode_unique_data(view_layer, r_len) \
+ BKE_view_layer_array_from_bases_in_mode( \
+ view_layer, r_len, { \
+ .object_mode = OB_MODE_EDIT, \
+ .no_dup_data = true});
+
+#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(view_layer, r_len) \
+ BKE_view_layer_array_from_objects_in_mode( \
+ view_layer, r_len, { \
+ .object_mode = OB_MODE_EDIT, \
+ .no_dup_data = true, \
+ .filter_fn = BKE_view_layer_filter_edit_mesh_has_uvs});
+
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index c698db2e8f5..c75bbf849a8 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -83,7 +83,9 @@ void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
bool BKE_object_exists_check(const struct Object *obtest);
bool BKE_object_is_in_editmode(const struct Object *ob);
bool BKE_object_is_in_editmode_vgroup(const struct Object *ob);
+bool BKE_object_is_in_editmode_and_selected(const struct Object *ob);
bool BKE_object_is_in_wpaint_select_vert(const struct Object *ob);
+bool BKE_object_has_mode_data(const struct Object *ob, eObjectMode object_mode);
typedef enum eObjectVisibilityCheck {
OB_VISIBILITY_CHECK_FOR_VIEWPORT,
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 6a1c3ea883c..e8fd71c2b2d 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -167,6 +167,7 @@ set(SRC
intern/pointcache.c
intern/property.c
intern/layer.c
+ intern/layer_utils.c
intern/lightprobe.c
intern/report.c
intern/rigidbody.c
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index c95da3b2569..b63ab276b14 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -89,11 +89,13 @@ BMEditMesh *BKE_editmesh_from_object(Object *ob)
{
BLI_assert(ob->type == OB_MESH);
/* sanity check */
+#if 0 /* disable in mutlti-object edit. */
#ifndef NDEBUG
if (((Mesh *)ob->data)->edit_btmesh) {
BLI_assert(((Mesh *)ob->data)->edit_btmesh->ob == ob);
}
#endif
+#endif
return ((Mesh *)ob->data)->edit_btmesh;
}
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index 50c7dc0c02f..5f24dd481e2 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -26,6 +26,7 @@
#include <string.h>
+#include "BLI_array.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
#include "BLI_string_utf8.h"
@@ -41,6 +42,7 @@
#include "BKE_main.h"
#include "BKE_node.h"
#include "BKE_workspace.h"
+#include "BKE_object.h"
#include "DEG_depsgraph.h"
@@ -2235,6 +2237,61 @@ void BKE_renderable_objects_iterator_end(BLI_Iterator *UNUSED(iter))
/* Do nothing - iter->data was static allocated, we can't free it. */
}
+/* -------------------------------------------------------------------- */
+/** \name BKE_view_layer_objects_in_mode_iterator
+ * \{ */
+
+void BKE_view_layer_objects_in_mode_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ struct ObjectsInModeIteratorData *data = data_in;
+ Base *base = data->base_active;
+
+ /* when there are no objects */
+ if (base == NULL) {
+ iter->valid = false;
+ return;
+ }
+ iter->data = data_in;
+ iter->current = base;
+}
+
+void BKE_view_layer_objects_in_mode_iterator_next(BLI_Iterator *iter)
+{
+ struct ObjectsInModeIteratorData *data = iter->data;
+ Base *base = iter->current;
+
+ if (base == data->base_active) {
+ /* first step */
+ base = data->view_layer->object_bases.first;
+ if (base == data->base_active) {
+ base = base->next;
+ }
+ }
+ else {
+ base = base->next;
+ }
+
+ while (base) {
+ if ((base->flag & BASE_SELECTED) != 0 &&
+ (base->object->type == data->base_active->object->type) &&
+ (base != data->base_active) &&
+ (base->object->mode & data->object_mode))
+ {
+ iter->current = base;
+ return;
+ }
+ base = base->next;
+ }
+ iter->valid = false;
+}
+
+void BKE_view_layer_objects_in_mode_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+/** \} */
+
/* Evaluation */
/**
diff --git a/source/blender/blenkernel/intern/layer_utils.c b/source/blender/blenkernel/intern/layer_utils.c
new file mode 100644
index 00000000000..94bac8a33d6
--- /dev/null
+++ b/source/blender/blenkernel/intern/layer_utils.c
@@ -0,0 +1,125 @@
+/*
+ * ***** 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.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/layer_utils.c
+ * \ingroup bke
+ */
+
+#include <string.h>
+
+#include "BLI_array.h"
+#include "BLI_listbase.h"
+
+#include "BKE_collection.h"
+#include "BKE_editmesh.h"
+#include "BKE_layer.h"
+
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+Base **BKE_view_layer_array_from_bases_in_mode_params(
+ ViewLayer *view_layer, uint *r_len,
+ const struct ObjectsInModeParams *params)
+{
+ if (params->no_dup_data) {
+ FOREACH_BASE_IN_MODE_BEGIN(view_layer, params->object_mode, base_iter) {
+ ID *id = base_iter->object->data;
+ if (id) {
+ id->tag |= LIB_TAG_DOIT;
+ }
+ } FOREACH_BASE_IN_MODE_END;
+ }
+
+ Base **base_array = NULL;
+ BLI_array_declare(base_array);
+
+ FOREACH_BASE_IN_MODE_BEGIN(view_layer, params->object_mode, base_iter) {
+ if (params->filter_fn) {
+ if (!params->filter_fn(base_iter->object, params->filter_userdata)) {
+ continue;
+ }
+ }
+ if (params->no_dup_data) {
+ ID *id = base_iter->object->data;
+ if (id) {
+ if (id->tag & LIB_TAG_DOIT) {
+ id->tag &= ~LIB_TAG_DOIT;
+ }
+ else {
+ continue;
+ }
+ }
+ }
+ BLI_array_append(base_array, base_iter);
+ } FOREACH_BASE_IN_MODE_END;
+
+ if (base_array != NULL) {
+ base_array = MEM_reallocN(base_array, sizeof(*base_array) * BLI_array_len(base_array));
+ }
+ *r_len = BLI_array_len(base_array);
+ return base_array;
+}
+
+Object **BKE_view_layer_array_from_objects_in_mode_params(
+ ViewLayer *view_layer, uint *r_len,
+ const struct ObjectsInModeParams *params)
+{
+ Base **base_array = BKE_view_layer_array_from_bases_in_mode_params(
+ view_layer, r_len, params);
+ if (base_array != NULL) {
+ for (uint i = 0; i < *r_len; i++) {
+ ((Object **)base_array)[i] = base_array[i]->object;
+ }
+ }
+ return (Object **)base_array;
+}
+
+bool BKE_view_layer_filter_edit_mesh_has_uvs(Object *ob, void *UNUSED(user_data))
+{
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ if (em != NULL) {
+ if (CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV) != -1) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool BKE_view_layer_filter_edit_mesh_has_edges(Object *ob, void *UNUSED(user_data))
+{
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ BMEditMesh *em = me->edit_btmesh;
+ if (em != NULL) {
+ if (em->bm->totedge != 0) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 875d716305f..081f9f15508 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -530,6 +530,15 @@ bool BKE_object_is_in_editmode(const Object *ob)
return false;
}
+bool BKE_object_is_in_editmode_and_selected(const Object *ob)
+{
+ if ((ob->flag & SELECT) && (BKE_object_is_in_editmode(ob))) {
+ return true;
+ }
+ return false;
+}
+
+
bool BKE_object_is_in_editmode_vgroup(const Object *ob)
{
return (OB_TYPE_SUPPORT_VGROUP(ob->type) &&
@@ -548,6 +557,36 @@ bool BKE_object_is_in_wpaint_select_vert(const Object *ob)
return false;
}
+bool BKE_object_has_mode_data(const struct Object *ob, eObjectMode object_mode)
+{
+ if (object_mode & OB_MODE_EDIT) {
+ if (BKE_object_is_in_editmode(ob)) {
+ return true;
+ }
+ }
+ else if (object_mode & OB_MODE_VERTEX_PAINT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) {
+ return true;
+ }
+ }
+ else if (object_mode & OB_MODE_WEIGHT_PAINT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) {
+ return true;
+ }
+ }
+ else if (object_mode & OB_MODE_SCULPT) {
+ if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) {
+ return true;
+ }
+ }
+ else if (object_mode & OB_MODE_POSE) {
+ if (ob->pose != NULL) {
+ return true;
+ }
+ }
+ return false;
+}
+
/**
* Return if the object is visible, as evaluated by depsgraph
*/
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index c70e07e6c4c..35ab4024f62 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -172,7 +172,15 @@ void BKE_object_handle_data_update(
switch (ob->type) {
case OB_MESH:
{
+#if 0
BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? BKE_editmesh_from_object(ob) : NULL;
+#else
+ BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? ((Mesh *)ob->data)->edit_btmesh : NULL;
+ if (em && em->ob != ob) {
+ em = NULL;
+ }
+#endif
+
uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH;
#ifdef WITH_FREESTYLE
/* make sure Freestyle edge/face marks appear in DM for render (see T40315) */