Compare commits
45 Commits
refactor-m
...
temp-objec
Author | SHA1 | Date | |
---|---|---|---|
69f366eff0 | |||
dbccbc63de | |||
917edd5e1e | |||
bee47fe7d5 | |||
aa93d417fc | |||
f0a3aa88c8 | |||
4f392784e6 | |||
f0083fc1d2 | |||
bbcbbf7212 | |||
fbccb08c28 | |||
05617a068e | |||
fcff5f80f9 | |||
3703483d03 | |||
99b8c0fe5d | |||
d7c0421493 | |||
8a410572c2 | |||
269e4e9b81 | |||
8a20cd92a9 | |||
![]() |
e5e686a667 | ||
cf8028e4a9 | |||
7ed100f13f | |||
4aab63d23e | |||
37573632f0 | |||
0ae714f082 | |||
5855d4051f | |||
e9173a0389 | |||
f9cdf4e20d | |||
1f94830d6e | |||
e7b4e4a94a | |||
b91185d6af | |||
e426838798 | |||
ad58a423ea | |||
b45a464794 | |||
c73d408ed8 | |||
![]() |
cb3fb8b259 | ||
b31a3ffc25 | |||
fc2974b06d | |||
04e76696f9 | |||
acfc5f7820 | |||
d897d52659 | |||
8651ddeb0e | |||
d25fea66e2 | |||
d67d85771f | |||
7ba6684f3e | |||
cb49e77eb1 |
@@ -188,10 +188,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_next(BLI_Iterator *iter);
|
||||||
void BKE_visible_objects_iterator_end(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_begin(BLI_Iterator *iter, void *data_in);
|
||||||
void BKE_renderable_objects_iterator_next(BLI_Iterator *iter);
|
void BKE_renderable_objects_iterator_next(BLI_Iterator *iter);
|
||||||
void BKE_renderable_objects_iterator_end(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_begin(BLI_Iterator *iter, void *data_in);
|
||||||
void BKE_selected_bases_iterator_next(BLI_Iterator *iter);
|
void BKE_selected_bases_iterator_next(BLI_Iterator *iter);
|
||||||
void BKE_selected_bases_iterator_end(BLI_Iterator *iter);
|
void BKE_selected_bases_iterator_end(BLI_Iterator *iter);
|
||||||
@@ -218,6 +228,43 @@ void BKE_visible_bases_iterator_end(BLI_Iterator *iter);
|
|||||||
#define FOREACH_VISIBLE_OBJECT_END \
|
#define FOREACH_VISIBLE_OBJECT_END \
|
||||||
ITER_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) \
|
#define FOREACH_SELECTED_BASE_BEGIN(view_layer, _instance) \
|
||||||
ITER_BEGIN(BKE_selected_bases_iterator_begin, \
|
ITER_BEGIN(BKE_selected_bases_iterator_begin, \
|
||||||
BKE_selected_bases_iterator_next, \
|
BKE_selected_bases_iterator_next, \
|
||||||
@@ -300,6 +347,44 @@ struct ObjectsRenderableIteratorData {
|
|||||||
ITER_END; \
|
ITER_END; \
|
||||||
} ((void)0)
|
} ((void)0)
|
||||||
|
|
||||||
|
|
||||||
|
/* layer_utils.c */
|
||||||
|
|
||||||
|
struct ObjectsInModeParams {
|
||||||
|
int object_mode;
|
||||||
|
uint no_dupe_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_edit_mode(view_layer, r_len, ...) \
|
||||||
|
BKE_view_layer_array_from_bases_in_mode_params( \
|
||||||
|
view_layer, r_len, \
|
||||||
|
&(const struct ObjectsInModeParams){ .object_mode = OB_MODE_EDIT, __VA_ARGS__})
|
||||||
|
|
||||||
|
#define BKE_view_layer_array_from_objects_in_edit_mode(view_layer, r_len, ...) \
|
||||||
|
BKE_view_layer_array_from_objects_in_mode_params( \
|
||||||
|
view_layer, r_len, \
|
||||||
|
&(const struct ObjectsInModeParams){ .object_mode = OB_MODE_EDIT, __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);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -81,9 +81,11 @@ void BKE_object_make_proxy(struct Object *ob, struct Object *target, struct Obje
|
|||||||
void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
|
void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
|
||||||
|
|
||||||
bool BKE_object_exists_check(struct Object *obtest);
|
bool BKE_object_exists_check(struct Object *obtest);
|
||||||
bool BKE_object_is_in_editmode(struct Object *ob);
|
bool BKE_object_is_in_editmode(const struct Object *ob);
|
||||||
bool BKE_object_is_in_editmode_vgroup(struct Object *ob);
|
bool BKE_object_is_in_editmode_vgroup(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_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 {
|
typedef enum eObjectVisibilityCheck {
|
||||||
OB_VISIBILITY_CHECK_FOR_VIEWPORT,
|
OB_VISIBILITY_CHECK_FOR_VIEWPORT,
|
||||||
|
@@ -167,6 +167,7 @@ set(SRC
|
|||||||
intern/pointcache.c
|
intern/pointcache.c
|
||||||
intern/property.c
|
intern/property.c
|
||||||
intern/layer.c
|
intern/layer.c
|
||||||
|
intern/layer_utils.c
|
||||||
intern/lightprobe.c
|
intern/lightprobe.c
|
||||||
intern/report.c
|
intern/report.c
|
||||||
intern/rigidbody.c
|
intern/rigidbody.c
|
||||||
|
@@ -89,15 +89,16 @@ BMEditMesh *BKE_editmesh_from_object(Object *ob)
|
|||||||
{
|
{
|
||||||
BLI_assert(ob->type == OB_MESH);
|
BLI_assert(ob->type == OB_MESH);
|
||||||
/* sanity check */
|
/* sanity check */
|
||||||
|
#if 0 /* disable in mutlti-object edit. */
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
if (((Mesh *)ob->data)->edit_btmesh) {
|
if (((Mesh *)ob->data)->edit_btmesh) {
|
||||||
BLI_assert(((Mesh *)ob->data)->edit_btmesh->ob == ob);
|
BLI_assert(((Mesh *)ob->data)->edit_btmesh->ob == ob);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
return ((Mesh *)ob->data)->edit_btmesh;
|
return ((Mesh *)ob->data)->edit_btmesh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void editmesh_tessface_calc_intern(BMEditMesh *em)
|
static void editmesh_tessface_calc_intern(BMEditMesh *em)
|
||||||
{
|
{
|
||||||
/* allocating space before calculating the tessellation */
|
/* allocating space before calculating the tessellation */
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "BLI_array.h"
|
||||||
#include "BLI_listbase.h"
|
#include "BLI_listbase.h"
|
||||||
#include "BLI_string.h"
|
#include "BLI_string.h"
|
||||||
#include "BLI_string_utf8.h"
|
#include "BLI_string_utf8.h"
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
#include "BKE_main.h"
|
#include "BKE_main.h"
|
||||||
#include "BKE_node.h"
|
#include "BKE_node.h"
|
||||||
#include "BKE_workspace.h"
|
#include "BKE_workspace.h"
|
||||||
|
#include "BKE_object.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
|
|
||||||
@@ -2231,6 +2233,59 @@ void BKE_renderable_objects_iterator_end(BLI_Iterator *UNUSED(iter))
|
|||||||
/* Do nothing - iter->data was static allocated, we can't free it. */
|
/* Do nothing - iter->data was static allocated, we can't free it. */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --- */
|
||||||
|
|
||||||
|
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) &&
|
||||||
|
(BKE_object_has_mode_data(base->object, data->object_mode) == true))
|
||||||
|
{
|
||||||
|
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 */
|
/* Evaluation */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
125
source/blender/blenkernel/intern/layer_utils.c
Normal file
125
source/blender/blenkernel/intern/layer_utils.c
Normal file
@@ -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_dupe_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_dupe_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;
|
||||||
|
}
|
@@ -487,7 +487,7 @@ void BKE_object_free(Object *ob)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* actual check for internal data, not context or flags */
|
/* actual check for internal data, not context or flags */
|
||||||
bool BKE_object_is_in_editmode(Object *ob)
|
bool BKE_object_is_in_editmode(const Object *ob)
|
||||||
{
|
{
|
||||||
if (ob->data == NULL)
|
if (ob->data == NULL)
|
||||||
return false;
|
return false;
|
||||||
@@ -530,6 +530,15 @@ bool BKE_object_is_in_editmode(Object *ob)
|
|||||||
return false;
|
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(Object *ob)
|
bool BKE_object_is_in_editmode_vgroup(Object *ob)
|
||||||
{
|
{
|
||||||
return (OB_TYPE_SUPPORT_VGROUP(ob->type) &&
|
return (OB_TYPE_SUPPORT_VGROUP(ob->type) &&
|
||||||
@@ -548,6 +557,31 @@ bool BKE_object_is_in_wpaint_select_vert(const Object *ob)
|
|||||||
return false;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return if the object is visible, as evaluated by depsgraph
|
* Return if the object is visible, as evaluated by depsgraph
|
||||||
*/
|
*/
|
||||||
|
@@ -172,7 +172,15 @@ void BKE_object_handle_data_update(
|
|||||||
switch (ob->type) {
|
switch (ob->type) {
|
||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
{
|
{
|
||||||
|
#if 0
|
||||||
BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? BKE_editmesh_from_object(ob) : NULL;
|
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;
|
uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH;
|
||||||
#ifdef WITH_FREESTYLE
|
#ifdef WITH_FREESTYLE
|
||||||
/* make sure Freestyle edge/face marks appear in DM for render (see T40315) */
|
/* make sure Freestyle edge/face marks appear in DM for render (see T40315) */
|
||||||
|
@@ -1160,7 +1160,7 @@ void bmesh_edit_end(BMesh *bm, BMOpTypeFlag type_flag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
|
void BM_mesh_elem_index_ensure_ex(BMesh *bm, const char htype, int elem_offset[4])
|
||||||
{
|
{
|
||||||
const char htype_needed = bm->elem_index_dirty & htype;
|
const char htype_needed = bm->elem_index_dirty & htype;
|
||||||
|
|
||||||
@@ -1173,15 +1173,15 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (htype & BM_VERT) {
|
if (htype & BM_VERT) {
|
||||||
if (bm->elem_index_dirty & BM_VERT) {
|
if ((bm->elem_index_dirty & BM_VERT) || (elem_offset && elem_offset[0])) {
|
||||||
BMIter iter;
|
BMIter iter;
|
||||||
BMElem *ele;
|
BMElem *ele;
|
||||||
|
|
||||||
int index;
|
int index = elem_offset ? elem_offset[0] : 0;
|
||||||
BM_ITER_MESH_INDEX (ele, &iter, bm, BM_VERTS_OF_MESH, index) {
|
BM_ITER_MESH (ele, &iter, bm, BM_VERTS_OF_MESH) {
|
||||||
BM_elem_index_set(ele, index); /* set_ok */
|
BM_elem_index_set(ele, index++); /* set_ok */
|
||||||
}
|
}
|
||||||
BLI_assert(index == bm->totvert);
|
BLI_assert(elem_offset || index == bm->totvert);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// printf("%s: skipping vert index calc!\n", __func__);
|
// printf("%s: skipping vert index calc!\n", __func__);
|
||||||
@@ -1189,15 +1189,15 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (htype & BM_EDGE) {
|
if (htype & BM_EDGE) {
|
||||||
if (bm->elem_index_dirty & BM_EDGE) {
|
if ((bm->elem_index_dirty & BM_EDGE) || (elem_offset && elem_offset[1])) {
|
||||||
BMIter iter;
|
BMIter iter;
|
||||||
BMElem *ele;
|
BMElem *ele;
|
||||||
|
|
||||||
int index;
|
int index = elem_offset ? elem_offset[1] : 0;
|
||||||
BM_ITER_MESH_INDEX (ele, &iter, bm, BM_EDGES_OF_MESH, index) {
|
BM_ITER_MESH (ele, &iter, bm, BM_EDGES_OF_MESH) {
|
||||||
BM_elem_index_set(ele, index); /* set_ok */
|
BM_elem_index_set(ele, index++); /* set_ok */
|
||||||
}
|
}
|
||||||
BLI_assert(index == bm->totedge);
|
BLI_assert(elem_offset || index == bm->totedge);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// printf("%s: skipping edge index calc!\n", __func__);
|
// printf("%s: skipping edge index calc!\n", __func__);
|
||||||
@@ -1205,19 +1205,19 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (htype & (BM_FACE | BM_LOOP)) {
|
if (htype & (BM_FACE | BM_LOOP)) {
|
||||||
if (bm->elem_index_dirty & (BM_FACE | BM_LOOP)) {
|
if ((bm->elem_index_dirty & (BM_FACE | BM_LOOP)) || (elem_offset && (elem_offset[2] || elem_offset[3]))) {
|
||||||
BMIter iter;
|
BMIter iter;
|
||||||
BMElem *ele;
|
BMElem *ele;
|
||||||
|
|
||||||
const bool update_face = (htype & BM_FACE) && (bm->elem_index_dirty & BM_FACE);
|
const bool update_face = (htype & BM_FACE) && (bm->elem_index_dirty & BM_FACE);
|
||||||
const bool update_loop = (htype & BM_LOOP) && (bm->elem_index_dirty & BM_LOOP);
|
const bool update_loop = (htype & BM_LOOP) && (bm->elem_index_dirty & BM_LOOP);
|
||||||
|
|
||||||
int index;
|
int index_loop = elem_offset ? elem_offset[2] : 0;
|
||||||
int index_loop = 0;
|
int index = elem_offset ? elem_offset[3] : 0;
|
||||||
|
|
||||||
BM_ITER_MESH_INDEX (ele, &iter, bm, BM_FACES_OF_MESH, index) {
|
BM_ITER_MESH (ele, &iter, bm, BM_FACES_OF_MESH) {
|
||||||
if (update_face) {
|
if (update_face) {
|
||||||
BM_elem_index_set(ele, index); /* set_ok */
|
BM_elem_index_set(ele, index++); /* set_ok */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (update_loop) {
|
if (update_loop) {
|
||||||
@@ -1230,9 +1230,9 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BLI_assert(index == bm->totface);
|
BLI_assert(elem_offset || !update_face || index == bm->totface);
|
||||||
if (update_loop) {
|
if (update_loop) {
|
||||||
BLI_assert(index_loop == bm->totloop);
|
BLI_assert(elem_offset || !update_loop || index_loop == bm->totloop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1242,6 +1242,37 @@ void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
|
|||||||
|
|
||||||
finally:
|
finally:
|
||||||
bm->elem_index_dirty &= ~htype;
|
bm->elem_index_dirty &= ~htype;
|
||||||
|
if (elem_offset) {
|
||||||
|
if (htype & BM_VERT) {
|
||||||
|
elem_offset[0] += bm->totvert;
|
||||||
|
if (elem_offset[0] != bm->totvert) {
|
||||||
|
bm->elem_index_dirty |= BM_VERT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (htype & BM_EDGE) {
|
||||||
|
elem_offset[1] += bm->totedge;
|
||||||
|
if (elem_offset[1] != bm->totedge) {
|
||||||
|
bm->elem_index_dirty |= BM_EDGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (htype & BM_LOOP) {
|
||||||
|
elem_offset[2] += bm->totloop;
|
||||||
|
if (elem_offset[2] != bm->totloop) {
|
||||||
|
bm->elem_index_dirty |= BM_LOOP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (htype & BM_FACE) {
|
||||||
|
elem_offset[3] += bm->totface;
|
||||||
|
if (elem_offset[3] != bm->totface) {
|
||||||
|
bm->elem_index_dirty |= BM_FACE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BM_mesh_elem_index_ensure(BMesh *bm, const char htype)
|
||||||
|
{
|
||||||
|
BM_mesh_elem_index_ensure_ex(bm, htype, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -60,7 +60,9 @@ void BM_edges_sharp_from_angle_set(BMesh *bm, const float split_angle);
|
|||||||
void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag);
|
void bmesh_edit_begin(BMesh *bm, const BMOpTypeFlag type_flag);
|
||||||
void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag);
|
void bmesh_edit_end(BMesh *bm, const BMOpTypeFlag type_flag);
|
||||||
|
|
||||||
|
void BM_mesh_elem_index_ensure_ex(BMesh *bm, const char htype, int elem_offset[4]);
|
||||||
void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag);
|
void BM_mesh_elem_index_ensure(BMesh *bm, const char hflag);
|
||||||
|
|
||||||
void BM_mesh_elem_index_validate(
|
void BM_mesh_elem_index_validate(
|
||||||
BMesh *bm, const char *location, const char *func,
|
BMesh *bm, const char *location, const char *func,
|
||||||
const char *msg_a, const char *msg_b);
|
const char *msg_a, const char *msg_b);
|
||||||
|
@@ -37,6 +37,8 @@
|
|||||||
|
|
||||||
#include "edit_mesh_mode_intern.h" /* own include */
|
#include "edit_mesh_mode_intern.h" /* own include */
|
||||||
|
|
||||||
|
#include "BKE_object.h"
|
||||||
|
|
||||||
extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
|
extern struct GPUUniformBuffer *globals_ubo; /* draw_common.c */
|
||||||
extern struct GlobalsUboStorage ts; /* draw_common.c */
|
extern struct GlobalsUboStorage ts; /* draw_common.c */
|
||||||
|
|
||||||
@@ -448,7 +450,13 @@ static void EDIT_MESH_cache_populate(void *vedata, Object *ob)
|
|||||||
struct Gwn_Batch *geom;
|
struct Gwn_Batch *geom;
|
||||||
|
|
||||||
if (ob->type == OB_MESH) {
|
if (ob->type == OB_MESH) {
|
||||||
if (ob == draw_ctx->object_edit) {
|
#if 0
|
||||||
|
if (ob == draw_ctx->object_edit)
|
||||||
|
#else
|
||||||
|
if ((ob == draw_ctx->object_edit) ||
|
||||||
|
((ob->type == OB_MESH) && BKE_object_is_in_editmode_and_selected(ob)))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
const Mesh *me = ob->data;
|
const Mesh *me = ob->data;
|
||||||
IDProperty *ces_mode_ed = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_EDIT, "");
|
IDProperty *ces_mode_ed = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_EDIT, "");
|
||||||
bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire");
|
bool do_occlude_wire = BKE_collection_engine_property_value_get_bool(ces_mode_ed, "show_occlude_wire");
|
||||||
|
@@ -340,6 +340,9 @@ struct MDeformVert *ED_mesh_active_dvert_get_em(struct Object *ob, struct BMVert
|
|||||||
struct MDeformVert *ED_mesh_active_dvert_get_ob(struct Object *ob, int *r_index);
|
struct MDeformVert *ED_mesh_active_dvert_get_ob(struct Object *ob, int *r_index);
|
||||||
struct MDeformVert *ED_mesh_active_dvert_get_only(struct Object *ob);
|
struct MDeformVert *ED_mesh_active_dvert_get_only(struct Object *ob);
|
||||||
|
|
||||||
|
void EDBM_mesh_stats_multi(struct Object **objects, const uint objects_len, int totelem[3], int totelem_sel[3]);
|
||||||
|
void EDBM_mesh_elem_index_ensure_multi(struct Object **objects, const uint objects_len, const char htype);
|
||||||
|
|
||||||
#define ED_MESH_PICK_DEFAULT_VERT_SIZE 50
|
#define ED_MESH_PICK_DEFAULT_VERT_SIZE 50
|
||||||
#define ED_MESH_PICK_DEFAULT_FACE_SIZE 3
|
#define ED_MESH_PICK_DEFAULT_FACE_SIZE 3
|
||||||
|
|
||||||
|
@@ -124,9 +124,12 @@ void ED_object_parent(struct Object *ob, struct Object *parent, const int type,
|
|||||||
#define EM_WAITCURSOR 4
|
#define EM_WAITCURSOR 4
|
||||||
#define EM_DO_UNDO 8
|
#define EM_DO_UNDO 8
|
||||||
#define EM_IGNORE_LAYER 16
|
#define EM_IGNORE_LAYER 16
|
||||||
|
#define EM_NO_CONTEXT 32
|
||||||
void ED_object_editmode_exit_ex(
|
void ED_object_editmode_exit_ex(
|
||||||
struct bContext *C, struct Scene *scene, struct Object *obedit, int flag);
|
struct bContext *C, struct Scene *scene, struct Object *obedit, int flag);
|
||||||
void ED_object_editmode_exit(struct bContext *C, int flag);
|
void ED_object_editmode_exit(struct bContext *C, int flag);
|
||||||
|
|
||||||
|
void ED_object_editmode_enter_ex(struct Scene *scene, struct Object *ob, int flag);
|
||||||
void ED_object_editmode_enter(struct bContext *C, int flag);
|
void ED_object_editmode_enter(struct bContext *C, int flag);
|
||||||
bool ED_object_editmode_load(struct Object *obedit);
|
bool ED_object_editmode_load(struct Object *obedit);
|
||||||
|
|
||||||
|
@@ -118,18 +118,21 @@ void ED_uvedit_live_unwrap_re_solve(void);
|
|||||||
void ED_uvedit_live_unwrap_end(short cancel);
|
void ED_uvedit_live_unwrap_end(short cancel);
|
||||||
|
|
||||||
void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit);
|
void ED_uvedit_live_unwrap(struct Scene *scene, struct Object *obedit);
|
||||||
void ED_uvedit_pack_islands(
|
void ED_uvedit_pack_islands_single(
|
||||||
struct Scene *scene, struct Object *ob, struct BMesh *bm, bool selected, bool correct_aspect, bool do_rotate);
|
struct Scene *scene, struct Object *ob, struct BMesh *bm, bool selected, bool correct_aspect, bool do_rotate);
|
||||||
|
void ED_uvedit_pack_islands_multi(
|
||||||
|
struct Scene *scene, struct Object **objects, const uint objects_len,
|
||||||
|
bool selected, bool correct_aspect, bool do_rotate);
|
||||||
void ED_uvedit_unwrap_cube_project(
|
void ED_uvedit_unwrap_cube_project(
|
||||||
struct BMesh *bm, float cube_size, bool use_select, const float center[3]);
|
struct BMesh *bm, float cube_size, bool use_select, const float center[3]);
|
||||||
|
|
||||||
/* single call up unwrap using scene settings, used for edge tag unwrapping */
|
/* single call up unwrap using scene settings, used for edge tag unwrapping */
|
||||||
void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel);
|
void ED_unwrap_lscm(struct Scene *scene, struct Object *obedit, const short sel, const bool pack);
|
||||||
|
|
||||||
|
|
||||||
/* uvedit_draw.c */
|
/* uvedit_draw.c */
|
||||||
void ED_image_draw_cursor(
|
void ED_image_draw_cursor(
|
||||||
struct ARegion *ar, const float cursor[2]);
|
struct ARegion *ar, const float cursor[2]);
|
||||||
void ED_uvedit_draw_main(
|
void ED_uvedit_draw_main(
|
||||||
struct SpaceImage *sima,
|
struct SpaceImage *sima,
|
||||||
struct ARegion *ar, struct Scene *scene, struct ViewLayer *view_layer,
|
struct ARegion *ar, struct Scene *scene, struct ViewLayer *view_layer,
|
||||||
|
@@ -352,6 +352,7 @@ int view3d_opengl_select(
|
|||||||
/* view3d_select.c */
|
/* view3d_select.c */
|
||||||
float ED_view3d_select_dist_px(void);
|
float ED_view3d_select_dist_px(void);
|
||||||
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc);
|
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc);
|
||||||
|
void ED_view3d_viewcontext_init_object(struct ViewContext *vc, struct Object *obact);
|
||||||
void view3d_operator_needs_opengl(const struct bContext *C);
|
void view3d_operator_needs_opengl(const struct bContext *C);
|
||||||
void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *ar);
|
void view3d_region_operator_needs_opengl(struct wmWindow *win, struct ARegion *ar);
|
||||||
void view3d_opengl_read_pixels(struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data);
|
void view3d_opengl_read_pixels(struct ARegion *ar, int x, int y, int w, int h, int format, int type, void *data);
|
||||||
|
@@ -45,6 +45,7 @@
|
|||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
#include "BKE_paint.h"
|
#include "BKE_paint.h"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
|
#include "BKE_layer.h"
|
||||||
|
|
||||||
#include "IMB_imbuf_types.h"
|
#include "IMB_imbuf_types.h"
|
||||||
#include "IMB_imbuf.h"
|
#include "IMB_imbuf.h"
|
||||||
@@ -917,7 +918,7 @@ BMFace *EDBM_face_find_nearest(const struct EvaluationContext *eval_ctx, ViewCon
|
|||||||
*/
|
*/
|
||||||
static int unified_findnearest(
|
static int unified_findnearest(
|
||||||
const struct EvaluationContext *eval_ctx, ViewContext *vc,
|
const struct EvaluationContext *eval_ctx, ViewContext *vc,
|
||||||
BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
|
Base **r_base, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
|
||||||
{
|
{
|
||||||
BMEditMesh *em = vc->em;
|
BMEditMesh *em = vc->em;
|
||||||
static short mval_prev[2] = {-1, -1};
|
static short mval_prev[2] = {-1, -1};
|
||||||
@@ -934,32 +935,69 @@ static int unified_findnearest(
|
|||||||
BMEdge *eed = NULL;
|
BMEdge *eed = NULL;
|
||||||
BMFace *efa = NULL;
|
BMFace *efa = NULL;
|
||||||
|
|
||||||
|
uint bases_len = 0;
|
||||||
|
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode(
|
||||||
|
eval_ctx->view_layer, &bases_len);
|
||||||
|
|
||||||
/* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
|
/* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
|
||||||
ED_view3d_backbuf_validate(eval_ctx, vc);
|
|
||||||
|
|
||||||
if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
|
if ((dist > 0.0f) && em->selectmode & SCE_SELECT_FACE) {
|
||||||
float dist_center = 0.0f;
|
float dist_center = 0.0f;
|
||||||
float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL;
|
float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ? &dist_center : NULL;
|
||||||
efa = EDBM_face_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
|
|
||||||
if (efa && dist_center_p) {
|
for (uint base_index = 0; base_index < bases_len; base_index++) {
|
||||||
dist = min_ff(dist_margin, dist_center);
|
Base *base_iter = bases[base_index];
|
||||||
}
|
Object *obedit = base_iter->object;
|
||||||
|
ED_view3d_viewcontext_init_object(vc, obedit);
|
||||||
|
ED_view3d_backbuf_validate(eval_ctx, vc);
|
||||||
|
|
||||||
|
BMFace *efa_test = EDBM_face_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
|
||||||
|
if (efa && dist_center_p) {
|
||||||
|
dist = min_ff(dist_margin, dist_center);
|
||||||
|
}
|
||||||
|
if (efa_test) {
|
||||||
|
*r_base = base_iter;
|
||||||
|
efa = efa_test;
|
||||||
|
}
|
||||||
|
} /* bases */
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
|
if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_EDGE)) {
|
||||||
float dist_center = 0.0f;
|
float dist_center = 0.0f;
|
||||||
float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
|
float *dist_center_p = (em->selectmode & SCE_SELECT_VERTEX) ? &dist_center : NULL;
|
||||||
eed = EDBM_edge_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
|
|
||||||
if (eed && dist_center_p) {
|
for (uint base_index = 0; base_index < bases_len; base_index++) {
|
||||||
dist = min_ff(dist_margin, dist_center);
|
Base *base_iter = bases[base_index];
|
||||||
}
|
Object *obedit = base_iter->object;
|
||||||
|
ED_view3d_viewcontext_init_object(vc, obedit);
|
||||||
|
ED_view3d_backbuf_validate(eval_ctx, vc);
|
||||||
|
BMEdge *eed_test = EDBM_edge_find_nearest_ex(eval_ctx, vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
|
||||||
|
if (eed && dist_center_p) {
|
||||||
|
dist = min_ff(dist_margin, dist_center);
|
||||||
|
}
|
||||||
|
if (eed_test) {
|
||||||
|
*r_base = base_iter;
|
||||||
|
eed = eed_test;
|
||||||
|
}
|
||||||
|
} /* bases */
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
|
if ((dist > 0.0f) && em->selectmode & SCE_SELECT_VERTEX) {
|
||||||
eve = EDBM_vert_find_nearest_ex(eval_ctx, vc, &dist, true, use_cycle);
|
for (uint base_index = 0; base_index < bases_len; base_index++) {
|
||||||
|
Base *base_iter = bases[base_index];
|
||||||
|
Object *obedit = base_iter->object;
|
||||||
|
ED_view3d_viewcontext_init_object(vc, obedit);
|
||||||
|
ED_view3d_backbuf_validate(eval_ctx, vc);
|
||||||
|
BMVert *eve_test = EDBM_vert_find_nearest_ex(eval_ctx, vc, &dist, true, use_cycle);
|
||||||
|
if (eve_test) {
|
||||||
|
*r_base = base_iter;
|
||||||
|
eve = eve_test;
|
||||||
|
}
|
||||||
|
} /* bases */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(bases);
|
||||||
|
|
||||||
/* return only one of 3 pointers, for frontbuffer redraws */
|
/* return only one of 3 pointers, for frontbuffer redraws */
|
||||||
if (eve) {
|
if (eve) {
|
||||||
efa = NULL; eed = NULL;
|
efa = NULL; eed = NULL;
|
||||||
@@ -1804,27 +1842,45 @@ void MESH_OT_edgering_select(wmOperatorType *ot)
|
|||||||
|
|
||||||
static int edbm_select_all_exec(bContext *C, wmOperator *op)
|
static int edbm_select_all_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
int action = RNA_enum_get(op->ptr, "action");
|
||||||
const int action = RNA_enum_get(op->ptr, "action");
|
|
||||||
|
|
||||||
switch (action) {
|
uint objects_len = 0;
|
||||||
case SEL_TOGGLE:
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
EDBM_select_toggle_all(em);
|
view_layer, &objects_len,
|
||||||
break;
|
.no_dupe_data = true);
|
||||||
case SEL_SELECT:
|
|
||||||
EDBM_flag_enable_all(em, BM_ELEM_SELECT);
|
if (action == SEL_TOGGLE) {
|
||||||
break;
|
action = SEL_SELECT;
|
||||||
case SEL_DESELECT:
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
|
Object *obedit = objects[ob_index];
|
||||||
break;
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
case SEL_INVERT:
|
if (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel) {
|
||||||
EDBM_select_swap(em);
|
action = SEL_DESELECT;
|
||||||
EDBM_selectmode_flush(em);
|
break;
|
||||||
break;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
switch (action) {
|
||||||
|
case SEL_SELECT:
|
||||||
|
EDBM_flag_enable_all(em, BM_ELEM_SELECT);
|
||||||
|
break;
|
||||||
|
case SEL_DESELECT:
|
||||||
|
EDBM_flag_disable_all(em, BM_ELEM_SELECT);
|
||||||
|
break;
|
||||||
|
case SEL_INVERT:
|
||||||
|
EDBM_select_swap(em);
|
||||||
|
EDBM_selectmode_flush(em);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
@@ -1896,6 +1952,8 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
|
|||||||
{
|
{
|
||||||
EvaluationContext eval_ctx;
|
EvaluationContext eval_ctx;
|
||||||
ViewContext vc;
|
ViewContext vc;
|
||||||
|
|
||||||
|
Base *basact = NULL;
|
||||||
BMVert *eve = NULL;
|
BMVert *eve = NULL;
|
||||||
BMEdge *eed = NULL;
|
BMEdge *eed = NULL;
|
||||||
BMFace *efa = NULL;
|
BMFace *efa = NULL;
|
||||||
@@ -1906,11 +1964,24 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
|
|||||||
vc.mval[0] = mval[0];
|
vc.mval[0] = mval[0];
|
||||||
vc.mval[1] = mval[1];
|
vc.mval[1] = mval[1];
|
||||||
|
|
||||||
if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa)) {
|
if (unified_findnearest(&eval_ctx, &vc, &basact, &eve, &eed, &efa)) {
|
||||||
|
ED_view3d_viewcontext_init_object(&vc, basact->object);
|
||||||
|
|
||||||
/* Deselect everything */
|
/* Deselect everything */
|
||||||
if (extend == false && deselect == false && toggle == false)
|
if (extend == false && deselect == false && toggle == false) {
|
||||||
EDBM_flag_disable_all(vc.em, BM_ELEM_SELECT);
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
eval_ctx.view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *ob_iter = objects[ob_index];
|
||||||
|
EDBM_flag_disable_all(BKE_editmesh_from_object(ob_iter), BM_ELEM_SELECT);
|
||||||
|
if (basact->object != ob_iter) {
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (efa) {
|
if (efa) {
|
||||||
if (extend) {
|
if (extend) {
|
||||||
@@ -2020,6 +2091,13 @@ bool EDBM_select_pick(bContext *C, const int mval[2], bool extend, bool deselect
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Changing active object is handy since it allows us to
|
||||||
|
* switch UV layers, vgroups for eg.
|
||||||
|
*
|
||||||
|
* XXX(MULTI_EDIT): Edit-mesh undo currently wont track these changes,
|
||||||
|
* we might need special handling for this case. */
|
||||||
|
eval_ctx.view_layer->basact = basact;
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -2242,11 +2320,14 @@ bool EDBM_selectmode_toggle(
|
|||||||
bContext *C, const short selectmode_new,
|
bContext *C, const short selectmode_new,
|
||||||
const int action, const bool use_extend, const bool use_expand)
|
const int action, const bool use_extend, const bool use_expand)
|
||||||
{
|
{
|
||||||
|
EvaluationContext eval_ctx;
|
||||||
ToolSettings *ts = CTX_data_tool_settings(C);
|
ToolSettings *ts = CTX_data_tool_settings(C);
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
Object *obedit = CTX_data_edit_object(C);
|
||||||
BMEditMesh *em = NULL;
|
BMEditMesh *em = NULL;
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
|
CTX_data_eval_ctx(C, &eval_ctx);
|
||||||
|
|
||||||
if (obedit && obedit->type == OB_MESH) {
|
if (obedit && obedit->type == OB_MESH) {
|
||||||
em = BKE_editmesh_from_object(obedit);
|
em = BKE_editmesh_from_object(obedit);
|
||||||
}
|
}
|
||||||
@@ -2255,6 +2336,7 @@ bool EDBM_selectmode_toggle(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool only_update = false;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case -1:
|
case -1:
|
||||||
/* already set */
|
/* already set */
|
||||||
@@ -2262,21 +2344,24 @@ bool EDBM_selectmode_toggle(
|
|||||||
case 0: /* disable */
|
case 0: /* disable */
|
||||||
/* check we have something to do */
|
/* check we have something to do */
|
||||||
if ((em->selectmode & selectmode_new) == 0) {
|
if ((em->selectmode & selectmode_new) == 0) {
|
||||||
return false;
|
only_update = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
em->selectmode &= ~selectmode_new;
|
em->selectmode &= ~selectmode_new;
|
||||||
break;
|
break;
|
||||||
case 1: /* enable */
|
case 1: /* enable */
|
||||||
/* check we have something to do */
|
/* check we have something to do */
|
||||||
if ((em->selectmode & selectmode_new) != 0) {
|
if ((em->selectmode & selectmode_new) != 0) {
|
||||||
return false;
|
only_update = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
em->selectmode |= selectmode_new;
|
em->selectmode |= selectmode_new;
|
||||||
break;
|
break;
|
||||||
case 2: /* toggle */
|
case 2: /* toggle */
|
||||||
/* can't disable this flag if its the only one set */
|
/* can't disable this flag if its the only one set */
|
||||||
if (em->selectmode == selectmode_new) {
|
if (em->selectmode == selectmode_new) {
|
||||||
return false;
|
only_update = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
em->selectmode ^= selectmode_new;
|
em->selectmode ^= selectmode_new;
|
||||||
break;
|
break;
|
||||||
@@ -2285,10 +2370,32 @@ bool EDBM_selectmode_toggle(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
eval_ctx.view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *ob_iter = objects[ob_index];
|
||||||
|
BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
|
||||||
|
if (em_iter != em) {
|
||||||
|
em_iter->selectmode = em->selectmode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (only_update) {
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (use_extend == 0 || em->selectmode == 0) {
|
if (use_extend == 0 || em->selectmode == 0) {
|
||||||
if (use_expand) {
|
if (use_expand) {
|
||||||
const short selmode_max = highest_order_bit_s(ts->selectmode);
|
const short selmode_max = highest_order_bit_s(ts->selectmode);
|
||||||
EDBM_selectmode_convert(em, selmode_max, selectmode_new);
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *ob_iter = objects[ob_index];
|
||||||
|
BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
|
||||||
|
EDBM_selectmode_convert(em_iter, selmode_max, selectmode_new);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2297,24 +2404,18 @@ bool EDBM_selectmode_toggle(
|
|||||||
if (use_extend == 0 || em->selectmode == 0) {
|
if (use_extend == 0 || em->selectmode == 0) {
|
||||||
em->selectmode = SCE_SELECT_VERTEX;
|
em->selectmode = SCE_SELECT_VERTEX;
|
||||||
}
|
}
|
||||||
ts->selectmode = em->selectmode;
|
|
||||||
EDBM_selectmode_set(em);
|
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
case SCE_SELECT_EDGE:
|
case SCE_SELECT_EDGE:
|
||||||
if (use_extend == 0 || em->selectmode == 0) {
|
if (use_extend == 0 || em->selectmode == 0) {
|
||||||
em->selectmode = SCE_SELECT_EDGE;
|
em->selectmode = SCE_SELECT_EDGE;
|
||||||
}
|
}
|
||||||
ts->selectmode = em->selectmode;
|
|
||||||
EDBM_selectmode_set(em);
|
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
case SCE_SELECT_FACE:
|
case SCE_SELECT_FACE:
|
||||||
if (use_extend == 0 || em->selectmode == 0) {
|
if (use_extend == 0 || em->selectmode == 0) {
|
||||||
em->selectmode = SCE_SELECT_FACE;
|
em->selectmode = SCE_SELECT_FACE;
|
||||||
}
|
}
|
||||||
ts->selectmode = em->selectmode;
|
|
||||||
EDBM_selectmode_set(em);
|
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -2323,10 +2424,18 @@ bool EDBM_selectmode_toggle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ret == true) {
|
if (ret == true) {
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
ts->selectmode = em->selectmode;
|
||||||
|
em = NULL;
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *ob_iter = objects[ob_index];
|
||||||
|
BMEditMesh *em_iter = BKE_editmesh_from_object(ob_iter);
|
||||||
|
EDBM_selectmode_set(em_iter);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob_iter->data);
|
||||||
|
}
|
||||||
WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
|
WM_main_add_notifier(NC_SCENE | ND_TOOLSETTINGS, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2528,7 +2637,7 @@ static bool select_linked_delimit_test(
|
|||||||
* Gets the default from the operator fallback to own last-used value
|
* Gets the default from the operator fallback to own last-used value
|
||||||
* (selected based on mode)
|
* (selected based on mode)
|
||||||
*/
|
*/
|
||||||
static int select_linked_delimit_default_from_op(wmOperator *op, int select_mode)
|
static int select_linked_delimit_default_from_op(wmOperator *op, const int select_mode)
|
||||||
{
|
{
|
||||||
static char delimit_last_store[2] = {0, BMO_DELIM_SEAM};
|
static char delimit_last_store[2] = {0, BMO_DELIM_SEAM};
|
||||||
int delimit_last_index = (select_mode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0;
|
int delimit_last_index = (select_mode & (SCE_SELECT_VERTEX | SCE_SELECT_EDGE)) == 0;
|
||||||
@@ -2594,17 +2703,29 @@ static void select_linked_delimit_end(BMEditMesh *em)
|
|||||||
|
|
||||||
static int edbm_select_linked_exec(bContext *C, wmOperator *op)
|
static int edbm_select_linked_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
|
|
||||||
|
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
|
||||||
|
const int delimit_init = select_linked_delimit_default_from_op(op, scene->toolsettings->selectmode);
|
||||||
|
#else
|
||||||
|
const int delimit_init = RNA_enum_get(op->ptr, "delimit");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
BMesh *bm = em->bm;
|
BMesh *bm = em->bm;
|
||||||
BMIter iter;
|
BMIter iter;
|
||||||
BMWalker walker;
|
BMWalker walker;
|
||||||
|
|
||||||
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
|
int delimit = delimit_init;
|
||||||
int delimit = select_linked_delimit_default_from_op(op, em->selectmode);
|
|
||||||
#else
|
|
||||||
int delimit = RNA_enum_get(op->ptr, "delimit");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
select_linked_delimit_validate(bm, &delimit);
|
select_linked_delimit_validate(bm, &delimit);
|
||||||
|
|
||||||
@@ -2761,6 +2882,10 @@ static int edbm_select_linked_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
||||||
|
|
||||||
|
} /* objects */
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2902,11 +3027,9 @@ static void edbm_select_linked_pick_ex(BMEditMesh *em, BMElem *ele, bool sel, in
|
|||||||
|
|
||||||
static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||||
{
|
{
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
|
||||||
EvaluationContext eval_ctx;
|
EvaluationContext eval_ctx;
|
||||||
ViewContext vc;
|
ViewContext vc;
|
||||||
BMEditMesh *em;
|
Base *basact = NULL;
|
||||||
BMesh *bm;
|
|
||||||
BMVert *eve;
|
BMVert *eve;
|
||||||
BMEdge *eed;
|
BMEdge *eed;
|
||||||
BMFace *efa;
|
BMFace *efa;
|
||||||
@@ -2923,25 +3046,41 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
|
|||||||
/* setup view context for argument to callbacks */
|
/* setup view context for argument to callbacks */
|
||||||
CTX_data_eval_ctx(C, &eval_ctx);
|
CTX_data_eval_ctx(C, &eval_ctx);
|
||||||
em_setup_viewcontext(C, &vc);
|
em_setup_viewcontext(C, &vc);
|
||||||
em = vc.em;
|
|
||||||
bm = em->bm;
|
|
||||||
|
|
||||||
if (bm->totedge == 0) {
|
{
|
||||||
return OPERATOR_CANCELLED;
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
eval_ctx.view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
bool has_edges = false;
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *ob_iter = objects[ob_index];
|
||||||
|
ED_view3d_viewcontext_init_object(&vc, ob_iter);
|
||||||
|
if (vc.em->bm->totedge) {
|
||||||
|
has_edges = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
if (has_edges == false) {
|
||||||
|
return OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vc.mval[0] = event->mval[0];
|
vc.mval[0] = event->mval[0];
|
||||||
vc.mval[1] = event->mval[1];
|
vc.mval[1] = event->mval[1];
|
||||||
|
|
||||||
/* return warning! */
|
/* return warning! */
|
||||||
if (unified_findnearest(&eval_ctx, &vc, &eve, &eed, &efa) == 0) {
|
if (unified_findnearest(&eval_ctx, &vc, &basact, &eve, &eed, &efa) == 0) {
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data);
|
||||||
|
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
ED_view3d_viewcontext_init_object(&vc, basact->object);
|
||||||
|
BMEditMesh *em = vc.em;
|
||||||
|
BMesh *bm = em->bm;
|
||||||
|
|
||||||
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
|
#ifdef USE_LINKED_SELECT_DEFAULT_HACK
|
||||||
int delimit = select_linked_delimit_default_from_op(op, em->selectmode);
|
int delimit = select_linked_delimit_default_from_op(op, vc.scene->toolsettings->selectmode);
|
||||||
#else
|
#else
|
||||||
int delimit = RNA_enum_get(op->ptr, "delimit");
|
int delimit = RNA_enum_get(op->ptr, "delimit");
|
||||||
#endif
|
#endif
|
||||||
@@ -2954,9 +3093,11 @@ static int edbm_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmE
|
|||||||
BM_mesh_elem_index_ensure(bm, ele->head.htype);
|
BM_mesh_elem_index_ensure(bm, ele->head.htype);
|
||||||
index = EDBM_elem_to_index_any(em, ele);
|
index = EDBM_elem_to_index_any(em, ele);
|
||||||
|
|
||||||
|
/* TODO(MULTI_EDIT), index doesn't know which object,
|
||||||
|
* index selections isn't very common. */
|
||||||
RNA_int_set(op->ptr, "index", index);
|
RNA_int_set(op->ptr, "index", index);
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, basact->object->data);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
@@ -93,7 +93,17 @@
|
|||||||
|
|
||||||
static int edbm_subdivide_exec(bContext *C, wmOperator *op)
|
static int edbm_subdivide_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
/* no indent for diff noise. */
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
const int cuts = RNA_int_get(op->ptr, "number_cuts");
|
const int cuts = RNA_int_get(op->ptr, "number_cuts");
|
||||||
float smooth = RNA_float_get(op->ptr, "smoothness");
|
float smooth = RNA_float_get(op->ptr, "smoothness");
|
||||||
@@ -117,6 +127,10 @@ static int edbm_subdivide_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
EDBM_update_generic(em, true, true);
|
EDBM_update_generic(em, true, true);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -367,16 +381,24 @@ enum {
|
|||||||
MESH_DELETE_ONLY_FACE = 4,
|
MESH_DELETE_ONLY_FACE = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void edbm_report_delete_info(ReportList *reports, BMesh *bm, const int totelem[3])
|
static void edbm_report_delete_info(ReportList *reports, const int totelem_old[3], const int totelem_new[3])
|
||||||
{
|
{
|
||||||
BKE_reportf(reports, RPT_INFO,
|
BKE_reportf(reports, RPT_INFO,
|
||||||
"Removed: %d vertices, %d edges, %d faces",
|
"Removed: %d vertices, %d edges, %d faces",
|
||||||
totelem[0] - bm->totvert, totelem[1] - bm->totedge, totelem[2] - bm->totface);
|
totelem_old[0] - totelem_new[0], totelem_old[1] - totelem_new[1], totelem_old[2] - totelem_new[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int edbm_delete_exec(bContext *C, wmOperator *op)
|
static int edbm_delete_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
const int type = RNA_enum_get(op->ptr, "type");
|
const int type = RNA_enum_get(op->ptr, "type");
|
||||||
|
|
||||||
@@ -412,6 +434,8 @@ static int edbm_delete_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
EDBM_update_generic(em, true, true);
|
EDBM_update_generic(em, true, true);
|
||||||
|
|
||||||
|
} /* objects */
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,18 +491,28 @@ static bool bm_face_is_loose(BMFace *f)
|
|||||||
|
|
||||||
static int edbm_delete_loose_exec(bContext *C, wmOperator *op)
|
static int edbm_delete_loose_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
|
int totelem_old_sel[3];
|
||||||
|
int totelem_old[3];
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
EDBM_mesh_stats_multi(objects, objects_len, totelem_old, totelem_old_sel);
|
||||||
|
|
||||||
|
const bool use_verts = (RNA_boolean_get(op->ptr, "use_verts") && totelem_old_sel[0]);
|
||||||
|
const bool use_edges = (RNA_boolean_get(op->ptr, "use_edges") && totelem_old_sel[1]);
|
||||||
|
const bool use_faces = (RNA_boolean_get(op->ptr, "use_faces") && totelem_old_sel[2]);
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
BMesh *bm = em->bm;
|
BMesh *bm = em->bm;
|
||||||
BMIter iter;
|
BMIter iter;
|
||||||
|
|
||||||
const bool use_verts = (RNA_boolean_get(op->ptr, "use_verts") && bm->totvertsel);
|
|
||||||
const bool use_edges = (RNA_boolean_get(op->ptr, "use_edges") && bm->totedgesel);
|
|
||||||
const bool use_faces = (RNA_boolean_get(op->ptr, "use_faces") && bm->totfacesel);
|
|
||||||
|
|
||||||
const int totelem[3] = {bm->totvert, bm->totedge, bm->totface};
|
|
||||||
|
|
||||||
|
|
||||||
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
|
BM_mesh_elem_hflag_disable_all(bm, BM_VERT | BM_EDGE | BM_FACE, BM_ELEM_TAG, false);
|
||||||
|
|
||||||
if (use_faces) {
|
if (use_faces) {
|
||||||
@@ -521,7 +555,15 @@ static int edbm_delete_loose_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
EDBM_update_generic(em, true, true);
|
EDBM_update_generic(em, true, true);
|
||||||
|
|
||||||
edbm_report_delete_info(op->reports, bm, totelem);
|
// no indent
|
||||||
|
}
|
||||||
|
|
||||||
|
int totelem_new[3];
|
||||||
|
EDBM_mesh_stats_multi(objects, objects_len, totelem_new, NULL);
|
||||||
|
|
||||||
|
edbm_report_delete_info(op->reports, totelem_old, totelem_new);
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
@@ -4096,11 +4138,21 @@ void MESH_OT_poke(wmOperatorType *ot)
|
|||||||
|
|
||||||
static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
|
static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
|
||||||
BMOperator bmop;
|
|
||||||
const int quad_method = RNA_enum_get(op->ptr, "quad_method");
|
const int quad_method = RNA_enum_get(op->ptr, "quad_method");
|
||||||
const int ngon_method = RNA_enum_get(op->ptr, "ngon_method");
|
const int ngon_method = RNA_enum_get(op->ptr, "ngon_method");
|
||||||
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
/* no indent for diff noise. */
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
BMOperator bmop;
|
||||||
BMOIter oiter;
|
BMOIter oiter;
|
||||||
BMFace *f;
|
BMFace *f;
|
||||||
|
|
||||||
@@ -4117,12 +4169,17 @@ static int edbm_quads_convert_to_tris_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
EDBM_selectmode_flush(em);
|
EDBM_selectmode_flush(em);
|
||||||
|
|
||||||
|
// XXX, TODO
|
||||||
|
#if 0
|
||||||
if (!EDBM_op_finish(em, &bmop, op, true)) {
|
if (!EDBM_op_finish(em, &bmop, op, true)) {
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
EDBM_update_generic(em, true, true);
|
EDBM_update_generic(em, true, true);
|
||||||
|
|
||||||
|
} /* objects */
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4155,7 +4212,25 @@ void MESH_OT_quads_convert_to_tris(wmOperatorType *ot)
|
|||||||
|
|
||||||
static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
|
static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
bool is_face_pair;
|
||||||
|
|
||||||
|
{
|
||||||
|
int totelem_sel[3];
|
||||||
|
EDBM_mesh_stats_multi(objects, objects_len, NULL, totelem_sel);
|
||||||
|
is_face_pair = (totelem_sel[2] == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no indent for diff noise. */
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
bool do_seam, do_sharp, do_uvs, do_vcols, do_materials;
|
bool do_seam, do_sharp, do_uvs, do_vcols, do_materials;
|
||||||
float angle_face_threshold, angle_shape_threshold;
|
float angle_face_threshold, angle_shape_threshold;
|
||||||
@@ -4164,7 +4239,7 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
|
|||||||
/* When joining exactly 2 faces, no limit.
|
/* When joining exactly 2 faces, no limit.
|
||||||
* this is useful for one off joins while editing. */
|
* this is useful for one off joins while editing. */
|
||||||
prop = RNA_struct_find_property(op->ptr, "face_threshold");
|
prop = RNA_struct_find_property(op->ptr, "face_threshold");
|
||||||
if ((em->bm->totfacesel == 2) &&
|
if (is_face_pair &&
|
||||||
(RNA_property_is_set(op->ptr, prop) == false))
|
(RNA_property_is_set(op->ptr, prop) == false))
|
||||||
{
|
{
|
||||||
angle_face_threshold = DEG2RADF(180.0f);
|
angle_face_threshold = DEG2RADF(180.0f);
|
||||||
@@ -4174,7 +4249,7 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
|
|||||||
}
|
}
|
||||||
|
|
||||||
prop = RNA_struct_find_property(op->ptr, "shape_threshold");
|
prop = RNA_struct_find_property(op->ptr, "shape_threshold");
|
||||||
if ((em->bm->totfacesel == 2) &&
|
if (is_face_pair &&
|
||||||
(RNA_property_is_set(op->ptr, prop) == false))
|
(RNA_property_is_set(op->ptr, prop) == false))
|
||||||
{
|
{
|
||||||
angle_shape_threshold = DEG2RADF(180.0f);
|
angle_shape_threshold = DEG2RADF(180.0f);
|
||||||
@@ -4197,11 +4272,13 @@ static int edbm_tris_convert_to_quads_exec(bContext *C, wmOperator *op)
|
|||||||
BM_ELEM_SELECT, angle_face_threshold, angle_shape_threshold,
|
BM_ELEM_SELECT, angle_face_threshold, angle_shape_threshold,
|
||||||
do_seam, do_sharp, do_uvs, do_vcols, do_materials))
|
do_seam, do_sharp, do_uvs, do_vcols, do_materials))
|
||||||
{
|
{
|
||||||
return OPERATOR_CANCELLED;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
EDBM_update_generic(em, true, true);
|
EDBM_update_generic(em, true, true);
|
||||||
|
|
||||||
|
} /* objects */
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4727,11 +4804,30 @@ void MESH_OT_dissolve_limited(wmOperatorType *ot)
|
|||||||
|
|
||||||
static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op)
|
static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
int totelem_old[3] = {0, 0, 0};
|
||||||
|
int totelem_new[3] = {0, 0, 0};
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
BMesh *bm = em->bm;
|
||||||
|
totelem_old[0] += bm->totvert;
|
||||||
|
totelem_old[1] += bm->totedge;
|
||||||
|
totelem_old[2] += bm->totface;
|
||||||
|
} /* objects */
|
||||||
|
|
||||||
const float thresh = RNA_float_get(op->ptr, "threshold");
|
const float thresh = RNA_float_get(op->ptr, "threshold");
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
BMesh *bm = em->bm;
|
BMesh *bm = em->bm;
|
||||||
const int totelem[3] = {bm->totvert, bm->totedge, bm->totface};
|
|
||||||
|
|
||||||
if (!EDBM_op_callf(
|
if (!EDBM_op_callf(
|
||||||
em, op,
|
em, op,
|
||||||
@@ -4746,7 +4842,14 @@ static int edbm_dissolve_degenerate_exec(bContext *C, wmOperator *op)
|
|||||||
|
|
||||||
EDBM_update_generic(em, true, true);
|
EDBM_update_generic(em, true, true);
|
||||||
|
|
||||||
edbm_report_delete_info(op->reports, bm, totelem);
|
totelem_new[0] += bm->totvert;
|
||||||
|
totelem_new[1] += bm->totedge;
|
||||||
|
totelem_new[2] += bm->totface;
|
||||||
|
|
||||||
|
// no indent
|
||||||
|
} /* objects */
|
||||||
|
|
||||||
|
edbm_report_delete_info(op->reports, totelem_old, totelem_new);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
#include "DNA_mesh_types.h"
|
#include "DNA_mesh_types.h"
|
||||||
#include "DNA_object_types.h"
|
#include "DNA_object_types.h"
|
||||||
#include "DNA_key_types.h"
|
#include "DNA_key_types.h"
|
||||||
|
#include "DNA_layer_types.h"
|
||||||
|
|
||||||
#include "BLI_listbase.h"
|
#include "BLI_listbase.h"
|
||||||
#include "BLI_array_utils.h"
|
#include "BLI_array_utils.h"
|
||||||
@@ -35,6 +36,7 @@
|
|||||||
#include "BKE_DerivedMesh.h"
|
#include "BKE_DerivedMesh.h"
|
||||||
#include "BKE_context.h"
|
#include "BKE_context.h"
|
||||||
#include "BKE_key.h"
|
#include "BKE_key.h"
|
||||||
|
#include "BKE_layer.h"
|
||||||
#include "BKE_mesh.h"
|
#include "BKE_mesh.h"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
#include "BKE_undo_system.h"
|
#include "BKE_undo_system.h"
|
||||||
@@ -670,14 +672,17 @@ static Object *editmesh_object_from_context(bContext *C)
|
|||||||
/** \name Implements ED Undo System
|
/** \name Implements ED Undo System
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
typedef struct MeshUndoStep {
|
typedef struct MeshUndoStep_Elem {
|
||||||
UndoStep step;
|
struct MeshUndoStep_Elem *next, *prev;
|
||||||
/* Use for all ID lookups (can be NULL). */
|
|
||||||
struct UndoIDPtrMap *id_map;
|
|
||||||
|
|
||||||
/* note: will split out into list for multi-object-editmode. */
|
|
||||||
UndoRefID_Object obedit_ref;
|
UndoRefID_Object obedit_ref;
|
||||||
UndoMesh data;
|
UndoMesh data;
|
||||||
|
} MeshUndoStep_Elem;
|
||||||
|
|
||||||
|
typedef struct MeshUndoStep {
|
||||||
|
UndoStep step;
|
||||||
|
struct UndoIDPtrMap *id_map;
|
||||||
|
MeshUndoStep_Elem *elems;
|
||||||
|
uint elems_len;
|
||||||
} MeshUndoStep;
|
} MeshUndoStep;
|
||||||
|
|
||||||
static bool mesh_undosys_poll(bContext *C)
|
static bool mesh_undosys_poll(bContext *C)
|
||||||
@@ -688,10 +693,25 @@ static bool mesh_undosys_poll(bContext *C)
|
|||||||
static bool mesh_undosys_step_encode(struct bContext *C, UndoStep *us_p)
|
static bool mesh_undosys_step_encode(struct bContext *C, UndoStep *us_p)
|
||||||
{
|
{
|
||||||
MeshUndoStep *us = (MeshUndoStep *)us_p;
|
MeshUndoStep *us = (MeshUndoStep *)us_p;
|
||||||
us->obedit_ref.ptr = editmesh_object_from_context(C);
|
|
||||||
Mesh *me = us->obedit_ref.ptr->data;
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
undomesh_from_editmesh(&us->data, me->edit_btmesh, me->key);
|
uint objects_len = 0;
|
||||||
us->step.data_size = us->data.undo_size;
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
us->elems = MEM_callocN(sizeof(*us->elems) * objects_len, __func__);
|
||||||
|
us->elems_len = objects_len;
|
||||||
|
|
||||||
|
for (uint i = 0; i < objects_len; i++) {
|
||||||
|
Object *ob = objects[i];
|
||||||
|
MeshUndoStep_Elem *elem = &us->elems[i];
|
||||||
|
|
||||||
|
elem->obedit_ref.ptr = ob;
|
||||||
|
Mesh *me = elem->obedit_ref.ptr->data;
|
||||||
|
undomesh_from_editmesh(&elem->data, me->edit_btmesh, me->key);
|
||||||
|
us->step.data_size += elem->data.undo_size;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -702,18 +722,28 @@ static void mesh_undosys_step_decode(struct bContext *C, UndoStep *us_p, int UNU
|
|||||||
BLI_assert(mesh_undosys_poll(C));
|
BLI_assert(mesh_undosys_poll(C));
|
||||||
|
|
||||||
MeshUndoStep *us = (MeshUndoStep *)us_p;
|
MeshUndoStep *us = (MeshUndoStep *)us_p;
|
||||||
Object *obedit = us->obedit_ref.ptr;
|
|
||||||
Mesh *me = obedit->data;
|
for (uint i = 0; i < us->elems_len; i++) {
|
||||||
BMEditMesh *em = me->edit_btmesh;
|
MeshUndoStep_Elem *elem = &us->elems[i];
|
||||||
undomesh_to_editmesh(&us->data, em, obedit->data);
|
Object *obedit = elem->obedit_ref.ptr;
|
||||||
DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
|
Mesh *me = obedit->data;
|
||||||
|
BMEditMesh *em = me->edit_btmesh;
|
||||||
|
undomesh_to_editmesh(&elem->data, em, obedit->data);
|
||||||
|
DEG_id_tag_update(&obedit->id, OB_RECALC_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mesh_undosys_step_free(UndoStep *us_p)
|
static void mesh_undosys_step_free(UndoStep *us_p)
|
||||||
{
|
{
|
||||||
MeshUndoStep *us = (MeshUndoStep *)us_p;
|
MeshUndoStep *us = (MeshUndoStep *)us_p;
|
||||||
undomesh_free_data(&us->data);
|
|
||||||
|
for (uint i = 0; i < us->elems_len; i++) {
|
||||||
|
MeshUndoStep_Elem *elem = &us->elems[i];
|
||||||
|
undomesh_free_data(&elem->data);
|
||||||
|
}
|
||||||
|
MEM_freeN(us->elems);
|
||||||
|
|
||||||
if (us->id_map != NULL) {
|
if (us->id_map != NULL) {
|
||||||
BKE_undosys_ID_map_destroy(us->id_map);
|
BKE_undosys_ID_map_destroy(us->id_map);
|
||||||
@@ -724,7 +754,12 @@ static void mesh_undosys_foreach_ID_ref(
|
|||||||
UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
|
UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
|
||||||
{
|
{
|
||||||
MeshUndoStep *us = (MeshUndoStep *)us_p;
|
MeshUndoStep *us = (MeshUndoStep *)us_p;
|
||||||
foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->obedit_ref));
|
|
||||||
|
for (uint i = 0; i < us->elems_len; i++) {
|
||||||
|
MeshUndoStep_Elem *elem = &us->elems[i];
|
||||||
|
foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
|
||||||
|
}
|
||||||
|
|
||||||
if (us->id_map != NULL) {
|
if (us->id_map != NULL) {
|
||||||
BKE_undosys_ID_map_foreach_ID_ref(us->id_map, foreach_ID_ref_fn, user_data);
|
BKE_undosys_ID_map_foreach_ID_ref(us->id_map, foreach_ID_ref_fn, user_data);
|
||||||
}
|
}
|
||||||
|
@@ -60,6 +60,7 @@
|
|||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
#include "BKE_multires.h"
|
#include "BKE_multires.h"
|
||||||
|
#include "BKE_layer.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
#include "DEG_depsgraph_build.h"
|
#include "DEG_depsgraph_build.h"
|
||||||
@@ -1297,3 +1298,47 @@ MDeformVert *ED_mesh_active_dvert_get_only(Object *ob)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EDBM_mesh_stats_multi(
|
||||||
|
struct Object **objects, const uint objects_len,
|
||||||
|
int totelem[3], int totelem_sel[3])
|
||||||
|
{
|
||||||
|
if (totelem) {
|
||||||
|
totelem[0] = 0;
|
||||||
|
totelem[1] = 0;
|
||||||
|
totelem[2] = 0;
|
||||||
|
}
|
||||||
|
if (totelem_sel) {
|
||||||
|
totelem_sel[0] = 0;
|
||||||
|
totelem_sel[1] = 0;
|
||||||
|
totelem_sel[2] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
BMesh *bm = em->bm;
|
||||||
|
if (totelem) {
|
||||||
|
totelem[0] += bm->totvert;
|
||||||
|
totelem[1] += bm->totedge;
|
||||||
|
totelem[2] += bm->totface;
|
||||||
|
}
|
||||||
|
if (totelem_sel) {
|
||||||
|
totelem_sel[0] += bm->totvertsel;
|
||||||
|
totelem_sel[1] += bm->totedgesel;
|
||||||
|
totelem_sel[2] += bm->totfacesel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EDBM_mesh_elem_index_ensure_multi(Object **objects, const uint objects_len, const char htype)
|
||||||
|
{
|
||||||
|
int elem_offset[4] = {0, 0, 0, 0};
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
BMesh *bm = em->bm;
|
||||||
|
BM_mesh_elem_index_ensure_ex(bm, htype, elem_offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -89,6 +89,7 @@
|
|||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
#include "BKE_object.h"
|
#include "BKE_object.h"
|
||||||
#include "BKE_workspace.h"
|
#include "BKE_workspace.h"
|
||||||
|
#include "BKE_layer.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
#include "DEG_depsgraph_build.h"
|
#include "DEG_depsgraph_build.h"
|
||||||
@@ -277,9 +278,6 @@ bool ED_object_editmode_load(Object *obedit)
|
|||||||
void ED_object_editmode_exit_ex(bContext *C, Scene *scene, Object *obedit, int flag)
|
void ED_object_editmode_exit_ex(bContext *C, Scene *scene, Object *obedit, int flag)
|
||||||
{
|
{
|
||||||
BLI_assert(C || !(flag & EM_DO_UNDO));
|
BLI_assert(C || !(flag & EM_DO_UNDO));
|
||||||
/* Note! only in exceptional cases should 'EM_DO_UNDO' NOT be in the flag */
|
|
||||||
/* Note! if 'EM_FREEDATA' isn't in the flag, use ED_object_editmode_load directly */
|
|
||||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
||||||
const bool freedata = (flag & EM_FREEDATA) != 0;
|
const bool freedata = (flag & EM_FREEDATA) != 0;
|
||||||
|
|
||||||
if (flag & EM_WAITCURSOR) waitcursor(1);
|
if (flag & EM_WAITCURSOR) waitcursor(1);
|
||||||
@@ -287,8 +285,8 @@ void ED_object_editmode_exit_ex(bContext *C, Scene *scene, Object *obedit, int f
|
|||||||
if (ED_object_editmode_load_ex(G.main, obedit, freedata) == false) {
|
if (ED_object_editmode_load_ex(G.main, obedit, freedata) == false) {
|
||||||
/* in rare cases (background mode) its possible active object
|
/* in rare cases (background mode) its possible active object
|
||||||
* is flagged for editmode, without 'obedit' being set [#35489] */
|
* is flagged for editmode, without 'obedit' being set [#35489] */
|
||||||
if (UNLIKELY(view_layer->basact && (view_layer->basact->object->mode & OB_MODE_EDIT))) {
|
if (UNLIKELY(obedit && obedit->mode & OB_MODE_EDIT)) {
|
||||||
view_layer->basact->object->mode &= ~OB_MODE_EDIT;
|
obedit->mode &= ~OB_MODE_EDIT;
|
||||||
}
|
}
|
||||||
if (flag & EM_WAITCURSOR) waitcursor(0);
|
if (flag & EM_WAITCURSOR) waitcursor(0);
|
||||||
return;
|
return;
|
||||||
@@ -315,15 +313,18 @@ void ED_object_editmode_exit_ex(bContext *C, Scene *scene, Object *obedit, int f
|
|||||||
if (flag & EM_DO_UNDO)
|
if (flag & EM_DO_UNDO)
|
||||||
ED_undo_push(C, "Editmode");
|
ED_undo_push(C, "Editmode");
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
|
if (C != NULL) {
|
||||||
|
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
obedit->mode &= ~OB_MODE_EDIT;
|
obedit->mode &= ~OB_MODE_EDIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag & EM_WAITCURSOR) waitcursor(0);
|
if (flag & EM_WAITCURSOR) waitcursor(0);
|
||||||
|
|
||||||
/* This way we ensure scene's obedit is copied into all CoW scenes. */
|
|
||||||
DEG_id_tag_update(&scene->id, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ED_object_editmode_exit(bContext *C, int flag)
|
void ED_object_editmode_exit(bContext *C, int flag)
|
||||||
@@ -333,25 +334,12 @@ void ED_object_editmode_exit(bContext *C, int flag)
|
|||||||
ED_object_editmode_exit_ex(C, scene, obedit, flag);
|
ED_object_editmode_exit_ex(C, scene, obedit, flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ED_object_editmode_enter(bContext *C, int flag)
|
void ED_object_editmode_enter_ex(Scene *scene, Object *ob, int flag)
|
||||||
{
|
{
|
||||||
Scene *scene = CTX_data_scene(C);
|
|
||||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
||||||
Object *ob;
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
if (ID_IS_LINKED(scene)) return;
|
|
||||||
|
|
||||||
if ((flag & EM_IGNORE_LAYER) == 0) {
|
|
||||||
ob = CTX_data_active_object(C); /* active layer checked here for view3d */
|
|
||||||
|
|
||||||
if (ob == NULL) return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ob = view_layer->basact->object;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ELEM(NULL, ob, ob->data)) return;
|
if (ELEM(NULL, ob, ob->data)) return;
|
||||||
|
if (ID_IS_LINKED(ob)) return;
|
||||||
|
|
||||||
/* this checks actual object->data, for cases when other scenes have it in editmode context */
|
/* this checks actual object->data, for cases when other scenes have it in editmode context */
|
||||||
if (BKE_object_is_in_editmode(ob))
|
if (BKE_object_is_in_editmode(ob))
|
||||||
@@ -366,11 +354,6 @@ void ED_object_editmode_enter(bContext *C, int flag)
|
|||||||
|
|
||||||
ob->restore_mode = ob->mode;
|
ob->restore_mode = ob->mode;
|
||||||
|
|
||||||
/* note, when switching scenes the object can have editmode data but
|
|
||||||
* not be scene->obedit: bug 22954, this avoids calling self eternally */
|
|
||||||
if ((ob->restore_mode & OB_MODE_EDIT) == 0)
|
|
||||||
ED_object_mode_toggle(C, ob->mode);
|
|
||||||
|
|
||||||
ob->mode = OB_MODE_EDIT;
|
ob->mode = OB_MODE_EDIT;
|
||||||
|
|
||||||
if (ob->type == OB_MESH) {
|
if (ob->type == OB_MESH) {
|
||||||
@@ -387,7 +370,7 @@ void ED_object_editmode_enter(bContext *C, int flag)
|
|||||||
BKE_editmesh_tessface_calc(em);
|
BKE_editmesh_tessface_calc(em);
|
||||||
}
|
}
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_MESH, scene);
|
WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MESH, NULL);
|
||||||
}
|
}
|
||||||
else if (ob->type == OB_ARMATURE) {
|
else if (ob->type == OB_ARMATURE) {
|
||||||
bArmature *arm = ob->data;
|
bArmature *arm = ob->data;
|
||||||
@@ -409,45 +392,64 @@ void ED_object_editmode_enter(bContext *C, int flag)
|
|||||||
/* to ensure all goes in restposition and without striding */
|
/* to ensure all goes in restposition and without striding */
|
||||||
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */
|
DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* XXX: should this be OB_RECALC_DATA? */
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
|
WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_ARMATURE, scene);
|
||||||
}
|
}
|
||||||
else if (ob->type == OB_FONT) {
|
else if (ob->type == OB_FONT) {
|
||||||
ok = 1;
|
ok = 1;
|
||||||
ED_curve_editfont_make(ob);
|
ED_curve_editfont_make(ob);
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene);
|
WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_TEXT, scene);
|
||||||
}
|
}
|
||||||
else if (ob->type == OB_MBALL) {
|
else if (ob->type == OB_MBALL) {
|
||||||
ok = 1;
|
ok = 1;
|
||||||
ED_mball_editmball_make(ob);
|
ED_mball_editmball_make(ob);
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene);
|
WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_MBALL, scene);
|
||||||
}
|
}
|
||||||
else if (ob->type == OB_LATTICE) {
|
else if (ob->type == OB_LATTICE) {
|
||||||
ok = 1;
|
ok = 1;
|
||||||
BKE_editlattice_make(ob);
|
BKE_editlattice_make(ob);
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene);
|
WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_LATTICE, scene);
|
||||||
}
|
}
|
||||||
else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
|
else if (ob->type == OB_SURF || ob->type == OB_CURVE) {
|
||||||
ok = 1;
|
ok = 1;
|
||||||
ED_curve_editnurb_make(ob);
|
ED_curve_editnurb_make(ob);
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene);
|
WM_main_add_notifier(NC_SCENE | ND_MODE | NS_EDITMODE_CURVE, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok) {
|
if (ok) {
|
||||||
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
/* This way we ensure scene's obedit is copied into all CoW scenes. */
|
|
||||||
DEG_id_tag_update(&scene->id, 0);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ob->mode &= ~OB_MODE_EDIT;
|
if ((flag & EM_NO_CONTEXT) == 0) {
|
||||||
WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
|
ob->mode &= ~OB_MODE_EDIT;
|
||||||
|
}
|
||||||
|
WM_main_add_notifier(NC_SCENE | ND_MODE | NS_MODE_OBJECT, scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flag & EM_DO_UNDO) ED_undo_push(C, "Enter Editmode");
|
|
||||||
if (flag & EM_WAITCURSOR) waitcursor(0);
|
if (flag & EM_WAITCURSOR) waitcursor(0);
|
||||||
|
BLI_assert((flag & EM_DO_UNDO) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ED_object_editmode_enter(bContext *C, int flag)
|
||||||
|
{
|
||||||
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
|
Object *ob;
|
||||||
|
|
||||||
|
if ((flag & EM_IGNORE_LAYER) == 0) {
|
||||||
|
ob = CTX_data_active_object(C); /* active layer checked here for view3d */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ob = view_layer->basact->object;
|
||||||
|
}
|
||||||
|
if (ob == NULL) return;
|
||||||
|
if (ID_IS_LINKED(ob)) return;
|
||||||
|
|
||||||
|
ED_object_editmode_enter_ex(scene, ob, flag & ~EM_DO_UNDO);
|
||||||
|
if (flag & EM_DO_UNDO) ED_undo_push(C, "Enter Editmode");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int editmode_toggle_exec(bContext *C, wmOperator *op)
|
static int editmode_toggle_exec(bContext *C, wmOperator *op)
|
||||||
@@ -455,18 +457,32 @@ static int editmode_toggle_exec(bContext *C, wmOperator *op)
|
|||||||
const int mode_flag = OB_MODE_EDIT;
|
const int mode_flag = OB_MODE_EDIT;
|
||||||
const bool is_mode_set = (CTX_data_edit_object(C) != NULL);
|
const bool is_mode_set = (CTX_data_edit_object(C) != NULL);
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
|
Object *obact = OBACT(view_layer);
|
||||||
|
|
||||||
if (!is_mode_set) {
|
if (!is_mode_set) {
|
||||||
Object *ob = CTX_data_active_object(C);
|
if (!ED_object_mode_compat_set(C, obact, mode_flag, op->reports)) {
|
||||||
if (!ED_object_mode_compat_set(C, ob, mode_flag, op->reports)) {
|
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_mode_set)
|
if (!is_mode_set) {
|
||||||
ED_object_editmode_enter(C, EM_WAITCURSOR);
|
ED_object_editmode_enter(C, EM_WAITCURSOR);
|
||||||
else
|
if (obact->mode & mode_flag) {
|
||||||
|
FOREACH_SELECTED_OBJECT_BEGIN(view_layer, ob)
|
||||||
|
{
|
||||||
|
if (ob != obact) {
|
||||||
|
if (ob->flag & SELECT) {
|
||||||
|
ED_object_editmode_enter_ex(scene, ob, EM_WAITCURSOR | EM_NO_CONTEXT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FOREACH_SELECTED_OBJECT_END;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
|
ED_object_editmode_exit(C, EM_FREEDATA | EM_FREEUNDO | EM_WAITCURSOR); /* had EM_DO_UNDO but op flag calls undo too [#24685] */
|
||||||
|
}
|
||||||
|
|
||||||
ED_space_image_uv_sculpt_update(CTX_wm_manager(C), scene);
|
ED_space_image_uv_sculpt_update(CTX_wm_manager(C), scene);
|
||||||
|
|
||||||
|
@@ -5924,7 +5924,7 @@ static int add_simple_uvs_exec(bContext *C, wmOperator *UNUSED(op))
|
|||||||
ED_uvedit_unwrap_cube_project(bm, 1.0, false, NULL);
|
ED_uvedit_unwrap_cube_project(bm, 1.0, false, NULL);
|
||||||
/* set the margin really quickly before the packing operation*/
|
/* set the margin really quickly before the packing operation*/
|
||||||
scene->toolsettings->uvcalc_margin = 0.001f;
|
scene->toolsettings->uvcalc_margin = 0.001f;
|
||||||
ED_uvedit_pack_islands(scene, ob, bm, false, false, true);
|
ED_uvedit_pack_islands_single(scene, ob, bm, false, false, true);
|
||||||
BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){0}));
|
BM_mesh_bm_to_me(bm, me, (&(struct BMeshToMeshParams){0}));
|
||||||
BM_mesh_free(bm);
|
BM_mesh_free(bm);
|
||||||
|
|
||||||
|
@@ -122,6 +122,21 @@ void ED_view3d_viewcontext_init(bContext *C, ViewContext *vc)
|
|||||||
vc->obedit = CTX_data_edit_object(C);
|
vc->obedit = CTX_data_edit_object(C);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
|
||||||
|
{
|
||||||
|
vc->obact = obact;
|
||||||
|
if (vc->obedit) {
|
||||||
|
BLI_assert(BKE_object_is_in_editmode(obact));
|
||||||
|
vc->obedit = obact;
|
||||||
|
/* previous selections are now invalid. */
|
||||||
|
vc->v3d->flag |= V3D_INVALID_BACKBUF;
|
||||||
|
|
||||||
|
if (vc->em) {
|
||||||
|
vc->em = BKE_editmesh_from_object(vc->obedit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ********************** view3d_select: selection manipulations ********************* */
|
/* ********************** view3d_select: selection manipulations ********************* */
|
||||||
|
|
||||||
/* local prototypes */
|
/* local prototypes */
|
||||||
@@ -834,6 +849,12 @@ static void view3d_lasso_select(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else { /* Edit Mode */
|
else { /* Edit Mode */
|
||||||
|
|
||||||
|
/* don't indent to avoid diff noise! */
|
||||||
|
FOREACH_OBJECT_IN_MODE_BEGIN (eval_ctx.view_layer, ob->mode, ob_iter) {
|
||||||
|
ED_view3d_viewcontext_init_object(vc, ob_iter);
|
||||||
|
/* --- */
|
||||||
|
|
||||||
switch (vc->obedit->type) {
|
switch (vc->obedit->type) {
|
||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
do_lasso_select_mesh(&eval_ctx, vc, mcords, moves, extend, select);
|
do_lasso_select_mesh(&eval_ctx, vc, mcords, moves, extend, select);
|
||||||
@@ -857,6 +878,8 @@ static void view3d_lasso_select(
|
|||||||
}
|
}
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc->obedit->data);
|
||||||
|
|
||||||
|
} FOREACH_OBJECT_IN_MODE_END;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2124,36 +2147,41 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
|
|||||||
WM_operator_properties_border_to_rcti(op, &rect);
|
WM_operator_properties_border_to_rcti(op, &rect);
|
||||||
|
|
||||||
if (vc.obedit) {
|
if (vc.obedit) {
|
||||||
|
|
||||||
|
/* don't indent to avoid diff noise! */
|
||||||
|
FOREACH_OBJECT_IN_MODE_BEGIN (eval_ctx.view_layer, vc.obedit->mode, ob_iter) {
|
||||||
|
ED_view3d_viewcontext_init_object(&vc, ob_iter);
|
||||||
|
/* --- */
|
||||||
|
|
||||||
switch (vc.obedit->type) {
|
switch (vc.obedit->type) {
|
||||||
case OB_MESH:
|
case OB_MESH:
|
||||||
vc.em = BKE_editmesh_from_object(vc.obedit);
|
vc.em = BKE_editmesh_from_object(vc.obedit);
|
||||||
ret = do_mesh_box_select(&eval_ctx, &vc, &rect, select, extend);
|
ret |= do_mesh_box_select(&eval_ctx, &vc, &rect, select, extend);
|
||||||
// if (EM_texFaceCheck())
|
|
||||||
if (ret & OPERATOR_FINISHED) {
|
if (ret & OPERATOR_FINISHED) {
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OB_CURVE:
|
case OB_CURVE:
|
||||||
case OB_SURF:
|
case OB_SURF:
|
||||||
ret = do_nurbs_box_select(&vc, &rect, select, extend);
|
ret |= do_nurbs_box_select(&vc, &rect, select, extend);
|
||||||
if (ret & OPERATOR_FINISHED) {
|
if (ret & OPERATOR_FINISHED) {
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OB_MBALL:
|
case OB_MBALL:
|
||||||
ret = do_meta_box_select(&eval_ctx, &vc, &rect, select, extend);
|
ret |= do_meta_box_select(&eval_ctx, &vc, &rect, select, extend);
|
||||||
if (ret & OPERATOR_FINISHED) {
|
if (ret & OPERATOR_FINISHED) {
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OB_ARMATURE:
|
case OB_ARMATURE:
|
||||||
ret = do_armature_box_select(&eval_ctx, &vc, &rect, select, extend);
|
ret |= do_armature_box_select(&eval_ctx, &vc, &rect, select, extend);
|
||||||
if (ret & OPERATOR_FINISHED) {
|
if (ret & OPERATOR_FINISHED) {
|
||||||
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
|
WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OB_LATTICE:
|
case OB_LATTICE:
|
||||||
ret = do_lattice_box_select(&vc, &rect, select, extend);
|
ret |= do_lattice_box_select(&vc, &rect, select, extend);
|
||||||
if (ret & OPERATOR_FINISHED) {
|
if (ret & OPERATOR_FINISHED) {
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
||||||
}
|
}
|
||||||
@@ -2161,26 +2189,33 @@ static int view3d_borderselect_exec(bContext *C, wmOperator *op)
|
|||||||
default:
|
default:
|
||||||
assert(!"border select on incorrect object type");
|
assert(!"border select on incorrect object type");
|
||||||
break;
|
break;
|
||||||
}
|
}} FOREACH_OBJECT_IN_MODE_END;
|
||||||
}
|
}
|
||||||
else { /* no editmode, unified for bones and objects */
|
else { /* no editmode, unified for bones and objects */
|
||||||
if (vc.obact && vc.obact->mode & OB_MODE_SCULPT) {
|
if (vc.obact && vc.obact->mode & OB_MODE_SCULPT) {
|
||||||
ret = ED_sculpt_mask_box_select(C, &vc, &rect, select, extend);
|
ret |= ED_sculpt_mask_box_select(C, &vc, &rect, select, extend);
|
||||||
}
|
}
|
||||||
else if (vc.obact && BKE_paint_select_face_test(vc.obact)) {
|
else if (vc.obact && BKE_paint_select_face_test(vc.obact)) {
|
||||||
ret = do_paintface_box_select(&eval_ctx, &vc, &rect, select, extend);
|
ret |= do_paintface_box_select(&eval_ctx, &vc, &rect, select, extend);
|
||||||
}
|
}
|
||||||
else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
|
else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
|
||||||
ret = do_paintvert_box_select(&eval_ctx, &vc, &rect, select, extend);
|
ret |= do_paintvert_box_select(&eval_ctx, &vc, &rect, select, extend);
|
||||||
}
|
}
|
||||||
else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
|
else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
|
||||||
ret = PE_border_select(C, &rect, select, extend);
|
ret |= PE_border_select(C, &rect, select, extend);
|
||||||
}
|
}
|
||||||
else { /* object mode with none active */
|
else { /* object mode with none active */
|
||||||
ret = do_object_pose_box_select(C, &vc, &rect, select, extend);
|
ret |= do_object_pose_box_select(C, &vc, &rect, select, extend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ret & OPERATOR_FINISHED) {
|
||||||
|
ret = OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = OPERATOR_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2821,23 +2856,32 @@ static bool object_circle_select(ViewContext *vc, const bool select, const int m
|
|||||||
/* not a real operator, only for circle test */
|
/* not a real operator, only for circle test */
|
||||||
static int view3d_circle_select_exec(bContext *C, wmOperator *op)
|
static int view3d_circle_select_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Scene *scene = CTX_data_scene(C);
|
ViewContext vc;
|
||||||
Object *obact = CTX_data_active_object(C);
|
EvaluationContext eval_ctx;
|
||||||
|
CTX_data_eval_ctx(C, &eval_ctx);
|
||||||
const int radius = RNA_int_get(op->ptr, "radius");
|
const int radius = RNA_int_get(op->ptr, "radius");
|
||||||
const bool select = !RNA_boolean_get(op->ptr, "deselect");
|
const bool select = !RNA_boolean_get(op->ptr, "deselect");
|
||||||
const int mval[2] = {RNA_int_get(op->ptr, "x"),
|
const int mval[2] = {RNA_int_get(op->ptr, "x"),
|
||||||
RNA_int_get(op->ptr, "y")};
|
RNA_int_get(op->ptr, "y")};
|
||||||
|
|
||||||
if (CTX_data_edit_object(C) || BKE_paint_select_elem_test(obact) ||
|
|
||||||
|
ED_view3d_viewcontext_init(C, &vc);
|
||||||
|
|
||||||
|
Object *obact = vc.obact;
|
||||||
|
Object *obedit = vc.obedit;
|
||||||
|
|
||||||
|
if (obedit || BKE_paint_select_elem_test(obact) ||
|
||||||
(obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) )
|
(obact && (obact->mode & (OB_MODE_PARTICLE_EDIT | OB_MODE_POSE))) )
|
||||||
{
|
{
|
||||||
EvaluationContext eval_ctx;
|
|
||||||
ViewContext vc;
|
|
||||||
|
|
||||||
view3d_operator_needs_opengl(C);
|
view3d_operator_needs_opengl(C);
|
||||||
|
|
||||||
CTX_data_eval_ctx(C, &eval_ctx);
|
/* don't indent to avoid diff noise! */
|
||||||
ED_view3d_viewcontext_init(C, &vc);
|
FOREACH_OBJECT_IN_MODE_BEGIN (eval_ctx.view_layer, obact->mode, ob_iter) {
|
||||||
|
ED_view3d_viewcontext_init_object(&vc, ob_iter);
|
||||||
|
/* --- */
|
||||||
|
|
||||||
|
obact = vc.obact;
|
||||||
|
obedit = vc.obedit;
|
||||||
|
|
||||||
if (CTX_data_edit_object(C)) {
|
if (CTX_data_edit_object(C)) {
|
||||||
obedit_circle_select(&eval_ctx, &vc, select, mval, (float)radius);
|
obedit_circle_select(&eval_ctx, &vc, select, mval, (float)radius);
|
||||||
@@ -2855,19 +2899,18 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
|
|||||||
pose_circle_select(&vc, select, mval, (float)radius);
|
pose_circle_select(&vc, select, mval, (float)radius);
|
||||||
else
|
else
|
||||||
return PE_circle_select(C, select, mval, (float)radius);
|
return PE_circle_select(C, select, mval, (float)radius);
|
||||||
|
|
||||||
|
} FOREACH_OBJECT_IN_MODE_END;
|
||||||
}
|
}
|
||||||
else if (obact && obact->mode & OB_MODE_SCULPT) {
|
else if (obact && obact->mode & OB_MODE_SCULPT) {
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ViewContext vc;
|
|
||||||
ED_view3d_viewcontext_init(C, &vc);
|
|
||||||
|
|
||||||
if (object_circle_select(&vc, select, mval, (float)radius)) {
|
if (object_circle_select(&vc, select, mval, (float)radius)) {
|
||||||
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, scene);
|
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc.scene);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
struct Depsgraph;
|
struct Depsgraph;
|
||||||
struct TransInfo;
|
struct TransInfo;
|
||||||
|
struct TransHandle;
|
||||||
struct TransData;
|
struct TransData;
|
||||||
struct TransformOrientation;
|
struct TransformOrientation;
|
||||||
struct TransSnap;
|
struct TransSnap;
|
||||||
@@ -109,7 +110,7 @@ typedef struct TransSnap {
|
|||||||
* \note Return value can be anything,
|
* \note Return value can be anything,
|
||||||
* where the smallest absolute value defines whats closest.
|
* where the smallest absolute value defines whats closest.
|
||||||
*/
|
*/
|
||||||
float (*distance)(struct TransInfo *, const float p1[3], const float p2[3]);
|
float (*distance)(struct TransInfo *t, const float p1[3], const float p2[3]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re-usable snap context data.
|
* Re-usable snap context data.
|
||||||
@@ -127,14 +128,16 @@ typedef struct TransCon {
|
|||||||
/* the one in TransInfo is not garanty to stay the same (Rotates change it) */
|
/* the one in TransInfo is not garanty to stay the same (Rotates change it) */
|
||||||
int mode; /* Mode flags of the Constraint */
|
int mode; /* Mode flags of the Constraint */
|
||||||
void (*drawExtra)(struct TransInfo *t);
|
void (*drawExtra)(struct TransInfo *t);
|
||||||
|
|
||||||
|
/* Note: if 'th' is NULL, 'td' must also be NULL. */
|
||||||
/* For constraints that needs to draw differently from the other
|
/* For constraints that needs to draw differently from the other
|
||||||
* uses this instead of the generic draw function */
|
* uses this instead of the generic draw function */
|
||||||
void (*applyVec)(struct TransInfo *t, struct TransData *td, const float in[3], float out[3], float pvec[3]);
|
void (*applyVec)(struct TransInfo *t, struct TransHandle *th, struct TransData *td, const float in[3], float out[3], float pvec[3]);
|
||||||
/* Apply function pointer for linear vectorial transformation */
|
/* Apply function pointer for linear vectorial transformation */
|
||||||
/* The last three parameters are pointers to the in/out/printable vectors */
|
/* The last three parameters are pointers to the in/out/printable vectors */
|
||||||
void (*applySize)(struct TransInfo *t, struct TransData *td, float smat[3][3]);
|
void (*applySize)(struct TransInfo *t, struct TransHandle *th, struct TransData *td, float smat[3][3]);
|
||||||
/* Apply function pointer for size transformation */
|
/* Apply function pointer for size transformation */
|
||||||
void (*applyRot)(struct TransInfo *t, struct TransData *td, float vec[3], float *angle);
|
void (*applyRot)(struct TransInfo *t, struct TransHandle *th, struct TransData *td, float vec[3], float *angle);
|
||||||
/* Apply function pointer for rotation transformation */
|
/* Apply function pointer for rotation transformation */
|
||||||
} TransCon;
|
} TransCon;
|
||||||
|
|
||||||
@@ -378,11 +381,50 @@ typedef struct TransCustomData {
|
|||||||
} TransCustomData;
|
} TransCustomData;
|
||||||
|
|
||||||
typedef struct TransCenterData {
|
typedef struct TransCenterData {
|
||||||
float local[3], global[3];
|
// float local[3],
|
||||||
|
float global[3];
|
||||||
unsigned int is_set : 1;
|
unsigned int is_set : 1;
|
||||||
} TransCenterData;
|
} TransCenterData;
|
||||||
|
|
||||||
|
typedef struct TransHandle {
|
||||||
|
/* Use for cases we care about the active, eg: active vert of active mesh.
|
||||||
|
* if set this will _always_ be the first item in the array. */
|
||||||
|
bool is_active;
|
||||||
|
|
||||||
|
TransData *data; /* transformed data (array) */
|
||||||
|
TransDataExtension *ext; /* transformed data extension (array) */
|
||||||
|
TransData2D *data2d; /* transformed data for 2d (array) */
|
||||||
|
int total; /* total number of transformed data */
|
||||||
|
|
||||||
|
struct Object *obedit;
|
||||||
|
float obedit_mat[3][3]; /* normalized editmode matrix (T_EDIT only) */
|
||||||
|
|
||||||
|
struct Object *poseobj; /* if t->flag & T_POSE, this denotes pose object */
|
||||||
|
|
||||||
|
/* center of transformation (in local-space) */
|
||||||
|
float center_local[3];
|
||||||
|
/**
|
||||||
|
* Rule of thumb for choosing between mode/type:
|
||||||
|
* - If transform mode uses the data, assign to `mode`
|
||||||
|
* (typically in transform.c).
|
||||||
|
* - If conversion uses the data as an extension to the #TransData, assign to `type`
|
||||||
|
* (typically in transform_conversion.c).
|
||||||
|
*/
|
||||||
|
struct {
|
||||||
|
/* owned by the mode (grab, scale, bend... )*/
|
||||||
|
union {
|
||||||
|
TransCustomData mode, first_elem;
|
||||||
|
};
|
||||||
|
TransCustomData type;
|
||||||
|
} custom;
|
||||||
|
#define TRANS_CUSTOM_DATA_ELEM_MAX (sizeof(((TransHandle *)NULL)->custom) / sizeof(TransCustomData))
|
||||||
|
} TransHandle;
|
||||||
|
|
||||||
typedef struct TransInfo {
|
typedef struct TransInfo {
|
||||||
|
TransHandle *thand;
|
||||||
|
int thand_len;
|
||||||
|
int total_all_handle;
|
||||||
|
|
||||||
int mode; /* current mode */
|
int mode; /* current mode */
|
||||||
int flag; /* generic flags for special behaviors */
|
int flag; /* generic flags for special behaviors */
|
||||||
int modifiers; /* special modifiers, by function, not key */
|
int modifiers; /* special modifiers, by function, not key */
|
||||||
@@ -393,10 +435,6 @@ typedef struct TransInfo {
|
|||||||
/* transform function pointer */
|
/* transform function pointer */
|
||||||
eRedrawFlag (*handleEvent)(struct TransInfo *, const struct wmEvent *);
|
eRedrawFlag (*handleEvent)(struct TransInfo *, const struct wmEvent *);
|
||||||
/* event handler function pointer RETURN 1 if redraw is needed */
|
/* event handler function pointer RETURN 1 if redraw is needed */
|
||||||
int total; /* total number of transformed data */
|
|
||||||
TransData *data; /* transformed data (array) */
|
|
||||||
TransDataExtension *ext; /* transformed data extension (array) */
|
|
||||||
TransData2D *data2d; /* transformed data for 2d (array) */
|
|
||||||
TransCon con; /* transformed constraint */
|
TransCon con; /* transformed constraint */
|
||||||
TransSnap tsnap;
|
TransSnap tsnap;
|
||||||
NumInput num; /* numerical input */
|
NumInput num; /* numerical input */
|
||||||
@@ -406,7 +444,6 @@ typedef struct TransInfo {
|
|||||||
char proptext[20]; /* proportional falloff text */
|
char proptext[20]; /* proportional falloff text */
|
||||||
float aspect[3]; /* spaces using non 1:1 aspect, (uv's, f-curve, movie-clip... etc)
|
float aspect[3]; /* spaces using non 1:1 aspect, (uv's, f-curve, movie-clip... etc)
|
||||||
* use for conversion and snapping. */
|
* use for conversion and snapping. */
|
||||||
float center[3]; /* center of transformation (in local-space) */
|
|
||||||
float center_global[3]; /* center of transformation (in global-space) */
|
float center_global[3]; /* center of transformation (in global-space) */
|
||||||
float center2d[2]; /* center in screen coordinates */
|
float center2d[2]; /* center in screen coordinates */
|
||||||
/* Lazy initialize center data for when we need other center values.
|
/* Lazy initialize center data for when we need other center values.
|
||||||
@@ -425,6 +462,7 @@ typedef struct TransInfo {
|
|||||||
short around;
|
short around;
|
||||||
char spacetype; /* spacetype where transforming is */
|
char spacetype; /* spacetype where transforming is */
|
||||||
char helpline; /* helpline modes (not to be confused with hotline) */
|
char helpline; /* helpline modes (not to be confused with hotline) */
|
||||||
|
short obedit_type; /* Avoid looking inside TransHandle obedit. */
|
||||||
|
|
||||||
float vec[3]; /* translation, to show for widget */
|
float vec[3]; /* translation, to show for widget */
|
||||||
float mat[3][3]; /* rot/rescale, to show for widget */
|
float mat[3][3]; /* rot/rescale, to show for widget */
|
||||||
@@ -432,25 +470,6 @@ typedef struct TransInfo {
|
|||||||
float spacemtx[3][3]; /* orientation matrix of the current space */
|
float spacemtx[3][3]; /* orientation matrix of the current space */
|
||||||
char spacename[64]; /* name of the current space, MAX_NAME */
|
char spacename[64]; /* name of the current space, MAX_NAME */
|
||||||
|
|
||||||
struct Object *poseobj; /* if t->flag & T_POSE, this denotes pose object */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Rule of thumb for choosing between mode/type:
|
|
||||||
* - If transform mode uses the data, assign to `mode`
|
|
||||||
* (typically in transform.c).
|
|
||||||
* - If conversion uses the data as an extension to the #TransData, assign to `type`
|
|
||||||
* (typically in transform_conversion.c).
|
|
||||||
*/
|
|
||||||
struct {
|
|
||||||
/* owned by the mode (grab, scale, bend... )*/
|
|
||||||
union {
|
|
||||||
TransCustomData mode, first_elem;
|
|
||||||
};
|
|
||||||
/* owned by the type (mesh, armature, nla...) */
|
|
||||||
TransCustomData type;
|
|
||||||
} custom;
|
|
||||||
#define TRANS_CUSTOM_DATA_ELEM_MAX (sizeof(((TransInfo *)NULL)->custom) / sizeof(TransCustomData))
|
|
||||||
|
|
||||||
/*************** NEW STUFF *********************/
|
/*************** NEW STUFF *********************/
|
||||||
short launch_event; /* event type used to launch transform */
|
short launch_event; /* event type used to launch transform */
|
||||||
|
|
||||||
@@ -484,8 +503,6 @@ typedef struct TransInfo {
|
|||||||
struct ReportList *reports; /* assign from the operator, or can be NULL */
|
struct ReportList *reports; /* assign from the operator, or can be NULL */
|
||||||
int mval[2]; /* current mouse position */
|
int mval[2]; /* current mouse position */
|
||||||
float zfac; /* use for 3d view */
|
float zfac; /* use for 3d view */
|
||||||
struct Object *obedit;
|
|
||||||
float obedit_mat[3][3]; /* normalized editmode matrix (T_EDIT only) */
|
|
||||||
void *draw_handle_apply;
|
void *draw_handle_apply;
|
||||||
void *draw_handle_view;
|
void *draw_handle_view;
|
||||||
void *draw_handle_pixel;
|
void *draw_handle_pixel;
|
||||||
@@ -773,9 +790,7 @@ void restoreTransObjects(TransInfo *t);
|
|||||||
void recalcData(TransInfo *t);
|
void recalcData(TransInfo *t);
|
||||||
|
|
||||||
void calculateCenter2D(TransInfo *t);
|
void calculateCenter2D(TransInfo *t);
|
||||||
void calculateCenterGlobal(
|
void calculateCenterLocal(TransInfo *t, const float center_global[3]);
|
||||||
TransInfo *t, const float center_local[3],
|
|
||||||
float r_center_global[3]);
|
|
||||||
|
|
||||||
const TransCenterData *transformCenter_from_type(TransInfo *t, int around);
|
const TransCenterData *transformCenter_from_type(TransInfo *t, int around);
|
||||||
void calculateCenter(TransInfo *t);
|
void calculateCenter(TransInfo *t);
|
||||||
@@ -831,4 +846,18 @@ bool checkUseAxisMatrix(TransInfo *t);
|
|||||||
#define TRANSFORM_SNAP_MAX_PX 100.0f
|
#define TRANSFORM_SNAP_MAX_PX 100.0f
|
||||||
#define TRANSFORM_DIST_INVALID -FLT_MAX
|
#define TRANSFORM_DIST_INVALID -FLT_MAX
|
||||||
|
|
||||||
|
/* Temp macros. */
|
||||||
|
|
||||||
|
/* This is to be replaced, just to get things compiling early on. */
|
||||||
|
#define THAND_FIRST_EVIL(t) (&(t)->thand[0])
|
||||||
|
#define THAND_FIRST_OK(t) (&(t)->thand[0])
|
||||||
|
/* For cases we _know_ there is only one handle. */
|
||||||
|
#define THAND_FIRST_SINGLE(t) (BLI_assert((t)->thand_len == 1), (&(t)->thand[0]))
|
||||||
|
|
||||||
|
#define FOREACH_THAND(t, th) \
|
||||||
|
for (TransHandle *th = t->thand, *th_end = t->thand + t->thand_len; th != th_end; th++)
|
||||||
|
|
||||||
|
#define FOREACH_THAND_INDEX(t, th, i) \
|
||||||
|
for (TransHandle *th = ((i = 0), t->thand), *th_end = t->thand + t->thand_len; th != th_end; th++, i++)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -333,7 +333,8 @@ static void planeProjection(TransInfo *t, const float in[3], float out[3])
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3])
|
static void applyAxisConstraintVec(
|
||||||
|
TransInfo *t, TransHandle *UNUSED(th), TransData *td, const float in[3], float out[3], float pvec[3])
|
||||||
{
|
{
|
||||||
copy_v3_v3(out, in);
|
copy_v3_v3(out, in);
|
||||||
if (!td && t->con.mode & CON_APPLY) {
|
if (!td && t->con.mode & CON_APPLY) {
|
||||||
@@ -380,7 +381,8 @@ static void applyAxisConstraintVec(TransInfo *t, TransData *td, const float in[3
|
|||||||
* Further down, that vector is mapped to each data's space.
|
* Further down, that vector is mapped to each data's space.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in[3], float out[3], float pvec[3])
|
static void applyObjectConstraintVec(
|
||||||
|
TransInfo *t, TransHandle *th, TransData *td, const float in[3], float out[3], float pvec[3])
|
||||||
{
|
{
|
||||||
copy_v3_v3(out, in);
|
copy_v3_v3(out, in);
|
||||||
if (t->con.mode & CON_APPLY) {
|
if (t->con.mode & CON_APPLY) {
|
||||||
@@ -428,7 +430,7 @@ static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in
|
|||||||
|
|
||||||
mul_m3_v3(td->axismtx, out);
|
mul_m3_v3(td->axismtx, out);
|
||||||
if (t->flag & T_EDIT) {
|
if (t->flag & T_EDIT) {
|
||||||
mul_m3_v3(t->obedit_mat, out);
|
mul_m3_v3(th->obedit_mat, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -438,7 +440,8 @@ static void applyObjectConstraintVec(TransInfo *t, TransData *td, const float in
|
|||||||
* Generic callback for constant spatial constraints applied to resize motion
|
* Generic callback for constant spatial constraints applied to resize motion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void applyAxisConstraintSize(TransInfo *t, TransData *td, float smat[3][3])
|
static void applyAxisConstraintSize(
|
||||||
|
TransInfo *t, TransHandle *UNUSED(th), TransData *td, float smat[3][3])
|
||||||
{
|
{
|
||||||
if (!td && t->con.mode & CON_APPLY) {
|
if (!td && t->con.mode & CON_APPLY) {
|
||||||
float tmat[3][3];
|
float tmat[3][3];
|
||||||
@@ -462,7 +465,8 @@ static void applyAxisConstraintSize(TransInfo *t, TransData *td, float smat[3][3
|
|||||||
* Callback for object based spatial constraints applied to resize motion
|
* Callback for object based spatial constraints applied to resize motion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void applyObjectConstraintSize(TransInfo *t, TransData *td, float smat[3][3])
|
static void applyObjectConstraintSize(
|
||||||
|
TransInfo *t, TransHandle *th, TransData *td, float smat[3][3])
|
||||||
{
|
{
|
||||||
if (td && t->con.mode & CON_APPLY) {
|
if (td && t->con.mode & CON_APPLY) {
|
||||||
float tmat[3][3];
|
float tmat[3][3];
|
||||||
@@ -482,7 +486,7 @@ static void applyObjectConstraintSize(TransInfo *t, TransData *td, float smat[3]
|
|||||||
|
|
||||||
mul_m3_m3m3(tmat, smat, imat);
|
mul_m3_m3m3(tmat, smat, imat);
|
||||||
if (t->flag & T_EDIT) {
|
if (t->flag & T_EDIT) {
|
||||||
mul_m3_m3m3(smat, t->obedit_mat, smat);
|
mul_m3_m3m3(smat, th->obedit_mat, smat);
|
||||||
}
|
}
|
||||||
mul_m3_m3m3(smat, td->axismtx, tmat);
|
mul_m3_m3m3(smat, td->axismtx, tmat);
|
||||||
}
|
}
|
||||||
@@ -502,7 +506,7 @@ static void applyObjectConstraintSize(TransInfo *t, TransData *td, float smat[3]
|
|||||||
* (ie: not doing counterclockwise rotations when the mouse moves clockwise).
|
* (ie: not doing counterclockwise rotations when the mouse moves clockwise).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3], float *angle)
|
static void applyAxisConstraintRot(TransInfo *t, TransHandle *UNUSED(th), TransData *td, float vec[3], float *angle)
|
||||||
{
|
{
|
||||||
if (!td && t->con.mode & CON_APPLY) {
|
if (!td && t->con.mode & CON_APPLY) {
|
||||||
int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
|
int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
|
||||||
@@ -544,7 +548,8 @@ static void applyAxisConstraintRot(TransInfo *t, TransData *td, float vec[3], fl
|
|||||||
* (ie: not doing counterclockwise rotations when the mouse moves clockwise).
|
* (ie: not doing counterclockwise rotations when the mouse moves clockwise).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void applyObjectConstraintRot(TransInfo *t, TransData *td, float vec[3], float *angle)
|
static void applyObjectConstraintRot(
|
||||||
|
TransInfo *t, TransHandle *th, TransData *td, float vec[3], float *angle)
|
||||||
{
|
{
|
||||||
if (t->con.mode & CON_APPLY) {
|
if (t->con.mode & CON_APPLY) {
|
||||||
int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
|
int mode = t->con.mode & (CON_AXIS0 | CON_AXIS1 | CON_AXIS2);
|
||||||
@@ -553,11 +558,11 @@ static void applyObjectConstraintRot(TransInfo *t, TransData *td, float vec[3],
|
|||||||
|
|
||||||
/* on setup call, use first object */
|
/* on setup call, use first object */
|
||||||
if (td == NULL) {
|
if (td == NULL) {
|
||||||
td = t->data;
|
td = th->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t->flag & T_EDIT) {
|
if (t->flag & T_EDIT) {
|
||||||
mul_m3_m3m3(tmp_axismtx, t->obedit_mat, td->axismtx);
|
mul_m3_m3m3(tmp_axismtx, th->obedit_mat, td->axismtx);
|
||||||
axismtx = tmp_axismtx;
|
axismtx = tmp_axismtx;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -607,20 +612,21 @@ void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[])
|
|||||||
/* applies individual td->axismtx constraints */
|
/* applies individual td->axismtx constraints */
|
||||||
void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[])
|
void setAxisMatrixConstraint(TransInfo *t, int mode, const char text[])
|
||||||
{
|
{
|
||||||
if (t->total == 1) {
|
TransHandle *th = t->thand;
|
||||||
|
if (t->total_all_handle == 1) {
|
||||||
float axismtx[3][3];
|
float axismtx[3][3];
|
||||||
if (t->flag & T_EDIT) {
|
if (t->flag & T_EDIT) {
|
||||||
mul_m3_m3m3(axismtx, t->obedit_mat, t->data->axismtx);
|
mul_m3_m3m3(axismtx, th->obedit_mat, th->data->axismtx);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
copy_m3_m3(axismtx, t->data->axismtx);
|
copy_m3_m3(axismtx, th->data->axismtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
setConstraint(t, axismtx, mode, text);
|
setConstraint(t, axismtx, mode, text);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
|
BLI_strncpy(t->con.text + 1, text, sizeof(t->con.text) - 1);
|
||||||
copy_m3_m3(t->con.mtx, t->data->axismtx);
|
copy_m3_m3(t->con.mtx, th->data->axismtx);
|
||||||
t->con.mode = mode;
|
t->con.mode = mode;
|
||||||
getConstraintMatrix(t);
|
getConstraintMatrix(t);
|
||||||
|
|
||||||
@@ -638,7 +644,9 @@ void setLocalConstraint(TransInfo *t, int mode, const char text[])
|
|||||||
{
|
{
|
||||||
/* edit-mode now allows local transforms too */
|
/* edit-mode now allows local transforms too */
|
||||||
if (t->flag & T_EDIT) {
|
if (t->flag & T_EDIT) {
|
||||||
setConstraint(t, t->obedit_mat, mode, text);
|
/* Use the active (first) edit object. */
|
||||||
|
TransHandle *th = t->thand;
|
||||||
|
setConstraint(t, th->obedit_mat, mode, text);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setAxisMatrixConstraint(t, mode, text);
|
setAxisMatrixConstraint(t, mode, text);
|
||||||
@@ -836,11 +844,12 @@ static void drawObjectConstraint(TransInfo *t)
|
|||||||
* Without drawing the first light, users have little clue what they are doing.
|
* Without drawing the first light, users have little clue what they are doing.
|
||||||
*/
|
*/
|
||||||
short options = DRAWLIGHT;
|
short options = DRAWLIGHT;
|
||||||
TransData *td = t->data;
|
|
||||||
int i;
|
int i;
|
||||||
float tmp_axismtx[3][3];
|
float tmp_axismtx[3][3];
|
||||||
|
|
||||||
for (i = 0; i < t->total; i++, td++) {
|
FOREACH_THAND (t, th) {
|
||||||
|
TransData *td = th->data;
|
||||||
|
for (i = 0; i < th->total; i++, td++) {
|
||||||
float co[3];
|
float co[3];
|
||||||
float (*axismtx)[3];
|
float (*axismtx)[3];
|
||||||
|
|
||||||
@@ -863,13 +872,13 @@ static void drawObjectConstraint(TransInfo *t)
|
|||||||
axismtx = td->axismtx;
|
axismtx = td->axismtx;
|
||||||
}
|
}
|
||||||
else if (t->flag & T_EDIT) {
|
else if (t->flag & T_EDIT) {
|
||||||
mul_v3_m4v3(co, t->obedit->obmat, td->center);
|
mul_v3_m4v3(co, th->obedit->obmat, td->center);
|
||||||
|
|
||||||
mul_m3_m3m3(tmp_axismtx, t->obedit_mat, td->axismtx);
|
mul_m3_m3m3(tmp_axismtx, th->obedit_mat, td->axismtx);
|
||||||
axismtx = tmp_axismtx;
|
axismtx = tmp_axismtx;
|
||||||
}
|
}
|
||||||
else if (t->flag & T_POSE) {
|
else if (t->flag & T_POSE) {
|
||||||
mul_v3_m4v3(co, t->poseobj->obmat, td->center);
|
mul_v3_m4v3(co, th->poseobj->obmat, td->center);
|
||||||
axismtx = td->axismtx;
|
axismtx = td->axismtx;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -888,6 +897,7 @@ static void drawObjectConstraint(TransInfo *t)
|
|||||||
}
|
}
|
||||||
options &= ~DRAWLIGHT;
|
options &= ~DRAWLIGHT;
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*--------------------- START / STOP CONSTRAINTS ---------------------- */
|
/*--------------------- START / STOP CONSTRAINTS ---------------------- */
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -82,6 +82,7 @@
|
|||||||
#include "BKE_tracking.h"
|
#include "BKE_tracking.h"
|
||||||
#include "BKE_mask.h"
|
#include "BKE_mask.h"
|
||||||
#include "BKE_workspace.h"
|
#include "BKE_workspace.h"
|
||||||
|
#include "BKE_layer.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
|
|
||||||
@@ -127,8 +128,10 @@ void getViewVector(TransInfo *t, float coord[3], float vec[3])
|
|||||||
/* ************************** GENERICS **************************** */
|
/* ************************** GENERICS **************************** */
|
||||||
|
|
||||||
|
|
||||||
static void clipMirrorModifier(TransInfo *t, Object *ob)
|
static void clipMirrorModifier(TransInfo *t)
|
||||||
{
|
{
|
||||||
|
FOREACH_THAND (t, th) {
|
||||||
|
Object *ob = th->obedit;
|
||||||
ModifierData *md = ob->modifiers.first;
|
ModifierData *md = ob->modifiers.first;
|
||||||
float tolerance[3] = {0.0f, 0.0f, 0.0f};
|
float tolerance[3] = {0.0f, 0.0f, 0.0f};
|
||||||
int axis = 0;
|
int axis = 0;
|
||||||
@@ -154,7 +157,6 @@ static void clipMirrorModifier(TransInfo *t, Object *ob)
|
|||||||
if (axis) {
|
if (axis) {
|
||||||
float mtx[4][4], imtx[4][4];
|
float mtx[4][4], imtx[4][4];
|
||||||
int i;
|
int i;
|
||||||
TransData *td = t->data;
|
|
||||||
|
|
||||||
if (mmd->mirror_ob) {
|
if (mmd->mirror_ob) {
|
||||||
float obinv[4][4];
|
float obinv[4][4];
|
||||||
@@ -164,7 +166,8 @@ static void clipMirrorModifier(TransInfo *t, Object *ob)
|
|||||||
invert_m4_m4(imtx, mtx);
|
invert_m4_m4(imtx, mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < t->total; i++, td++) {
|
TransData *td = th->data;
|
||||||
|
for (i = 0; i < th->total; i++, td++) {
|
||||||
int clip;
|
int clip;
|
||||||
float loc[3], iloc[3];
|
float loc[3], iloc[3];
|
||||||
|
|
||||||
@@ -222,16 +225,18 @@ static void clipMirrorModifier(TransInfo *t, Object *ob)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* assumes obedit set to mesh object */
|
/* assumes obedit set to mesh object */
|
||||||
static void editbmesh_apply_to_mirror(TransInfo *t)
|
static void editbmesh_apply_to_mirror(TransInfo *t)
|
||||||
{
|
{
|
||||||
TransData *td = t->data;
|
FOREACH_THAND (t, th) {
|
||||||
|
TransData *td = th->data;
|
||||||
BMVert *eve;
|
BMVert *eve;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < t->total; i++, td++) {
|
for (i = 0; i < th->total; i++, td++) {
|
||||||
if (td->flag & TD_NOACTION)
|
if (td->flag & TD_NOACTION)
|
||||||
break;
|
break;
|
||||||
if (td->loc == NULL)
|
if (td->loc == NULL)
|
||||||
@@ -250,6 +255,8 @@ static void editbmesh_apply_to_mirror(TransInfo *t)
|
|||||||
td->loc[0] = 0;
|
td->loc[0] = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for the realtime animation recording feature, handle overlapping data */
|
/* for the realtime animation recording feature, handle overlapping data */
|
||||||
@@ -427,17 +434,19 @@ static void recalcData_graphedit(TransInfo *t)
|
|||||||
/* helper for recalcData() - for NLA Editor transforms */
|
/* helper for recalcData() - for NLA Editor transforms */
|
||||||
static void recalcData_nla(TransInfo *t)
|
static void recalcData_nla(TransInfo *t)
|
||||||
{
|
{
|
||||||
TransDataNla *tdn = t->custom.type.data;
|
TransDataNla *tdn = THAND_FIRST_SINGLE(t)->custom.type.data;
|
||||||
SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
|
SpaceNla *snla = (SpaceNla *)t->sa->spacedata.first;
|
||||||
Scene *scene = t->scene;
|
Scene *scene = t->scene;
|
||||||
double secf = FPS;
|
double secf = FPS;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
TransHandle *th = THAND_FIRST_SINGLE(t);
|
||||||
|
|
||||||
/* for each strip we've got, perform some additional validation of the values that got set before
|
/* for each strip we've got, perform some additional validation of the values that got set before
|
||||||
* using RNA to set the value (which does some special operations when setting these values to make
|
* using RNA to set the value (which does some special operations when setting these values to make
|
||||||
* sure that everything works ok)
|
* sure that everything works ok)
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < t->total; i++, tdn++) {
|
for (i = 0; i < th->total; i++, tdn++) {
|
||||||
NlaStrip *strip = tdn->strip;
|
NlaStrip *strip = tdn->strip;
|
||||||
PointerRNA strip_ptr;
|
PointerRNA strip_ptr;
|
||||||
short pExceeded, nExceeded, iter;
|
short pExceeded, nExceeded, iter;
|
||||||
@@ -654,14 +663,18 @@ static void recalcData_image(TransInfo *t)
|
|||||||
else if (t->options & CTX_PAINT_CURVE) {
|
else if (t->options & CTX_PAINT_CURVE) {
|
||||||
flushTransPaintCurve(t);
|
flushTransPaintCurve(t);
|
||||||
}
|
}
|
||||||
else if (t->obedit && t->obedit->type == OB_MESH) {
|
else if ((t->flag & T_EDIT) && t->obedit_type == OB_MESH) {
|
||||||
SpaceImage *sima = t->sa->spacedata.first;
|
SpaceImage *sima = t->sa->spacedata.first;
|
||||||
|
|
||||||
flushTransUVs(t);
|
flushTransUVs(t);
|
||||||
if (sima->flag & SI_LIVE_UNWRAP)
|
if (sima->flag & SI_LIVE_UNWRAP)
|
||||||
ED_uvedit_live_unwrap_re_solve();
|
ED_uvedit_live_unwrap_re_solve();
|
||||||
|
|
||||||
DEG_id_tag_update(t->obedit->data, 0);
|
FOREACH_THAND (t, th) {
|
||||||
|
if (th->total) {
|
||||||
|
DEG_id_tag_update(th->obedit->data, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -716,19 +729,21 @@ static void recalcData_objects(TransInfo *t)
|
|||||||
{
|
{
|
||||||
Base *base = t->view_layer->basact;
|
Base *base = t->view_layer->basact;
|
||||||
|
|
||||||
if (t->obedit) {
|
if (t->obedit_type != -1) {
|
||||||
if (ELEM(t->obedit->type, OB_CURVE, OB_SURF)) {
|
if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) {
|
||||||
Curve *cu = t->obedit->data;
|
|
||||||
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
|
|
||||||
Nurb *nu = nurbs->first;
|
|
||||||
|
|
||||||
if (t->state != TRANS_CANCEL) {
|
if (t->state != TRANS_CANCEL) {
|
||||||
clipMirrorModifier(t, t->obedit);
|
clipMirrorModifier(t);
|
||||||
applyProject(t);
|
applyProject(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
|
FOREACH_THAND (t, th) {
|
||||||
|
Curve *cu = th->obedit->data;
|
||||||
|
ListBase *nurbs = BKE_curve_editNurbs_get(cu);
|
||||||
|
Nurb *nu = nurbs->first;
|
||||||
|
|
||||||
|
DEG_id_tag_update(th->obedit->data, 0); /* sets recalc flags */
|
||||||
|
|
||||||
if (t->state == TRANS_CANCEL) {
|
if (t->state == TRANS_CANCEL) {
|
||||||
while (nu) {
|
while (nu) {
|
||||||
BKE_nurb_handles_calc(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
|
BKE_nurb_handles_calc(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
|
||||||
@@ -743,25 +758,28 @@ static void recalcData_objects(TransInfo *t)
|
|||||||
nu = nu->next;
|
nu = nu->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
else if (t->obedit->type == OB_LATTICE) {
|
else if (t->obedit_type == OB_LATTICE) {
|
||||||
Lattice *la = t->obedit->data;
|
|
||||||
|
|
||||||
if (t->state != TRANS_CANCEL) {
|
if (t->state != TRANS_CANCEL) {
|
||||||
applyProject(t);
|
applyProject(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
|
FOREACH_THAND (t, th) {
|
||||||
|
Lattice *la = th->obedit->data;
|
||||||
if (la->editlatt->latt->flag & LT_OUTSIDE) outside_lattice(la->editlatt->latt);
|
DEG_id_tag_update(th->obedit->data, 0); /* sets recalc flags */
|
||||||
|
if (la->editlatt->latt->flag & LT_OUTSIDE) {
|
||||||
|
outside_lattice(la->editlatt->latt);
|
||||||
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
else if (t->obedit->type == OB_MESH) {
|
else if (t->obedit_type == OB_MESH) {
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(t->obedit);
|
|
||||||
/* mirror modifier clipping? */
|
/* mirror modifier clipping? */
|
||||||
if (t->state != TRANS_CANCEL) {
|
if (t->state != TRANS_CANCEL) {
|
||||||
/* apply clipping after so we never project past the clip plane [#25423] */
|
/* apply clipping after so we never project past the clip plane [#25423] */
|
||||||
applyProject(t);
|
applyProject(t);
|
||||||
clipMirrorModifier(t, t->obedit);
|
clipMirrorModifier(t);
|
||||||
}
|
}
|
||||||
if ((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
|
if ((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
|
||||||
editbmesh_apply_to_mirror(t);
|
editbmesh_apply_to_mirror(t);
|
||||||
@@ -773,26 +791,32 @@ static void recalcData_objects(TransInfo *t)
|
|||||||
projectVertSlideData(t, false);
|
projectVertSlideData(t, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
|
FOREACH_THAND (t, th) {
|
||||||
|
DEG_id_tag_update(th->obedit->data, 0); /* sets recalc flags */
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(th->obedit);
|
||||||
EDBM_mesh_normals_update(em);
|
EDBM_mesh_normals_update(em);
|
||||||
BKE_editmesh_tessface_calc(em);
|
BKE_editmesh_tessface_calc(em);
|
||||||
}
|
} // FIXME(indent)
|
||||||
else if (t->obedit->type == OB_ARMATURE) { /* no recalc flag, does pose */
|
|
||||||
bArmature *arm = t->obedit->data;
|
|
||||||
ListBase *edbo = arm->edbo;
|
|
||||||
EditBone *ebo, *ebo_parent;
|
|
||||||
TransData *td = t->data;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (t->obedit_type == OB_ARMATURE) { /* no recalc flag, does pose */
|
||||||
|
|
||||||
if (t->state != TRANS_CANCEL) {
|
if (t->state != TRANS_CANCEL) {
|
||||||
applyProject(t);
|
applyProject(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FOREACH_THAND (t, th) {
|
||||||
|
bArmature *arm = th->obedit->data;
|
||||||
|
ListBase *edbo = arm->edbo;
|
||||||
|
EditBone *ebo, *ebo_parent;
|
||||||
|
TransData *td = th->data;
|
||||||
|
int i;
|
||||||
|
|
||||||
/* Ensure all bones are correctly adjusted */
|
/* Ensure all bones are correctly adjusted */
|
||||||
for (ebo = edbo->first; ebo; ebo = ebo->next) {
|
for (ebo = edbo->first; ebo; ebo = ebo->next) {
|
||||||
ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : NULL;
|
ebo_parent = (ebo->flag & BONE_CONNECTED) ? ebo->parent : NULL;
|
||||||
|
|
||||||
if (ebo_parent) {
|
if (ebo_parent) {
|
||||||
/* If this bone has a parent tip that has been moved */
|
/* If this bone has a parent tip that has been moved */
|
||||||
if (ebo_parent->flag & BONE_TIPSEL) {
|
if (ebo_parent->flag & BONE_TIPSEL) {
|
||||||
@@ -832,7 +856,7 @@ static void recalcData_objects(TransInfo *t)
|
|||||||
|
|
||||||
if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONE_ENVELOPE_DIST, TFM_BONESIZE)) {
|
if (!ELEM(t->mode, TFM_BONE_ROLL, TFM_BONE_ENVELOPE, TFM_BONE_ENVELOPE_DIST, TFM_BONESIZE)) {
|
||||||
/* fix roll */
|
/* fix roll */
|
||||||
for (i = 0; i < t->total; i++, td++) {
|
for (i = 0; i < th->total; i++, td++) {
|
||||||
if (td->extra) {
|
if (td->extra) {
|
||||||
float vec[3], up_axis[3];
|
float vec[3], up_axis[3];
|
||||||
float qrot[4];
|
float qrot[4];
|
||||||
@@ -859,23 +883,32 @@ static void recalcData_objects(TransInfo *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arm->flag & ARM_MIRROR_EDIT) {
|
if (arm->flag & ARM_MIRROR_EDIT) {
|
||||||
if (t->state != TRANS_CANCEL)
|
if (t->state != TRANS_CANCEL) {
|
||||||
transform_armature_mirror_update(t->obedit);
|
transform_armature_mirror_update(th->obedit);
|
||||||
else
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
restoreBones(t);
|
restoreBones(t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (t->state != TRANS_CANCEL) {
|
if (t->state != TRANS_CANCEL) {
|
||||||
applyProject(t);
|
applyProject(t);
|
||||||
}
|
}
|
||||||
DEG_id_tag_update(t->obedit->data, 0); /* sets recalc flags */
|
FOREACH_THAND (t, th) {
|
||||||
|
if (th->total) {
|
||||||
|
DEG_id_tag_update(th->obedit->data, 0); /* sets recalc flags */
|
||||||
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if ((t->flag & T_POSE) && t->poseobj) {
|
else if (t->flag & T_POSE) {
|
||||||
Object *ob = t->poseobj;
|
FOREACH_THAND (t, th) {
|
||||||
|
Object *ob = th->poseobj;
|
||||||
bArmature *arm = ob->data;
|
bArmature *arm = ob->data;
|
||||||
|
|
||||||
/* if animtimer is running, and the object already has animation data,
|
/* if animtimer is running, and the object already has animation data,
|
||||||
@@ -900,6 +933,7 @@ static void recalcData_objects(TransInfo *t)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
BKE_pose_where_is(&t->eval_ctx, t->scene, ob);
|
BKE_pose_where_is(&t->eval_ctx, t->scene, ob);
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) &&
|
else if (base && (base->object->mode & OB_MODE_PARTICLE_EDIT) &&
|
||||||
PE_get_current(t->scene, base->object))
|
PE_get_current(t->scene, base->object))
|
||||||
@@ -915,9 +949,11 @@ static void recalcData_objects(TransInfo *t)
|
|||||||
if (t->state != TRANS_CANCEL) {
|
if (t->state != TRANS_CANCEL) {
|
||||||
applyProject(t);
|
applyProject(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < t->total; i++) {
|
FOREACH_THAND (t, th) {
|
||||||
TransData *td = t->data + i;
|
TransData *td = th->data;
|
||||||
|
|
||||||
|
for (i = 0; i < th->total; i++, td++) {
|
||||||
Object *ob = td->ob;
|
Object *ob = td->ob;
|
||||||
|
|
||||||
if (td->flag & TD_NOACTION)
|
if (td->flag & TD_NOACTION)
|
||||||
@@ -944,6 +980,7 @@ static void recalcData_objects(TransInfo *t)
|
|||||||
if (t->flag & T_TEXTURE)
|
if (t->flag & T_TEXTURE)
|
||||||
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -954,7 +991,9 @@ static void recalcData_sequencer(TransInfo *t)
|
|||||||
int a;
|
int a;
|
||||||
Sequence *seq_prev = NULL;
|
Sequence *seq_prev = NULL;
|
||||||
|
|
||||||
for (a = 0, td = t->data; a < t->total; a++, td++) {
|
TransHandle *th = THAND_FIRST_SINGLE(t);
|
||||||
|
|
||||||
|
for (a = 0, td = th->data; a < th->total; a++, td++) {
|
||||||
TransDataSeq *tdsq = (TransDataSeq *) td->extra;
|
TransDataSeq *tdsq = (TransDataSeq *) td->extra;
|
||||||
Sequence *seq = tdsq->seq;
|
Sequence *seq = tdsq->seq;
|
||||||
|
|
||||||
@@ -979,8 +1018,10 @@ static void recalcData_sequencer(TransInfo *t)
|
|||||||
/* force recalculation of triangles during transformation */
|
/* force recalculation of triangles during transformation */
|
||||||
static void recalcData_gpencil_strokes(TransInfo *t)
|
static void recalcData_gpencil_strokes(TransInfo *t)
|
||||||
{
|
{
|
||||||
TransData *td = t->data;
|
TransHandle *th = THAND_FIRST_SINGLE(t);
|
||||||
for (int i = 0; i < t->total; i++, td++) {
|
|
||||||
|
TransData *td = th->data;
|
||||||
|
for (int i = 0; i < th->total; i++, td++) {
|
||||||
bGPDstroke *gps = td->extra;
|
bGPDstroke *gps = td->extra;
|
||||||
if (gps != NULL) {
|
if (gps != NULL) {
|
||||||
gps->flag |= GP_STROKE_RECALC_CACHES;
|
gps->flag |= GP_STROKE_RECALC_CACHES;
|
||||||
@@ -1078,12 +1119,18 @@ void drawLine(TransInfo *t, const float center[3], const float dir[3], char axis
|
|||||||
*/
|
*/
|
||||||
void resetTransModal(TransInfo *t)
|
void resetTransModal(TransInfo *t)
|
||||||
{
|
{
|
||||||
|
FOREACH_THAND (t, th) {
|
||||||
if (t->mode == TFM_EDGE_SLIDE) {
|
if (t->mode == TFM_EDGE_SLIDE) {
|
||||||
freeEdgeSlideVerts(t, &t->custom.mode);
|
freeEdgeSlideVerts(t, &th->custom.mode);
|
||||||
}
|
}
|
||||||
else if (t->mode == TFM_VERT_SLIDE) {
|
else if (t->mode == TFM_VERT_SLIDE) {
|
||||||
freeVertSlideVerts(t, &t->custom.mode);
|
freeVertSlideVerts(t, &th->custom.mode);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
/* no need to keep looping... */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
void resetTransRestrictions(TransInfo *t)
|
void resetTransRestrictions(TransInfo *t)
|
||||||
@@ -1133,22 +1180,40 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||||||
t->engine_type = engine_type;
|
t->engine_type = engine_type;
|
||||||
t->sa = sa;
|
t->sa = sa;
|
||||||
t->ar = ar;
|
t->ar = ar;
|
||||||
t->obedit = obedit;
|
|
||||||
t->settings = ts;
|
t->settings = ts;
|
||||||
t->reports = op ? op->reports : NULL;
|
t->reports = op ? op->reports : NULL;
|
||||||
|
|
||||||
if (obedit) {
|
if (t->thand == NULL) {
|
||||||
copy_m3_m4(t->obedit_mat, obedit->obmat);
|
t->thand = MEM_callocN(sizeof(*t->thand), __func__);
|
||||||
normalize_m3(t->obedit_mat);
|
t->thand_len = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
t->data = NULL;
|
|
||||||
t->ext = NULL;
|
|
||||||
|
|
||||||
t->helpline = HLP_NONE;
|
t->helpline = HLP_NONE;
|
||||||
|
|
||||||
t->flag = 0;
|
t->flag = 0;
|
||||||
|
|
||||||
|
if (CTX_data_edit_object(C) /* || pose mode .. etc. */) {
|
||||||
|
uint objects_len;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_mode(
|
||||||
|
t->view_layer, &objects_len,
|
||||||
|
.object_mode = OB_MODE_EDIT,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
t->thand = MEM_callocN(sizeof(*t->thand) * objects_len, __func__);
|
||||||
|
t->thand_len = objects_len;
|
||||||
|
|
||||||
|
for (int i = 0; i < objects_len; i++) {
|
||||||
|
TransHandle *th = &t->thand[i];
|
||||||
|
th->obedit = objects[i];
|
||||||
|
copy_m3_m4(th->obedit_mat, obedit->obmat);
|
||||||
|
normalize_m3(th->obedit_mat);
|
||||||
|
}
|
||||||
|
t->obedit_type = objects[0]->type;
|
||||||
|
t->flag |= T_EDIT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
t->obedit_type = -1;
|
||||||
|
}
|
||||||
|
|
||||||
t->redraw = TREDRAW_HARD; /* redraw first time */
|
t->redraw = TREDRAW_HARD; /* redraw first time */
|
||||||
|
|
||||||
if (event) {
|
if (event) {
|
||||||
@@ -1169,12 +1234,11 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||||||
t->transform = NULL;
|
t->transform = NULL;
|
||||||
t->handleEvent = NULL;
|
t->handleEvent = NULL;
|
||||||
|
|
||||||
t->total = 0;
|
t->total_all_handle = 0;
|
||||||
|
|
||||||
t->val = 0.0f;
|
t->val = 0.0f;
|
||||||
|
|
||||||
zero_v3(t->vec);
|
zero_v3(t->vec);
|
||||||
zero_v3(t->center);
|
|
||||||
zero_v3(t->center_global);
|
zero_v3(t->center_global);
|
||||||
|
|
||||||
unit_m3(t->mat);
|
unit_m3(t->mat);
|
||||||
@@ -1295,7 +1359,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||||||
t->view = &ar->v2d;
|
t->view = &ar->v2d;
|
||||||
t->around = sima->around;
|
t->around = sima->around;
|
||||||
|
|
||||||
if (ED_space_image_show_uvedit(sima, t->obedit)) {
|
if (ED_space_image_show_uvedit(sima, OBACT(t->view_layer))) {
|
||||||
/* UV transform */
|
/* UV transform */
|
||||||
}
|
}
|
||||||
else if (sima->mode == SI_MODE_MASK) {
|
else if (sima->mode == SI_MODE_MASK) {
|
||||||
@@ -1385,7 +1449,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||||||
}
|
}
|
||||||
// Need stuff to take it from edit mesh or whatnot here
|
// Need stuff to take it from edit mesh or whatnot here
|
||||||
else if (t->spacetype == SPACE_VIEW3D) {
|
else if (t->spacetype == SPACE_VIEW3D) {
|
||||||
if (t->obedit && t->obedit->type == OB_MESH && (((Mesh *)t->obedit->data)->editflag & ME_EDIT_MIRROR_X)) {
|
/* TODO(campbell): xform, get mirror from each object. */
|
||||||
|
if (t->obedit_type == OB_MESH && (((Mesh *)OBACT(t->view_layer)->data)->editflag & ME_EDIT_MIRROR_X)) {
|
||||||
t->flag |= T_MIRROR;
|
t->flag |= T_MIRROR;
|
||||||
t->mirror = 1;
|
t->mirror = 1;
|
||||||
}
|
}
|
||||||
@@ -1406,7 +1471,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||||||
else if (t->spacetype == SPACE_ACTION) {
|
else if (t->spacetype == SPACE_ACTION) {
|
||||||
t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action);
|
t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional_action);
|
||||||
}
|
}
|
||||||
else if (t->obedit) {
|
else if (t->obedit_type != -1) {
|
||||||
t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
|
t->flag |= initTransInfo_edit_pet_to_flag(ts->proportional);
|
||||||
}
|
}
|
||||||
else if (t->options & CTX_GPENCIL_STROKES) {
|
else if (t->options & CTX_GPENCIL_STROKES) {
|
||||||
@@ -1421,7 +1486,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (t->obedit == NULL && ts->proportional_objects) {
|
else if ((t->obedit_type == -1) && ts->proportional_objects) {
|
||||||
t->flag |= T_PROP_EDIT;
|
t->flag |= T_PROP_EDIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1467,8 +1532,8 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||||||
setTransformViewAspect(t, t->aspect);
|
setTransformViewAspect(t, t->aspect);
|
||||||
|
|
||||||
if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) && RNA_property_is_set(op->ptr, prop)) {
|
if (op && (prop = RNA_struct_find_property(op->ptr, "center_override")) && RNA_property_is_set(op->ptr, prop)) {
|
||||||
RNA_property_float_get_array(op->ptr, prop, t->center);
|
RNA_property_float_get_array(op->ptr, prop, t->center_global);
|
||||||
mul_v3_v3(t->center, t->aspect);
|
mul_v3_v3(t->center_global, t->aspect);
|
||||||
t->flag |= T_OVERRIDE_CENTER;
|
t->flag |= T_OVERRIDE_CENTER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1479,8 +1544,6 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
|
|||||||
/* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
|
/* Here I would suggest only TransInfo related issues, like free data & reset vars. Not redraws */
|
||||||
void postTrans(bContext *C, TransInfo *t)
|
void postTrans(bContext *C, TransInfo *t)
|
||||||
{
|
{
|
||||||
TransData *td;
|
|
||||||
|
|
||||||
if (t->draw_handle_view)
|
if (t->draw_handle_view)
|
||||||
ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view);
|
ED_region_draw_cb_exit(t->ar->type, t->draw_handle_view);
|
||||||
if (t->draw_handle_apply)
|
if (t->draw_handle_apply)
|
||||||
@@ -1491,8 +1554,8 @@ void postTrans(bContext *C, TransInfo *t)
|
|||||||
WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
|
WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
|
||||||
|
|
||||||
/* Free all custom-data */
|
/* Free all custom-data */
|
||||||
{
|
FOREACH_THAND (t, th) {
|
||||||
TransCustomData *custom_data = &t->custom.first_elem;
|
TransCustomData *custom_data = &th->custom.first_elem;
|
||||||
for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
|
for (int i = 0; i < TRANS_CUSTOM_DATA_ELEM_MAX; i++, custom_data++) {
|
||||||
if (custom_data->free_cb) {
|
if (custom_data->free_cb) {
|
||||||
/* Can take over freeing t->data and data2d etc... */
|
/* Can take over freeing t->data and data2d etc... */
|
||||||
@@ -1507,30 +1570,31 @@ void postTrans(bContext *C, TransInfo *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* postTrans can be called when nothing is selected, so data is NULL already */
|
/* postTrans can be called when nothing is selected, so data is NULL already */
|
||||||
if (t->data) {
|
if (t->total_all_handle) {
|
||||||
|
FOREACH_THAND (t, th) {
|
||||||
/* free data malloced per trans-data */
|
/* free data malloced per trans-data */
|
||||||
if ((t->obedit && ELEM(t->obedit->type, OB_CURVE, OB_SURF)) ||
|
if (ELEM(t->obedit_type, OB_CURVE, OB_SURF) ||
|
||||||
(t->spacetype == SPACE_IPO))
|
(t->spacetype == SPACE_IPO))
|
||||||
{
|
{
|
||||||
int a;
|
TransData *td = th->data;
|
||||||
for (a = 0, td = t->data; a < t->total; a++, td++) {
|
for (int a = 0; a < th->total; a++, td++) {
|
||||||
if (td->flag & TD_BEZTRIPLE) {
|
if (td->flag & TD_BEZTRIPLE) {
|
||||||
MEM_freeN(td->hdata);
|
MEM_freeN(td->hdata);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
MEM_freeN(th->data);
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(th->ext);
|
||||||
|
MEM_SAFE_FREE(th->data2d);
|
||||||
}
|
}
|
||||||
MEM_freeN(t->data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(t->thand);
|
||||||
|
t->thand = NULL;
|
||||||
|
|
||||||
BLI_freelistN(&t->tsnap.points);
|
BLI_freelistN(&t->tsnap.points);
|
||||||
|
|
||||||
if (t->ext) MEM_freeN(t->ext);
|
|
||||||
if (t->data2d) {
|
|
||||||
MEM_freeN(t->data2d);
|
|
||||||
t->data2d = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (t->spacetype == SPACE_IMAGE) {
|
if (t->spacetype == SPACE_IMAGE) {
|
||||||
if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
|
if (t->options & (CTX_MASK | CTX_PAINT_CURVE)) {
|
||||||
/* pass */
|
/* pass */
|
||||||
@@ -1558,9 +1622,11 @@ void postTrans(bContext *C, TransInfo *t)
|
|||||||
|
|
||||||
void applyTransObjects(TransInfo *t)
|
void applyTransObjects(TransInfo *t)
|
||||||
{
|
{
|
||||||
|
TransHandle *th = THAND_FIRST_SINGLE(t);
|
||||||
|
|
||||||
TransData *td;
|
TransData *td;
|
||||||
|
|
||||||
for (td = t->data; td < t->data + t->total; td++) {
|
for (td = th->data; td < th->data + th->total; td++) {
|
||||||
copy_v3_v3(td->iloc, td->loc);
|
copy_v3_v3(td->iloc, td->loc);
|
||||||
if (td->ext->rot) {
|
if (td->ext->rot) {
|
||||||
copy_v3_v3(td->ext->irot, td->ext->rot);
|
copy_v3_v3(td->ext->irot, td->ext->rot);
|
||||||
@@ -1609,14 +1675,16 @@ static void restoreElement(TransData *td)
|
|||||||
|
|
||||||
void restoreTransObjects(TransInfo *t)
|
void restoreTransObjects(TransInfo *t)
|
||||||
{
|
{
|
||||||
|
FOREACH_THAND (t, th) {
|
||||||
|
|
||||||
TransData *td;
|
TransData *td;
|
||||||
TransData2D *td2d;
|
TransData2D *td2d;
|
||||||
|
|
||||||
for (td = t->data; td < t->data + t->total; td++) {
|
for (td = th->data; td < th->data + th->total; td++) {
|
||||||
restoreElement(td);
|
restoreElement(td);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (td2d = t->data2d; t->data2d && td2d < t->data2d + t->total; td2d++) {
|
for (td2d = th->data2d; th->data2d && td2d < th->data2d + th->total; td2d++) {
|
||||||
if (td2d->h1) {
|
if (td2d->h1) {
|
||||||
td2d->h1[0] = td2d->ih1[0];
|
td2d->h1[0] = td2d->ih1[0];
|
||||||
td2d->h1[1] = td2d->ih1[1];
|
td2d->h1[1] = td2d->ih1[1];
|
||||||
@@ -1628,6 +1696,8 @@ void restoreTransObjects(TransInfo *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
unit_m3(t->mat);
|
unit_m3(t->mat);
|
||||||
|
|
||||||
|
} // FIXME(indent)
|
||||||
|
|
||||||
recalcData(t);
|
recalcData(t);
|
||||||
}
|
}
|
||||||
@@ -1635,32 +1705,26 @@ void restoreTransObjects(TransInfo *t)
|
|||||||
void calculateCenter2D(TransInfo *t)
|
void calculateCenter2D(TransInfo *t)
|
||||||
{
|
{
|
||||||
BLI_assert(!is_zero_v3(t->aspect));
|
BLI_assert(!is_zero_v3(t->aspect));
|
||||||
|
projectFloatView(t, t->center_global, t->center2d);
|
||||||
if (t->flag & (T_EDIT | T_POSE)) {
|
|
||||||
Object *ob = t->obedit ? t->obedit : t->poseobj;
|
|
||||||
float vec[3];
|
|
||||||
|
|
||||||
copy_v3_v3(vec, t->center);
|
|
||||||
mul_m4_v3(ob->obmat, vec);
|
|
||||||
projectFloatView(t, vec, t->center2d);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
projectFloatView(t, t->center, t->center2d);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void calculateCenterGlobal(
|
void calculateCenterLocal(
|
||||||
TransInfo *t, const float center_local[3],
|
TransInfo *t, const float center_global[3])
|
||||||
float r_center_global[3])
|
|
||||||
{
|
{
|
||||||
/* setting constraint center */
|
/* setting constraint center */
|
||||||
/* note, init functions may over-ride t->center */
|
/* note, init functions may over-ride t->center */
|
||||||
if (t->flag & (T_EDIT | T_POSE)) {
|
if (t->flag & (T_EDIT | T_POSE)) {
|
||||||
Object *ob = t->obedit ? t->obedit : t->poseobj;
|
FOREACH_THAND (t, th) {
|
||||||
mul_v3_m4v3(r_center_global, ob->obmat, center_local);
|
float obinv[4][4];
|
||||||
|
Object *ob = th->obedit ? th->obedit : th->poseobj;
|
||||||
|
invert_m4_m4(obinv, ob->obmat);
|
||||||
|
mul_v3_m4v3(th->center_local, obinv, center_global);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
copy_v3_v3(r_center_global, center_local);
|
FOREACH_THAND (t, th) {
|
||||||
|
copy_v3_v3(th->center_local, center_global);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1672,16 +1736,7 @@ void calculateCenterCursor(TransInfo *t, float r_center[3])
|
|||||||
copy_v3_v3(r_center, cursor);
|
copy_v3_v3(r_center, cursor);
|
||||||
|
|
||||||
/* If edit or pose mode, move cursor in local space */
|
/* If edit or pose mode, move cursor in local space */
|
||||||
if (t->flag & (T_EDIT | T_POSE)) {
|
if (t->options & CTX_PAINT_CURVE) {
|
||||||
Object *ob = t->obedit ? t->obedit : t->poseobj;
|
|
||||||
float mat[3][3], imat[3][3];
|
|
||||||
|
|
||||||
sub_v3_v3v3(r_center, r_center, ob->obmat[3]);
|
|
||||||
copy_m3_m4(mat, ob->obmat);
|
|
||||||
invert_m3_m3(imat, mat);
|
|
||||||
mul_m3_v3(imat, r_center);
|
|
||||||
}
|
|
||||||
else if (t->options & CTX_PAINT_CURVE) {
|
|
||||||
if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
|
if (ED_view3d_project_float_global(t->ar, cursor, r_center, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) {
|
||||||
r_center[0] = t->ar->winx / 2.0f;
|
r_center[0] = t->ar->winx / 2.0f;
|
||||||
r_center[1] = t->ar->winy / 2.0f;
|
r_center[1] = t->ar->winy / 2.0f;
|
||||||
@@ -1755,12 +1810,21 @@ void calculateCenterMedian(TransInfo *t, float r_center[3])
|
|||||||
{
|
{
|
||||||
float partial[3] = {0.0f, 0.0f, 0.0f};
|
float partial[3] = {0.0f, 0.0f, 0.0f};
|
||||||
int total = 0;
|
int total = 0;
|
||||||
|
|
||||||
|
FOREACH_THAND (t, th) {
|
||||||
|
Object *ob_xform = th->obedit ? th->obedit : th->poseobj;
|
||||||
int i;
|
int i;
|
||||||
|
for (i = 0; i < th->total; i++) {
|
||||||
for (i = 0; i < t->total; i++) {
|
if (th->data[i].flag & TD_SELECTED) {
|
||||||
if (t->data[i].flag & TD_SELECTED) {
|
if (!(th->data[i].flag & TD_NOCENTER)) {
|
||||||
if (!(t->data[i].flag & TD_NOCENTER)) {
|
if (ob_xform) {
|
||||||
add_v3_v3(partial, t->data[i].center);
|
float v[3];
|
||||||
|
mul_v3_m4v3(v, ob_xform->obmat, th->data[i].center);
|
||||||
|
add_v3_v3(partial, v);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
add_v3_v3(partial, th->data[i].center);
|
||||||
|
}
|
||||||
total++;
|
total++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1768,6 +1832,7 @@ void calculateCenterMedian(TransInfo *t, float r_center[3])
|
|||||||
if (total) {
|
if (total) {
|
||||||
mul_v3_fl(partial, 1.0f / (float)total);
|
mul_v3_fl(partial, 1.0f / (float)total);
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
copy_v3_v3(r_center, partial);
|
copy_v3_v3(r_center, partial);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1776,18 +1841,30 @@ void calculateCenterBound(TransInfo *t, float r_center[3])
|
|||||||
float max[3];
|
float max[3];
|
||||||
float min[3];
|
float min[3];
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < t->total; i++) {
|
bool is_first = true;
|
||||||
if (i) {
|
FOREACH_THAND (t, th) {
|
||||||
if (t->data[i].flag & TD_SELECTED) {
|
Object *ob_xform = th->obedit ? th->obedit : th->poseobj;
|
||||||
if (!(t->data[i].flag & TD_NOCENTER))
|
for (i = 0; i < th->total; i++) {
|
||||||
minmax_v3v3_v3(min, max, t->data[i].center);
|
if (is_first == false) {
|
||||||
|
if (th->data[i].flag & TD_SELECTED) {
|
||||||
|
if (!(th->data[i].flag & TD_NOCENTER)) {
|
||||||
|
if (ob_xform) {
|
||||||
|
float v[3];
|
||||||
|
mul_v3_m4v3(v, ob_xform->obmat, th->data[i].center);
|
||||||
|
minmax_v3v3_v3(min, max, v);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
minmax_v3v3_v3(min, max, th->data[i].center);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
copy_v3_v3(max, t->data[i].center);
|
copy_v3_v3(max, th->data[i].center);
|
||||||
copy_v3_v3(min, t->data[i].center);
|
copy_v3_v3(min, th->data[i].center);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
mid_v3_v3v3(r_center, min, max);
|
mid_v3_v3v3(r_center, min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1796,10 +1873,13 @@ void calculateCenterBound(TransInfo *t, float r_center[3])
|
|||||||
*/
|
*/
|
||||||
bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
|
bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
|
||||||
{
|
{
|
||||||
|
TransHandle *th = THAND_FIRST_OK(t);
|
||||||
|
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
|
|
||||||
if (t->obedit) {
|
if (th->obedit) {
|
||||||
if (ED_object_editmode_calc_active_center(t->obedit, select_only, r_center)) {
|
if (ED_object_editmode_calc_active_center(th->obedit, select_only, r_center)) {
|
||||||
|
mul_m4_v3(th->obedit->obmat, r_center);
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1810,6 +1890,7 @@ bool calculateCenterActive(TransInfo *t, bool select_only, float r_center[3])
|
|||||||
bPoseChannel *pchan = BKE_pose_channel_active(ob);
|
bPoseChannel *pchan = BKE_pose_channel_active(ob);
|
||||||
if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) {
|
if (pchan && (!select_only || (pchan->bone->flag & BONE_SELECTED))) {
|
||||||
copy_v3_v3(r_center, pchan->pose_head);
|
copy_v3_v3(r_center, pchan->pose_head);
|
||||||
|
mul_m4_v3(th->obedit->obmat, r_center);
|
||||||
ok = true;
|
ok = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1874,14 +1955,13 @@ static void calculateCenter_FromAround(TransInfo *t, int around, float r_center[
|
|||||||
void calculateCenter(TransInfo *t)
|
void calculateCenter(TransInfo *t)
|
||||||
{
|
{
|
||||||
if ((t->flag & T_OVERRIDE_CENTER) == 0) {
|
if ((t->flag & T_OVERRIDE_CENTER) == 0) {
|
||||||
calculateCenter_FromAround(t, t->around, t->center);
|
calculateCenter_FromAround(t, t->around, t->center_global);
|
||||||
}
|
}
|
||||||
calculateCenterGlobal(t, t->center, t->center_global);
|
calculateCenterLocal(t, t->center_global);
|
||||||
|
|
||||||
/* avoid calculating again */
|
/* avoid calculating again */
|
||||||
{
|
{
|
||||||
TransCenterData *cd = &t->center_cache[t->around];
|
TransCenterData *cd = &t->center_cache[t->around];
|
||||||
copy_v3_v3(cd->local, t->center);
|
|
||||||
copy_v3_v3(cd->global, t->center_global);
|
copy_v3_v3(cd->global, t->center_global);
|
||||||
cd->is_set = true;
|
cd->is_set = true;
|
||||||
}
|
}
|
||||||
@@ -1899,16 +1979,15 @@ void calculateCenter(TransInfo *t)
|
|||||||
normalize_v3(axis);
|
normalize_v3(axis);
|
||||||
|
|
||||||
/* 6.0 = 6 grid units */
|
/* 6.0 = 6 grid units */
|
||||||
axis[0] = t->center[0] - 6.0f * axis[0];
|
axis[0] = t->center_global[0] - 6.0f * axis[0];
|
||||||
axis[1] = t->center[1] - 6.0f * axis[1];
|
axis[1] = t->center_global[1] - 6.0f * axis[1];
|
||||||
axis[2] = t->center[2] - 6.0f * axis[2];
|
axis[2] = t->center_global[2] - 6.0f * axis[2];
|
||||||
|
|
||||||
projectFloatView(t, axis, t->center2d);
|
projectFloatView(t, axis, t->center2d);
|
||||||
|
|
||||||
/* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
|
/* rotate only needs correct 2d center, grab needs ED_view3d_calc_zfac() value */
|
||||||
if (t->mode == TFM_TRANSLATION) {
|
if (t->mode == TFM_TRANSLATION) {
|
||||||
copy_v3_v3(t->center, axis);
|
copy_v3_v3(t->center_global, axis);
|
||||||
copy_v3_v3(t->center_global, t->center);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1942,8 +2021,7 @@ const TransCenterData *transformCenter_from_type(TransInfo *t, int around)
|
|||||||
BLI_assert(around <= V3D_AROUND_ACTIVE);
|
BLI_assert(around <= V3D_AROUND_ACTIVE);
|
||||||
TransCenterData *cd = &t->center_cache[around];
|
TransCenterData *cd = &t->center_cache[around];
|
||||||
if (cd->is_set == false) {
|
if (cd->is_set == false) {
|
||||||
calculateCenter_FromAround(t, around, cd->local);
|
calculateCenter_FromAround(t, around, cd->global);
|
||||||
calculateCenterGlobal(t, cd->local, cd->global);
|
|
||||||
cd->is_set = true;
|
cd->is_set = true;
|
||||||
}
|
}
|
||||||
return cd;
|
return cd;
|
||||||
@@ -1951,7 +2029,6 @@ const TransCenterData *transformCenter_from_type(TransInfo *t, int around)
|
|||||||
|
|
||||||
void calculatePropRatio(TransInfo *t)
|
void calculatePropRatio(TransInfo *t)
|
||||||
{
|
{
|
||||||
TransData *td = t->data;
|
|
||||||
int i;
|
int i;
|
||||||
float dist;
|
float dist;
|
||||||
const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
|
const bool connected = (t->flag & T_PROP_CONNECTED) != 0;
|
||||||
@@ -1960,7 +2037,9 @@ void calculatePropRatio(TransInfo *t)
|
|||||||
|
|
||||||
if (t->flag & T_PROP_EDIT) {
|
if (t->flag & T_PROP_EDIT) {
|
||||||
const char *pet_id = NULL;
|
const char *pet_id = NULL;
|
||||||
for (i = 0; i < t->total; i++, td++) {
|
FOREACH_THAND (t, th) {
|
||||||
|
TransData *td = th->data;
|
||||||
|
for (i = 0; i < th->total; i++, td++) {
|
||||||
if (td->flag & TD_SELECTED) {
|
if (td->flag & TD_SELECTED) {
|
||||||
td->factor = 1.0f;
|
td->factor = 1.0f;
|
||||||
}
|
}
|
||||||
@@ -2029,6 +2108,8 @@ void calculatePropRatio(TransInfo *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
|
|
||||||
switch (t->prop_mode) {
|
switch (t->prop_mode) {
|
||||||
case PROP_SHARP:
|
case PROP_SHARP:
|
||||||
pet_id = N_("(Sharp)");
|
pet_id = N_("(Sharp)");
|
||||||
@@ -2063,8 +2144,11 @@ void calculatePropRatio(TransInfo *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (i = 0; i < t->total; i++, td++) {
|
FOREACH_THAND (t, th) {
|
||||||
td->factor = 1.0;
|
TransData *td = th->data;
|
||||||
|
for (i = 0; i < th->total; i++, td++) {
|
||||||
|
td->factor = 1.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -272,17 +272,19 @@ void applyProject(TransInfo *t)
|
|||||||
{
|
{
|
||||||
/* XXX FLICKER IN OBJECT MODE */
|
/* XXX FLICKER IN OBJECT MODE */
|
||||||
if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) {
|
if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) {
|
||||||
TransData *td = t->data;
|
|
||||||
float tvec[3];
|
float tvec[3];
|
||||||
float imat[4][4];
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
FOREACH_THAND(t, th) {
|
||||||
|
TransData *td = th->data;
|
||||||
|
|
||||||
|
float imat[4][4];
|
||||||
if (t->flag & (T_EDIT | T_POSE)) {
|
if (t->flag & (T_EDIT | T_POSE)) {
|
||||||
Object *ob = t->obedit ? t->obedit : t->poseobj;
|
Object *ob = th->obedit ? th->obedit : th->poseobj;
|
||||||
invert_m4_m4(imat, ob->obmat);
|
invert_m4_m4(imat, ob->obmat);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < t->total; i++, td++) {
|
for (i = 0; i < th->total; i++, td++) {
|
||||||
float iloc[3], loc[3], no[3];
|
float iloc[3], loc[3], no[3];
|
||||||
float mval_fl[2];
|
float mval_fl[2];
|
||||||
float dist_px = TRANSFORM_DIST_MAX_PX;
|
float dist_px = TRANSFORM_DIST_MAX_PX;
|
||||||
@@ -298,7 +300,7 @@ void applyProject(TransInfo *t)
|
|||||||
|
|
||||||
copy_v3_v3(iloc, td->loc);
|
copy_v3_v3(iloc, td->loc);
|
||||||
if (t->flag & (T_EDIT | T_POSE)) {
|
if (t->flag & (T_EDIT | T_POSE)) {
|
||||||
Object *ob = t->obedit ? t->obedit : t->poseobj;
|
Object *ob = th->obedit ? th->obedit : th->poseobj;
|
||||||
mul_m4_v3(ob->obmat, iloc);
|
mul_m4_v3(ob->obmat, iloc);
|
||||||
}
|
}
|
||||||
else if (t->flag & T_OBJECT) {
|
else if (t->flag & T_OBJECT) {
|
||||||
@@ -340,6 +342,7 @@ void applyProject(TransInfo *t)
|
|||||||
|
|
||||||
//XXX constraintTransLim(t, td);
|
//XXX constraintTransLim(t, td);
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,7 +350,6 @@ void applyGridAbsolute(TransInfo *t)
|
|||||||
{
|
{
|
||||||
float grid_size = 0.0f;
|
float grid_size = 0.0f;
|
||||||
GearsType grid_action;
|
GearsType grid_action;
|
||||||
TransData *td;
|
|
||||||
float (*obmat)[4] = NULL;
|
float (*obmat)[4] = NULL;
|
||||||
bool use_obmat = false;
|
bool use_obmat = false;
|
||||||
int i;
|
int i;
|
||||||
@@ -368,13 +370,16 @@ void applyGridAbsolute(TransInfo *t)
|
|||||||
if (grid_size == 0.0f)
|
if (grid_size == 0.0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
FOREACH_THAND(t, th) {
|
||||||
|
TransData *td;
|
||||||
|
|
||||||
if (t->flag & (T_EDIT | T_POSE)) {
|
if (t->flag & (T_EDIT | T_POSE)) {
|
||||||
Object *ob = t->obedit ? t->obedit : t->poseobj;
|
Object *ob = th->obedit ? th->obedit : th->poseobj;
|
||||||
obmat = ob->obmat;
|
obmat = ob->obmat;
|
||||||
use_obmat = true;
|
use_obmat = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0, td = t->data; i < t->total; i++, td++) {
|
for (i = 0, td = th->data; i < th->total; i++, td++) {
|
||||||
float iloc[3], loc[3], tvec[3];
|
float iloc[3], loc[3], tvec[3];
|
||||||
|
|
||||||
if (td->flag & TD_NOACTION)
|
if (td->flag & TD_NOACTION)
|
||||||
@@ -405,6 +410,7 @@ void applyGridAbsolute(TransInfo *t)
|
|||||||
mul_m3_v3(td->smtx, tvec);
|
mul_m3_v3(td->smtx, tvec);
|
||||||
add_v3_v3(td->loc, tvec);
|
add_v3_v3(td->loc, tvec);
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
void applySnapping(TransInfo *t, float *vec)
|
void applySnapping(TransInfo *t, float *vec)
|
||||||
@@ -501,7 +507,8 @@ static bool bm_face_is_snap_target(BMFace *f, void *UNUSED(user_data))
|
|||||||
static void initSnappingMode(TransInfo *t)
|
static void initSnappingMode(TransInfo *t)
|
||||||
{
|
{
|
||||||
ToolSettings *ts = t->settings;
|
ToolSettings *ts = t->settings;
|
||||||
Object *obedit = t->obedit;
|
/* All obedit types will match. */
|
||||||
|
const int obedit_type = t->thand->obedit ? t->thand->obedit->type : -1;
|
||||||
ViewLayer *view_layer = t->view_layer;
|
ViewLayer *view_layer = t->view_layer;
|
||||||
Base *base_act = view_layer->basact;
|
Base *base_act = view_layer->basact;
|
||||||
|
|
||||||
@@ -532,10 +539,10 @@ static void initSnappingMode(TransInfo *t)
|
|||||||
|
|
||||||
/* Edit mode */
|
/* Edit mode */
|
||||||
if (t->tsnap.applySnap != NULL && // A snapping function actually exist
|
if (t->tsnap.applySnap != NULL && // A snapping function actually exist
|
||||||
(obedit != NULL && ELEM(obedit->type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) ) // Temporary limited to edit mode meshes, armature, curves, mballs
|
((obedit_type != -1) && ELEM(obedit_type, OB_MESH, OB_ARMATURE, OB_CURVE, OB_LATTICE, OB_MBALL)) ) // Temporary limited to edit mode meshes, armature, curves, mballs
|
||||||
{
|
{
|
||||||
/* Exclude editmesh if using proportional edit */
|
/* Exclude editmesh if using proportional edit */
|
||||||
if ((obedit->type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
|
if ((obedit_type == OB_MESH) && (t->flag & T_PROP_EDIT)) {
|
||||||
t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
|
t->tsnap.modeSelect = SNAP_NOT_ACTIVE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -544,13 +551,13 @@ static void initSnappingMode(TransInfo *t)
|
|||||||
}
|
}
|
||||||
/* Particles edit mode*/
|
/* Particles edit mode*/
|
||||||
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
|
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
|
||||||
(obedit == NULL && base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT))
|
((obedit_type == -1) && base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT))
|
||||||
{
|
{
|
||||||
t->tsnap.modeSelect = SNAP_ALL;
|
t->tsnap.modeSelect = SNAP_ALL;
|
||||||
}
|
}
|
||||||
/* Object mode */
|
/* Object mode */
|
||||||
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
|
else if (t->tsnap.applySnap != NULL && // A snapping function actually exist
|
||||||
(obedit == NULL) ) // Object Mode
|
(obedit_type == -1) ) // Object Mode
|
||||||
{
|
{
|
||||||
/* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632)
|
/* In "Edit Strokes" mode, Snap tool can perform snap to selected or active objects (see T49632)
|
||||||
* TODO: perform self snap in gpencil_strokes */
|
* TODO: perform self snap in gpencil_strokes */
|
||||||
@@ -864,7 +871,8 @@ static float TranslationBetween(TransInfo *UNUSED(t), const float p1[3], const f
|
|||||||
return len_squared_v3v3(p1, p2);
|
return len_squared_v3v3(p1, p2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
|
static float RotationBetween(
|
||||||
|
TransInfo *t, const float p1[3], const float p2[3])
|
||||||
{
|
{
|
||||||
float angle, start[3], end[3];
|
float angle, start[3], end[3];
|
||||||
|
|
||||||
@@ -875,7 +883,7 @@ static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3])
|
|||||||
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
|
if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) {
|
||||||
float axis[3], tmp[3];
|
float axis[3], tmp[3];
|
||||||
|
|
||||||
t->con.applyRot(t, NULL, axis, NULL);
|
t->con.applyRot(t, NULL, NULL, axis, NULL);
|
||||||
|
|
||||||
project_v3_v3v3(tmp, end, axis);
|
project_v3_v3v3(tmp, end, axis);
|
||||||
sub_v3_v3v3(end, end, tmp);
|
sub_v3_v3v3(end, end, tmp);
|
||||||
@@ -978,14 +986,14 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
|
|||||||
t->tsnap.status &= ~POINT_INIT;
|
t->tsnap.status &= ~POINT_INIT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (t->spacetype == SPACE_IMAGE && t->obedit != NULL && t->obedit->type == OB_MESH) {
|
else if (t->spacetype == SPACE_IMAGE && t->obedit_type == OB_MESH) {
|
||||||
/* same as above but for UV's */
|
/* same as above but for UV's */
|
||||||
Image *ima = ED_space_image(t->sa->spacedata.first);
|
Image *ima = ED_space_image(t->sa->spacedata.first);
|
||||||
float co[2];
|
float co[2];
|
||||||
|
|
||||||
UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
|
UI_view2d_region_to_view(&t->ar->v2d, t->mval[0], t->mval[1], &co[0], &co[1]);
|
||||||
|
|
||||||
if (ED_uvedit_nearest_uv(t->scene, t->obedit, ima, co, t->tsnap.snapPoint)) {
|
if (ED_uvedit_nearest_uv(t->scene, THAND_FIRST_EVIL(t)->obedit, ima, co, t->tsnap.snapPoint)) {
|
||||||
t->tsnap.snapPoint[0] *= t->aspect[0];
|
t->tsnap.snapPoint[0] *= t->aspect[0];
|
||||||
t->tsnap.snapPoint[1] *= t->aspect[1];
|
t->tsnap.snapPoint[1] *= t->aspect[1];
|
||||||
|
|
||||||
@@ -1061,7 +1069,7 @@ static void TargetSnapActive(TransInfo *t)
|
|||||||
if ((t->tsnap.status & TARGET_INIT) == 0) {
|
if ((t->tsnap.status & TARGET_INIT) == 0) {
|
||||||
if (calculateCenterActive(t, true, t->tsnap.snapTarget)) {
|
if (calculateCenterActive(t, true, t->tsnap.snapTarget)) {
|
||||||
if (t->flag & (T_EDIT | T_POSE)) {
|
if (t->flag & (T_EDIT | T_POSE)) {
|
||||||
Object *ob = t->obedit ? t->obedit : t->poseobj;
|
Object *ob = THAND_FIRST_EVIL(t)->obedit ? THAND_FIRST_EVIL(t)->obedit : THAND_FIRST_EVIL(t)->poseobj;
|
||||||
mul_m4_v3(ob->obmat, t->tsnap.snapTarget);
|
mul_m4_v3(ob->obmat, t->tsnap.snapTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1082,23 +1090,34 @@ static void TargetSnapMedian(TransInfo *t)
|
|||||||
{
|
{
|
||||||
// Only need to calculate once
|
// Only need to calculate once
|
||||||
if ((t->tsnap.status & TARGET_INIT) == 0) {
|
if ((t->tsnap.status & TARGET_INIT) == 0) {
|
||||||
TransData *td = NULL;
|
int i_accum = 0;
|
||||||
int i;
|
|
||||||
|
|
||||||
t->tsnap.snapTarget[0] = 0;
|
t->tsnap.snapTarget[0] = 0;
|
||||||
t->tsnap.snapTarget[1] = 0;
|
t->tsnap.snapTarget[1] = 0;
|
||||||
t->tsnap.snapTarget[2] = 0;
|
t->tsnap.snapTarget[2] = 0;
|
||||||
|
|
||||||
for (td = t->data, i = 0; i < t->total && td->flag & TD_SELECTED; i++, td++) {
|
FOREACH_THAND (t, th) {
|
||||||
add_v3_v3(t->tsnap.snapTarget, td->center);
|
Object *ob_xform = NULL;
|
||||||
}
|
if (t->flag & (T_EDIT | T_POSE)) {
|
||||||
|
ob_xform = th->obedit ? th->obedit : th->poseobj;
|
||||||
mul_v3_fl(t->tsnap.snapTarget, 1.0 / i);
|
}
|
||||||
|
TransData *td = th->data;
|
||||||
if (t->flag & (T_EDIT | T_POSE)) {
|
int i;
|
||||||
Object *ob = t->obedit ? t->obedit : t->poseobj;
|
for (i = 0; i < th->total && td->flag & TD_SELECTED; i++, td++) {
|
||||||
mul_m4_v3(ob->obmat, t->tsnap.snapTarget);
|
/* TODO(campbell): perform the global transformation once per TransHandle */
|
||||||
|
if (ob_xform) {
|
||||||
|
float v[3];
|
||||||
|
mul_v3_m4v3(v, ob_xform->obmat, td->center);
|
||||||
|
add_v3_v3(t->tsnap.snapTarget, v);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
add_v3_v3(t->tsnap.snapTarget, td->center);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i_accum += i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum);
|
||||||
|
|
||||||
TargetSnapOffset(t, NULL);
|
TargetSnapOffset(t, NULL);
|
||||||
|
|
||||||
@@ -1111,12 +1130,14 @@ static void TargetSnapClosest(TransInfo *t)
|
|||||||
// Only valid if a snap point has been selected
|
// Only valid if a snap point has been selected
|
||||||
if (t->tsnap.status & POINT_INIT) {
|
if (t->tsnap.status & POINT_INIT) {
|
||||||
float dist_closest = 0.0f;
|
float dist_closest = 0.0f;
|
||||||
TransData *closest = NULL, *td = NULL;
|
TransData *closest = NULL;
|
||||||
|
|
||||||
/* Object mode */
|
/* Object mode */
|
||||||
if (t->flag & T_OBJECT) {
|
if (t->flag & T_OBJECT) {
|
||||||
int i;
|
int i;
|
||||||
for (td = t->data, i = 0; i < t->total && td->flag & TD_SELECTED; i++, td++) {
|
FOREACH_THAND(t, th) {
|
||||||
|
TransData *td = th->data;
|
||||||
|
for (td = th->data, i = 0; i < th->total && td->flag & TD_SELECTED; i++, td++) {
|
||||||
struct BoundBox *bb = BKE_object_boundbox_get(td->ob);
|
struct BoundBox *bb = BKE_object_boundbox_get(td->ob);
|
||||||
|
|
||||||
/* use boundbox if possible */
|
/* use boundbox if possible */
|
||||||
@@ -1158,17 +1179,20 @@ static void TargetSnapClosest(TransInfo *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
FOREACH_THAND(t, th) {
|
||||||
|
TransData *td = th->data;
|
||||||
int i;
|
int i;
|
||||||
for (td = t->data, i = 0; i < t->total && td->flag & TD_SELECTED; i++, td++) {
|
for (i = 0; i < th->total && td->flag & TD_SELECTED; i++, td++) {
|
||||||
float loc[3];
|
float loc[3];
|
||||||
float dist;
|
float dist;
|
||||||
|
|
||||||
copy_v3_v3(loc, td->center);
|
copy_v3_v3(loc, td->center);
|
||||||
|
|
||||||
if (t->flag & (T_EDIT | T_POSE)) {
|
if (t->flag & (T_EDIT | T_POSE)) {
|
||||||
Object *ob = t->obedit ? t->obedit : t->poseobj;
|
Object *ob = th->obedit ? th->obedit : th->poseobj;
|
||||||
mul_m4_v3(ob->obmat, loc);
|
mul_m4_v3(ob->obmat, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1182,6 +1206,7 @@ static void TargetSnapClosest(TransInfo *t)
|
|||||||
dist_closest = dist;
|
dist_closest = dist;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} // FIXME(indent)
|
||||||
}
|
}
|
||||||
|
|
||||||
TargetSnapOffset(t, closest);
|
TargetSnapOffset(t, closest);
|
||||||
@@ -1443,7 +1468,7 @@ void snapSequenceBounds(TransInfo *t, const int mval[2])
|
|||||||
float xmouse, ymouse;
|
float xmouse, ymouse;
|
||||||
int frame;
|
int frame;
|
||||||
int mframe;
|
int mframe;
|
||||||
TransSeq *ts = t->custom.type.data;
|
TransSeq *ts = THAND_FIRST_SINGLE(t)->custom.type.data;
|
||||||
/* reuse increment, strictly speaking could be another snap mode, but leave as is */
|
/* reuse increment, strictly speaking could be another snap mode, but leave as is */
|
||||||
if (!(t->modifiers & MOD_SNAP_INVERT))
|
if (!(t->modifiers & MOD_SNAP_INVERT))
|
||||||
return;
|
return;
|
||||||
|
@@ -51,6 +51,7 @@
|
|||||||
#include "BKE_DerivedMesh.h"
|
#include "BKE_DerivedMesh.h"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
#include "BKE_material.h"
|
#include "BKE_material.h"
|
||||||
|
#include "BKE_layer.h"
|
||||||
|
|
||||||
#include "BKE_scene.h"
|
#include "BKE_scene.h"
|
||||||
|
|
||||||
@@ -1100,12 +1101,24 @@ void ED_uvedit_draw_main(
|
|||||||
draw_uv_shadows_get(sima, obact, obedit, &show_uvshadow, &show_texpaint_uvshadow);
|
draw_uv_shadows_get(sima, obact, obedit, &show_uvshadow, &show_texpaint_uvshadow);
|
||||||
|
|
||||||
if (show_uvedit || show_uvshadow || show_texpaint_uvshadow) {
|
if (show_uvedit || show_uvshadow || show_texpaint_uvshadow) {
|
||||||
if (show_uvshadow)
|
if (show_uvshadow) {
|
||||||
draw_uvs_shadow(obedit);
|
draw_uvs_shadow(obedit);
|
||||||
else if (show_uvedit)
|
}
|
||||||
draw_uvs(sima, scene, view_layer, obedit, depsgraph);
|
else if (show_uvedit) {
|
||||||
else
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.filter_fn = BKE_view_layer_filter_edit_mesh_has_uvs,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *ob_iter = objects[ob_index];
|
||||||
|
draw_uvs(sima, scene, view_layer, ob_iter, depsgraph);
|
||||||
|
}
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
}
|
||||||
|
else {
|
||||||
draw_uvs_texpaint(sima, scene, view_layer, obact);
|
draw_uvs_texpaint(sima, scene, view_layer, obact);
|
||||||
|
}
|
||||||
|
|
||||||
if (show_uvedit && !(toolsettings->use_uv_sculpt))
|
if (show_uvedit && !(toolsettings->use_uv_sculpt))
|
||||||
ED_image_draw_cursor(ar, sima->cursor);
|
ED_image_draw_cursor(ar, sima->cursor);
|
||||||
|
@@ -51,6 +51,8 @@ void uv_poly_center(struct BMFace *f, float r_cent[2], const int cd_loop_uv_off
|
|||||||
/* find nearest */
|
/* find nearest */
|
||||||
|
|
||||||
typedef struct UvNearestHit {
|
typedef struct UvNearestHit {
|
||||||
|
/** Only for `*_multi(..)` versions of functions. */
|
||||||
|
struct Object *ob;
|
||||||
/** Always set if we have a hit. */
|
/** Always set if we have a hit. */
|
||||||
struct BMFace *efa;
|
struct BMFace *efa;
|
||||||
struct BMLoop *l;
|
struct BMLoop *l;
|
||||||
@@ -66,14 +68,23 @@ typedef struct UvNearestHit {
|
|||||||
bool uv_find_nearest_vert(
|
bool uv_find_nearest_vert(
|
||||||
struct Scene *scene, struct Image *ima, struct Object *obedit,
|
struct Scene *scene, struct Image *ima, struct Object *obedit,
|
||||||
const float co[2], const float penalty_dist, struct UvNearestHit *hit_final);
|
const float co[2], const float penalty_dist, struct UvNearestHit *hit_final);
|
||||||
|
bool uv_find_nearest_vert_multi(
|
||||||
|
struct Scene *scene, struct Image *ima, struct Object **objects, const uint objects_len,
|
||||||
|
const float co[2], const float penalty_dist, struct UvNearestHit *hit_final);
|
||||||
|
|
||||||
bool uv_find_nearest_edge(
|
bool uv_find_nearest_edge(
|
||||||
struct Scene *scene, struct Image *ima, struct Object *obedit,
|
struct Scene *scene, struct Image *ima, struct Object *obedit,
|
||||||
const float co[2], struct UvNearestHit *hit_final);
|
const float co[2], struct UvNearestHit *hit_final);
|
||||||
|
bool uv_find_nearest_edge_multi(
|
||||||
|
struct Scene *scene, struct Image *ima, struct Object **objects, const uint objects_len,
|
||||||
|
const float co[2], struct UvNearestHit *hit_final);
|
||||||
|
|
||||||
bool uv_find_nearest_face(
|
bool uv_find_nearest_face(
|
||||||
struct Scene *scene, struct Image *ima, struct Object *obedit,
|
struct Scene *scene, struct Image *ima, struct Object *obedit,
|
||||||
const float co[2], struct UvNearestHit *hit_final);
|
const float co[2], struct UvNearestHit *hit_final);
|
||||||
|
bool uv_find_nearest_face_multi(
|
||||||
|
struct Scene *scene, struct Image *ima, struct Object **objects, const uint objects_len,
|
||||||
|
const float co[2], struct UvNearestHit *hit_final);
|
||||||
|
|
||||||
/* utility tool functions */
|
/* utility tool functions */
|
||||||
|
|
||||||
|
@@ -66,6 +66,7 @@
|
|||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
#include "BKE_scene.h"
|
#include "BKE_scene.h"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
|
#include "BKE_layer.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
|
|
||||||
@@ -89,7 +90,10 @@
|
|||||||
|
|
||||||
#include "uvedit_intern.h"
|
#include "uvedit_intern.h"
|
||||||
|
|
||||||
static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, BMEditMesh *em, int action);
|
static bool uv_select_is_any_selected(Scene *scene, Image *ima, Object *obedit);
|
||||||
|
static bool uv_select_is_any_selected_multi(Scene *scene, Image *ima, Object **objects, const uint objects_len);
|
||||||
|
static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action);
|
||||||
|
static void uv_select_all_perform_multi(Scene *scene, Image *ima, Object **objects, const uint objects_len, int action);
|
||||||
static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object *obedit, const bool select);
|
static void uv_select_flush_from_tag_face(SpaceImage *sima, Scene *scene, Object *obedit, const bool select);
|
||||||
static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object *obedit, const bool select);
|
static void uv_select_flush_from_tag_loop(SpaceImage *sima, Scene *scene, Object *obedit, const bool select);
|
||||||
|
|
||||||
@@ -794,6 +798,21 @@ bool uv_find_nearest_edge(
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool uv_find_nearest_edge_multi(
|
||||||
|
Scene *scene, Image *ima, Object **objects, const uint objects_len,
|
||||||
|
const float co[2], UvNearestHit *hit_final)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
if (uv_find_nearest_edge(scene, ima, obedit, co, hit_final)) {
|
||||||
|
hit_final->ob = obedit;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
bool uv_find_nearest_face(
|
bool uv_find_nearest_face(
|
||||||
Scene *scene, Image *ima, Object *obedit, const float co[2],
|
Scene *scene, Image *ima, Object *obedit, const float co[2],
|
||||||
UvNearestHit *hit_final)
|
UvNearestHit *hit_final)
|
||||||
@@ -837,6 +856,21 @@ bool uv_find_nearest_face(
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool uv_find_nearest_face_multi(
|
||||||
|
Scene *scene, Image *ima, Object **objects, const uint objects_len,
|
||||||
|
const float co[2], UvNearestHit *hit_final)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
if (uv_find_nearest_face(scene, ima, obedit, co, hit_final)) {
|
||||||
|
hit_final->ob = obedit;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
static bool uv_nearest_between(
|
static bool uv_nearest_between(
|
||||||
const BMLoop *l, const float co[2],
|
const BMLoop *l, const float co[2],
|
||||||
const int cd_loop_uv_offset)
|
const int cd_loop_uv_offset)
|
||||||
@@ -918,6 +952,21 @@ bool uv_find_nearest_vert(
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool uv_find_nearest_vert_multi(
|
||||||
|
Scene *scene, Image *ima, Object **objects, const uint objects_len,
|
||||||
|
float const co[2], const float penalty_dist, UvNearestHit *hit_final)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
if (uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, hit_final)) {
|
||||||
|
hit_final->ob = obedit;
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float co[2], float r_uv[2])
|
bool ED_uvedit_nearest_uv(Scene *scene, Object *obedit, Image *ima, const float co[2], float r_uv[2])
|
||||||
{
|
{
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
@@ -1043,9 +1092,10 @@ static bool uv_select_edgeloop_edge_tag_faces(BMEditMesh *em, UvMapVert *first1,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int uv_select_edgeloop(
|
static int uv_select_edgeloop(
|
||||||
Scene *scene, Image *ima, Object *obedit, BMEditMesh *em, UvNearestHit *hit,
|
Scene *scene, Image *ima, Object *obedit, UvNearestHit *hit,
|
||||||
const float limit[2], const bool extend)
|
const float limit[2], const bool extend)
|
||||||
{
|
{
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
BMFace *efa;
|
BMFace *efa;
|
||||||
BMIter iter, liter;
|
BMIter iter, liter;
|
||||||
BMLoop *l;
|
BMLoop *l;
|
||||||
@@ -1064,7 +1114,7 @@ static int uv_select_edgeloop(
|
|||||||
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
|
BM_mesh_elem_index_ensure(em->bm, BM_VERT | BM_FACE);
|
||||||
|
|
||||||
if (!extend) {
|
if (!extend) {
|
||||||
uv_select_all_perform(scene, ima, obedit, em, SEL_DESELECT);
|
uv_select_all_perform(scene, ima, obedit, SEL_DESELECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
|
BM_mesh_elem_hflag_disable_all(em->bm, BM_FACE, BM_ELEM_TAG, false);
|
||||||
@@ -1147,10 +1197,17 @@ static int uv_select_edgeloop(
|
|||||||
/** \name Select Linked
|
/** \name Select Linked
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static void uv_select_linked(
|
static void uv_select_linked_multi(
|
||||||
Scene *scene, Image *ima, Object *obedit, BMEditMesh *em, const float limit[2],
|
Scene *scene, Image *ima, Object **objects, const uint objects_len, const float limit[2],
|
||||||
UvNearestHit *hit_final, bool extend, bool select_faces)
|
UvNearestHit *hit_final, bool extend, bool select_faces)
|
||||||
{
|
{
|
||||||
|
/* loop over objects, or just use hit_final->ob */
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
if (hit_final && ob_index != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Object *obedit = hit_final ? hit_final->ob : objects[ob_index];
|
||||||
|
|
||||||
BMFace *efa;
|
BMFace *efa;
|
||||||
BMLoop *l;
|
BMLoop *l;
|
||||||
BMIter iter, liter;
|
BMIter iter, liter;
|
||||||
@@ -1161,6 +1218,7 @@ static void uv_select_linked(
|
|||||||
unsigned int a;
|
unsigned int a;
|
||||||
char *flag;
|
char *flag;
|
||||||
|
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||||
|
|
||||||
BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
|
BM_mesh_elem_table_ensure(em->bm, BM_FACE); /* we can use this too */
|
||||||
@@ -1336,6 +1394,8 @@ static void uv_select_linked(
|
|||||||
MEM_freeN(stack);
|
MEM_freeN(stack);
|
||||||
MEM_freeN(flag);
|
MEM_freeN(flag);
|
||||||
BM_uv_vert_map_free(vmap);
|
BM_uv_vert_map_free(vmap);
|
||||||
|
|
||||||
|
} /* objects */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* WATCH IT: this returns first selected UV,
|
/* WATCH IT: this returns first selected UV,
|
||||||
@@ -1957,9 +2017,53 @@ static void UV_OT_weld(wmOperatorType *ot)
|
|||||||
/** \name (De)Select All Operator
|
/** \name (De)Select All Operator
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, BMEditMesh *em, int action)
|
|
||||||
|
static bool uv_select_is_any_selected(Scene *scene, Image *ima, Object *obedit)
|
||||||
{
|
{
|
||||||
ToolSettings *ts = scene->toolsettings;
|
ToolSettings *ts = scene->toolsettings;
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
BMFace *efa;
|
||||||
|
BMLoop *l;
|
||||||
|
BMIter iter, liter;
|
||||||
|
MLoopUV *luv;
|
||||||
|
|
||||||
|
if (ts->uv_flag & UV_SYNC_SELECTION) {
|
||||||
|
return (em->bm->totvertsel || em->bm->totedgesel || em->bm->totfacesel);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||||
|
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||||
|
if (!uvedit_face_visible_test(scene, obedit, ima, efa)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||||
|
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
|
||||||
|
if (luv->flag & MLOOPUV_VERTSEL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool uv_select_is_any_selected_multi(Scene *scene, Image *ima, Object **objects, const uint objects_len)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
if (uv_select_is_any_selected(scene, ima, obedit)) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, int action)
|
||||||
|
{
|
||||||
|
ToolSettings *ts = scene->toolsettings;
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
BMFace *efa;
|
BMFace *efa;
|
||||||
BMLoop *l;
|
BMLoop *l;
|
||||||
BMIter iter, liter;
|
BMIter iter, liter;
|
||||||
@@ -1967,8 +2071,11 @@ static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, BMEd
|
|||||||
|
|
||||||
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||||
|
|
||||||
if (ts->uv_flag & UV_SYNC_SELECTION) {
|
if (action == SEL_TOGGLE) {
|
||||||
|
action = uv_select_is_any_selected(scene, ima, obedit) ? SEL_DESELECT : SEL_SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ts->uv_flag & UV_SYNC_SELECTION) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case SEL_TOGGLE:
|
case SEL_TOGGLE:
|
||||||
EDBM_select_toggle_all(em);
|
EDBM_select_toggle_all(em);
|
||||||
@@ -1986,24 +2093,6 @@ static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, BMEd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (action == SEL_TOGGLE) {
|
|
||||||
action = SEL_SELECT;
|
|
||||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
|
||||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
|
||||||
luv = BM_ELEM_CD_GET_VOID_P(l, cd_loop_uv_offset);
|
|
||||||
|
|
||||||
if (luv->flag & MLOOPUV_VERTSEL) {
|
|
||||||
action = SEL_DESELECT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||||
if (!uvedit_face_visible_test(scene, obedit, ima, efa))
|
if (!uvedit_face_visible_test(scene, obedit, ima, efa))
|
||||||
continue;
|
continue;
|
||||||
@@ -2027,18 +2116,41 @@ static void uv_select_all_perform(Scene *scene, Image *ima, Object *obedit, BMEd
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void uv_select_all_perform_multi(
|
||||||
|
Scene *scene, Image *ima, Object **objects, const uint objects_len, int action)
|
||||||
|
{
|
||||||
|
if (action == SEL_TOGGLE) {
|
||||||
|
action = uv_select_is_any_selected_multi(scene, ima, objects, objects_len) ? SEL_DESELECT : SEL_SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
uv_select_all_perform(scene, ima, obedit, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int uv_select_all_exec(bContext *C, wmOperator *op)
|
static int uv_select_all_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
|
||||||
Image *ima = CTX_data_edit_image(C);
|
Image *ima = CTX_data_edit_image(C);
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
|
|
||||||
int action = RNA_enum_get(op->ptr, "action");
|
int action = RNA_enum_get(op->ptr, "action");
|
||||||
|
|
||||||
uv_select_all_perform(scene, ima, obedit, em, action);
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.filter_fn = BKE_view_layer_filter_edit_mesh_has_uvs,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
uv_select_all_perform_multi(scene, ima, objects, objects_len, action);
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
@@ -2092,9 +2204,8 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
|
|||||||
SpaceImage *sima = CTX_wm_space_image(C);
|
SpaceImage *sima = CTX_wm_space_image(C);
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
ToolSettings *ts = scene->toolsettings;
|
ToolSettings *ts = scene->toolsettings;
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
Image *ima = CTX_data_edit_image(C);
|
Image *ima = CTX_data_edit_image(C);
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
|
||||||
BMFace *efa;
|
BMFace *efa;
|
||||||
BMLoop *l;
|
BMLoop *l;
|
||||||
BMIter iter, liter;
|
BMIter iter, liter;
|
||||||
@@ -2105,7 +2216,8 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
|
|||||||
int flush = 0, hitlen = 0; /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
|
int flush = 0, hitlen = 0; /* 0 == don't flush, 1 == sel, -1 == desel; only use when selection sync is enabled */
|
||||||
float limit[2], **hituv = NULL;
|
float limit[2], **hituv = NULL;
|
||||||
|
|
||||||
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
// BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
// const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||||
|
|
||||||
/* notice 'limit' is the same no matter the zoom level, since this is like
|
/* notice 'limit' is the same no matter the zoom level, since this is like
|
||||||
* remove doubles and could annoying if it joined points when zoomed out.
|
* remove doubles and could annoying if it joined points when zoomed out.
|
||||||
@@ -2140,10 +2252,16 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
|
|||||||
sticky = (sima) ? sima->sticky : 1;
|
sticky = (sima) ? sima->sticky : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.filter_fn = BKE_view_layer_filter_edit_mesh_has_uvs,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
/* find nearest element */
|
/* find nearest element */
|
||||||
if (loop) {
|
if (loop) {
|
||||||
/* find edge */
|
/* find edge */
|
||||||
if (!uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
|
if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2151,7 +2269,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
|
|||||||
}
|
}
|
||||||
else if (selectmode == UV_SELECT_VERTEX) {
|
else if (selectmode == UV_SELECT_VERTEX) {
|
||||||
/* find vertex */
|
/* find vertex */
|
||||||
if (!uv_find_nearest_vert(scene, ima, obedit, co, penalty_dist, &hit)) {
|
if (!uv_find_nearest_vert_multi(scene, ima, objects, objects_len, co, penalty_dist, &hit)) {
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2167,7 +2285,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
|
|||||||
}
|
}
|
||||||
else if (selectmode == UV_SELECT_EDGE) {
|
else if (selectmode == UV_SELECT_EDGE) {
|
||||||
/* find edge */
|
/* find edge */
|
||||||
if (!uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
|
if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2185,10 +2303,13 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
|
|||||||
}
|
}
|
||||||
else if (selectmode == UV_SELECT_FACE) {
|
else if (selectmode == UV_SELECT_FACE) {
|
||||||
/* find face */
|
/* find face */
|
||||||
if (!uv_find_nearest_face(scene, ima, obedit, co, &hit)) {
|
if (!uv_find_nearest_face_multi(scene, ima, objects, objects_len, co, &hit)) {
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(hit.ob);
|
||||||
|
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||||
|
|
||||||
/* make active */
|
/* make active */
|
||||||
BM_mesh_active_face_set(em->bm, hit.efa);
|
BM_mesh_active_face_set(em->bm, hit.efa);
|
||||||
|
|
||||||
@@ -2201,11 +2322,10 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
|
|||||||
hituv[i] = luv->uv;
|
hituv[i] = luv->uv;
|
||||||
hitv[i] = BM_elem_index_get(l->v);
|
hitv[i] = BM_elem_index_get(l->v);
|
||||||
}
|
}
|
||||||
|
|
||||||
hitlen = hit.efa->len;
|
hitlen = hit.efa->len;
|
||||||
}
|
}
|
||||||
else if (selectmode == UV_SELECT_ISLAND) {
|
else if (selectmode == UV_SELECT_ISLAND) {
|
||||||
if (!uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
|
if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2216,12 +2336,24 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
|
|||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Object *obedit = hit.ob;
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||||
|
|
||||||
/* do selection */
|
/* do selection */
|
||||||
if (loop) {
|
if (loop) {
|
||||||
flush = uv_select_edgeloop(scene, ima, obedit, em, &hit, limit, extend);
|
if (!extend) {
|
||||||
|
/* TODO(MULTI_EDIT): We only need to de-select non-active */
|
||||||
|
uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
|
||||||
|
}
|
||||||
|
flush = uv_select_edgeloop(scene, ima, obedit, &hit, limit, extend);
|
||||||
}
|
}
|
||||||
else if (selectmode == UV_SELECT_ISLAND) {
|
else if (selectmode == UV_SELECT_ISLAND) {
|
||||||
uv_select_linked(scene, ima, obedit, em, limit, &hit, extend, false);
|
if (!extend) {
|
||||||
|
/* TODO(MULTI_EDIT): We only need to de-select non-active */
|
||||||
|
uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
|
||||||
|
}
|
||||||
|
uv_select_linked_multi(scene, ima, objects, objects_len, limit, &hit, extend, false);
|
||||||
}
|
}
|
||||||
else if (extend) {
|
else if (extend) {
|
||||||
if (selectmode == UV_SELECT_VERTEX) {
|
if (selectmode == UV_SELECT_VERTEX) {
|
||||||
@@ -2271,7 +2403,7 @@ static int uv_mouse_select(bContext *C, const float co[2], bool extend, bool loo
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* deselect all */
|
/* deselect all */
|
||||||
uv_select_all_perform(scene, ima, obedit, em, SEL_DESELECT);
|
uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
|
||||||
|
|
||||||
if (selectmode == UV_SELECT_VERTEX) {
|
if (selectmode == UV_SELECT_VERTEX) {
|
||||||
/* select vertex */
|
/* select vertex */
|
||||||
@@ -2443,9 +2575,8 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
|
|||||||
SpaceImage *sima = CTX_wm_space_image(C);
|
SpaceImage *sima = CTX_wm_space_image(C);
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
ToolSettings *ts = scene->toolsettings;
|
ToolSettings *ts = scene->toolsettings;
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
Image *ima = CTX_data_edit_image(C);
|
Image *ima = CTX_data_edit_image(C);
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
|
||||||
float limit[2];
|
float limit[2];
|
||||||
int extend;
|
int extend;
|
||||||
bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
|
bool select_faces = (ts->uv_flag & UV_SYNC_SELECTION) && (ts->selectmode & SCE_SELECT_FACE);
|
||||||
@@ -2460,6 +2591,12 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
|
|||||||
extend = RNA_boolean_get(op->ptr, "extend");
|
extend = RNA_boolean_get(op->ptr, "extend");
|
||||||
uvedit_pixel_to_float(sima, limit, 0.05f);
|
uvedit_pixel_to_float(sima, limit, 0.05f);
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.filter_fn = BKE_view_layer_filter_edit_mesh_has_uvs,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
if (pick) {
|
if (pick) {
|
||||||
float co[2];
|
float co[2];
|
||||||
|
|
||||||
@@ -2475,15 +2612,32 @@ static int uv_select_linked_internal(bContext *C, wmOperator *op, const wmEvent
|
|||||||
RNA_float_get_array(op->ptr, "location", co);
|
RNA_float_get_array(op->ptr, "location", co);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uv_find_nearest_edge(scene, ima, obedit, co, &hit)) {
|
if (!uv_find_nearest_edge_multi(scene, ima, objects, objects_len, co, &hit)) {
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uv_select_linked(scene, ima, obedit, em, limit, pick ? &hit : NULL, extend, select_faces);
|
if (!extend) {
|
||||||
|
uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
|
||||||
|
}
|
||||||
|
|
||||||
DEG_id_tag_update(obedit->data, 0);
|
uv_select_linked_multi(scene, ima, objects, objects_len, limit, pick ? &hit : NULL, extend, select_faces);
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
|
||||||
|
/* weak!, but works */
|
||||||
|
Object **objects_free = objects;
|
||||||
|
if (pick) {
|
||||||
|
objects = &hit.ob;
|
||||||
|
objects_len = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
DEG_id_tag_update(obedit->data, 0);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(objects_free);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
@@ -2879,23 +3033,20 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
|
|||||||
SpaceImage *sima = CTX_wm_space_image(C);
|
SpaceImage *sima = CTX_wm_space_image(C);
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
ToolSettings *ts = scene->toolsettings;
|
ToolSettings *ts = scene->toolsettings;
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
Image *ima = CTX_data_edit_image(C);
|
Image *ima = CTX_data_edit_image(C);
|
||||||
ARegion *ar = CTX_wm_region(C);
|
ARegion *ar = CTX_wm_region(C);
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
|
||||||
BMFace *efa;
|
BMFace *efa;
|
||||||
BMLoop *l;
|
BMLoop *l;
|
||||||
BMIter iter, liter;
|
BMIter iter, liter;
|
||||||
MLoopUV *luv;
|
MLoopUV *luv;
|
||||||
rctf rectf;
|
rctf rectf;
|
||||||
bool changed, pinned, select, extend;
|
bool pinned, select, extend;
|
||||||
const bool use_face_center = (
|
const bool use_face_center = (
|
||||||
(ts->uv_flag & UV_SYNC_SELECTION) ?
|
(ts->uv_flag & UV_SYNC_SELECTION) ?
|
||||||
(ts->selectmode == SCE_SELECT_FACE) :
|
(ts->selectmode == SCE_SELECT_FACE) :
|
||||||
(ts->uv_selectmode == UV_SELECT_FACE));
|
(ts->uv_selectmode == UV_SELECT_FACE));
|
||||||
|
|
||||||
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
|
||||||
|
|
||||||
/* get rectangle from operator */
|
/* get rectangle from operator */
|
||||||
WM_operator_properties_border_to_rctf(op, &rectf);
|
WM_operator_properties_border_to_rctf(op, &rectf);
|
||||||
UI_view2d_region_to_view_rctf(&ar->v2d, &rectf, &rectf);
|
UI_view2d_region_to_view_rctf(&ar->v2d, &rectf, &rectf);
|
||||||
@@ -2905,8 +3056,25 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
|
|||||||
extend = RNA_boolean_get(op->ptr, "extend");
|
extend = RNA_boolean_get(op->ptr, "extend");
|
||||||
pinned = RNA_boolean_get(op->ptr, "pinned");
|
pinned = RNA_boolean_get(op->ptr, "pinned");
|
||||||
|
|
||||||
|
bool changed_multi = false;
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.filter_fn = BKE_view_layer_filter_edit_mesh_has_uvs,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
/* don't indent to avoid diff noise! */
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||||
|
|
||||||
if (!extend)
|
if (!extend)
|
||||||
uv_select_all_perform(scene, ima, obedit, em, SEL_DESELECT);
|
uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
|
||||||
|
|
||||||
/* do actual selection */
|
/* do actual selection */
|
||||||
if (use_face_center && !pinned) {
|
if (use_face_center && !pinned) {
|
||||||
@@ -2972,12 +3140,19 @@ static int uv_border_select_exec(bContext *C, wmOperator *op)
|
|||||||
if (ts->uv_flag & UV_SYNC_SELECTION) {
|
if (ts->uv_flag & UV_SYNC_SELECTION) {
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changed_multi |= changed;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
|
||||||
|
if (changed_multi) {
|
||||||
|
return OPERATOR_FINISHED;
|
||||||
|
}
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void UV_OT_select_border(wmOperatorType *ot)
|
static void UV_OT_select_border(wmOperatorType *ot)
|
||||||
{
|
{
|
||||||
@@ -3131,36 +3306,49 @@ static void UV_OT_circle_select(wmOperatorType *ot)
|
|||||||
/** \name Lasso Select Operator
|
/** \name Lasso Select Operator
|
||||||
* \{ */
|
* \{ */
|
||||||
|
|
||||||
static bool do_lasso_select_mesh_uv(
|
static bool do_lasso_select_mesh_uv(bContext *C, const int mcords[][2], short moves,
|
||||||
bContext *C, const int mcords[][2], short moves,
|
const bool select, const bool extend)
|
||||||
const bool select, const bool extend)
|
|
||||||
{
|
{
|
||||||
SpaceImage *sima = CTX_wm_space_image(C);
|
SpaceImage *sima = CTX_wm_space_image(C);
|
||||||
Image *ima = CTX_data_edit_image(C);
|
Image *ima = CTX_data_edit_image(C);
|
||||||
ARegion *ar = CTX_wm_region(C);
|
ARegion *ar = CTX_wm_region(C);
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
ToolSettings *ts = scene->toolsettings;
|
ToolSettings *ts = scene->toolsettings;
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
const bool use_face_center = (
|
const bool use_face_center = (
|
||||||
(ts->uv_flag & UV_SYNC_SELECTION) ?
|
(ts->uv_flag & UV_SYNC_SELECTION) ?
|
||||||
(ts->selectmode == SCE_SELECT_FACE) :
|
(ts->selectmode == SCE_SELECT_FACE) :
|
||||||
(ts->uv_selectmode == UV_SELECT_FACE));
|
(ts->uv_selectmode == UV_SELECT_FACE));
|
||||||
|
|
||||||
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
|
||||||
|
|
||||||
BMIter iter, liter;
|
BMIter iter, liter;
|
||||||
|
|
||||||
BMFace *efa;
|
BMFace *efa;
|
||||||
BMLoop *l;
|
BMLoop *l;
|
||||||
int screen_uv[2];
|
int screen_uv[2];
|
||||||
bool changed = false;
|
bool changed_multi = false;
|
||||||
rcti rect;
|
rcti rect;
|
||||||
|
|
||||||
BLI_lasso_boundbox(&rect, mcords, moves);
|
BLI_lasso_boundbox(&rect, mcords, moves);
|
||||||
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.filter_fn = BKE_view_layer_filter_edit_mesh_has_uvs,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
/* don't indent to avoid diff noise! */
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
|
||||||
|
bool changed = false;
|
||||||
|
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
|
||||||
|
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||||
|
|
||||||
if (!extend && select) {
|
if (!extend && select) {
|
||||||
uv_select_all_perform(scene, ima, obedit, em, SEL_DESELECT);
|
uv_select_all_perform_multi(scene, ima, objects, objects_len, SEL_DESELECT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_face_center) { /* Face Center Sel */
|
if (use_face_center) { /* Face Center Sel */
|
||||||
@@ -3223,7 +3411,11 @@ static bool do_lasso_select_mesh_uv(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return changed;
|
changed_multi |= changed;
|
||||||
|
|
||||||
|
} /* objects */
|
||||||
|
|
||||||
|
return changed_multi;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int uv_lasso_select_exec(bContext *C, wmOperator *op)
|
static int uv_lasso_select_exec(bContext *C, wmOperator *op)
|
||||||
@@ -4175,7 +4367,7 @@ static int uv_mark_seam_exec(bContext *C, wmOperator *op)
|
|||||||
me->drawflag |= ME_DRAWSEAMS;
|
me->drawflag |= ME_DRAWSEAMS;
|
||||||
|
|
||||||
if (scene->toolsettings->edge_mode_live_unwrap)
|
if (scene->toolsettings->edge_mode_live_unwrap)
|
||||||
ED_unwrap_lscm(scene, ob, false);
|
ED_unwrap_lscm(scene, ob, false, false);
|
||||||
|
|
||||||
DEG_id_tag_update(&me->id, 0);
|
DEG_id_tag_update(&me->id, 0);
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
|
||||||
|
@@ -61,6 +61,7 @@
|
|||||||
#include "BKE_report.h"
|
#include "BKE_report.h"
|
||||||
#include "BKE_scene.h"
|
#include "BKE_scene.h"
|
||||||
#include "BKE_editmesh.h"
|
#include "BKE_editmesh.h"
|
||||||
|
#include "BKE_layer.h"
|
||||||
|
|
||||||
#include "DEG_depsgraph.h"
|
#include "DEG_depsgraph.h"
|
||||||
|
|
||||||
@@ -202,6 +203,21 @@ static bool uvedit_have_selection(Scene *scene, BMEditMesh *em, bool implicit)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool uvedit_have_selection_multi(
|
||||||
|
Scene *scene, Object **objects, const uint objects_len, bool implicit)
|
||||||
|
{
|
||||||
|
bool have_select = false;
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
if (uvedit_have_selection(scene, em, implicit)) {
|
||||||
|
have_select = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return have_select;
|
||||||
|
}
|
||||||
|
|
||||||
void ED_uvedit_get_aspect(Scene *scene, Object *ob, BMesh *bm, float *aspx, float *aspy)
|
void ED_uvedit_get_aspect(Scene *scene, Object *ob, BMesh *bm, float *aspx, float *aspy)
|
||||||
{
|
{
|
||||||
bool sloppy = true;
|
bool sloppy = true;
|
||||||
@@ -258,9 +274,10 @@ static void construct_param_handle_face_add(ParamHandle *handle, Scene *scene,
|
|||||||
param_face_add(handle, key, i, vkeys, co, uv, pin, select, efa->no);
|
param_face_add(handle, key, i, vkeys, co, uv, pin, select, efa->no);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm,
|
static ParamHandle *construct_param_handle_single(
|
||||||
const bool implicit, const bool fill, const bool sel,
|
Scene *scene, Object *ob, BMesh *bm,
|
||||||
const bool correct_aspect)
|
const bool implicit, const bool fill, const bool sel,
|
||||||
|
const bool correct_aspect)
|
||||||
{
|
{
|
||||||
ParamHandle *handle;
|
ParamHandle *handle;
|
||||||
BMFace *efa;
|
BMFace *efa;
|
||||||
@@ -324,6 +341,92 @@ static ParamHandle *construct_param_handle(Scene *scene, Object *ob, BMesh *bm,
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version of #construct_param_handle_single that handles multiple objects.
|
||||||
|
*/
|
||||||
|
static ParamHandle *construct_param_handle_multi(
|
||||||
|
Scene *scene, Object **objects, const uint objects_len,
|
||||||
|
const bool implicit, const bool fill, const bool sel,
|
||||||
|
const bool correct_aspect)
|
||||||
|
{
|
||||||
|
ParamHandle *handle;
|
||||||
|
BMFace *efa;
|
||||||
|
BMLoop *l;
|
||||||
|
BMEdge *eed;
|
||||||
|
BMIter iter, liter;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
handle = param_construct_begin();
|
||||||
|
|
||||||
|
if (correct_aspect) {
|
||||||
|
Object *ob = objects[0];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(ob);
|
||||||
|
BMesh *bm = em->bm;
|
||||||
|
float aspx, aspy;
|
||||||
|
|
||||||
|
ED_uvedit_get_aspect(scene, ob, bm, &aspx, &aspy);
|
||||||
|
|
||||||
|
if (aspx != aspy)
|
||||||
|
param_aspect_ratio(handle, aspx, aspy);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we need the vert indices */
|
||||||
|
EDBM_mesh_elem_index_ensure_multi(objects, objects_len, BM_VERT);
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
/* no indent, avoid diff noise */
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
BMesh *bm = em->bm;
|
||||||
|
|
||||||
|
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
|
||||||
|
|
||||||
|
BM_ITER_MESH_INDEX (efa, &iter, bm, BM_FACES_OF_MESH, i) {
|
||||||
|
|
||||||
|
if ((BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) || (sel && BM_elem_flag_test(efa, BM_ELEM_SELECT) == 0)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (implicit) {
|
||||||
|
bool is_loopsel = false;
|
||||||
|
|
||||||
|
BM_ITER_ELEM (l, &liter, efa, BM_LOOPS_OF_FACE) {
|
||||||
|
if (uvedit_uv_select_test(scene, l, cd_loop_uv_offset)) {
|
||||||
|
is_loopsel = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (is_loopsel == false) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
construct_param_handle_face_add(handle, scene, efa, i + offset, cd_loop_uv_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!implicit) {
|
||||||
|
BM_ITER_MESH (eed, &iter, bm, BM_EDGES_OF_MESH) {
|
||||||
|
if (BM_elem_flag_test(eed, BM_ELEM_SEAM)) {
|
||||||
|
ParamKey vkeys[2];
|
||||||
|
vkeys[0] = (ParamKey)BM_elem_index_get(eed->v1);
|
||||||
|
vkeys[1] = (ParamKey)BM_elem_index_get(eed->v2);
|
||||||
|
param_edge_set_seam(handle, vkeys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
offset += bm->totface;
|
||||||
|
|
||||||
|
} /* objects */
|
||||||
|
|
||||||
|
param_construct_end(handle, fill, implicit);
|
||||||
|
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select,
|
static void texface_from_original_index(BMFace *efa, int index, float **uv, ParamBool *pin, ParamBool *select,
|
||||||
Scene *scene, const int cd_loop_uv_offset)
|
Scene *scene, const int cd_loop_uv_offset)
|
||||||
@@ -535,7 +638,7 @@ static bool minimize_stretch_init(bContext *C, wmOperator *op)
|
|||||||
ms->blend = RNA_float_get(op->ptr, "blend");
|
ms->blend = RNA_float_get(op->ptr, "blend");
|
||||||
ms->iterations = RNA_int_get(op->ptr, "iterations");
|
ms->iterations = RNA_int_get(op->ptr, "iterations");
|
||||||
ms->i = 0;
|
ms->i = 0;
|
||||||
ms->handle = construct_param_handle(scene, obedit, em->bm, implicit, fill_holes, 1, 1);
|
ms->handle = construct_param_handle_single(scene, obedit, em->bm, implicit, fill_holes, 1, 1);
|
||||||
ms->lasttime = PIL_check_seconds_timer();
|
ms->lasttime = PIL_check_seconds_timer();
|
||||||
|
|
||||||
param_stretch_begin(ms->handle);
|
param_stretch_begin(ms->handle);
|
||||||
@@ -715,10 +818,23 @@ void UV_OT_minimize_stretch(wmOperatorType *ot)
|
|||||||
|
|
||||||
/* ******************** Pack Islands operator **************** */
|
/* ******************** Pack Islands operator **************** */
|
||||||
|
|
||||||
void ED_uvedit_pack_islands(Scene *scene, Object *ob, BMesh *bm, bool selected, bool correct_aspect, bool do_rotate)
|
|
||||||
|
void ED_uvedit_pack_islands_single(Scene *scene, Object *ob, BMesh *bm, bool selected, bool correct_aspect, bool do_rotate)
|
||||||
{
|
{
|
||||||
ParamHandle *handle;
|
ParamHandle *handle;
|
||||||
handle = construct_param_handle(scene, ob, bm, true, false, selected, correct_aspect);
|
handle = construct_param_handle_single(scene, ob, bm, true, false, selected, correct_aspect);
|
||||||
|
param_pack(handle, scene->toolsettings->uvcalc_margin, do_rotate);
|
||||||
|
param_flush(handle);
|
||||||
|
param_delete(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ED_uvedit_pack_islands_multi(
|
||||||
|
Scene *scene, Object **objects, const uint objects_len,
|
||||||
|
bool selected, bool correct_aspect, bool do_rotate)
|
||||||
|
{
|
||||||
|
ParamHandle *handle;
|
||||||
|
handle = construct_param_handle_multi(
|
||||||
|
scene, objects, objects_len, true, false, selected, correct_aspect);
|
||||||
param_pack(handle, scene->toolsettings->uvcalc_margin, do_rotate);
|
param_pack(handle, scene->toolsettings->uvcalc_margin, do_rotate);
|
||||||
param_flush(handle);
|
param_flush(handle);
|
||||||
param_delete(handle);
|
param_delete(handle);
|
||||||
@@ -726,12 +842,18 @@ void ED_uvedit_pack_islands(Scene *scene, Object *ob, BMesh *bm, bool selected,
|
|||||||
|
|
||||||
static int pack_islands_exec(bContext *C, wmOperator *op)
|
static int pack_islands_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
|
||||||
bool do_rotate = RNA_boolean_get(op->ptr, "rotate");
|
bool do_rotate = RNA_boolean_get(op->ptr, "rotate");
|
||||||
|
|
||||||
if (!uvedit_have_selection(scene, em, true)) {
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.filter_fn = BKE_view_layer_filter_edit_mesh_has_uvs,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
if (!uvedit_have_selection_multi(scene, objects, objects_len, true)) {
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -740,10 +862,15 @@ static int pack_islands_exec(bContext *C, wmOperator *op)
|
|||||||
else
|
else
|
||||||
RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
|
RNA_float_set(op->ptr, "margin", scene->toolsettings->uvcalc_margin);
|
||||||
|
|
||||||
ED_uvedit_pack_islands(scene, obedit, em->bm, true, true, do_rotate);
|
ED_uvedit_pack_islands_multi(scene, objects, objects_len, true, true, do_rotate);
|
||||||
|
|
||||||
DEG_id_tag_update(obedit->data, 0);
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
Object *obedit = objects[ob_index];
|
||||||
|
DEG_id_tag_update(obedit->data, 0);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
@@ -780,7 +907,7 @@ static int average_islands_scale_exec(bContext *C, wmOperator *UNUSED(op))
|
|||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle = construct_param_handle(scene, obedit, em->bm, implicit, 0, 1, 1);
|
handle = construct_param_handle_single(scene, obedit, em->bm, implicit, 0, 1, 1);
|
||||||
param_average(handle);
|
param_average(handle);
|
||||||
param_flush(handle);
|
param_flush(handle);
|
||||||
param_delete(handle);
|
param_delete(handle);
|
||||||
@@ -825,7 +952,7 @@ void ED_uvedit_live_unwrap_begin(Scene *scene, Object *obedit)
|
|||||||
if (use_subsurf)
|
if (use_subsurf)
|
||||||
liveHandle = construct_param_handle_subsurfed(scene, obedit, em, fillholes, false, true);
|
liveHandle = construct_param_handle_subsurfed(scene, obedit, em, fillholes, false, true);
|
||||||
else
|
else
|
||||||
liveHandle = construct_param_handle(scene, obedit, em->bm, false, fillholes, false, true);
|
liveHandle = construct_param_handle_single(scene, obedit, em->bm, false, fillholes, false, true);
|
||||||
|
|
||||||
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
|
param_lscm_begin(liveHandle, PARAM_TRUE, abf);
|
||||||
}
|
}
|
||||||
@@ -856,7 +983,7 @@ void ED_uvedit_live_unwrap(Scene *scene, Object *obedit)
|
|||||||
if (scene->toolsettings->edge_mode_live_unwrap &&
|
if (scene->toolsettings->edge_mode_live_unwrap &&
|
||||||
CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV))
|
CustomData_has_layer(&em->bm->ldata, CD_MLOOPUV))
|
||||||
{
|
{
|
||||||
ED_unwrap_lscm(scene, obedit, false); /* unwrap all not just sel */
|
ED_unwrap_lscm(scene, obedit, false, false); /* unwrap all not just sel */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1178,7 +1305,7 @@ static void uv_map_clip_correct(Scene *scene, Object *ob, BMEditMesh *em, wmOper
|
|||||||
/* ******************** Unwrap operator **************** */
|
/* ******************** Unwrap operator **************** */
|
||||||
|
|
||||||
/* assumes UV Map is checked, doesn't run update funcs */
|
/* assumes UV Map is checked, doesn't run update funcs */
|
||||||
void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
|
void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel, const bool pack)
|
||||||
{
|
{
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
ParamHandle *handle;
|
ParamHandle *handle;
|
||||||
@@ -1192,14 +1319,17 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
|
|||||||
if (use_subsurf)
|
if (use_subsurf)
|
||||||
handle = construct_param_handle_subsurfed(scene, obedit, em, fill_holes, sel, correct_aspect);
|
handle = construct_param_handle_subsurfed(scene, obedit, em, fill_holes, sel, correct_aspect);
|
||||||
else
|
else
|
||||||
handle = construct_param_handle(scene, obedit, em->bm, false, fill_holes, sel, correct_aspect);
|
handle = construct_param_handle_single(scene, obedit, em->bm, false, fill_holes, sel, correct_aspect);
|
||||||
|
|
||||||
param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
|
param_lscm_begin(handle, PARAM_FALSE, scene->toolsettings->unwrapper == 0);
|
||||||
param_lscm_solve(handle);
|
param_lscm_solve(handle);
|
||||||
param_lscm_end(handle);
|
param_lscm_end(handle);
|
||||||
|
|
||||||
param_average(handle);
|
param_average(handle);
|
||||||
param_pack(handle, scene->toolsettings->uvcalc_margin, false);
|
|
||||||
|
if (pack) {
|
||||||
|
param_pack(handle, scene->toolsettings->uvcalc_margin, false);
|
||||||
|
}
|
||||||
|
|
||||||
param_flush(handle);
|
param_flush(handle);
|
||||||
|
|
||||||
@@ -1208,33 +1338,48 @@ void ED_unwrap_lscm(Scene *scene, Object *obedit, const short sel)
|
|||||||
|
|
||||||
static int unwrap_exec(bContext *C, wmOperator *op)
|
static int unwrap_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
#if 0
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
Object *obedit = CTX_data_edit_object(C);
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
#endif
|
||||||
|
|
||||||
int method = RNA_enum_get(op->ptr, "method");
|
int method = RNA_enum_get(op->ptr, "method");
|
||||||
const bool fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
|
const bool fill_holes = RNA_boolean_get(op->ptr, "fill_holes");
|
||||||
const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
|
const bool correct_aspect = RNA_boolean_get(op->ptr, "correct_aspect");
|
||||||
const bool use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
|
const bool use_subsurf = RNA_boolean_get(op->ptr, "use_subsurf_data");
|
||||||
|
#if 0
|
||||||
bool use_subsurf_final;
|
bool use_subsurf_final;
|
||||||
|
#endif
|
||||||
float obsize[3];
|
float obsize[3];
|
||||||
bool implicit = false;
|
bool implicit = false;
|
||||||
|
|
||||||
if (!uvedit_have_selection(scene, em, implicit)) {
|
uint objects_len = 0;
|
||||||
return OPERATOR_CANCELLED;
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
}
|
view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
/* add uvs if they don't exist yet */
|
|
||||||
if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
|
if (!uvedit_have_selection_multi(scene, objects, objects_len, implicit)) {
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
return OPERATOR_CANCELLED;
|
return OPERATOR_CANCELLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4_to_size(obsize, obedit->obmat);
|
/* add uvs if they don't exist yet */
|
||||||
if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f))
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
BKE_report(op->reports, RPT_INFO,
|
Object *obedit = objects[ob_index];
|
||||||
"Object has non-uniform scale, unwrap will operate on a non-scaled version of the mesh");
|
if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
|
||||||
else if (is_negative_m4(obedit->obmat))
|
continue;
|
||||||
BKE_report(op->reports, RPT_INFO,
|
}
|
||||||
"Object has negative scale, unwrap will operate on a non-flipped version of the mesh");
|
|
||||||
|
mat4_to_size(obsize, obedit->obmat);
|
||||||
|
if (!(fabsf(obsize[0] - obsize[1]) < 1e-4f && fabsf(obsize[1] - obsize[2]) < 1e-4f))
|
||||||
|
BKE_report(op->reports, RPT_INFO,
|
||||||
|
"Object has non-uniform scale, unwrap will operate on a non-scaled version of the mesh");
|
||||||
|
else if (is_negative_m4(obedit->obmat))
|
||||||
|
BKE_report(op->reports, RPT_INFO,
|
||||||
|
"Object has negative scale, unwrap will operate on a non-flipped version of the mesh");
|
||||||
|
}
|
||||||
|
|
||||||
/* remember last method for live unwrap */
|
/* remember last method for live unwrap */
|
||||||
if (RNA_struct_property_is_set(op->ptr, "method"))
|
if (RNA_struct_property_is_set(op->ptr, "method"))
|
||||||
@@ -1257,17 +1402,25 @@ static int unwrap_exec(bContext *C, wmOperator *op)
|
|||||||
if (use_subsurf) scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
|
if (use_subsurf) scene->toolsettings->uvcalc_flag |= UVCALC_USESUBSURF;
|
||||||
else scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
|
else scene->toolsettings->uvcalc_flag &= ~UVCALC_USESUBSURF;
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* double up the check here but better keep ED_unwrap_lscm interface simple and not
|
/* double up the check here but better keep ED_unwrap_lscm interface simple and not
|
||||||
* pass operator for warning append */
|
* pass operator for warning append */
|
||||||
modifier_unwrap_state(obedit, scene, &use_subsurf_final);
|
modifier_unwrap_state(obedit, scene, &use_subsurf_final);
|
||||||
if (use_subsurf != use_subsurf_final)
|
if (use_subsurf != use_subsurf_final)
|
||||||
BKE_report(op->reports, RPT_INFO, "Subdivision Surface modifier needs to be first to work with unwrap");
|
BKE_report(op->reports, RPT_INFO, "Subdivision Surface modifier needs to be first to work with unwrap");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* execute unwrap */
|
/* execute unwrap */
|
||||||
ED_unwrap_lscm(scene, obedit, true);
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
ED_unwrap_lscm(scene, obedit, true, false);
|
||||||
|
DEG_id_tag_update(obedit->data, 0);
|
||||||
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
||||||
|
}
|
||||||
|
|
||||||
DEG_id_tag_update(obedit->data, 0);
|
ED_uvedit_pack_islands_multi(scene, objects, objects_len, true, true, true);
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
@@ -1322,9 +1475,8 @@ static int uv_from_view_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSE
|
|||||||
|
|
||||||
static int uv_from_view_exec(bContext *C, wmOperator *op)
|
static int uv_from_view_exec(bContext *C, wmOperator *op)
|
||||||
{
|
{
|
||||||
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||||
Scene *scene = CTX_data_scene(C);
|
Scene *scene = CTX_data_scene(C);
|
||||||
Object *obedit = CTX_data_edit_object(C);
|
|
||||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
|
||||||
ARegion *ar = CTX_wm_region(C);
|
ARegion *ar = CTX_wm_region(C);
|
||||||
View3D *v3d = CTX_wm_view3d(C);
|
View3D *v3d = CTX_wm_view3d(C);
|
||||||
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
RegionView3D *rv3d = CTX_wm_region_view3d(C);
|
||||||
@@ -1335,14 +1487,22 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
|
|||||||
MLoopUV *luv;
|
MLoopUV *luv;
|
||||||
float rotmat[4][4];
|
float rotmat[4][4];
|
||||||
|
|
||||||
int cd_loop_uv_offset;
|
|
||||||
|
uint objects_len = 0;
|
||||||
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode(
|
||||||
|
view_layer, &objects_len,
|
||||||
|
.no_dupe_data = true);
|
||||||
|
|
||||||
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
||||||
|
Object *obedit = objects[ob_index];
|
||||||
|
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||||
|
|
||||||
/* add uvs if they don't exist yet */
|
/* add uvs if they don't exist yet */
|
||||||
if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
|
if (!ED_uvedit_ensure_uvs(C, scene, obedit)) {
|
||||||
return OPERATOR_CANCELLED;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
const int cd_loop_uv_offset = CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV);
|
||||||
|
|
||||||
if (RNA_boolean_get(op->ptr, "orthographic")) {
|
if (RNA_boolean_get(op->ptr, "orthographic")) {
|
||||||
uv_map_rotation_matrix(rotmat, rv3d, obedit, 90.0f, 0.0f, 1.0f);
|
uv_map_rotation_matrix(rotmat, rv3d, obedit, 90.0f, 0.0f, 1.0f);
|
||||||
@@ -1396,6 +1556,9 @@ static int uv_from_view_exec(bContext *C, wmOperator *op)
|
|||||||
DEG_id_tag_update(obedit->data, 0);
|
DEG_id_tag_update(obedit->data, 0);
|
||||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
||||||
|
|
||||||
|
}
|
||||||
|
MEM_SAFE_FREE(objects);
|
||||||
|
|
||||||
return OPERATOR_FINISHED;
|
return OPERATOR_FINISHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user