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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors')
-rw-r--r--source/blender/editors/include/ED_mesh.h10
-rw-r--r--source/blender/editors/include/ED_screen.h2
-rw-r--r--source/blender/editors/include/ED_transform_snap_object_context.h2
-rw-r--r--source/blender/editors/mesh/editmesh_bevel.c113
-rw-r--r--source/blender/editors/mesh/editmesh_intersect.c466
-rw-r--r--source/blender/editors/mesh/editmesh_select.c85
-rw-r--r--source/blender/editors/mesh/editmesh_utils.c2
-rw-r--r--source/blender/editors/mesh/mesh_mirror.c127
-rw-r--r--source/blender/editors/mesh/meshtools.c118
-rw-r--r--source/blender/editors/object/object_edit.c10
-rw-r--r--source/blender/editors/object/object_relations.c20
-rw-r--r--source/blender/editors/physics/particle_edit.c139
-rw-r--r--source/blender/editors/physics/particle_object.c76
-rw-r--r--source/blender/editors/screen/screen_edit.c8
-rw-r--r--source/blender/editors/sculpt_paint/paint_image_proj.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_collections.c187
-rw-r--r--source/blender/editors/space_outliner/outliner_draw.c81
-rw-r--r--source/blender/editors/space_outliner/outliner_edit.c12
-rw-r--r--source/blender/editors/space_outliner/outliner_intern.h4
-rw-r--r--source/blender/editors/space_outliner/outliner_ops.c4
-rw-r--r--source/blender/editors/space_outliner/outliner_select.c34
-rw-r--r--source/blender/editors/space_outliner/outliner_tools.c17
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c195
-rw-r--r--source/blender/editors/space_outliner/space_outliner.c5
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c16
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c2
-rw-r--r--source/blender/editors/transform/transform_conversions.c4
-rw-r--r--source/blender/editors/transform/transform_snap.c7
-rw-r--r--source/blender/editors/transform/transform_snap_object.c764
29 files changed, 1608 insertions, 904 deletions
diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h
index 787cf7f0524..dfa5a51a775 100644
--- a/source/blender/editors/include/ED_mesh.h
+++ b/source/blender/editors/include/ED_mesh.h
@@ -226,9 +226,14 @@ typedef struct MirrTopoStore_t {
bool ED_mesh_mirrtopo_recalc_check(
struct Mesh *me, struct DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store);
+bool ED_mesh_mirrtopo_recalc_check__real_mesh(
+ struct Mesh *me, struct Mesh *dm, MirrTopoStore_t *mesh_topo_store);
void ED_mesh_mirrtopo_init(
struct Mesh *me, struct DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store,
const bool skip_em_vert_array_init);
+void ED_mesh_mirrtopo_init__real_mesh(
+ struct Mesh *me, struct Mesh *dm, MirrTopoStore_t *mesh_topo_store,
+ const bool skip_em_vert_array_init);
void ED_mesh_mirrtopo_free(MirrTopoStore_t *mesh_topo_store);
@@ -318,16 +323,21 @@ int join_mesh_shapes_exec(struct bContext *C, struct wmOperator *op);
/* mirror lookup api */
int ED_mesh_mirror_spatial_table(
struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, const float co[3], char mode);
+int ED_mesh_mirror_spatial_table__real_mesh(
+ struct Object *ob, struct BMEditMesh *em, struct Mesh *mesh, const float co[3], char mode);
int ED_mesh_mirror_topo_table(struct Object *ob, struct DerivedMesh *dm, char mode);
+int ED_mesh_mirror_topo_table__real_mesh(struct Object *ob, struct Mesh *mesh, char mode);
/* retrieves mirrored cache vert, or NULL if there isn't one.
* note: calling this without ensuring the mirror cache state
* is bad.*/
int mesh_get_x_mirror_vert(struct Object *ob, struct DerivedMesh *dm, int index, const bool use_topology);
+int mesh_get_x_mirror_vert__real_mesh(struct Object *ob, struct Mesh *mesh, int index, const bool use_topology);
struct BMVert *editbmesh_get_x_mirror_vert(struct Object *ob, struct BMEditMesh *em,
struct BMVert *eve, const float co[3],
int index, const bool use_topology);
int *mesh_get_x_mirror_faces(struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm);
+int *mesh_get_x_mirror_faces__real_mesh(struct Object *ob, struct BMEditMesh *em, struct Mesh *mesh);
int ED_mesh_mirror_get_vert(struct Object *ob, int index);
diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h
index 4b22e691885..3d17afc2878 100644
--- a/source/blender/editors/include/ED_screen.h
+++ b/source/blender/editors/include/ED_screen.h
@@ -173,7 +173,7 @@ void ED_screen_update_after_scene_change(
const struct bScreen *screen,
struct Scene *scene_new,
struct ViewLayer *view_layer);
-void ED_screen_set_active_region(struct bContext *C, const int xy[2]);
+void ED_screen_set_active_region(struct bContext *C, struct wmWindow *win, const int xy[2]);
void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen);
void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable);
void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh);
diff --git a/source/blender/editors/include/ED_transform_snap_object_context.h b/source/blender/editors/include/ED_transform_snap_object_context.h
index 465a91ad0d0..d65679e1872 100644
--- a/source/blender/editors/include/ED_transform_snap_object_context.h
+++ b/source/blender/editors/include/ED_transform_snap_object_context.h
@@ -119,7 +119,6 @@ bool ED_transform_snap_object_project_view3d_ex(
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2], float *dist_px,
- float *ray_depth,
float r_loc[3], float r_no[3], int *r_index,
struct Object **r_ob, float r_obmat[4][4]);
bool ED_transform_snap_object_project_view3d(
@@ -127,7 +126,6 @@ bool ED_transform_snap_object_project_view3d(
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2], float *dist_px,
- float *ray_depth,
/* return args */
float r_loc[3], float r_no[3]);
bool ED_transform_snap_object_project_view3d_mixed(
diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c
index ca5af7a535d..e75b133b5bd 100644
--- a/source/blender/editors/mesh/editmesh_bevel.c
+++ b/source/blender/editors/mesh/editmesh_bevel.c
@@ -37,6 +37,7 @@
#include "BKE_global.h"
#include "BKE_editmesh.h"
#include "BKE_unit.h"
+#include "BKE_layer.h"
#include "RNA_define.h"
#include "RNA_access.h"
@@ -77,15 +78,22 @@ static const float value_scale_per_inch[NUM_VALUE_KINDS] = { 0.0f, 100.0f, 1.0f,
typedef struct {
BMEditMesh *em;
+ BMBackup mesh_backup;
+} BevelObjectStore;
+
+
+typedef struct {
float initial_length[NUM_VALUE_KINDS];
float scale[NUM_VALUE_KINDS];
NumInput num_input[NUM_VALUE_KINDS];
float shift_value[NUM_VALUE_KINDS]; /* The current value when shift is pressed. Negative when shift not active. */
bool is_modal;
+ BevelObjectStore *ob_store;
+ uint ob_store_len;
+
/* modal only */
float mcenter[2];
- BMBackup mesh_backup;
void *draw_handle_pixel;
short twflag;
short value_mode; /* Which value does mouse movement and numeric input affect? */
@@ -128,24 +136,35 @@ static void edbm_bevel_update_header(bContext *C, wmOperator *op)
static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
{
- Object *obedit = CTX_data_edit_object(C);
Scene *scene = CTX_data_scene(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
BevelData *opdata;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
float pixels_per_inch;
int i;
- if (em->bm->totvertsel == 0) {
- return false;
- }
-
if (is_modal) {
RNA_float_set(op->ptr, "offset", 0.0f);
}
op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator");
+ uint objects_used_len = 0;
+
+ {
+ uint ob_store_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &ob_store_len);
+ opdata->ob_store = MEM_malloc_arrayN(ob_store_len, sizeof(*opdata->ob_store), __func__);
+ for (uint ob_index = 0; ob_index < ob_store_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+ if (em->bm->totvertsel > 0) {
+ opdata->ob_store[objects_used_len].em = em;
+ objects_used_len++;
+ }
+ }
+ MEM_freeN(objects);
+ opdata->ob_store_len = objects_used_len;
+ }
- opdata->em = em;
opdata->is_modal = is_modal;
opdata->value_mode = OFFSET_VALUE;
opdata->segments = (float) RNA_int_get(op->ptr, "segments");
@@ -174,7 +193,9 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
- opdata->mesh_backup = EDBM_redo_state_store(em);
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ opdata->ob_store[ob_index].mesh_backup = EDBM_redo_state_store(opdata->ob_store[ob_index].em);
+ }
opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb,
opdata->mcenter, REGION_DRAW_POST_PIXEL);
G.moving = G_TRANSFORM_EDIT;
@@ -191,8 +212,10 @@ static bool edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal)
static bool edbm_bevel_calc(wmOperator *op)
{
BevelData *opdata = op->customdata;
- BMEditMesh *em = opdata->em;
+ BMEditMesh *em;
BMOperator bmop;
+ bool changed = false;
+
const float offset = RNA_float_get(op->ptr, "offset");
const int offset_type = RNA_enum_get(op->ptr, "offset_type");
const int segments = RNA_int_get(op->ptr, "segments");
@@ -202,40 +225,45 @@ static bool edbm_bevel_calc(wmOperator *op)
int material = RNA_int_get(op->ptr, "material");
const bool loop_slide = RNA_boolean_get(op->ptr, "loop_slide");
- /* revert to original mesh */
- if (opdata->is_modal) {
- EDBM_redo_state_restore(opdata->mesh_backup, em, false);
- }
- if (em->ob) {
- material = CLAMPIS(material, -1, em->ob->totcol - 1);
- }
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ em = opdata->ob_store[ob_index].em;
- EDBM_op_init(em, &bmop, op,
- "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b "
- "material=%i loop_slide=%b",
- BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
- clamp_overlap, material, loop_slide);
+ /* revert to original mesh */
+ if (opdata->is_modal) {
+ EDBM_redo_state_restore(opdata->ob_store[ob_index].mesh_backup, em, false);
+ }
- BMO_op_exec(em->bm, &bmop);
+ if (em->ob) {
+ material = CLAMPIS(material, -1, em->ob->totcol - 1);
+ }
- if (offset != 0.0f) {
- /* not essential, but we may have some loose geometry that
- * won't get bevel'd and better not leave it selected */
- EDBM_flag_disable_all(em, BM_ELEM_SELECT);
- BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
- }
+ EDBM_op_init(em, &bmop, op,
+ "bevel geom=%hev offset=%f segments=%i vertex_only=%b offset_type=%i profile=%f clamp_overlap=%b "
+ "material=%i loop_slide=%b",
+ BM_ELEM_SELECT, offset, segments, vertex_only, offset_type, profile,
+ clamp_overlap, material, loop_slide);
- /* no need to de-select existing geometry */
- if (!EDBM_op_finish(em, &bmop, op, true)) {
- return false;
- }
+ BMO_op_exec(em->bm, &bmop);
- EDBM_mesh_normals_update(opdata->em);
+ if (offset != 0.0f) {
+ /* not essential, but we may have some loose geometry that
+ * won't get bevel'd and better not leave it selected */
+ EDBM_flag_disable_all(em, BM_ELEM_SELECT);
+ BMO_slot_buffer_hflag_enable(em->bm, bmop.slots_out, "faces.out", BM_FACE, BM_ELEM_SELECT, true);
+ }
+
+ /* no need to de-select existing geometry */
+ if (!EDBM_op_finish(em, &bmop, op, true)) {
+ continue;
+ }
- EDBM_update_generic(opdata->em, true, true);
+ EDBM_mesh_normals_update(em);
- return true;
+ EDBM_update_generic(em, true, true);
+ changed = true;
+ }
+ return changed;
}
static void edbm_bevel_exit(bContext *C, wmOperator *op)
@@ -251,14 +279,17 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op)
if (opdata->is_modal) {
View3D *v3d = CTX_wm_view3d(C);
ARegion *ar = CTX_wm_region(C);
- EDBM_redo_state_free(&opdata->mesh_backup, NULL, false);
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, NULL, false);
+ }
ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel);
if (v3d) {
v3d->twflag = opdata->twflag;
}
G.moving = 0;
}
- MEM_freeN(opdata);
+ MEM_SAFE_FREE(opdata->ob_store);
+ MEM_SAFE_FREE(op->customdata);
op->customdata = NULL;
}
@@ -266,8 +297,10 @@ static void edbm_bevel_cancel(bContext *C, wmOperator *op)
{
BevelData *opdata = op->customdata;
if (opdata->is_modal) {
- EDBM_redo_state_free(&opdata->mesh_backup, opdata->em, true);
- EDBM_update_generic(opdata->em, false, true);
+ for (uint ob_index = 0; ob_index < opdata->ob_store_len; ob_index++) {
+ EDBM_redo_state_free(&opdata->ob_store[ob_index].mesh_backup, opdata->ob_store[ob_index].em, true);
+ EDBM_update_generic(opdata->ob_store[ob_index].em, false, true);
+ }
}
edbm_bevel_exit(C, op);
diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c
index d681d904e74..4d76dba4c3a 100644
--- a/source/blender/editors/mesh/editmesh_intersect.c
+++ b/source/blender/editors/mesh/editmesh_intersect.c
@@ -33,6 +33,7 @@
#include "BLI_kdopbvh.h"
#include "BLI_linklist_stack.h"
+#include "BKE_layer.h"
#include "BKE_editmesh_bvh.h"
#include "BKE_context.h"
#include "BKE_report.h"
@@ -146,9 +147,6 @@ enum {
static int edbm_intersect_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
const int mode = RNA_enum_get(op->ptr, "mode");
int (*test_fn)(BMFace *, void *);
bool use_separate_all = false;
@@ -186,29 +184,45 @@ static int edbm_intersect_exec(bContext *C, wmOperator *op)
default: /* ISECT_SEPARATE_NONE */
break;
}
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ uint isect_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
- has_isect = BM_mesh_intersect(
- bm,
- em->looptris, em->tottri,
- test_fn, NULL,
- use_self, use_separate_all, true, true, true,
- -1,
- eps);
-
- if (use_separate_cut) {
- /* detach selected/un-selected faces */
- BM_mesh_separate_faces(
- bm,
- BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
- }
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
+
+ has_isect = BM_mesh_intersect(
+ em->bm,
+ em->looptris, em->tottri,
+ test_fn, NULL,
+ use_self, use_separate_all, true, true, true,
+ -1,
+ eps);
+
+ if (use_separate_cut) {
+ /* detach selected/un-selected faces */
+ BM_mesh_separate_faces(
+ em->bm,
+ BM_elem_cb_check_hflag_enabled_simple(const BMFace *, BM_ELEM_SELECT));
+ }
- if (has_isect) {
- edbm_intersect_select(em);
+ if (has_isect) {
+ edbm_intersect_select(em);
+ }
+ else {
+ isect_len++;
+ }
}
- else {
+ MEM_freeN(objects);
+
+ if (isect_len == objects_len) {
BKE_report(op->reports, RPT_WARNING, "No intersections found");
}
-
return OPERATOR_FINISHED;
}
@@ -266,9 +280,6 @@ void MESH_OT_intersect(struct wmOperatorType *ot)
static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
const int boolean_operation = RNA_enum_get(op->ptr, "operation");
bool use_swap = RNA_boolean_get(op->ptr, "use_swap");
const float eps = RNA_float_get(op->ptr, "threshold");
@@ -276,23 +287,39 @@ static int edbm_intersect_boolean_exec(bContext *C, wmOperator *op)
bool has_isect;
test_fn = use_swap ? bm_face_isect_pair_swap : bm_face_isect_pair;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ uint isect_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+ for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+ Object *obedit = objects[ob_index];
+ BMEditMesh *em = BKE_editmesh_from_object(obedit);
+
+ if (em->bm->totfacesel == 0) {
+ continue;
+ }
- has_isect = BM_mesh_intersect(
- bm,
- em->looptris, em->tottri,
- test_fn, NULL,
- false, false, true, true, true,
- boolean_operation,
- eps);
+ has_isect = BM_mesh_intersect(
+ em->bm,
+ em->looptris, em->tottri,
+ test_fn, NULL,
+ false, false, true, true, true,
+ boolean_operation,
+ eps);
- if (has_isect) {
- edbm_intersect_select(em);
+ if (has_isect) {
+ edbm_intersect_select(em);
+ }
+ else {
+ isect_len++;
+ }
}
- else {
+ MEM_freeN(objects);
+
+ if (isect_len == objects_len) {
BKE_report(op->reports, RPT_WARNING, "No intersections found");
}
-
return OPERATOR_FINISHED;
}
@@ -652,257 +679,270 @@ static BMEdge *bm_face_split_edge_find(
static int edbm_face_split_by_edges_exec(bContext *C, wmOperator *UNUSED(op))
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
const char hflag = BM_ELEM_TAG;
BMEdge *e;
BMIter iter;
- BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
+ 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;
- {
- BMVert *v;
- BM_ITER_MESH (v, &iter, bm, BM_VERTS_OF_MESH) {
- BM_elem_flag_disable(v, hflag);
+ if ((bm->totedgesel == 0) ||
+ (bm->totfacesel == 0))
+ {
+ continue;
}
- }
-
- /* edge index is set to -1 then used to assosiate them with faces */
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
- BM_elem_flag_enable(e, hflag);
- BM_elem_flag_enable(e->v1, hflag);
- BM_elem_flag_enable(e->v2, hflag);
+ BLI_SMALLSTACK_DECLARE(loop_stack, BMLoop *);
+ {
+ BMVert *v;
+ BM_ITER_MESH(v, &iter, bm, BM_VERTS_OF_MESH) {
+ BM_elem_flag_disable(v, hflag);
+ }
}
- else {
- BM_elem_flag_disable(e, hflag);
- }
- BM_elem_index_set(e, -1); /* set_dirty */
- }
- bm->elem_index_dirty |= BM_EDGE;
- {
- BMFace *f;
- int i;
- BM_ITER_MESH_INDEX (f, &iter, bm, BM_FACES_OF_MESH, i) {
- if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
- BM_elem_flag_enable(f, hflag);
+ /* edge index is set to -1 then used to assosiate them with faces */
+ BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
+ BM_elem_flag_enable(e, hflag);
+
+ BM_elem_flag_enable(e->v1, hflag);
+ BM_elem_flag_enable(e->v2, hflag);
+
}
else {
- BM_elem_flag_disable(f, hflag);
+ BM_elem_flag_disable(e, hflag);
}
- BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
- BM_elem_index_set(f, i); /* set_ok */
+ BM_elem_index_set(e, -1); /* set_dirty */
}
- }
- bm->elem_index_dirty &= ~BM_FACE;
-
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, hflag)) {
- BMIter viter;
- BMVert *v;
- BM_ITER_ELEM (v, &viter, e, BM_VERTS_OF_EDGE) {
- BMIter liter;
- BMLoop *l;
-
- unsigned int loop_stack_len;
- BMLoop *l_best = NULL;
-
- BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
- loop_stack_len = 0;
-
- BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) {
- if (BM_elem_flag_test(l->f, hflag)) {
- BLI_SMALLSTACK_PUSH(loop_stack, l);
- loop_stack_len++;
- }
- }
+ bm->elem_index_dirty |= BM_EDGE;
- if (loop_stack_len == 0) {
- /* pass */
- }
- else if (loop_stack_len == 1) {
- l_best = BLI_SMALLSTACK_POP(loop_stack);
+ {
+ BMFace *f;
+ int i;
+ BM_ITER_MESH_INDEX(f, &iter, bm, BM_FACES_OF_MESH, i) {
+ if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+ BM_elem_flag_enable(f, hflag);
}
else {
- /* complicated case, match the edge with a face-loop */
+ BM_elem_flag_disable(f, hflag);
+ }
+ BM_elem_flag_disable(f, BM_ELEM_INTERNAL_TAG);
+ BM_elem_index_set(f, i); /* set_ok */
+ }
+ }
+ bm->elem_index_dirty &= ~BM_FACE;
+
+ BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, hflag)) {
+ BMIter viter;
+ BMVert *v;
+ BM_ITER_ELEM(v, &viter, e, BM_VERTS_OF_EDGE) {
+ BMIter liter;
+ BMLoop *l;
+
+ unsigned int loop_stack_len;
+ BMLoop *l_best = NULL;
+
+ BLI_assert(BLI_SMALLSTACK_IS_EMPTY(loop_stack));
+ loop_stack_len = 0;
+
+ BM_ITER_ELEM(l, &liter, v, BM_LOOPS_OF_VERT) {
+ if (BM_elem_flag_test(l->f, hflag)) {
+ BLI_SMALLSTACK_PUSH(loop_stack, l);
+ loop_stack_len++;
+ }
+ }
+
+ if (loop_stack_len == 0) {
+ /* pass */
+ }
+ else if (loop_stack_len == 1) {
+ l_best = BLI_SMALLSTACK_POP(loop_stack);
+ }
+ else {
+ /* complicated case, match the edge with a face-loop */
- BMVert *v_other = BM_edge_other_vert(e, v);
- float e_dir[3];
+ BMVert *v_other = BM_edge_other_vert(e, v);
+ float e_dir[3];
- /* we want closest to zero */
- float dot_best = FLT_MAX;
+ /* we want closest to zero */
+ float dot_best = FLT_MAX;
- sub_v3_v3v3(e_dir, v_other->co, v->co);
- normalize_v3(e_dir);
+ sub_v3_v3v3(e_dir, v_other->co, v->co);
+ normalize_v3(e_dir);
- while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
- float dot_test;
+ while ((l = BLI_SMALLSTACK_POP(loop_stack))) {
+ float dot_test;
- /* Check dot first to save on expensive angle-comparison.
- * ideal case is 90d difference == 0.0 dot */
- dot_test = fabsf(dot_v3v3(e_dir, l->f->no));
- if (dot_test < dot_best) {
+ /* Check dot first to save on expensive angle-comparison.
+ * ideal case is 90d difference == 0.0 dot */
+ dot_test = fabsf(dot_v3v3(e_dir, l->f->no));
+ if (dot_test < dot_best) {
- /* check we're in the correct corner (works with convex loops too) */
- if (angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, v_other->co, l->f->no) <
- angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, l->next->v->co, l->f->no))
- {
- dot_best = dot_test;
- l_best = l;
+ /* check we're in the correct corner (works with convex loops too) */
+ if (angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, v_other->co, l->f->no) <
+ angle_signed_on_axis_v3v3v3_v3(l->prev->v->co, l->v->co, l->next->v->co, l->f->no))
+ {
+ dot_best = dot_test;
+ l_best = l;
+ }
}
}
}
- }
- if (l_best) {
- BM_elem_index_set(e, BM_elem_index_get(l_best->f)); /* set_dirty */
+ if (l_best) {
+ BM_elem_index_set(e, BM_elem_index_get(l_best->f)); /* set_dirty */
+ }
}
}
}
- }
- {
- BMFace *f;
- BLI_buffer_declare_static(BMEdge **, edge_net_temp_buf, 0, 128);
+ {
+ BMFace *f;
+ BLI_buffer_declare_static(BMEdge **, edge_net_temp_buf, 0, 128);
- BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if (BM_elem_flag_test(f, hflag)) {
- bm_face_split_by_edges(bm, f, hflag, &edge_net_temp_buf);
+ BM_ITER_MESH(f, &iter, bm, BM_FACES_OF_MESH) {
+ if (BM_elem_flag_test(f, hflag)) {
+ bm_face_split_by_edges(bm, f, hflag, &edge_net_temp_buf);
+ }
}
+ BLI_buffer_free(&edge_net_temp_buf);
}
- BLI_buffer_free(&edge_net_temp_buf);
- }
#ifdef USE_NET_ISLAND_CONNECT
- /* before overwriting edge index values, collect edges left untouched */
- BLI_Stack *edges_loose = BLI_stack_new(sizeof(BMEdge * ), __func__);
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
- BLI_stack_push(edges_loose, &e);
+ /* before overwriting edge index values, collect edges left untouched */
+ BLI_Stack *edges_loose = BLI_stack_new(sizeof(BMEdge *), __func__);
+ BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
+ if (BM_elem_flag_test(e, BM_ELEM_SELECT) && BM_edge_is_wire(e)) {
+ BLI_stack_push(edges_loose, &e);
+ }
}
- }
#endif
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
#ifdef USE_NET_ISLAND_CONNECT
- /* we may have remaining isolated regions remaining,
- * these will need to have connecting edges created */
- if (!BLI_stack_is_empty(edges_loose)) {
- GHash *face_edge_map = BLI_ghash_ptr_new(__func__);
+ /* we may have remaining isolated regions remaining,
+ * these will need to have connecting edges created */
+ if (!BLI_stack_is_empty(edges_loose)) {
+ GHash *face_edge_map = BLI_ghash_ptr_new(__func__);
- MemArena *mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ MemArena *mem_arena = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- BM_mesh_elem_index_ensure(bm, BM_FACE);
+ BM_mesh_elem_index_ensure(bm, BM_FACE);
- {
- BMBVHTree *bmbvh = BKE_bmbvh_new(bm, em->looptris, em->tottri, BMBVH_RESPECT_SELECT, NULL, false);
+ {
+ BMBVHTree *bmbvh = BKE_bmbvh_new(bm, em->looptris, em->tottri, BMBVH_RESPECT_SELECT, NULL, false);
- BM_ITER_MESH (e, &iter, bm, BM_EDGES_OF_MESH) {
- BM_elem_index_set(e, -1); /* set_dirty */
- }
+ BM_ITER_MESH(e, &iter, bm, BM_EDGES_OF_MESH) {
+ BM_elem_index_set(e, -1); /* set_dirty */
+ }
- while (!BLI_stack_is_empty(edges_loose)) {
- BLI_stack_pop(edges_loose, &e);
- float e_center[3];
- mid_v3_v3v3(e_center, e->v1->co, e->v2->co);
+ while (!BLI_stack_is_empty(edges_loose)) {
+ BLI_stack_pop(edges_loose, &e);
+ float e_center[3];
+ mid_v3_v3v3(e_center, e->v1->co, e->v2->co);
- BMFace *f = BKE_bmbvh_find_face_closest(bmbvh, e_center, FLT_MAX);
- if (f) {
- ghash_insert_face_edge_link(face_edge_map, f, e, mem_arena);
- BM_elem_index_set(e, BM_elem_index_get(f)); /* set_dirty */
+ BMFace *f = BKE_bmbvh_find_face_closest(bmbvh, e_center, FLT_MAX);
+ if (f) {
+ ghash_insert_face_edge_link(face_edge_map, f, e, mem_arena);
+ BM_elem_index_set(e, BM_elem_index_get(f)); /* set_dirty */
+ }
}
- }
- BKE_bmbvh_free(bmbvh);
- }
+ BKE_bmbvh_free(bmbvh);
+ }
- bm->elem_index_dirty |= BM_EDGE;
+ bm->elem_index_dirty |= BM_EDGE;
- BM_mesh_elem_table_ensure(bm, BM_FACE);
+ BM_mesh_elem_table_ensure(bm, BM_FACE);
- /* detect edges chains that span faces
- * and splice vertices into the closest edges */
- {
- GHashIterator gh_iter;
-
- GHASH_ITER(gh_iter, face_edge_map) {
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
- LinkNode *e_link = e_ls_base->list;
-
- do {
- e = e_link->link;
-
- for (int j = 0; j < 2; j++) {
- BMVert *v_pivot = (&e->v1)[j];
- /* checking that \a v_pivot isn't in the face
- * prevents attempting to splice the same vertex into an edge from multiple faces */
- if (!BM_vert_in_face(v_pivot, f)) {
- float v_pivot_co[3];
- float v_pivot_fac;
- BMEdge *e_split = bm_face_split_edge_find(
- e, f, v_pivot, bm->ftable, bm->totface,
- v_pivot_co, &v_pivot_fac);
-
- if (e_split) {
- /* for degenerate cases this vertex may be in one of this edges radial faces */
- if (!bm_vert_in_faces_radial(v_pivot, e_split, f)) {
- BMEdge *e_new;
- BMVert *v_new = BM_edge_split(bm, e_split, e_split->v1, &e_new, v_pivot_fac);
- if (v_new) {
- /* we _know_ these don't share an edge */
- BM_vert_splice(bm, v_pivot, v_new);
- BM_elem_index_set(e_new, BM_elem_index_get(e_split));
+ /* detect edges chains that span faces
+ * and splice vertices into the closest edges */
+ {
+ GHashIterator gh_iter;
+
+ GHASH_ITER(gh_iter, face_edge_map) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+ LinkNode *e_link = e_ls_base->list;
+
+ do {
+ e = e_link->link;
+
+ for (int j = 0; j < 2; j++) {
+ BMVert *v_pivot = (&e->v1)[j];
+ /* checking that \a v_pivot isn't in the face
+ * prevents attempting to splice the same vertex into an edge from multiple faces */
+ if (!BM_vert_in_face(v_pivot, f)) {
+ float v_pivot_co[3];
+ float v_pivot_fac;
+ BMEdge *e_split = bm_face_split_edge_find(
+ e, f, v_pivot, bm->ftable, bm->totface,
+ v_pivot_co, &v_pivot_fac);
+
+ if (e_split) {
+ /* for degenerate cases this vertex may be in one of this edges radial faces */
+ if (!bm_vert_in_faces_radial(v_pivot, e_split, f)) {
+ BMEdge *e_new;
+ BMVert *v_new = BM_edge_split(bm, e_split, e_split->v1, &e_new, v_pivot_fac);
+ if (v_new) {
+ /* we _know_ these don't share an edge */
+ BM_vert_splice(bm, v_pivot, v_new);
+ BM_elem_index_set(e_new, BM_elem_index_get(e_split));
+ }
}
}
}
}
- }
- } while ((e_link = e_link->next));
+ } while ((e_link = e_link->next));
+ }
}
- }
- {
- MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
+ {
+ MemArena *mem_arena_edgenet = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, __func__);
- GHashIterator gh_iter;
+ GHashIterator gh_iter;
- GHASH_ITER(gh_iter, face_edge_map) {
- BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
- struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
+ GHASH_ITER(gh_iter, face_edge_map) {
+ BMFace *f = BLI_ghashIterator_getKey(&gh_iter);
+ struct LinkBase *e_ls_base = BLI_ghashIterator_getValue(&gh_iter);
- bm_face_split_by_edges_island_connect(
- bm, f,
- e_ls_base->list, e_ls_base->list_len,
- mem_arena_edgenet);
+ bm_face_split_by_edges_island_connect(
+ bm, f,
+ e_ls_base->list, e_ls_base->list_len,
+ mem_arena_edgenet);
- BLI_memarena_clear(mem_arena_edgenet);
- }
+ BLI_memarena_clear(mem_arena_edgenet);
+ }
- BLI_memarena_free(mem_arena_edgenet);
- }
+ BLI_memarena_free(mem_arena_edgenet);
+ }
- BLI_memarena_free(mem_arena);
+ BLI_memarena_free(mem_arena);
- BLI_ghash_free(face_edge_map, NULL, NULL);
+ BLI_ghash_free(face_edge_map, NULL, NULL);
- EDBM_mesh_normals_update(em);
- EDBM_update_generic(em, true, true);
- }
+ EDBM_mesh_normals_update(em);
+ EDBM_update_generic(em, true, true);
+ }
- BLI_stack_free(edges_loose);
+ BLI_stack_free(edges_loose);
#endif /* USE_NET_ISLAND_CONNECT */
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c
index 0066afca540..41a0fa9ce38 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -3885,59 +3885,70 @@ void MESH_OT_edges_select_sharp(wmOperatorType *ot)
static int edbm_select_linked_flat_faces_exec(bContext *C, wmOperator *op)
{
- Object *obedit = CTX_data_edit_object(C);
- BMEditMesh *em = BKE_editmesh_from_object(obedit);
- BMesh *bm = em->bm;
-
- BLI_LINKSTACK_DECLARE(stack, BMFace *);
-
- BMIter iter, liter, liter2;
- BMFace *f;
- BMLoop *l, *l2;
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ uint objects_len = 0;
+ Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, &objects_len);
const float angle_limit_cos = cosf(RNA_float_get(op->ptr, "sharpness"));
- BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
-
- BLI_LINKSTACK_INIT(stack);
+ 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_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
- if ((BM_elem_flag_test(f, BM_ELEM_HIDDEN) != 0) ||
- (BM_elem_flag_test(f, BM_ELEM_TAG) != 0) ||
- (BM_elem_flag_test(f, BM_ELEM_SELECT) == 0))
- {
+ if (bm->totfacesel == 0) {
continue;
}
- BLI_assert(BLI_LINKSTACK_SIZE(stack) == 0);
+ BLI_LINKSTACK_DECLARE(stack, BMFace *);
- do {
- BM_face_select_set(bm, f, true);
+ BMIter iter, liter, liter2;
+ BMFace *f;
+ BMLoop *l, *l2;
- BM_elem_flag_enable(f, BM_ELEM_TAG);
+ BM_mesh_elem_hflag_disable_all(bm, BM_FACE, BM_ELEM_TAG, false);
- BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
- BM_ITER_ELEM (l2, &liter2, l, BM_LOOPS_OF_LOOP) {
- float angle_cos;
+ BLI_LINKSTACK_INIT(stack);
- if (BM_elem_flag_test(l2->f, BM_ELEM_TAG) ||
- BM_elem_flag_test(l2->f, BM_ELEM_HIDDEN))
- {
- continue;
- }
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if ((BM_elem_flag_test(f, BM_ELEM_HIDDEN) != 0) ||
+ (BM_elem_flag_test(f, BM_ELEM_TAG) != 0) ||
+ (BM_elem_flag_test(f, BM_ELEM_SELECT) == 0))
+ {
+ continue;
+ }
+
+ BLI_assert(BLI_LINKSTACK_SIZE(stack) == 0);
- angle_cos = dot_v3v3(f->no, l2->f->no);
+ do {
+ BM_face_select_set(bm, f, true);
+
+ BM_elem_flag_enable(f, BM_ELEM_TAG);
+
+ BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
+ BM_ITER_ELEM (l2, &liter2, l, BM_LOOPS_OF_LOOP) {
+ float angle_cos;
+
+ if (BM_elem_flag_test(l2->f, BM_ELEM_TAG) ||
+ BM_elem_flag_test(l2->f, BM_ELEM_HIDDEN))
+ {
+ continue;
+ }
- if (angle_cos > angle_limit_cos) {
- BLI_LINKSTACK_PUSH(stack, l2->f);
+ angle_cos = dot_v3v3(f->no, l2->f->no);
+
+ if (angle_cos > angle_limit_cos) {
+ BLI_LINKSTACK_PUSH(stack, l2->f);
+ }
}
}
- }
- } while ((f = BLI_LINKSTACK_POP(stack)));
- }
+ } while ((f = BLI_LINKSTACK_POP(stack)));
+ }
- BLI_LINKSTACK_FREE(stack);
+ BLI_LINKSTACK_FREE(stack);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+ }
+ MEM_freeN(objects);
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/mesh/editmesh_utils.c b/source/blender/editors/mesh/editmesh_utils.c
index e8f3e592715..ab44e017fc6 100644
--- a/source/blender/editors/mesh/editmesh_utils.c
+++ b/source/blender/editors/mesh/editmesh_utils.c
@@ -1030,7 +1030,7 @@ void EDBM_verts_mirror_cache_begin_ex(
BM_mesh_elem_index_ensure(bm, BM_VERT);
if (use_topology) {
- ED_mesh_mirrtopo_init(me, NULL, &mesh_topo_store, true);
+ ED_mesh_mirrtopo_init__real_mesh(me, NULL, &mesh_topo_store, true);
}
else {
tree = BLI_kdtree_new(bm->totvert);
diff --git a/source/blender/editors/mesh/mesh_mirror.c b/source/blender/editors/mesh/mesh_mirror.c
index 22bfd8eedea..4c078d2ac8b 100644
--- a/source/blender/editors/mesh/mesh_mirror.c
+++ b/source/blender/editors/mesh/mesh_mirror.c
@@ -37,6 +37,8 @@
#include "BKE_DerivedMesh.h"
#include "BLI_kdtree.h"
#include "BKE_editmesh.h"
+#include "BKE_library.h"
+#include "BKE_mesh.h"
#include "ED_mesh.h"
@@ -93,7 +95,73 @@ int ED_mesh_mirror_spatial_table(Object *ob, BMEditMesh *em, DerivedMesh *dm, co
else {
MVert *mvert = dm ? dm->getVertArray(dm) : me->mvert;
int i;
-
+
+ for (i = 0; i < totvert; i++, mvert++) {
+ BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co);
+ }
+ }
+
+ BLI_kdtree_balance(MirrKdStore.tree);
+ }
+ else if (mode == 'e') { /* end table */
+ if (MirrKdStore.tree) {
+ BLI_kdtree_free(MirrKdStore.tree);
+ MirrKdStore.tree = NULL;
+ }
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ return 0;
+}
+
+/* mode is 's' start, or 'e' end, or 'u' use */
+/* if end, ob can be NULL */
+int ED_mesh_mirror_spatial_table__real_mesh(Object *ob, BMEditMesh *em, Mesh *mesh, const float co[3], char mode)
+{
+ if (mode == 'u') { /* use table */
+ if (MirrKdStore.tree == NULL)
+ ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 's');
+
+ if (MirrKdStore.tree) {
+ KDTreeNearest nearest;
+ const int i = BLI_kdtree_find_nearest(MirrKdStore.tree, co, &nearest);
+
+ if (i != -1) {
+ if (nearest.dist < KD_THRESH) {
+ return i;
+ }
+ }
+ }
+ return -1;
+ }
+ else if (mode == 's') { /* start table */
+ Mesh *me = ob->data;
+ const bool use_em = (!mesh && em && me->edit_btmesh == em);
+ const int totvert = use_em ? em->bm->totvert : mesh ? mesh->totvert : me->totvert;
+
+ if (MirrKdStore.tree) /* happens when entering this call without ending it */
+ ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, co, 'e');
+
+ MirrKdStore.tree = BLI_kdtree_new(totvert);
+
+ if (use_em) {
+ BMVert *eve;
+ BMIter iter;
+ int i;
+
+ /* this needs to be valid for index lookups later (callers need) */
+ BM_mesh_elem_table_ensure(em->bm, BM_VERT);
+
+ BM_ITER_MESH_INDEX (eve, &iter, em->bm, BM_VERTS_OF_MESH, i) {
+ BLI_kdtree_insert(MirrKdStore.tree, i, eve->co);
+ }
+ }
+ else {
+ MVert *mvert = mesh ? mesh->mvert : me->mvert;
+ int i;
+
for (i = 0; i < totvert; i++, mvert++) {
BLI_kdtree_insert(MirrKdStore.tree, i, mvert->co);
}
@@ -172,11 +240,62 @@ bool ED_mesh_mirrtopo_recalc_check(Mesh *me, DerivedMesh *dm, MirrTopoStore_t *m
}
}
+bool ED_mesh_mirrtopo_recalc_check__real_mesh(Mesh *me, Mesh *dm, MirrTopoStore_t *mesh_topo_store)
+{
+ const bool is_editmode = (me->edit_btmesh != NULL);
+ int totvert;
+ int totedge;
+
+ if (dm) {
+ totvert = dm->totvert;
+ totedge = dm->totedge;
+ }
+ else if (me->edit_btmesh) {
+ totvert = me->edit_btmesh->bm->totvert;
+ totedge = me->edit_btmesh->bm->totedge;
+ }
+ else {
+ totvert = me->totvert;
+ totedge = me->totedge;
+ }
+
+ if ((mesh_topo_store->index_lookup == NULL) ||
+ (mesh_topo_store->prev_is_editmode != is_editmode) ||
+ (totvert != mesh_topo_store->prev_vert_tot) ||
+ (totedge != mesh_topo_store->prev_edge_tot))
+ {
+ return true;
+ }
+ else {
+ return false;
+ }
+
+}
+
void ED_mesh_mirrtopo_init(
Mesh *me, DerivedMesh *dm, MirrTopoStore_t *mesh_topo_store,
const bool skip_em_vert_array_init)
{
+ Mesh *fake_mesh = NULL;
+
+ if (dm != NULL) {
+ /* ED_real_mesh_mirrtopo_init() only uses the counts, not the actual data */
+ fake_mesh = BKE_mesh_new_nomain(dm->getNumVerts(dm), dm->getNumEdges(dm), dm->getNumTessFaces(dm),
+ dm->getNumLoops(dm), dm->getNumPolys(dm));
+ }
+
+ ED_mesh_mirrtopo_init__real_mesh(me, fake_mesh, mesh_topo_store, skip_em_vert_array_init);
+
+ if (dm != NULL) {
+ BKE_id_free(NULL, fake_mesh);
+ }
+}
+
+void ED_mesh_mirrtopo_init__real_mesh(
+ Mesh *me, Mesh *dm, MirrTopoStore_t *mesh_topo_store,
+ const bool skip_em_vert_array_init)
+{
const bool is_editmode = (me->edit_btmesh != NULL);
MEdge *medge = NULL, *med;
BMEditMesh *em = dm ? NULL : me->edit_btmesh;
@@ -208,7 +327,7 @@ void ED_mesh_mirrtopo_init(
totvert = em->bm->totvert;
}
else {
- totvert = dm ? dm->getNumVerts(dm) : me->totvert;
+ totvert = dm ? dm->totvert : me->totvert;
}
topo_hash = MEM_callocN(totvert * sizeof(MirrTopoHash_t), "TopoMirr");
@@ -224,8 +343,8 @@ void ED_mesh_mirrtopo_init(
}
}
else {
- totedge = dm ? dm->getNumEdges(dm) : me->totedge;
- medge = dm ? dm->getEdgeArray(dm) : me->medge;
+ totedge = dm ? dm->totedge : me->totedge;
+ medge = dm ? dm->medge : me->medge;
for (a = 0, med = medge; a < totedge; a++, med++) {
const unsigned int i1 = med->v1, i2 = med->v2;
diff --git a/source/blender/editors/mesh/meshtools.c b/source/blender/editors/mesh/meshtools.c
index 83458127820..9b86f904161 100644
--- a/source/blender/editors/mesh/meshtools.c
+++ b/source/blender/editors/mesh/meshtools.c
@@ -707,6 +707,30 @@ int ED_mesh_mirror_topo_table(
return 0;
}
+/* mode is 's' start, or 'e' end, or 'u' use */
+/* if end, ob can be NULL */
+/* note, is supposed return -1 on error, which callers are currently checking for, but is not used so far */
+int ED_mesh_mirror_topo_table__real_mesh(
+ Object *ob, Mesh *mesh, char mode)
+{
+ if (mode == 'u') { /* use table */
+ if (ED_mesh_mirrtopo_recalc_check__real_mesh(ob->data, mesh, &mesh_topo_store)) {
+ ED_mesh_mirror_topo_table__real_mesh(ob, mesh, 's');
+ }
+ }
+ else if (mode == 's') { /* start table */
+ ED_mesh_mirrtopo_init__real_mesh(ob->data, mesh, &mesh_topo_store, false);
+ }
+ else if (mode == 'e') { /* end table */
+ ED_mesh_mirrtopo_free(&mesh_topo_store);
+ }
+ else {
+ BLI_assert(0);
+ }
+
+ return 0;
+}
+
/** \} */
@@ -742,6 +766,38 @@ int mesh_get_x_mirror_vert(Object *ob, DerivedMesh *dm, int index, const bool us
}
}
+static int mesh_get_x_mirror_vert_spatial__real_mesh(Object *ob, Mesh *mesh, int index)
+{
+ Mesh *me = ob->data;
+ MVert *mvert = mesh ? mesh->mvert : me->mvert;
+ float vec[3];
+
+ mvert = &mvert[index];
+ vec[0] = -mvert->co[0];
+ vec[1] = mvert->co[1];
+ vec[2] = mvert->co[2];
+
+ return ED_mesh_mirror_spatial_table__real_mesh(ob, NULL, mesh, vec, 'u');
+}
+
+static int mesh_get_x_mirror_vert_topo__real_mesh(Object *ob, Mesh *mesh, int index)
+{
+ if (ED_mesh_mirror_topo_table__real_mesh(ob, mesh, 'u') == -1)
+ return -1;
+
+ return mesh_topo_store.index_lookup[index];
+}
+
+int mesh_get_x_mirror_vert__real_mesh(Object *ob, Mesh *mesh, int index, const bool use_topology)
+{
+ if (use_topology) {
+ return mesh_get_x_mirror_vert_topo__real_mesh(ob, mesh, index);
+ }
+ else {
+ return mesh_get_x_mirror_vert_spatial__real_mesh(ob, mesh, index);
+ }
+}
+
static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, const float co[3])
{
float vec[3];
@@ -991,7 +1047,67 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm)
BLI_ghash_free(fhash, NULL, NULL);
MEM_freeN(mirrorverts);
-
+
+ return mirrorfaces;
+}
+
+/* This is a Mesh-based copy of mesh_get_x_mirror_faces() */
+int *mesh_get_x_mirror_faces__real_mesh(Object *ob, BMEditMesh *em, Mesh *mesh)
+{
+ Mesh *me = ob->data;
+ MVert *mv, *mvert;
+ MFace mirrormf, *mf, *hashmf, *mface;
+ GHash *fhash;
+ int *mirrorverts, *mirrorfaces;
+
+ BLI_assert(em == NULL); /* Does not work otherwise, currently... */
+
+ const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+ const int totvert = mesh ? mesh->totvert : me->totvert;
+ const int totface = mesh ? mesh->totface : me->totface;
+ int a;
+
+ mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts");
+ mirrorfaces = MEM_callocN(sizeof(int) * 2 * totface, "MirrorFaces");
+
+ mvert = mesh ? mesh->mvert : me->mvert;
+ mface = mesh ? mesh->mface : me->mface;
+
+ ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 's');
+
+ for (a = 0, mv = mvert; a < totvert; a++, mv++)
+ mirrorverts[a] = mesh_get_x_mirror_vert__real_mesh(ob, mesh, a, use_topology);
+
+ ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 'e');
+
+ fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface);
+ for (a = 0, mf = mface; a < totface; a++, mf++)
+ BLI_ghash_insert(fhash, mf, mf);
+
+ for (a = 0, mf = mface; a < totface; a++, mf++) {
+ mirrormf.v1 = mirrorverts[mf->v3];
+ mirrormf.v2 = mirrorverts[mf->v2];
+ mirrormf.v3 = mirrorverts[mf->v1];
+ mirrormf.v4 = (mf->v4) ? mirrorverts[mf->v4] : 0;
+
+ /* make sure v4 is not 0 if a quad */
+ if (mf->v4 && mirrormf.v4 == 0) {
+ SWAP(unsigned int, mirrormf.v1, mirrormf.v3);
+ SWAP(unsigned int, mirrormf.v2, mirrormf.v4);
+ }
+
+ hashmf = BLI_ghash_lookup(fhash, &mirrormf);
+ if (hashmf) {
+ mirrorfaces[a * 2] = hashmf - mface;
+ mirrorfaces[a * 2 + 1] = mirror_facerotation(&mirrormf, hashmf);
+ }
+ else
+ mirrorfaces[a * 2] = -1;
+ }
+
+ BLI_ghash_free(fhash, NULL, NULL);
+ MEM_freeN(mirrorverts);
+
return mirrorfaces;
}
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index eb0492daf9c..6f8b50bb68a 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1629,9 +1629,17 @@ static void move_to_collection_menus_free(MoveToCollectionData **menu)
static void move_to_collection_menu_create(bContext *UNUSED(C), uiLayout *layout, void *menu_v)
{
MoveToCollectionData *menu = menu_v;
+ const char *name;
+
+ if (menu->collection->flag & COLLECTION_IS_MASTER) {
+ name = IFACE_("Scene Collection");
+ }
+ else {
+ name = menu->collection->id.name + 2;
+ }
uiItemIntO(layout,
- menu->collection->id.name + 2,
+ name,
ICON_NONE,
menu->ot->idname,
"collection_index",
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 6a73e1912ab..3ac7a14753b 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2287,8 +2287,6 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
bool success = false;
if (!ID_IS_LINKED(obact) && obact->dup_group != NULL && ID_IS_LINKED(obact->dup_group)) {
- // TODO: support making the group itself override and putting
- // it directly into the scene collections
const ListBase dup_collection_objects = BKE_collection_object_cache_get(obact->dup_group);
Base *base = BLI_findlink(&dup_collection_objects, RNA_enum_get(op->ptr, "object"));
Object *obcollection = obact;
@@ -2305,6 +2303,19 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+ /* Then, we make static override of the whole set of objects in the collection. */
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(collection, ob)
+ {
+ if (ob->type == OB_ARMATURE && ob->pose != NULL) {
+ for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
+ if (pchan->custom != NULL) {
+ pchan->custom->id.tag &= ~ LIB_TAG_DOIT;
+ }
+ }
+ }
+ }
+ FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
+
success = BKE_override_static_create_from_tag(bmain);
/* Intantiate our newly overridden objects in scene, if not yet done. */
@@ -2313,7 +2324,10 @@ static int make_override_static_exec(bContext *C, wmOperator *op)
Collection *new_collection = (Collection *)collection->id.newid;
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(new_collection, new_ob)
{
- if (new_ob != NULL && (base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) {
+ if (new_ob != NULL &&
+ new_ob->id.override_static != NULL &&
+ (base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL)
+ {
BKE_collection_object_add_from(bmain, scene, obcollection, new_ob);
DEG_id_tag_update_ex(bmain, &new_ob->id, OB_RECALC_OB | DEG_TAG_BASE_FLAGS_UPDATE);
/* parent to 'collection' empty */
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 3df934a8dca..e0427b4797c 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -55,6 +55,7 @@
#include "BKE_DerivedMesh.h"
#include "BKE_global.h"
#include "BKE_object.h"
+#include "BKE_library.h"
#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_particle.h"
@@ -364,7 +365,7 @@ typedef struct PEData {
Scene *scene;
ViewLayer *view_layer;
Object *ob;
- DerivedMesh *dm;
+ Mesh *mesh;
PTCacheEdit *edit;
BVHTreeFromMesh shape_bvh;
Depsgraph *depsgraph;
@@ -426,15 +427,15 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
static bool PE_create_shape_tree(PEData *data, Object *shapeob)
{
- DerivedMesh *dm = shapeob->derivedFinal;
+ Mesh *mesh = BKE_modifier_get_evaluated_mesh_from_object(shapeob, 0);
memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
- if (!dm) {
+ if (!mesh) {
return false;
}
- return (bvhtree_from_mesh_get(&data->shape_bvh, dm, BVHTREE_FROM_LOOPTRI, 4) != NULL);
+ return (BKE_bvhtree_from_mesh_get(&data->shape_bvh, mesh, BVHTREE_FROM_LOOPTRI, 4) != NULL);
}
static void PE_free_shape_tree(PEData *data)
@@ -641,9 +642,11 @@ static void foreach_mouse_hit_point(PEData *data, ForPointFunc func, int selecte
static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected)
{
+ Object *ob_eval = DEG_get_evaluated_object(data->depsgraph, data->ob);
PTCacheEdit *edit = data->edit;
ParticleSystem *psys = edit->psys;
ParticleSystemModifierData *psmd = NULL;
+ ParticleSystemModifierData *psmd_eval = NULL;
ParticleEditSettings *pset= PE_settings(data->scene);
POINT_P; KEY_K;
float mat[4][4], imat[4][4];
@@ -654,6 +657,10 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
if (edit->psys)
psmd= psys_get_modifier(data->ob, edit->psys);
+ if (psmd != NULL) {
+ psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name);
+ }
+
/* all is selected in path mode */
if (pset->selectmode==SCE_SELECT_PATH)
selected= 0;
@@ -667,7 +674,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
if (selected==0 || key->flag & PEK_SELECT) {
if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
+ psys_mat_hair_to_global(data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
invert_m4_m4(imat, mat);
}
@@ -682,7 +689,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
if (selected==0 || key->flag & PEK_SELECT) {
if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
+ psys_mat_hair_to_global(data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
invert_m4_m4(imat, mat);
}
@@ -769,7 +776,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
psmd= psys_get_modifier(ob, psys);
totpart= psys->totpart;
- if (!psmd->dm_final)
+ if (!psmd->mesh_final)
return;
tree= BLI_kdtree_new(totpart);
@@ -777,7 +784,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
/* insert particles into kd tree */
LOOP_PARTICLES {
key = pa->hair;
- psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
+ psys_mat_hair_to_orco(ob, psmd->mesh_final, psys->part->from, pa, mat);
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
BLI_kdtree_insert(tree, p, co);
@@ -791,7 +798,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
LOOP_PARTICLES {
key = pa->hair;
- psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
+ psys_mat_hair_to_orco(ob, psmd->mesh_final, psys->part->from, pa, mat);
copy_v3_v3(co, key->co);
mul_m4_v3(mat, co);
co[0] = -co[0];
@@ -817,7 +824,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
BLI_kdtree_free(tree);
}
-static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
+static void PE_mirror_particle(Object *ob, Mesh *mesh, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
{
HairKey *hkey, *mhkey;
PTCacheEditPoint *point, *mpoint;
@@ -868,8 +875,8 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
}
/* mirror positions and tags */
- psys_mat_hair_to_orco(ob, dm, psys->part->from, pa, mat);
- psys_mat_hair_to_orco(ob, dm, psys->part->from, mpa, mmat);
+ psys_mat_hair_to_orco(ob, mesh, psys->part->from, pa, mat);
+ psys_mat_hair_to_orco(ob, mesh, psys->part->from, mpa, mmat);
invert_m4_m4(immat, mmat);
hkey=pa->hair;
@@ -906,7 +913,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
edit= psys->edit;
psmd= psys_get_modifier(ob, psys);
- if (!psmd->dm_final)
+ if (!psmd->mesh_final)
return;
if (!edit->mirror_cache)
@@ -919,7 +926,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
* to avoid doing mirror twice */
LOOP_POINTS {
if (point->flag & PEP_EDIT_RECALC) {
- PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
if (edit->mirror_cache[p] != -1)
edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
@@ -954,11 +961,11 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
psys = edit->psys;
psmd = psys_get_modifier(ob, psys);
- if (!psmd->dm_final)
+ if (!psmd->mesh_final)
return;
LOOP_EDITED_POINTS {
- psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, hairmat);
+ psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles + p, hairmat);
LOOP_KEYS {
mul_m4_v3(hairmat, key->co);
@@ -1105,12 +1112,12 @@ void recalc_emitter_field(Depsgraph *depsgraph, Object *ob, ParticleSystem *psys
{
Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
- DerivedMesh *dm = psys_get_modifier(object_eval, psys_eval)->dm_final;
+ Mesh *mesh = psys_get_modifier(object_eval, psys_eval)->mesh_final;
PTCacheEdit *edit = psys->edit;
float *vec, *nor;
int i, totface /*, totvert*/;
- if (!dm)
+ if (!mesh)
return;
if (edit->emitter_cosnos)
@@ -1118,7 +1125,7 @@ void recalc_emitter_field(Depsgraph *depsgraph, Object *ob, ParticleSystem *psys
BLI_kdtree_free(edit->emitter_field);
- totface=dm->getNumTessFaces(dm);
+ totface = mesh->totface;
/*totvert=dm->getNumVerts(dm);*/ /*UNSUED*/
edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float), "emitter cosnos");
@@ -1129,23 +1136,23 @@ void recalc_emitter_field(Depsgraph *depsgraph, Object *ob, ParticleSystem *psys
nor=vec+3;
for (i=0; i<totface; i++, vec+=6, nor+=6) {
- MFace *mface=dm->getTessFaceData(dm, i, CD_MFACE);
+ MFace *mface = &mesh->mface[i];
MVert *mvert;
- mvert=dm->getVertData(dm, mface->v1, CD_MVERT);
+ mvert = &mesh->mvert[mface->v1];
copy_v3_v3(vec, mvert->co);
VECCOPY(nor, mvert->no);
- mvert=dm->getVertData(dm, mface->v2, CD_MVERT);
+ mvert = &mesh->mvert[mface->v2];
add_v3_v3v3(vec, vec, mvert->co);
VECADD(nor, nor, mvert->no);
- mvert=dm->getVertData(dm, mface->v3, CD_MVERT);
+ mvert = &mesh->mvert[mface->v3];
add_v3_v3v3(vec, vec, mvert->co);
VECADD(nor, nor, mvert->no);
if (mface->v4) {
- mvert=dm->getVertData(dm, mface->v4, CD_MVERT);
+ mvert = &mesh->mvert[mface->v4];
add_v3_v3v3(vec, vec, mvert->co);
VECADD(nor, nor, mvert->no);
@@ -1208,12 +1215,12 @@ void update_world_cos(Depsgraph *depsgraph, Object *ob, PTCacheEdit *edit)
psys_eval = psmd_eval->psys;
}
- if (psys == 0 || psys->edit == 0 || psmd_eval->dm_final == NULL)
+ if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL)
return;
LOOP_POINTS {
if (!(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob_eval, psmd_eval->dm_final, psys->part->from, psys_eval->particles+p, hairmat);
+ psys_mat_hair_to_global(ob_eval, psmd_eval->mesh_final, psys->part->from, psys_eval->particles+p, hairmat);
LOOP_KEYS {
copy_v3_v3(key->world_co, key->co);
@@ -1860,7 +1867,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
LOOP_VISIBLE_POINTS {
if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat);
if (pset->selectmode==SCE_SELECT_POINT) {
LOOP_KEYS {
@@ -2305,7 +2312,7 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
psmd= psys_get_modifier(ob, psys);
LOOP_TAGGED_POINTS {
- PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
}
}
@@ -2385,7 +2392,7 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
LOOP_POINTS {
LOOP_TAGGED_KEYS {
- PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
+ PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
break;
}
}
@@ -2600,7 +2607,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
/* insert particles into kd tree */
LOOP_SELECTED_POINTS {
- psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
+ psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
copy_v3_v3(co, point->keys->co);
mul_m4_v3(mat, co);
BLI_kdtree_insert(tree, p, co);
@@ -2610,7 +2617,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
/* tag particles to be removed */
LOOP_SELECTED_POINTS {
- psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
+ psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
copy_v3_v3(co, point->keys->co);
mul_m4_v3(mat, co);
@@ -2845,17 +2852,17 @@ static void PE_mirror_x(
return;
psmd= psys_get_modifier(ob, psys);
- if (!psmd->dm_final)
+ if (!psmd->mesh_final)
return;
- const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly);
+ const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->mesh_final->runtime.deformed_only);
/* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
BKE_mesh_tessface_ensure(me);
- /* Note: In case psys uses DM tessface indices, we mirror final DM itself, not orig mesh. Avoids an (impossible)
- * dm -> orig -> dm tessface indices conversion... */
- mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? psmd->dm_final : NULL);
+ /* Note: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh. Avoids an (impossible)
+ * mesh -> orig -> mesh tessface indices conversion... */
+ mirrorfaces = mesh_get_x_mirror_faces__real_mesh(ob, NULL, use_dm_final_indices ? psmd->mesh_final : NULL);
if (!edit->mirror_cache)
PE_update_mirror_cache(ob, psys);
@@ -2869,7 +2876,7 @@ static void PE_mirror_x(
if (point_is_selected(point)) {
if (edit->mirror_cache[p] != -1) {
/* already has a mirror, don't need to duplicate */
- PE_mirror_particle(ob, psmd->dm_final, psys, pa, NULL);
+ PE_mirror_particle(ob, psmd->mesh_final, psys, pa, NULL);
continue;
}
else
@@ -2882,7 +2889,7 @@ static void PE_mirror_x(
}
if (newtotpart != psys->totpart) {
- MFace *mtessface = use_dm_final_indices ? psmd->dm_final->getTessFaceArray(psmd->dm_final) : me->mface;
+ MFace *mtessface = use_dm_final_indices ? psmd->mesh_final->mface : me->mface;
/* allocate new arrays and copy existing */
new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
@@ -2951,7 +2958,7 @@ static void PE_mirror_x(
}
else {
newpa->num_dmcache = psys_particle_dm_face_lookup(
- psmd->dm_final, psmd->dm_deformed, newpa->num, newpa->fuv, NULL);
+ psmd->mesh_final, psmd->mesh_deformed, newpa->num, newpa->fuv, NULL);
}
/* update edit key pointers */
@@ -2962,7 +2969,7 @@ static void PE_mirror_x(
}
/* map key positions as mirror over x axis */
- PE_mirror_particle(ob, psmd->dm_final, psys, pa, newpa);
+ PE_mirror_particle(ob, psmd->mesh_final, psys, pa, newpa);
newpa++;
newpoint++;
@@ -3172,7 +3179,7 @@ static void brush_puff(PEData *data, int point_index)
}
if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, psys->particles + point_index, mat);
+ psys_mat_hair_to_global(data->ob, data->mesh, psys->part->from, psys->particles + point_index, mat);
invert_m4_m4(imat, mat);
}
else {
@@ -3367,7 +3374,7 @@ static void intersect_dm_quad_weights(const float v1[3], const float v2[3], cons
}
/* check intersection with a derivedmesh */
-static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, DerivedMesh *dm,
+static int particle_intersect_mesh(const bContext *C, Scene *scene, Object *ob, Mesh *mesh,
float *vert_cos,
const float co1[3], const float co2[3],
float *min_d, int *min_face, float *min_w,
@@ -3381,10 +3388,11 @@ static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, De
float cur_d, cur_uv[2], v1[3], v2[3], v3[3], v4[3], min[3], max[3], p_min[3], p_max[3];
float cur_ipoint[3];
- if (dm == NULL) {
+ if (mesh == NULL) {
psys_disable_all(ob);
- dm = mesh_get_derived_final(depsgraph, scene, ob, 0);
+ /* TODO(Sybren): port to Mesh when we have decided how to handle derivedFinal and derivedDeform */
+ DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, 0);
if (dm == NULL)
dm = mesh_get_derived_deform(depsgraph, scene, ob, 0);
@@ -3392,10 +3400,13 @@ static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, De
if (dm == NULL)
return 0;
+
+ mesh = BKE_id_new_nomain(ID_ME, NULL);
+ DM_to_mesh(dm, mesh, ob, CD_MASK_EVERYTHING, false);
}
/* BMESH_ONLY, deform dm may not have tessface */
- DM_ensure_tessface(dm);
+ BKE_mesh_tessface_ensure(mesh);
if (pa_minmax==0) {
@@ -3408,9 +3419,9 @@ static int particle_intersect_dm(const bContext *C, Scene *scene, Object *ob, De
copy_v3_v3(p_max, pa_minmax+3);
}
- totface=dm->getNumTessFaces(dm);
- mface=dm->getTessFaceDataArray(dm, CD_MFACE);
- mvert=dm->getVertDataArray(dm, CD_MVERT);
+ totface = mesh->totface;
+ mface = mesh->mface;
+ mvert = mesh->mvert;
/* lets intersect the faces */
for (i=0; i<totface; i++, mface++) {
@@ -3504,7 +3515,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene= data->scene;
Object *ob= data->ob;
- DerivedMesh *dm;
+ Mesh *mesh;
PTCacheEdit *edit = data->edit;
ParticleSystem *psys= edit->psys;
ParticleData *add_pars;
@@ -3537,13 +3548,13 @@ static int brush_add(const bContext *C, PEData *data, short number)
timestep= psys_get_timestep(&sim);
- if (psys->part->use_modifier_stack || psmd->dm_final->deformedOnly) {
- dm = psmd->dm_final;
+ if (psys->part->use_modifier_stack || psmd->mesh_final->runtime.deformed_only) {
+ mesh = psmd->mesh_final;
}
else {
- dm = psmd->dm_deformed;
+ mesh = psmd->mesh_deformed;
}
- BLI_assert(dm);
+ BLI_assert(mesh);
for (i=0; i<number; i++) {
if (number>1) {
@@ -3570,16 +3581,16 @@ static int brush_add(const bContext *C, PEData *data, short number)
min_d=2.0;
/* warning, returns the derived mesh face */
- if (particle_intersect_dm(C, scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
- if (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly) {
+ if (particle_intersect_mesh(C, scene, ob, mesh, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
+ if (psys->part->use_modifier_stack && !psmd->mesh_final->runtime.deformed_only) {
add_pars[n].num = add_pars[n].num_dmcache;
add_pars[n].num_dmcache = DMCACHE_ISCHILD;
}
- else if (dm == psmd->dm_deformed) {
+ else if (mesh == psmd->mesh_deformed) {
/* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
add_pars[n].num = add_pars[n].num_dmcache;
add_pars[n].num_dmcache = psys_particle_dm_face_lookup(
- psmd->dm_final, psmd->dm_deformed,
+ psmd->mesh_final, psmd->mesh_deformed,
add_pars[n].num, add_pars[n].fuv, NULL);
}
else {
@@ -3621,7 +3632,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
tree=BLI_kdtree_new(psys->totpart);
for (i=0, pa=psys->particles; i<totpart; i++, pa++) {
- psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0);
+ psys_particle_on_dm(psmd->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0);
BLI_kdtree_insert(tree, i, cur_co);
}
@@ -3665,7 +3676,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
int w, maxw;
float maxd, totw=0.0, weight[3];
- psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0);
+ psys_particle_on_dm(psmd->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0);
maxw = BLI_kdtree_find_nearest_n(tree, co1, ptn, 3);
maxd= ptn[maxw-1].dist;
@@ -3730,7 +3741,7 @@ static int brush_add(const bContext *C, PEData *data, short number)
}
}
for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, pa, hairmat);
invert_m4_m4(imat, hairmat);
mul_m4_v3(imat, hkey->co);
}
@@ -3922,7 +3933,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_PUFF:
{
if (edit->psys) {
- data.dm= psmd->dm_final;
+ data.mesh = psmd->mesh_final;
data.mval= mval;
data.rad= pe_brush_size_get(scene, brush);
data.select= selected;
@@ -3978,7 +3989,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
case PE_BRUSH_WEIGHT:
{
if (edit->psys) {
- data.dm= psmd->dm_final;
+ data.mesh = psmd->mesh_final;
data.mval= mval;
data.rad= pe_brush_size_get(scene, brush);
@@ -4325,7 +4336,7 @@ int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
LOOP_VISIBLE_POINTS {
if (psys)
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
LOOP_SELECTED_KEYS {
copy_v3_v3(co, key->co);
@@ -4363,7 +4374,7 @@ void PE_create_particle_edit(
}
/* no psmd->dm happens in case particle system modifier is not enabled */
- if (!(psys && psmd_eval && psmd_eval->dm_final) && !cache)
+ if (!(psys && psmd_eval && psmd_eval->mesh_final) && !cache)
return;
if (cache && cache->flag & PTCACHE_DISK_CACHE)
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index 79d52abb32d..cb7c90a6c3d 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -33,6 +33,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
#include "DNA_scene_types.h"
@@ -48,6 +49,7 @@
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
+#include "BKE_mesh.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
#include "BKE_particle.h"
@@ -574,7 +576,7 @@ static void disconnect_hair(
point++;
}
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, pa, hairmat);
for (k=0, key=pa->hair; k<pa->totkey; k++, key++) {
mul_m4_v3(hairmat, key->co);
@@ -653,13 +655,13 @@ static bool remap_hair_emitter(
MFace *mface = NULL, *mf;
MEdge *medge = NULL, *me;
MVert *mvert;
- DerivedMesh *dm, *target_dm;
+ Mesh *mesh, *target_mesh;
int numverts;
int i, k;
float from_ob_imat[4][4], to_ob_imat[4][4];
float from_imat[4][4], to_imat[4][4];
- if (!target_psmd->dm_final)
+ if (!target_psmd->mesh_final)
return false;
if (!psys->part || psys->part->type != PART_HAIR)
return false;
@@ -673,40 +675,46 @@ static bool remap_hair_emitter(
invert_m4_m4(from_imat, from_mat);
invert_m4_m4(to_imat, to_mat);
- if (target_psmd->dm_final->deformedOnly) {
+ if (target_psmd->mesh_final->runtime.deformed_only) {
/* we don't want to mess up target_psmd->dm when converting to global coordinates below */
- dm = target_psmd->dm_final;
+ mesh = target_psmd->mesh_final;
}
else {
- dm = target_psmd->dm_deformed;
+ mesh = target_psmd->mesh_deformed;
}
- target_dm = target_psmd->dm_final;
- if (dm == NULL) {
+ target_mesh = target_psmd->mesh_final;
+ if (mesh == NULL) {
return false;
}
/* don't modify the original vertices */
- dm = CDDM_copy(dm);
+ BKE_id_copy_ex(
+ NULL, &mesh->id, (ID **)&mesh,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
/* BMESH_ONLY, deform dm may not have tessface */
- DM_ensure_tessface(dm);
+ BKE_mesh_tessface_ensure(mesh);
- numverts = dm->getNumVerts(dm);
- mvert = dm->getVertArray(dm);
+ numverts = mesh->totvert;
+ mvert = mesh->mvert;
/* convert to global coordinates */
for (i=0; i<numverts; i++)
mul_m4_v3(to_mat, mvert[i].co);
- if (dm->getNumTessFaces(dm) != 0) {
- mface = dm->getTessFaceArray(dm);
- bvhtree_from_mesh_get(&bvhtree, dm, BVHTREE_FROM_FACES, 2);
+ if (mesh->totface != 0) {
+ mface = mesh->mface;
+ BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_FACES, 2);
}
- else if (dm->getNumEdges(dm) != 0) {
- medge = dm->getEdgeArray(dm);
- bvhtree_from_mesh_get(&bvhtree, dm, BVHTREE_FROM_EDGES, 2);
+ else if (mesh->totedge != 0) {
+ medge = mesh->medge;
+ BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_EDGES, 2);
}
else {
- dm->release(dm);
+ BKE_id_free(NULL, mesh);
return false;
}
@@ -751,7 +759,7 @@ static bool remap_hair_emitter(
tpa->foffset = 0.0f;
tpa->num = nearest.index;
- tpa->num_dmcache = psys_particle_dm_face_lookup(target_dm, dm, tpa->num, tpa->fuv, NULL);
+ tpa->num_dmcache = psys_particle_dm_face_lookup(target_mesh, mesh, tpa->num, tpa->fuv, NULL);
}
else {
me = &medge[nearest.index];
@@ -777,7 +785,7 @@ static bool remap_hair_emitter(
copy_m4_m4(imat, target_ob->obmat);
else {
/* note: using target_dm here, which is in target_ob object space and has full modifiers */
- psys_mat_hair_to_object(target_ob, target_dm, target_psys->part->from, tpa, hairmat);
+ psys_mat_hair_to_object(target_ob, target_mesh, target_psys->part->from, tpa, hairmat);
invert_m4_m4(imat, hairmat);
}
mul_m4_m4m4(imat, imat, to_imat);
@@ -823,7 +831,7 @@ static bool remap_hair_emitter(
}
free_bvhtree_from_mesh(&bvhtree);
- dm->release(dm);
+ BKE_id_free(NULL, mesh);
psys_free_path_cache(target_psys, target_edit);
@@ -994,7 +1002,7 @@ static bool copy_particle_systems_to_object(const bContext *C,
ModifierData *md;
ParticleSystem *psys_start = NULL, *psys, *psys_from;
ParticleSystem **tmp_psys;
- DerivedMesh *final_dm;
+ Mesh *final_mesh;
CustomDataMask cdmask;
int i, totpsys;
@@ -1036,8 +1044,11 @@ static bool copy_particle_systems_to_object(const bContext *C,
psys_start = totpsys > 0 ? tmp_psys[0] : NULL;
/* get the DM (psys and their modifiers have not been appended yet) */
- final_dm = mesh_get_derived_final(depsgraph, scene, ob_to, cdmask);
-
+ /* TODO(Sybren): use mesh_evaluated instead */
+ DerivedMesh *final_dm = mesh_get_derived_final(depsgraph, scene, ob_to, cdmask);
+ final_mesh = BKE_id_new_nomain(ID_ME, NULL);
+ DM_to_mesh(final_dm, final_mesh, ob_to, CD_MASK_EVERYTHING, false);
+
/* now append psys to the object and make modifiers */
for (i = 0, psys_from = PSYS_FROM_FIRST;
i < totpsys;
@@ -1060,10 +1071,17 @@ static bool copy_particle_systems_to_object(const bContext *C,
modifier_unique_name(&ob_to->modifiers, (ModifierData *)psmd);
psmd->psys = psys;
- psmd->dm_final = CDDM_copy(final_dm);
- CDDM_calc_normals(psmd->dm_final);
- DM_ensure_tessface(psmd->dm_final);
-
+ BKE_id_copy_ex(
+ NULL, &final_mesh->id, (ID **)&psmd->mesh_final,
+ LIB_ID_CREATE_NO_MAIN |
+ LIB_ID_CREATE_NO_USER_REFCOUNT |
+ LIB_ID_CREATE_NO_DEG_TAG |
+ LIB_ID_COPY_NO_PREVIEW,
+ false);
+
+ BKE_mesh_calc_normals(psmd->mesh_final);
+ BKE_mesh_tessface_ensure(psmd->mesh_final);
+
if (psys_from->edit) {
copy_particle_edit(depsgraph, scene, ob_to, psys, psys_from);
}
diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c
index 8ebdb5f32b8..7167b48c06e 100644
--- a/source/blender/editors/screen/screen_edit.c
+++ b/source/blender/editors/screen/screen_edit.c
@@ -848,6 +848,7 @@ void ED_screens_initialize(wmWindowManager *wm)
ED_screen_global_areas_create(win);
}
ED_screen_refresh(wm, win);
+ ED_screen_set_active_region(NULL, win, &win->eventstate->x);
}
}
@@ -992,9 +993,8 @@ static void screen_cursor_set(wmWindow *win, const int xy[2])
/* called in wm_event_system.c. sets state vars in screen, cursors */
/* event type is mouse move */
-void ED_screen_set_active_region(bContext *C, const int xy[2])
+void ED_screen_set_active_region(bContext *C, wmWindow *win, const int xy[2])
{
- wmWindow *win = CTX_wm_window(C);
bScreen *scr = WM_window_get_active_screen(win);
if (scr) {
@@ -1058,7 +1058,9 @@ void ED_screen_set_active_region(bContext *C, const int xy[2])
/* this used to be a notifier, but needs to be done immediate
* because it can undo setting the right button as active due
* to delayed notifier handling */
- UI_screen_free_active_but(C, scr);
+ if (C) {
+ UI_screen_free_active_but(C, scr);
+ }
}
else
region_cursor_set(win, false);
diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c
index fd8fe84cffc..a1435d5916a 100644
--- a/source/blender/editors/sculpt_paint/paint_image_proj.c
+++ b/source/blender/editors/sculpt_paint/paint_image_proj.c
@@ -5761,7 +5761,7 @@ void PAINT_OT_add_texture_paint_slot(wmOperatorType *ot)
/* api callbacks */
ot->invoke = texture_paint_add_texture_paint_slot_invoke;
ot->exec = texture_paint_add_texture_paint_slot_exec;
- ot->poll = ED_operator_region_view3d_active;
+ ot->poll = ED_operator_object_active;
/* flags */
ot->flag = OPTYPE_UNDO;
diff --git a/source/blender/editors/space_outliner/outliner_collections.c b/source/blender/editors/space_outliner/outliner_collections.c
index e0041d36a24..206cdd57342 100644
--- a/source/blender/editors/space_outliner/outliner_collections.c
+++ b/source/blender/editors/space_outliner/outliner_collections.c
@@ -65,7 +65,7 @@ bool outliner_is_collection_tree_element(const TreeElement *te)
return false;
}
- if (tselem->type == TSE_LAYER_COLLECTION) {
+ if (ELEM(tselem->type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
return true;
}
else if (tselem->type == 0 && te->idcode == ID_GR) {
@@ -87,7 +87,7 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te)
LayerCollection *lc = te->directdata;
return lc->collection;
}
- else if (ELEM(tselem->type, TSE_R_LAYER, TSE_SCENE_COLLECTION_BASE)) {
+ else if (ELEM(tselem->type, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
Scene *scene = (Scene*)tselem->id;
return BKE_collection_master(scene);
}
@@ -104,7 +104,7 @@ Collection *outliner_collection_from_tree_element(const TreeElement *te)
static int collections_editor_poll(bContext *C)
{
SpaceOops *so = CTX_wm_space_outliner(C);
- return (so != NULL) && ELEM(so->outlinevis, SO_COLLECTIONS, SO_VIEW_LAYER, SO_SCENES);
+ return (so != NULL) && ELEM(so->outlinevis, SO_VIEW_LAYER, SO_SCENES);
}
@@ -145,19 +145,17 @@ static int collection_new_exec(bContext *C, wmOperator *op)
.collection = NULL,
};
- outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
+ if (RNA_boolean_get(op->ptr, "nested")) {
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, collection_find_selected_to_add, &data);
- if (data.error) {
- BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
- return OPERATOR_CANCELLED;
+ if (data.error) {
+ BKE_report(op->reports, RPT_ERROR, "More than one collection is selected");
+ return OPERATOR_CANCELLED;
+ }
}
- if (!data.collection) {
- if (!(soops->outlinevis == SO_COLLECTIONS &&
- ELEM(soops->filter_collection, SO_FILTER_COLLECTION_UNLINKED, SO_FILTER_COLLECTION_ALL)))
- {
- data.collection = BKE_collection_master(scene);
- }
+ if (!data.collection && (soops->outlinevis == SO_VIEW_LAYER)) {
+ data.collection = BKE_collection_master(scene);
}
BKE_collection_add(
@@ -184,6 +182,10 @@ void OUTLINER_OT_collection_new(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* properties */
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "nested", true, "Nested", "Add as child of selected collection");;
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/**************************** Delete Collection ******************************/
@@ -265,7 +267,8 @@ void OUTLINER_OT_collection_delete(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
/* properties */
- RNA_def_boolean(ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections");
+ PropertyRNA *prop = RNA_def_boolean(ot->srna, "hierarchy", false, "Hierarchy", "Delete child objects and collections");
+ RNA_def_property_flag(prop, PROP_SKIP_SAVE);
}
/****************************** Select Objects *******************************/
@@ -285,6 +288,8 @@ static TreeTraversalAction outliner_find_first_selected_layer_collection(TreeEle
data->layer_collection = te->directdata;
return TRAVERSE_BREAK;
case TSE_R_LAYER:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
return TRAVERSE_CONTINUE;
default:
return TRAVERSE_SKIP_CHILDS;
@@ -365,6 +370,8 @@ static TreeTraversalAction outliner_find_first_selected_collection(TreeElement *
data->te = te;
return TRAVERSE_BREAK;
case TSE_R_LAYER:
+ case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
default:
return TRAVERSE_CONTINUE;
}
@@ -400,7 +407,7 @@ static int collection_duplicate_exec(bContext *C, wmOperator *op)
switch (soops->outlinevis) {
case SO_SCENES:
case SO_VIEW_LAYER:
- case SO_COLLECTIONS:
+ case SO_LIBRARIES:
BKE_collection_copy(bmain, parent, collection);
break;
}
@@ -538,3 +545,153 @@ void OUTLINER_OT_collection_instance(wmOperatorType *ot)
/* flags */
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
+
+/************************** Exclude Collection ******************************/
+
+static TreeTraversalAction layer_collection_find_data_to_edit(TreeElement *te, void *customdata)
+{
+ struct CollectionEditData *data = customdata;
+ TreeStoreElem *tselem = TREESTORE(te);
+
+ if (!(tselem && tselem->type == TSE_LAYER_COLLECTION)) {
+ return TRAVERSE_CONTINUE;
+ }
+
+ LayerCollection *lc = te->directdata;
+
+ if (lc->collection->flag & COLLECTION_IS_MASTER) {
+ /* skip - showing warning/error message might be missleading
+ * when deleting multiple collections, so just do nothing */
+ }
+ else {
+ /* Delete, duplicate and link don't edit children, those will come along
+ * with the parents. */
+ BLI_gset_add(data->collections_to_edit, lc);
+ }
+
+ return TRAVERSE_CONTINUE;
+}
+
+static int collections_view_layer_poll(bContext *C, bool include)
+{
+ /* Poll function so the right click menu show current state of selected collections. */
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ if (!(soops && soops->outlinevis == SO_VIEW_LAYER)) {
+ return false;
+ }
+
+ Scene *scene = CTX_data_scene(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
+ bool result = false;
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
+
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+
+ if (include && (lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ result = true;
+ }
+ else if (!include && !(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ result = true;
+ }
+ }
+
+ BLI_gset_free(data.collections_to_edit, NULL);
+ return result;
+}
+
+static int collections_exclude_poll(bContext *C)
+{
+ return collections_view_layer_poll(C, false);
+}
+
+static int collections_include_poll(bContext *C)
+{
+ return collections_view_layer_poll(C, true);
+}
+
+static void layer_collection_exclude_recursive_set(LayerCollection *lc)
+{
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
+ nlc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
+ else {
+ nlc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ }
+
+ layer_collection_exclude_recursive_set(nlc);
+ }
+}
+
+static int collection_view_layer_exec(bContext *C, wmOperator *op)
+{
+ Main *bmain = CTX_data_main(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ SpaceOops *soops = CTX_wm_space_outliner(C);
+ struct CollectionEditData data = {.scene = scene, .soops = soops};
+ bool include = STREQ(op->idname, "OUTLINER_OT_collection_include_set");
+
+ data.collections_to_edit = BLI_gset_ptr_new(__func__);
+
+ outliner_tree_traverse(soops, &soops->tree, 0, TSE_SELECTED, layer_collection_find_data_to_edit, &data);
+
+ GSetIterator collections_to_edit_iter;
+ GSET_ITER(collections_to_edit_iter, data.collections_to_edit) {
+ LayerCollection *lc = BLI_gsetIterator_getKey(&collections_to_edit_iter);
+
+ if (!(lc->collection->flag & COLLECTION_IS_MASTER)) {
+ if (include) {
+ lc->flag &= ~LAYER_COLLECTION_EXCLUDE;
+ }
+ else {
+ lc->flag |= LAYER_COLLECTION_EXCLUDE;
+ }
+
+ layer_collection_exclude_recursive_set(lc);
+ }
+ }
+
+ BLI_gset_free(data.collections_to_edit, NULL);
+
+ BKE_layer_collection_sync(scene, view_layer);
+ DEG_relations_tag_update(bmain);
+
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+
+ return OPERATOR_FINISHED;
+}
+
+void OUTLINER_OT_collection_exclude_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Exclude from View Layer";
+ ot->idname = "OUTLINER_OT_collection_exclude_set";
+ ot->description = "Exclude collection from the active view layer";
+
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_exclude_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
+
+void OUTLINER_OT_collection_include_set(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Include in View Layer";
+ ot->idname = "OUTLINER_OT_collection_include_set";
+ ot->description = "Include collection in the active view layer";
+
+ /* api callbacks */
+ ot->exec = collection_view_layer_exec;
+ ot->poll = collections_include_poll;
+
+ /* flags */
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+}
diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c
index d92b5df56be..90b137bcd7d 100644
--- a/source/blender/editors/space_outliner/outliner_draw.c
+++ b/source/blender/editors/space_outliner/outliner_draw.c
@@ -262,38 +262,6 @@ static void restrictbutton_id_user_toggle(bContext *UNUSED(C), void *poin, void
}
}
-static void layer_collection_exclude_recursive_set(LayerCollection *lc)
-{
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- if (lc->flag & LAYER_COLLECTION_EXCLUDE) {
- nlc->flag |= LAYER_COLLECTION_EXCLUDE;
- }
- else {
- nlc->flag &= ~LAYER_COLLECTION_EXCLUDE;
- }
-
- layer_collection_exclude_recursive_set(nlc);
- }
-}
-
-static void layer_collection_exclude_cb(bContext *C, void *poin, void *poin2)
-{
- Main *bmain = CTX_data_main(C);
- Scene *scene = (Scene *)poin;
- LayerCollection *lc = (LayerCollection *)poin2;
- ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, lc);
-
- layer_collection_exclude_recursive_set(lc);
-
- BKE_layer_collection_sync(scene, view_layer);
-
- /* TODO(sergey): Use proper flag for tagging here. */
- DEG_id_tag_update(&scene->id, 0);
- DEG_relations_tag_update(bmain);
- WM_main_add_notifier(NC_SCENE | ND_LAYER_CONTENT, NULL);
-}
-
-
static void namebutton_cb(bContext *C, void *tsep, char *oldname)
{
Main *bmain = CTX_data_main(C);
@@ -423,10 +391,6 @@ static void namebutton_cb(bContext *C, void *tsep, char *oldname)
WM_event_add_notifier(C, NC_GPENCIL | ND_DATA, gpd);
break;
}
- case TSE_R_LAYER:
- {
- break;
- }
case TSE_LAYER_COLLECTION:
{
BLI_libblock_ensure_unique_name(bmain, tselem->id->name);
@@ -450,15 +414,12 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
PropertyRNA *collection_prop_hide_viewport;
PropertyRNA *collection_prop_hide_select;
PropertyRNA *collection_prop_hide_render;
- PropertyRNA *collection_prop_exclude;
collection_prop_hide_select = RNA_struct_type_find_property(&RNA_Collection, "hide_select");
collection_prop_hide_viewport = RNA_struct_type_find_property(&RNA_Collection, "hide_viewport");
collection_prop_hide_render = RNA_struct_type_find_property(&RNA_Collection, "hide_render");
- collection_prop_exclude = RNA_struct_type_find_property(&RNA_LayerCollection, "use");
BLI_assert(collection_prop_hide_viewport &&
collection_prop_hide_select &&
- collection_prop_hide_render &&
- collection_prop_exclude);
+ collection_prop_hide_render);
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
@@ -568,20 +529,9 @@ static void outliner_draw_restrictbuts(uiBlock *block, Scene *scene, ARegion *ar
UI_block_emboss_set(block, UI_EMBOSS_NONE);
- if (soops->outlinevis == SO_VIEW_LAYER) {
- if (lc && !(collection->flag & COLLECTION_IS_MASTER)) {
- PointerRNA layer_collection_ptr;
- RNA_pointer_create(&scene->id, &RNA_LayerCollection, lc, &layer_collection_ptr);
-
- bt = uiDefIconButR_prop(block, UI_BTYPE_ICON_TOGGLE, 0,
- (lc->flag & LAYER_COLLECTION_EXCLUDE) ? ICON_CHECKBOX_DEHLT : ICON_CHECKBOX_HLT,
- (int)(ar->v2d.cur.xmax - OL_TOG_RESTRICT_RENDERX), te->ys, UI_UNIT_X,
- UI_UNIT_Y, &layer_collection_ptr, collection_prop_exclude, -1, 0, 0, 0, 0, NULL);
- UI_but_func_set(bt, layer_collection_exclude_cb, scene, lc);
- UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK);
- }
- }
- else if (!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
+ if ((!lc || !(lc->flag & LAYER_COLLECTION_EXCLUDE)) &&
+ !(collection->flag & COLLECTION_IS_MASTER))
+ {
PointerRNA collection_ptr;
RNA_id_pointer_create(&collection->id, &collection_ptr);
@@ -1111,6 +1061,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
break;
case TSE_LAYER_COLLECTION:
case TSE_SCENE_COLLECTION_BASE:
+ case TSE_VIEW_COLLECTION_BASE:
ICON_DRAW(ICON_GROUP);
break;
/* Removed the icons from outliner. Need a better structure with Layers, Palettes and Colors */
@@ -1249,6 +1200,11 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto
}
break;
}
+ case ID_BR:
+ tselem_draw_icon_uibut(&arg, ICON_BRUSH_DATA); break;
+ case ID_SCR:
+ case ID_WS:
+ tselem_draw_icon_uibut(&arg, ICON_SPLITSCREEN); break;
default:
break;
}
@@ -1320,10 +1276,11 @@ static void outliner_draw_iconrow(
}
/* this tree element always has same amount of branches, so don't draw */
- if (tselem->type != TSE_R_LAYER)
+ if (tselem->type != TSE_R_LAYER) {
outliner_draw_iconrow(
C, block, scene, view_layer, obedit, soops,
&te->subtree, level + 1, xmax, offsx, ys, alpha_fac);
+ }
}
}
@@ -1442,8 +1399,8 @@ static void outliner_draw_tree_element(
te->flag |= TE_ACTIVE; // for lookup in display hierarchies
}
- if (tselem->type == TSE_R_LAYER && ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS, SO_OBJECTS)) {
- /* View layer in collections can't expand/collapse. */
+ if (tselem->type == TSE_VIEW_COLLECTION_BASE) {
+ /* Scene collection in view layer can't expand/collapse. */
}
else if (te->subtree.first || (tselem->type == 0 && te->idcode == ID_SCE) || (te->flag & TE_LAZY_CLOSED)) {
/* open/close icon, only when sublevels, except for scene */
@@ -1461,7 +1418,7 @@ static void outliner_draw_tree_element(
/* datatype icon */
- if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM))) {
+ if (!(ELEM(tselem->type, TSE_RNA_PROPERTY, TSE_RNA_ARRAY_ELEM, TSE_ID_BASE))) {
tselem_draw_icon(block, xmax, (float)startx + offsx, (float)*starty, tselem, te, alpha_fac);
offsx += UI_UNIT_X + 2 * ufac;
}
@@ -1746,7 +1703,7 @@ static void outliner_draw_highlights_recursive(
int start_x, int *io_start_y)
{
const bool is_searching = SEARCHING_OUTLINER(soops) ||
- (soops->outlinevis == SO_DATABLOCKS &&
+ (soops->outlinevis == SO_DATA_API &&
(soops->filter & SO_FILTER_SEARCH) &&
soops->search_string[0] != 0);
@@ -1814,7 +1771,7 @@ static void outliner_draw_tree(
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // only once
- if (soops->outlinevis == SO_DATABLOCKS) {
+ if (soops->outlinevis == SO_DATA_API) {
/* struct marks */
starty = (int)ar->v2d.tot.ymax - UI_UNIT_Y - OL_Y_OFFSET;
outliner_draw_struct_marks(ar, soops, &soops->tree, &starty);
@@ -1940,7 +1897,7 @@ void draw_outliner(const bContext *C)
/* get extents of data */
outliner_height(soops, &soops->tree, &sizey);
- if (soops->outlinevis == SO_DATABLOCKS) {
+ if (soops->outlinevis == SO_DATA_API) {
/* RNA has two columns:
* - column 1 is (max_width + OL_RNA_COL_SPACEX) or
* (OL_RNA_COL_X), whichever is wider...
@@ -1990,7 +1947,7 @@ void draw_outliner(const bContext *C)
(bContext *)C, block, scene, view_layer, obedit,
ar, soops, has_restrict_icons, &te_edit);
- if (soops->outlinevis == SO_DATABLOCKS) {
+ if (soops->outlinevis == SO_DATA_API) {
/* draw rna buttons */
outliner_draw_rnacols(ar, sizex_rna);
outliner_draw_rnabuts(block, ar, soops, sizex_rna, &soops->tree);
diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c
index 4bb2f49fd08..5922e208f36 100644
--- a/source/blender/editors/space_outliner/outliner_edit.c
+++ b/source/blender/editors/space_outliner/outliner_edit.c
@@ -264,7 +264,8 @@ static void do_item_rename(ARegion *ar, TreeElement *te, TreeStoreElem *tselem,
/* do nothing */;
}
else if (ELEM(tselem->type, TSE_ANIM_DATA, TSE_NLA, TSE_DEFGROUP_BASE, TSE_CONSTRAINT_BASE, TSE_MODIFIER_BASE,
- TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE))
+ TSE_DRIVER_BASE, TSE_POSE_BASE, TSE_POSEGRP_BASE, TSE_R_LAYER_BASE, TSE_SCENE_COLLECTION_BASE,
+ TSE_VIEW_COLLECTION_BASE))
{
BKE_report(reports, RPT_WARNING, "Cannot edit builtin name");
}
@@ -1338,7 +1339,7 @@ static int ed_operator_outliner_datablocks_active(bContext *C)
ScrArea *sa = CTX_wm_area(C);
if ((sa) && (sa->spacetype == SPACE_OUTLINER)) {
SpaceOops *so = CTX_wm_space_outliner(C);
- return (so->outlinevis == SO_DATABLOCKS);
+ return (so->outlinevis == SO_DATA_API);
}
return 0;
}
@@ -2063,7 +2064,12 @@ static int outliner_parenting_poll(bContext *C)
SpaceOops *soops = CTX_wm_space_outliner(C);
if (soops) {
- if (ELEM(soops->outlinevis, SO_SCENES, SO_OBJECTS)) {
+ if (soops->outlinevis == SO_SCENES) {
+ return true;
+ }
+ else if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION))
+ {
return true;
}
}
diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h
index 86208dcb22d..73494b890ed 100644
--- a/source/blender/editors/space_outliner/outliner_intern.h
+++ b/source/blender/editors/space_outliner/outliner_intern.h
@@ -163,7 +163,7 @@ typedef enum {
/* The outliner display modes that support the filter system.
* Note: keep it synced with space_outliner.py */
-#define SUPPORT_FILTER_OUTLINER(soops_) (ELEM((soops_)->outlinevis, SO_COLLECTIONS, SO_OBJECTS))
+#define SUPPORT_FILTER_OUTLINER(soops_) (ELEM((soops_)->outlinevis, SO_VIEW_LAYER))
/* Outliner Searching --
*
@@ -345,6 +345,8 @@ void OUTLINER_OT_collection_objects_select(struct wmOperatorType *ot);
void OUTLINER_OT_collection_objects_deselect(struct wmOperatorType *ot);
void OUTLINER_OT_collection_link(struct wmOperatorType *ot);
void OUTLINER_OT_collection_instance(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_exclude_set(struct wmOperatorType *ot);
+void OUTLINER_OT_collection_include_set(struct wmOperatorType *ot);
/* outliner_utils.c ---------------------------------------------- */
diff --git a/source/blender/editors/space_outliner/outliner_ops.c b/source/blender/editors/space_outliner/outliner_ops.c
index d7a158b92a6..9c1b9bf2630 100644
--- a/source/blender/editors/space_outliner/outliner_ops.c
+++ b/source/blender/editors/space_outliner/outliner_ops.c
@@ -69,7 +69,7 @@ static int outliner_item_drag_drop_poll(bContext *C)
SpaceOops *soops = CTX_wm_space_outliner(C);
return ED_operator_outliner_active(C) &&
/* Only collection display modes supported for now. Others need more design work */
- ELEM(soops->outlinevis, SO_COLLECTIONS, SO_OBJECTS);
+ ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_LIBRARIES);
}
static TreeElement *outliner_item_drag_element_find(SpaceOops *soops, ARegion *ar, const wmEvent *event)
@@ -455,6 +455,8 @@ void outliner_operatortypes(void)
WM_operatortype_append(OUTLINER_OT_collection_objects_deselect);
WM_operatortype_append(OUTLINER_OT_collection_link);
WM_operatortype_append(OUTLINER_OT_collection_instance);
+ WM_operatortype_append(OUTLINER_OT_collection_exclude_set);
+ WM_operatortype_append(OUTLINER_OT_collection_include_set);
}
static wmKeyMap *outliner_item_drag_drop_modal_keymap(wmKeyConfig *keyconf)
diff --git a/source/blender/editors/space_outliner/outliner_select.c b/source/blender/editors/space_outliner/outliner_select.c
index 810b7815214..42fe70be527 100644
--- a/source/blender/editors/space_outliner/outliner_select.c
+++ b/source/blender/editors/space_outliner/outliner_select.c
@@ -681,6 +681,27 @@ static eOLDrawState tree_element_active_keymap_item(
return OL_DRAWSEL_NONE;
}
+static eOLDrawState tree_element_active_master_collection(
+ bContext *C, TreeElement *UNUSED(te), const eOLSetState set)
+{
+ if (set == OL_SETSEL_NONE) {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *active = CTX_data_layer_collection(C);
+
+ if (active == view_layer->layer_collections.first) {
+ return OL_DRAWSEL_NORMAL;
+ }
+ }
+ else {
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *layer_collection = view_layer->layer_collections.first;
+ BKE_layer_collection_activate(view_layer, layer_collection);
+ WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
+ }
+
+ return OL_DRAWSEL_NONE;
+}
+
static eOLDrawState tree_element_active_layer_collection(
bContext *C, TreeElement *te, const eOLSetState set)
{
@@ -695,7 +716,7 @@ static eOLDrawState tree_element_active_layer_collection(
Scene *scene = CTX_data_scene(C);
LayerCollection *layer_collection = te->directdata;
ViewLayer *view_layer = BKE_view_layer_find_from_collection(scene, layer_collection);
- view_layer->active_collection = layer_collection;
+ BKE_layer_collection_activate(view_layer, layer_collection);
WM_main_add_notifier(NC_SCENE | ND_LAYER, NULL);
}
@@ -763,12 +784,7 @@ eOLDrawState tree_element_type_active(
case TSE_CONSTRAINT:
return tree_element_active_constraint(C, scene, view_layer, te, tselem, set);
case TSE_R_LAYER:
- if (soops->outlinevis == SO_SCENES) {
- return active_viewlayer(C, scene, view_layer, te, tselem, set);
- }
- else {
- return OL_DRAWSEL_NONE;
- }
+ return active_viewlayer(C, scene, view_layer, te, tselem, set);
case TSE_POSEGRP:
return tree_element_active_posegroup(C, scene, view_layer, te, tselem, set);
case TSE_SEQUENCE:
@@ -780,6 +796,8 @@ eOLDrawState tree_element_type_active(
case TSE_GP_LAYER:
//return tree_element_active_gplayer(C, scene, s, te, tselem, set);
break;
+ case TSE_VIEW_COLLECTION_BASE:
+ return tree_element_active_master_collection(C, te, set);
case TSE_LAYER_COLLECTION:
return tree_element_active_layer_collection(C, te, set);
}
@@ -905,7 +923,7 @@ static bool outliner_item_is_co_within_close_toggle(TreeElement *te, float view_
static bool outliner_is_co_within_restrict_columns(const SpaceOops *soops, const ARegion *ar, float view_co_x)
{
- return ((soops->outlinevis != SO_DATABLOCKS) &&
+ return ((soops->outlinevis != SO_DATA_API) &&
!(soops->flag & SO_HIDE_RESTRICTCOLS) &&
(view_co_x > ar->v2d.cur.xmax - OL_TOG_RESTRICT_VIEWX));
}
diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c
index 6ee8b354772..5ae6cec84ba 100644
--- a/source/blender/editors/space_outliner/outliner_tools.c
+++ b/source/blender/editors/space_outliner/outliner_tools.c
@@ -105,11 +105,8 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
for (te = lb->first; te; te = te->next) {
tselem = TREESTORE(te);
if (tselem->flag & TSE_SELECTED) {
- if (tselem->type == TSE_R_LAYER && soops->outlinevis == SO_COLLECTIONS) {
- /* Don't let immutable render layer item affect menu. */
- }
- else if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
- /* Layer collection points to collection ID. */
+ /* Layer collection points to collection ID. */
+ if (!ELEM(tselem->type, 0, TSE_LAYER_COLLECTION)) {
if (*datalevel == 0)
*datalevel = tselem->type;
else if (*datalevel != tselem->type)
@@ -133,6 +130,9 @@ static void set_operation_types(SpaceOops *soops, ListBase *lb,
case ID_LI:
if (*idlevel == 0) *idlevel = idcode;
else if (*idlevel != idcode) *idlevel = -1;
+ if (ELEM(*datalevel, TSE_VIEW_COLLECTION_BASE, TSE_SCENE_COLLECTION_BASE)) {
+ *datalevel = 0;
+ }
break;
}
}
@@ -1824,12 +1824,9 @@ static int do_outliner_operation_event(bContext *C, ARegion *ar, SpaceOops *soop
else if (datalevel == TSE_LAYER_COLLECTION) {
WM_menu_name_call(C, "OUTLINER_MT_collection", WM_OP_INVOKE_REGION_WIN);
}
- else if (datalevel == TSE_R_LAYER && ELEM(soops->outlinevis, SO_COLLECTIONS, SO_VIEW_LAYER)) {
+ else if (ELEM(datalevel, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
}
- else if (ELEM(datalevel, TSE_R_LAYER_BASE, TSE_R_LAYER)) {
- /*WM_operator_name_call(C, "OUTLINER_OT_renderdata_operation", WM_OP_INVOKE_REGION_WIN, NULL)*/
- }
else if (datalevel == TSE_ID_BASE) {
/* do nothing... there are no ops needed here yet */
}
@@ -1880,7 +1877,7 @@ static int outliner_operation(bContext *C, wmOperator *UNUSED(op), const wmEvent
if (!found) {
/* Menus for clicking in empty space. */
- if (ELEM(soops->outlinevis, SO_COLLECTIONS, SO_VIEW_LAYER)) {
+ if (soops->outlinevis == SO_VIEW_LAYER) {
WM_menu_name_call(C, "OUTLINER_MT_collection_new", WM_OP_INVOKE_REGION_WIN);
}
}
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 22d70a12261..58ab8f3735e 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -299,7 +299,7 @@ static void outliner_add_scene_contents(SpaceOops *soops, ListBase *lb, Scene *s
/* Collections */
ten = outliner_add_element(soops, lb, &sce->id, te, TSE_SCENE_COLLECTION_BASE, 0);
- ten->name = IFACE_("Collections");
+ ten->name = IFACE_("Scene Collection");
outliner_add_collection_recursive(soops, sce->master_collection, ten);
/* Objects */
@@ -877,7 +877,7 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
else if (type == TSE_GP_LAYER) {
/* pass */
}
- else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE)) {
+ else if (ELEM(type, TSE_LAYER_COLLECTION, TSE_SCENE_COLLECTION_BASE, TSE_VIEW_COLLECTION_BASE)) {
/* pass */
}
else if (type == TSE_ID_BASE) {
@@ -896,8 +896,9 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
TreeStoreElem *tsepar = parent ? TREESTORE(parent) : NULL;
/* ID datablock */
- if (tsepar == NULL || tsepar->type != TSE_ID_BASE)
+ if (tsepar == NULL || tsepar->type != TSE_ID_BASE || soops->filter_id_type) {
outliner_add_id_contents(soops, te, tselem, id);
+ }
}
else if (type == TSE_ANIM_DATA) {
IdAdtTemplate *iat = (IdAdtTemplate *)idv;
@@ -1252,16 +1253,56 @@ static void outliner_add_seq_dup(SpaceOops *soops, Sequence *seq, TreeElement *t
/* ----------------------------------------------- */
+static const char *outliner_idcode_to_plural(short idcode)
+{
+ const char *propname = BKE_idcode_to_name_plural(idcode);
+ PropertyRNA *prop = RNA_struct_type_find_property(&RNA_BlendData, propname);
+ return (prop) ? RNA_property_ui_name(prop) : "UNKNOWN";
+}
+
+static bool outliner_library_id_show(Library *lib, ID *id, short filter_id_type)
+{
+ if (id->lib != lib) {
+ return false;
+ }
+
+ if (filter_id_type == ID_GR) {
+ /* Don't show child collections of non-scene master collection,
+ * they are already shown as children. */
+ Collection *collection = (Collection *)id;
+ bool has_non_scene_parent = false;
+
+ for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
+ if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
+ has_non_scene_parent = true;
+ }
+ }
+
+ if (has_non_scene_parent) {
+ return false;
+ }
+ }
+
+ return true;
+}
static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeElement *te, Library *lib)
{
TreeElement *ten;
ListBase *lbarray[MAX_LIBARRAY];
int a, tot;
+ short filter_id_type = (soops->filter & SO_FILTER_ID_TYPE) ? soops->filter_id_type : 0;
- tot = set_listbasepointers(mainvar, lbarray);
+ if (filter_id_type) {
+ lbarray[0] = which_libbase(mainvar, soops->filter_id_type);
+ tot = 1;
+ }
+ else {
+ tot = set_listbasepointers(mainvar, lbarray);
+ }
+
for (a = 0; a < tot; a++) {
- if (lbarray[a]->first) {
+ if (lbarray[a] && lbarray[a]->first) {
ID *id = lbarray[a]->first;
/* check if there's data in current lib */
@@ -1270,21 +1311,23 @@ static void outliner_add_library_contents(Main *mainvar, SpaceOops *soops, TreeE
break;
if (id) {
- ten = outliner_add_element(soops, &te->subtree, lbarray[a], NULL, TSE_ID_BASE, 0);
- ten->directdata = lbarray[a];
-
- ten->name = BKE_idcode_to_name_plural(GS(id->name));
- if (ten->name == NULL)
- ten->name = "UNKNOWN";
+ if (filter_id_type) {
+ ten = te;
+ }
+ else {
+ ten = outliner_add_element(soops, &te->subtree, lbarray[a], NULL, TSE_ID_BASE, 0);
+ ten->directdata = lbarray[a];
+ ten->name = outliner_idcode_to_plural(GS(id->name));
+ }
for (id = lbarray[a]->first; id; id = id->next) {
- if (id->lib == lib)
+ if (outliner_library_id_show(lib, id, filter_id_type)) {
outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
+ }
}
}
}
}
-
}
static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
@@ -1292,10 +1335,18 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
TreeElement *ten;
ListBase *lbarray[MAX_LIBARRAY];
int a, tot;
+ short filter_id_type = (soops->filter & SO_FILTER_ID_TYPE) ? soops->filter_id_type : 0;
- tot = set_listbasepointers(mainvar, lbarray);
+ if (filter_id_type) {
+ lbarray[0] = which_libbase(mainvar, soops->filter_id_type);
+ tot = 1;
+ }
+ else {
+ tot = set_listbasepointers(mainvar, lbarray);
+ }
+
for (a = 0; a < tot; a++) {
- if (lbarray[a]->first) {
+ if (lbarray[a] && lbarray[a]->first) {
ID *id = lbarray[a]->first;
/* check if there are any datablocks of this type which are orphans */
@@ -1306,21 +1357,19 @@ static void outliner_add_orphaned_datablocks(Main *mainvar, SpaceOops *soops)
if (id) {
/* header for this type of datablock */
- /* TODO's:
- * - Add a parameter to BKE_idcode_to_name_plural to get a sane "user-visible" name instead?
- * - Ensure that this uses nice icons for the datablock type involved instead of the dot?
- */
- ten = outliner_add_element(soops, &soops->tree, lbarray[a], NULL, TSE_ID_BASE, 0);
- ten->directdata = lbarray[a];
-
- ten->name = BKE_idcode_to_name_plural(GS(id->name));
- if (ten->name == NULL)
- ten->name = "UNKNOWN";
+ if (filter_id_type) {
+ ten = NULL;
+ }
+ else {
+ ten = outliner_add_element(soops, &soops->tree, lbarray[a], NULL, TSE_ID_BASE, 0);
+ ten->directdata = lbarray[a];
+ ten->name = outliner_idcode_to_plural(GS(id->name));
+ }
/* add the orphaned datablocks - these will not be added with any subtrees attached */
for (id = lbarray[a]->first; id; id = id->next) {
if (ID_REAL_USERS(id) <= 0)
- outliner_add_element(soops, &ten->subtree, id, ten, 0, 0);
+ outliner_add_element(soops, (ten) ? &ten->subtree : &soops->tree, id, ten, 0, 0);
}
}
}
@@ -1412,33 +1461,12 @@ static void outliner_add_layer_collection_objects(
}
}
-static bool outliner_layer_collection_is_visible(LayerCollection *lc)
-{
- if (!(lc->flag & LAYER_COLLECTION_EXCLUDE)) {
- return true;
- }
-
- for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
- if (outliner_layer_collection_is_visible(nlc)) {
- return true;
- }
- }
-
- return false;
-}
-
static void outliner_add_layer_collections_recursive(
SpaceOops *soops, ListBase *tree, ViewLayer *layer,
ListBase *layer_collections, TreeElement *parent_ten,
const bool show_objects)
{
for (LayerCollection *lc = layer_collections->first; lc; lc = lc->next) {
- if ((soops->outlinevis != SO_VIEW_LAYER) &&
- !outliner_layer_collection_is_visible(lc))
- {
- continue;
- }
-
ID *id = &lc->collection->id;
TreeElement *ten = outliner_add_element(soops, tree, id, parent_ten, TSE_LAYER_COLLECTION, 0);
@@ -1477,7 +1505,7 @@ static void outliner_add_view_layer(SpaceOops *soops, ListBase *tree, TreeElemen
BLI_INLINE void outliner_add_collection_init(TreeElement *te, Collection *collection)
{
if (collection->flag & COLLECTION_IS_MASTER) {
- te->name = IFACE_("Collections");
+ te->name = IFACE_("Scene Collection");
}
else {
te->name = collection->id.name + 2;
@@ -1776,7 +1804,8 @@ static TreeElement *outliner_find_first_desired_element_at_y(
te = outliner_find_item_at_y(soops, &soops->tree, view_co);
bool (*callback_test)(TreeElement *);
- if (soops->outlinevis == SO_OBJECTS) {
+ if ((soops->outlinevis == SO_VIEW_LAYER) &&
+ (soops->filter & SO_FILTER_NO_COLLECTION)) {
callback_test = test_object_callback;
}
else {
@@ -1855,7 +1884,7 @@ static int outliner_exclude_filter_get(SpaceOops *soops)
return (exclude_filter & SO_FILTER_SEARCH);
}
- if (soops->outlinevis == SO_COLLECTIONS && (soops->filter & SO_FILTER_NO_OBJECT)) {
+ if (soops->filter & SO_FILTER_NO_OBJECT) {
exclude_filter |= SO_FILTER_OB_TYPE;
}
@@ -2070,7 +2099,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
/* Are we looking for something - we want to tag parents to filter child matches
* - NOT in datablocks view - searching all datablocks takes way too long to be useful
* - this variable is only set once per tree build */
- if (soops->search_string[0] != 0 && soops->outlinevis != SO_DATABLOCKS)
+ if (soops->search_string[0] != 0 && soops->outlinevis != SO_DATA_API)
soops->search_flags |= SO_SEARCH_RECURSIVE;
else
soops->search_flags &= ~SO_SEARCH_RECURSIVE;
@@ -2177,7 +2206,7 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
seq = seq->next;
}
}
- else if (soops->outlinevis == SO_DATABLOCKS) {
+ else if (soops->outlinevis == SO_DATA_API) {
PointerRNA mainptr;
RNA_main_pointer_create(mainvar, &mainptr);
@@ -2192,59 +2221,25 @@ void outliner_build_tree(Main *mainvar, Scene *scene, ViewLayer *view_layer, Spa
else if (soops->outlinevis == SO_ID_ORPHANS) {
outliner_add_orphaned_datablocks(mainvar, soops);
}
- else if (soops->outlinevis == SO_COLLECTIONS &&
- soops->filter_collection != SO_FILTER_COLLECTION_SCENE) {
- Collection *collection;
- for (collection = mainvar->collection.first; collection; collection = collection->id.next) {
- if (soops->filter_collection == SO_FILTER_COLLECTION_UNLINKED) {
- /* Skip collections used in a scene */
- if (BKE_collection_is_in_scene(collection)) {
- continue;
- }
- }
-
- if (collection->parents.first) {
- /* Don't show child collections of non-scene master collection,
- * they are already shown as children. */
- bool has_non_scene_parent = false;
-
- for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
- if (!(cparent->collection->flag & COLLECTION_IS_MASTER)) {
- has_non_scene_parent = true;
- }
- }
-
- if (has_non_scene_parent) {
- continue;
- }
+ else if (soops->outlinevis == SO_VIEW_LAYER) {
+ if (soops->filter & SO_FILTER_NO_COLLECTION) {
+ /* Show objects in the view layer. */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ TreeElement *te_object = outliner_add_element(soops, &soops->tree, base->object, NULL, 0, 0);
+ te_object->directdata = base;
}
- te = outliner_add_element(soops, &soops->tree, collection, NULL, 0, 0);
+ outliner_make_object_parent_hierarchy(&soops->tree);
}
- }
- else if (ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS)) {
- /* Show collections and objects in the view layer. */
- TreeElement *tenlay = outliner_add_element(soops, &soops->tree, scene, te, TSE_R_LAYER, 0);
- tenlay->name = view_layer->name;
- tenlay->directdata = view_layer;
- TREESTORE(tenlay)->flag &= ~TSE_CLOSED;
-
- bool show_objects = (soops->outlinevis == SO_COLLECTIONS) &&
- !(soops->filter & SO_FILTER_NO_OBJECT);
- outliner_add_view_layer(soops, &tenlay->subtree, tenlay, view_layer, show_objects);
- }
- else { /* SO_OBJECTS */
- /* Show objects in the view layer. */
- TreeElement *tenlay = outliner_add_element(soops, &soops->tree, scene, te, TSE_R_LAYER, 0);
- tenlay->name = view_layer->name;
- tenlay->directdata = view_layer;
- TREESTORE(tenlay)->flag &= ~TSE_CLOSED;
+ else {
+ /* Show collections in the view layer. */
+ ten = outliner_add_element(soops, &soops->tree, scene, NULL, TSE_VIEW_COLLECTION_BASE, 0);
+ ten->name = IFACE_("Scene Collection");
+ TREESTORE(ten)->flag &= ~TSE_CLOSED;
- for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- TreeElement *te_object = outliner_add_element(soops, &tenlay->subtree, base->object, NULL, 0, 0);
- te_object->directdata = base;
+ bool show_objects = !(soops->filter & SO_FILTER_NO_OBJECT);
+ outliner_add_view_layer(soops, &ten->subtree, ten, view_layer, show_objects);
}
- outliner_make_object_parent_hierarchy(&tenlay->subtree);
}
if ((soops->flag & SO_SKIP_SORT_ALPHA) == 0) {
diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c
index dc6406fcc18..72ce24aaff5 100644
--- a/source/blender/editors/space_outliner/space_outliner.c
+++ b/source/blender/editors/space_outliner/space_outliner.c
@@ -159,7 +159,7 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent *
UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]);
- if (!ELEM(soops->outlinevis, SO_SCENES, SO_COLLECTIONS, SO_OBJECTS)) {
+ if (!ELEM(soops->outlinevis, SO_VIEW_LAYER)) {
return false;
}
@@ -434,7 +434,7 @@ static void outliner_main_region_message_subscribe(
.notify = ED_region_do_msg_notify_tag_redraw,
};
- if (ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_COLLECTIONS, SO_OBJECTS)) {
+ if (ELEM(soops->outlinevis, SO_VIEW_LAYER, SO_SCENES)) {
WM_msg_subscribe_rna_anon_prop(mbus, Window, view_layer, &msg_sub_value_region_tag_redraw);
}
}
@@ -483,6 +483,7 @@ static SpaceLink *outliner_new(const ScrArea *UNUSED(area), const Scene *UNUSED(
soutliner = MEM_callocN(sizeof(SpaceOops), "initoutliner");
soutliner->spacetype = SPACE_OUTLINER;
+ soutliner->filter_id_type = ID_GR;
/* header */
ar = MEM_callocN(sizeof(ARegion), "header for outliner");
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index ede18b73175..3f795651c65 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1017,7 +1017,7 @@ static void view3d_main_region_listener(
static void view3d_main_region_message_subscribe(
const struct bContext *C,
- struct WorkSpace *workspace, struct Scene *scene,
+ struct WorkSpace *workspace, struct Scene *UNUSED(scene),
struct bScreen *UNUSED(screen), struct ScrArea *UNUSED(sa), struct ARegion *ar,
struct wmMsgBus *mbus)
{
@@ -1075,19 +1075,7 @@ static void view3d_main_region_message_subscribe(
WM_msg_subscribe_rna_anon_prop(mbus, RenderSettings, use_border, &msg_sub_value_region_tag_redraw);
}
- /* Each engine could be responsible for its own engine data types.
- * For now this is simplest. */
- if (STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE)) {
- extern StructRNA RNA_ViewLayerEngineSettingsEevee;
- WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsEevee, &msg_sub_value_region_tag_redraw);
- }
-#ifdef WITH_CLAY_ENGINE
- else if (STREQ(scene->r.engine, RE_engine_id_BLENDER_CLAY)) {
- extern StructRNA RNA_ViewLayerEngineSettingsClay;
- WM_msg_subscribe_rna_anon_type(mbus, ViewLayerEngineSettingsClay, &msg_sub_value_region_tag_redraw);
- }
-#endif
-
+ WM_msg_subscribe_rna_anon_type(mbus, SceneEEVEE, &msg_sub_value_region_tag_redraw);
WM_msg_subscribe_rna_anon_type(mbus, SceneDisplay, &msg_sub_value_region_tag_redraw);
WM_msg_subscribe_rna_anon_type(mbus, ObjectDisplay, &msg_sub_value_region_tag_redraw);
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index a3990091b12..c479267603d 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -4607,7 +4607,7 @@ void ED_view3d_cursor3d_update(bContext *C, const int mval[2])
.snap_select = SNAP_ALL,
.use_object_edit_cage = false,
},
- mval_fl, &dist_px, NULL,
+ mval_fl, &dist_px,
cursor_curr->location, ray_no, NULL,
&ob_dummy, obmat))
{
diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c
index 3c026f71769..12229b8c940 100644
--- a/source/blender/editors/transform/transform_conversions.c
+++ b/source/blender/editors/transform/transform_conversions.c
@@ -2027,7 +2027,7 @@ static void createTransParticleVerts(bContext *C, TransInfo *t)
if (!(point->flag & PEP_TRANSFORM)) continue;
if (psys && !(psys->flag & PSYS_GLOBAL_HAIR))
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles + i, mat);
for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
if (key->flag & PEK_USE_WCO) {
@@ -2105,7 +2105,7 @@ void flushTransParticles(TransInfo *t)
if (!(point->flag & PEP_TRANSFORM)) continue;
if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
- psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + i, mat);
+ psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles + i, mat);
invert_m4_m4(imat, mat);
for (k = 0, key = point->keys; k < point->totkey; k++, key++) {
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 681f955087a..948eb47965f 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -1195,16 +1195,15 @@ bool snapObjectsTransform(
float *dist_px,
float r_loc[3], float r_no[3])
{
- return ED_transform_snap_object_project_view3d_ex(
+ return ED_transform_snap_object_project_view3d(
t->tsnap.object_context,
t->scene->toolsettings->snap_mode,
&(const struct SnapObjectParams){
.snap_select = t->tsnap.modeSelect,
.use_object_edit_cage = (t->flag & T_EDIT) != 0,
+ .use_occlusion_test = t->scene->toolsettings->snap_mode != SCE_SNAP_MODE_FACE,
},
- mval, dist_px, NULL,
- r_loc, r_no, NULL,
- NULL, NULL);
+ mval, dist_px, r_loc, r_no);
}
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index eb8fa0480ce..ec3f9793889 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -71,6 +71,8 @@
/** Internal Data Types
* \{ */
+#define MAX_CLIPPLANE_LEN 3
+
enum eViewProj {
VIEW_PROJ_NONE = -1,
VIEW_PROJ_ORTHO = 0,
@@ -80,12 +82,11 @@ enum eViewProj {
typedef struct SnapData {
short snap_to;
float mval[2];
- float ray_start[3];
- float ray_dir[3];
float pmat[4][4]; /* perspective matrix */
float win_size[2];/* win x and y */
enum eViewProj view_proj;
- float depth_range[2];
+ float clip_plane[MAX_CLIPPLANE_LEN][4];
+ short clip_plane_len;
} SnapData;
typedef struct SnapObjectData {
@@ -196,38 +197,6 @@ static void iter_snap_objects(
}
-/**
- * Generates a struct with the immutable parameters that will be used on all objects.
- *
- * \param snap_to: Element to snap, Vertice, Edge or Face.
- * \param view_proj: ORTHO or PERSP.
- * Currently only works one at a time, but can eventually operate as flag.
- *
- * \param mval: Mouse coords.
- * (When NULL, ray-casting is handled without any projection matrix correction.)
- * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min.
- * \param ray_start: ray_origin moved for the start clipping plane (clip_min).
- * \param ray_direction: Unit length direction of the ray.
- * \param depth_range: distances of clipe plane min and clip plane max;
- */
-static void snap_data_set(
- SnapData *snapdata,
- const ARegion *ar, const unsigned short snap_to, const enum eViewProj view_proj,
- const float mval[2], const float ray_start[3], const float ray_direction[3],
- const float depth_range[2])
-{
- copy_m4_m4(snapdata->pmat, ((RegionView3D *)ar->regiondata)->persmat);
- snapdata->win_size[0] = ar->winx;
- snapdata->win_size[1] = ar->winy;
- copy_v2_v2(snapdata->mval, mval);
- snapdata->snap_to = snap_to;
- copy_v3_v3(snapdata->ray_start, ray_start);
- copy_v3_v3(snapdata->ray_dir, ray_direction);
- snapdata->view_proj = view_proj;
- copy_v2_v2(snapdata->depth_range, depth_range);
-}
-
-
MINLINE float depth_get(const float co[3], const float ray_start[3], const float ray_dir[3])
{
float dvec[3];
@@ -682,7 +651,7 @@ static bool raycastObj(
SnapObjectContext *sctx,
const float ray_start[3], const float ray_dir[3],
Object *ob, float obmat[4][4], const unsigned int ob_index,
- bool use_obedit,
+ bool use_obedit, bool use_occlusion_test,
/* read/write args */
float *ray_depth,
/* return args */
@@ -692,6 +661,15 @@ static bool raycastObj(
{
bool retval = false;
+ if (use_occlusion_test) {
+ if (use_obedit && sctx->use_v3d &&
+ !(sctx->v3d_data.v3d->flag & V3D_ZBUF_SELECT))
+ {
+ /* Use of occlude geometry in editing mode disabled. */
+ return false;
+ }
+ }
+
switch (ob->type) {
case OB_MESH:
if (use_obedit) {
@@ -739,16 +717,19 @@ struct RaycastObjUserData {
Object **r_ob;
float (*r_obmat)[4];
ListBase *r_hit_list;
+ bool use_occlusion_test;
bool ret;
};
static void raycast_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, float obmat[4][4], void *data)
{
struct RaycastObjUserData *dt = data;
+
dt->ret |= raycastObj(
sctx,
dt->ray_start, dt->ray_dir,
- ob, obmat, dt->ob_index++, is_obedit,
+ ob, obmat, dt->ob_index++,
+ is_obedit, dt->use_occlusion_test,
dt->ray_depth,
dt->r_loc, dt->r_no, dt->r_index,
dt->r_ob, dt->r_obmat,
@@ -805,6 +786,7 @@ static bool raycastObjects(
.r_ob = r_ob,
.r_obmat = r_obmat,
.r_hit_list = r_hit_list,
+ .use_occlusion_test = params->use_occlusion_test,
.ret = false,
};
@@ -900,29 +882,26 @@ static void cb_mlooptri_verts_get(
}
static bool test_projected_vert_dist(
- const struct DistProjectedAABBPrecalc *neasrest_precalc,
- const float depth_range[2],
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4], const int clip_plane_len,
const bool is_persp, const float co[3],
float *dist_px_sq, float r_co[3])
{
- float w;
- if (is_persp) {
- w = mul_project_m4_v3_zfac(neasrest_precalc->pmat, co);
- if (w < depth_range[0] || w > depth_range[1]) {
- return false;
- }
+ if (!isect_point_planes_v3_negated(clip_plane, clip_plane_len, co)) {
+ return false;
}
float co2d[2] = {
- (dot_m4_v3_row_x(neasrest_precalc->pmat, co) + neasrest_precalc->pmat[3][0]),
- (dot_m4_v3_row_y(neasrest_precalc->pmat, co) + neasrest_precalc->pmat[3][1]),
+ (dot_m4_v3_row_x(precalc->pmat, co) + precalc->pmat[3][0]),
+ (dot_m4_v3_row_y(precalc->pmat, co) + precalc->pmat[3][1]),
};
if (is_persp) {
+ float w = mul_project_m4_v3_zfac(precalc->pmat, co);
mul_v2_fl(co2d, 1.0f / w);
}
- const float dist_sq = len_squared_v2v2(neasrest_precalc->mval, co2d);
+ const float dist_sq = len_squared_v2v2(precalc->mval, co2d);
if (dist_sq < *dist_px_sq) {
copy_v3_v3(r_co, co);
*dist_px_sq = dist_sq;
@@ -932,23 +911,158 @@ static bool test_projected_vert_dist(
}
static bool test_projected_edge_dist(
- const struct DistProjectedAABBPrecalc *neasrest_precalc,
- const float depth_range[2], const bool is_persp,
- const float va[3], const float vb[3],
+ const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4], const int clip_plane_len,
+ const bool is_persp, const float va[3], const float vb[3],
float *dist_px_sq, float r_co[3])
{
-
- float near_co[3], dummy_depth;
- dist_squared_ray_to_seg_v3(
- neasrest_precalc->ray_origin,
- neasrest_precalc->ray_direction,
- va, vb, near_co, &dummy_depth);
+ float near_co[3], lambda;
+ if (!isect_ray_seg_v3(
+ precalc->ray_origin,
+ precalc->ray_direction,
+ va, vb, &lambda))
+ {
+ copy_v3_v3(near_co, va);
+ }
+ else {
+ if (lambda <= 0.0f) {
+ copy_v3_v3(near_co, va);
+ }
+ else if (lambda >= 1.0f) {
+ copy_v3_v3(near_co, vb);
+ }
+ else {
+ interp_v3_v3v3(near_co, va, vb, lambda);
+ }
+ }
return test_projected_vert_dist(
- neasrest_precalc, depth_range,
+ precalc, clip_plane, clip_plane_len,
is_persp, near_co, dist_px_sq, r_co);
}
+static bool snapMeshPolygon(
+ SnapObjectContext *sctx, SnapData *snapdata,
+ Object *ob, float obmat[4][4],
+ /* read/write args */
+ float *dist_px,
+ /* return args */
+ float r_loc[3], float r_no[3], int *r_index)
+{
+ bool retval = false;
+
+ float lpmat[4][4], dist_px_sq = SQUARE(*dist_px);
+ mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+
+ struct DistProjectedAABBPrecalc neasrest_precalc;
+ dist_squared_to_projected_aabb_precalc(
+ &neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
+
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
+ bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+
+ SnapObjectData *sod = BLI_ghash_lookup(sctx->cache.object_map, ob);
+ BLI_assert(sod != NULL);
+
+ if (sod->type == SNAP_MESH) {
+ Mesh *me = ob->data;
+ MPoly *mp = &me->mpoly[*r_index];
+
+ const MLoop *ml = &me->mloop[mp->loopstart];
+ for (int i = mp->totloop; i--; ml++) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) {
+ const MVert *vert = &me->mvert[ml->v];
+ if (test_projected_vert_dist(
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
+ is_persp, vert->co,
+ &dist_px_sq, r_loc))
+ {
+ normal_short_to_float_v3(r_no, vert->no);
+ *r_index = ml->v;
+ retval = true;
+ }
+ }
+ else {
+ float co_pair[2][3];
+ const MEdge *edge = &me->medge[ml->e];
+ copy_v3_v3(co_pair[0], me->mvert[edge->v1].co);
+ copy_v3_v3(co_pair[1], me->mvert[edge->v2].co);
+ if (test_projected_edge_dist(
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
+ is_persp, co_pair[0], co_pair[1],
+ &dist_px_sq, r_loc))
+ {
+ sub_v3_v3v3(r_no, co_pair[0], co_pair[1]);
+ *r_index = ml->e;
+ retval = true;
+ }
+ }
+ }
+ }
+ else {
+ BLI_assert(sod->type == SNAP_EDIT_MESH);
+
+ BMEditMesh *em = BKE_editmesh_from_object(ob);
+ BM_mesh_elem_table_ensure(em->bm, BM_FACE);
+ BMFace *f = BM_face_at_index(em->bm, *r_index);
+
+ BMLoop *l_iter, *l_first;
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+
+ do {
+ if (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) {
+ const float *co = l_iter->v->co;
+ if (test_projected_vert_dist(
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
+ is_persp, co,
+ &dist_px_sq, r_loc))
+ {
+ copy_v3_v3(r_no, l_iter->v->no);
+ *r_index = BM_elem_index_get(l_iter->v);
+ retval = true;
+ }
+ }
+ else {
+ float co_pair[2][3];
+ copy_v3_v3(co_pair[0], l_iter->e->v1->co);
+ copy_v3_v3(co_pair[1], l_iter->e->v2->co);
+ if (test_projected_edge_dist(
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
+ is_persp, co_pair[0], co_pair[1],
+ &dist_px_sq, r_loc))
+ {
+ sub_v3_v3v3(r_no, co_pair[0], co_pair[1]);
+ *r_index = BM_elem_index_get(l_iter->e);
+ retval = true;
+ }
+ }
+ } while ((l_iter = l_iter->next) != l_first);
+ }
+
+ if (retval) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
+ mul_m4_v3(obmat, r_loc);
+ mul_transposed_mat3_m4_v3(obmat, r_no);
+ normalize_v3(r_no);
+
+ *dist_px = sqrtf(dist_px_sq);
+
+ return true;
+ }
+ return false;
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -963,7 +1077,6 @@ typedef void (*Nearest2DCopyVertNoCallback)(const int index, float r_no[3], void
typedef struct Nearest2dUserData {
bool is_persp;
- float depth_range[2];
short snap_to;
void *userdata;
@@ -979,6 +1092,7 @@ typedef struct Nearest2dUserData {
static void cb_walk_leaf_snap_vert(
void *userdata, int index,
const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4], const int clip_plane_len,
BVHTreeNearest *nearest)
{
struct Nearest2dUserData *data = userdata;
@@ -988,9 +1102,9 @@ static void cb_walk_leaf_snap_vert(
if (test_projected_vert_dist(
precalc,
- data->depth_range,
- data->is_persp,
- co,
+ clip_plane,
+ clip_plane_len,
+ data->is_persp, co,
&nearest->dist_sq,
nearest->co))
{
@@ -1002,6 +1116,7 @@ static void cb_walk_leaf_snap_vert(
static void cb_walk_leaf_snap_edge(
void *userdata, int index,
const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4], const int clip_plane_len,
BVHTreeNearest *nearest)
{
struct Nearest2dUserData *data = userdata;
@@ -1016,7 +1131,8 @@ static void cb_walk_leaf_snap_edge(
if (test_projected_edge_dist(
precalc,
- data->depth_range,
+ clip_plane,
+ clip_plane_len,
data->is_persp,
v_pair[0], v_pair[1],
&nearest->dist_sq,
@@ -1031,7 +1147,9 @@ static void cb_walk_leaf_snap_edge(
if (vindex[i] == nearest->index) {
continue;
}
- cb_walk_leaf_snap_vert(userdata, vindex[i], precalc, nearest);
+ cb_walk_leaf_snap_vert(
+ userdata, vindex[i], precalc,
+ clip_plane, clip_plane_len, nearest);
}
}
}
@@ -1039,6 +1157,7 @@ static void cb_walk_leaf_snap_edge(
static void cb_walk_leaf_snap_tri(
void *userdata, int index,
const struct DistProjectedAABBPrecalc *precalc,
+ const float (*clip_plane)[4], const int clip_plane_len,
BVHTreeNearest *nearest)
{
struct Nearest2dUserData *data = userdata;
@@ -1051,7 +1170,9 @@ static void cb_walk_leaf_snap_tri(
if (eindex[i] == nearest->index) {
continue;
}
- cb_walk_leaf_snap_edge(userdata, eindex[i], precalc, nearest);
+ cb_walk_leaf_snap_edge(
+ userdata, eindex[i], precalc,
+ clip_plane, clip_plane_len, nearest);
}
}
}
@@ -1062,7 +1183,9 @@ static void cb_walk_leaf_snap_tri(
if (vindex[i] == nearest->index) {
continue;
}
- cb_walk_leaf_snap_vert(userdata, vindex[i], precalc, nearest);
+ cb_walk_leaf_snap_vert(
+ userdata, vindex[i], precalc,
+ clip_plane, clip_plane_len, nearest);
}
}
}
@@ -1075,11 +1198,11 @@ static void cb_walk_leaf_snap_tri(
static bool snapArmature(
SnapData *snapdata,
- Object *ob, bArmature *arm, float obmat[4][4],
+ Object *ob, float obmat[4][4], bool use_obedit,
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float *UNUSED(r_no))
+ float r_loc[3], float *UNUSED(r_no), int *r_index)
{
bool retval = false;
@@ -1094,21 +1217,30 @@ static bool snapArmature(
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
- /* Test BoundBox */
- BoundBox *bb = BKE_armature_boundbox_get(ob);
- if (bb) {
- bool dummy[3];
- /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- float bb_dist_px_sq = dist_squared_to_projected_aabb(
- &neasrest_precalc, bb->vec[0], bb->vec[6], dummy);
-
- if (bb_dist_px_sq > dist_px_sq) {
- return retval;
+ if (use_obedit == false) {
+ /* Test BoundBox */
+ BoundBox *bb = BKE_armature_boundbox_get(ob);
+ if (bb) {
+ bool dummy[3];
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
+ float bb_dist_px_sq = dist_squared_to_projected_aabb(
+ &neasrest_precalc, bb->vec[0], bb->vec[6], dummy);
+
+ if (bb_dist_px_sq > dist_px_sq) {
+ return retval;
+ }
}
}
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
+ bArmature *arm = ob->data;
if (arm->edbo) {
for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) {
if (eBone->layer & arm->layer) {
@@ -1117,15 +1249,18 @@ static bool snapArmature(
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
is_persp, eBone->head, &dist_px_sq, r_loc);
retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
is_persp, eBone->tail, &dist_px_sq, r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
- &neasrest_precalc, snapdata->depth_range,
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
is_persp, eBone->head, eBone->tail,
&dist_px_sq, r_loc);
break;
@@ -1145,15 +1280,18 @@ static bool snapArmature(
switch (snapdata->snap_to) {
case SCE_SNAP_MODE_VERTEX:
retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
is_persp, head_vec, &dist_px_sq, r_loc);
retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
is_persp, tail_vec, &dist_px_sq, r_loc);
break;
case SCE_SNAP_MODE_EDGE:
retval |= test_projected_edge_dist(
- &neasrest_precalc, snapdata->depth_range,
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
is_persp, head_vec, tail_vec,
&dist_px_sq, r_loc);
break;
@@ -1164,7 +1302,10 @@ static bool snapArmature(
if (retval) {
*dist_px = sqrtf(dist_px_sq);
mul_m4_v3(obmat, r_loc);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
return true;
}
return false;
@@ -1174,9 +1315,9 @@ static bool snapCurve(
SnapData *snapdata,
Object *ob, float obmat[4][4], bool use_obedit,
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float *UNUSED(r_no))
+ float r_loc[3], float *UNUSED(r_no), int *r_index)
{
bool retval = false;
@@ -1195,83 +1336,93 @@ static bool snapCurve(
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, lpmat, snapdata->win_size, snapdata->mval);
- /* Test BoundBox */
- BoundBox *bb = BKE_curve_boundbox_get(ob);
- if (bb) {
- bool dummy[3];
- /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
- float bb_dist_px_sq = dist_squared_to_projected_aabb(
- &neasrest_precalc, bb->vec[0], bb->vec[6], dummy);
-
- if (bb_dist_px_sq > dist_px_sq) {
- return retval;
+ if (use_obedit == false) {
+ /* Test BoundBox */
+ BoundBox *bb = BKE_curve_boundbox_get(ob);
+ if (bb) {
+ bool dummy[3];
+ /* In vertex and edges you need to get the pixel distance from ray to BoundBox, see: T46099, T46816 */
+ float bb_dist_px_sq = dist_squared_to_projected_aabb(
+ &neasrest_precalc, bb->vec[0], bb->vec[6], dummy);
+
+ if (bb_dist_px_sq > dist_px_sq) {
+ return retval;
+ }
}
}
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
for (Nurb *nu = (use_obedit ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) {
for (int u = 0; u < nu->pntsu; u++) {
- switch (snapdata->snap_to) {
- case SCE_SNAP_MODE_VERTEX:
- {
- if (use_obedit) {
+ if (snapdata->snap_to == SCE_SNAP_MODE_VERTEX) {
+ if (use_obedit) {
+ if (nu->bezt) {
+ /* don't snap to selected (moving) or hidden */
+ if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
+ break;
+ }
+ retval |= test_projected_vert_dist(
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
+ is_persp, nu->bezt[u].vec[1], &dist_px_sq,
+ r_loc);
+ /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
+ if (!(nu->bezt[u].f1 & SELECT) &&
+ !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT))
+ {
+ retval |= test_projected_vert_dist(
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
+ is_persp, nu->bezt[u].vec[0], &dist_px_sq,
+ r_loc);
+ }
+ if (!(nu->bezt[u].f3 & SELECT) &&
+ !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
+ {
+ retval |= test_projected_vert_dist(
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
+ is_persp, nu->bezt[u].vec[2], &dist_px_sq,
+ r_loc);
+ }
+ }
+ else {
+ /* don't snap to selected (moving) or hidden */
+ if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
+ break;
+ }
+ retval |= test_projected_vert_dist(
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
+ is_persp, nu->bp[u].vec, &dist_px_sq,
+ r_loc);
+ }
+ }
+ else {
+ /* curve is not visible outside editmode if nurb length less than two */
+ if (nu->pntsu > 1) {
if (nu->bezt) {
- /* don't snap to selected (moving) or hidden */
- if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) {
- break;
- }
retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
is_persp, nu->bezt[u].vec[1], &dist_px_sq,
r_loc);
- /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */
- if (!(nu->bezt[u].f1 & SELECT) &&
- !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT))
- {
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- is_persp, nu->bezt[u].vec[0], &dist_px_sq,
- r_loc);
- }
- if (!(nu->bezt[u].f3 & SELECT) &&
- !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT))
- {
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- is_persp, nu->bezt[u].vec[2], &dist_px_sq,
- r_loc);
- }
}
else {
- /* don't snap to selected (moving) or hidden */
- if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) {
- break;
- }
retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
is_persp, nu->bp[u].vec, &dist_px_sq,
r_loc);
}
}
- else {
- /* curve is not visible outside editmode if nurb length less than two */
- if (nu->pntsu > 1) {
- if (nu->bezt) {
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- is_persp, nu->bezt[u].vec[1], &dist_px_sq,
- r_loc);
- }
- else {
- retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
- is_persp, nu->bp[u].vec, &dist_px_sq,
- r_loc);
- }
- }
- }
- break;
}
}
}
@@ -1279,7 +1430,10 @@ static bool snapCurve(
if (retval) {
*dist_px = sqrtf(dist_px_sq);
mul_m4_v3(obmat, r_loc);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ if (r_index) {
+ /* Does not support index yet. */
+ *r_index = -1;
+ }
return true;
}
return false;
@@ -1290,9 +1444,9 @@ static bool snapEmpty(
SnapData *snapdata,
Object *ob, float obmat[4][4],
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float *UNUSED(r_no))
+ float r_loc[3], float *UNUSED(r_no), int *r_index)
{
bool retval = false;
@@ -1308,32 +1462,46 @@ static bool snapEmpty(
dist_squared_to_projected_aabb_precalc(
&neasrest_precalc, snapdata->pmat, snapdata->win_size, snapdata->mval);
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
bool is_persp = snapdata->view_proj == VIEW_PROJ_PERSP;
float dist_px_sq = SQUARE(*dist_px);
float co[3];
copy_v3_v3(co, obmat[3]);
if (test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
is_persp, co, &dist_px_sq, r_loc))
{
*dist_px = sqrtf(dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
retval = true;
}
break;
}
}
- return retval;
+ if (retval) {
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
+ return true;
+ }
+
+ return false;
}
static bool snapCamera(
const SnapObjectContext *sctx, SnapData *snapdata,
Object *object, float obmat[4][4],
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float *UNUSED(r_no))
+ float r_loc[3], float *UNUSED(r_no), int *r_index)
{
Scene *scene = sctx->scene;
@@ -1352,6 +1520,12 @@ static bool snapCamera(
return retval;
}
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
tracking = &clip->tracking;
BKE_tracking_get_camera_object_matrix(scene, object, orig_camera_mat);
@@ -1402,7 +1576,8 @@ static bool snapCamera(
mul_m4_v3(vertex_obmat, bundle_pos);
retval |= test_projected_vert_dist(
- &neasrest_precalc, snapdata->depth_range,
+ &neasrest_precalc,
+ clip_planes_local, snapdata->clip_plane_len,
is_persp, bundle_pos, &dist_px_sq, r_loc);
}
}
@@ -1413,7 +1588,10 @@ static bool snapCamera(
if (retval) {
*dist_px = sqrtf(dist_px_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ if (r_index) {
+ /* Does not support index. */
+ *r_index = -1;
+ }
return true;
}
return false;
@@ -1423,9 +1601,9 @@ static bool snapMesh(
SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, Mesh *me, float obmat[4][4],
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float r_no[3])
+ float r_loc[3], float r_no[3], int *r_index)
{
bool retval = false;
@@ -1553,15 +1731,8 @@ static bool snapMesh(
}
}
- /* Warning: the depth_max is currently being used only in perspective view.
- * It is not correct to limit the maximum depth for elements obtained with nearest
- * since this limitation depends on the normal and the size of the occlusion face.
- * And more... ray_depth is being confused with Z-depth here... (varies only the precision) */
- const float ray_depth_max_global = *ray_depth + snapdata->depth_range[0];
-
Nearest2dUserData neasrest2d = {
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .depth_range = {snapdata->depth_range[0], ray_depth_max_global},
.snap_to = snapdata->snap_to,
.userdata = treedata,
.get_vert_co = (Nearest2DGetVertCoCallback)cb_mvert_co_get,
@@ -1576,42 +1747,53 @@ static bool snapMesh(
.dist_sq = dist_px_sq,
};
+ float tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
+ transpose_m4_m4(tobmat, obmat);
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
if (bvhtree[1]) {
/* snap to loose verts */
BLI_bvhtree_find_nearest_projected(
bvhtree[1], lpmat, snapdata->win_size, snapdata->mval,
- NULL, 0, &nearest, cb_walk_leaf_snap_vert, &neasrest2d);
+ clip_planes_local, snapdata->clip_plane_len,
+ &nearest, cb_walk_leaf_snap_vert, &neasrest2d);
}
if (bvhtree[0]) {
/* snap to loose edges */
BLI_bvhtree_find_nearest_projected(
bvhtree[0], lpmat, snapdata->win_size, snapdata->mval,
- NULL, 0, &nearest, cb_walk_leaf_snap_edge, &neasrest2d);
+ clip_planes_local, snapdata->clip_plane_len,
+ &nearest, cb_walk_leaf_snap_edge, &neasrest2d);
}
if (treedata->tree) {
/* snap to looptris */
BLI_bvhtree_find_nearest_projected(
treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
- NULL, 0, &nearest, cb_walk_leaf_snap_tri, &neasrest2d);
+ clip_planes_local, snapdata->clip_plane_len,
+ &nearest, cb_walk_leaf_snap_tri, &neasrest2d);
}
if (nearest.index != -1) {
- float imat[4][4];
- float timat[3][3]; /* transpose inverse matrix for normals */
- invert_m4_m4(imat, obmat);
- transpose_m3_m4(timat, imat);
+ *dist_px = sqrtf(nearest.dist_sq);
copy_v3_v3(r_loc, nearest.co);
mul_m4_v3(obmat, r_loc);
+
if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
copy_v3_v3(r_no, nearest.no);
- mul_m3_v3(timat, r_no);
+ mul_transposed_mat3_m4_v3(obmat, r_no);
normalize_v3(r_no);
}
- *dist_px = sqrtf(nearest.dist_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ if (r_index) {
+ *r_index = nearest.index;
+ }
retval = true;
}
@@ -1623,9 +1805,9 @@ static bool snapEditMesh(
SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, BMEditMesh *em, float obmat[4][4],
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float r_no[3])
+ float r_loc[3], float r_no[3], int *r_index)
{
bool retval = false;
@@ -1713,7 +1895,6 @@ static bool snapEditMesh(
Nearest2dUserData neasrest2d = {
.is_persp = snapdata->view_proj == VIEW_PROJ_PERSP,
- .depth_range = {snapdata->depth_range[0], *ray_depth + snapdata->depth_range[0]},
.snap_to = snapdata->snap_to,
.userdata = treedata->em,
.get_vert_co = (Nearest2DGetVertCoCallback)cb_bvert_co_get,
@@ -1736,27 +1917,35 @@ static bool snapEditMesh(
BM_mesh_elem_table_ensure(em->bm, BM_EDGE | BM_VERT);
}
- float lpmat[4][4];
+ float lpmat[4][4], tobmat[4][4], clip_planes_local[MAX_CLIPPLANE_LEN][4];
mul_m4_m4m4(lpmat, snapdata->pmat, obmat);
+ transpose_m4_m4(tobmat, obmat);
+
+ for (int i = snapdata->clip_plane_len; i--;) {
+ mul_v4_m4v4(clip_planes_local[i], tobmat, snapdata->clip_plane[i]);
+ }
+
BLI_bvhtree_find_nearest_projected(
treedata->tree, lpmat, snapdata->win_size, snapdata->mval,
- NULL, 0, &nearest, cb_walk_leaf, &neasrest2d);
+ clip_planes_local, snapdata->clip_plane_len,
+ &nearest, cb_walk_leaf, &neasrest2d);
if (nearest.index != -1) {
- float imat[4][4];
- float timat[3][3]; /* transpose inverse matrix for normals */
- invert_m4_m4(imat, obmat);
- transpose_m3_m4(timat, imat);
+ *dist_px = sqrtf(nearest.dist_sq);
copy_v3_v3(r_loc, nearest.co);
mul_m4_v3(obmat, r_loc);
if (r_no) {
+ float imat[4][4];
+ invert_m4_m4(imat, obmat);
+
copy_v3_v3(r_no, nearest.no);
- mul_m3_v3(timat, r_no);
+ mul_transposed_mat3_m4_v3(obmat, r_no);
normalize_v3(r_no);
}
- *dist_px = sqrtf(nearest.dist_sq);
- *ray_depth = depth_get(r_loc, snapdata->ray_start, snapdata->ray_dir);
+ if (r_index) {
+ *r_index = nearest.index;
+ }
retval = true;
}
@@ -1773,9 +1962,9 @@ static bool snapObject(
SnapObjectContext *sctx, SnapData *snapdata,
Object *ob, float obmat[4][4], bool use_obedit,
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float r_no[3],
+ float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
bool retval = false;
@@ -1786,45 +1975,45 @@ static bool snapObject(
BMEditMesh *em = BKE_editmesh_from_object(ob);
retval = snapEditMesh(
sctx, snapdata, ob, em, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
+ dist_px,
+ r_loc, r_no, r_index);
}
else {
retval = snapMesh(
sctx, snapdata, ob, ob->data, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
+ dist_px,
+ r_loc, r_no, r_index);
}
break;
case OB_ARMATURE:
retval = snapArmature(
snapdata,
- ob, ob->data, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
+ ob, obmat, use_obedit,
+ dist_px,
+ r_loc, r_no, r_index);
break;
case OB_CURVE:
retval = snapCurve(
snapdata,
ob, obmat, use_obedit,
- ray_depth, dist_px,
- r_loc, r_no);
+ dist_px,
+ r_loc, r_no, r_index);
break;
case OB_EMPTY:
retval = snapEmpty(
snapdata, ob, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
+ dist_px,
+ r_loc, r_no, r_index);
break;
case OB_CAMERA:
retval = snapCamera(
sctx, snapdata, ob, obmat,
- ray_depth, dist_px,
- r_loc, r_no);
+ dist_px,
+ r_loc, r_no, r_index);
break;
}
@@ -1845,11 +2034,11 @@ static bool snapObject(
struct SnapObjUserData {
SnapData *snapdata;
/* read/write args */
- float *ray_depth;
float *dist_px;
/* return args */
float *r_loc;
float *r_no;
+ int *r_index;
Object **r_ob;
float (*r_obmat)[4];
bool ret;
@@ -1862,9 +2051,9 @@ static void sanp_obj_cb(SnapObjectContext *sctx, bool is_obedit, Object *ob, flo
sctx, dt->snapdata,
ob, obmat, is_obedit,
/* read/write args */
- dt->ray_depth, dt->dist_px,
+ dt->dist_px,
/* return args */
- dt->r_loc, dt->r_no,
+ dt->r_loc, dt->r_no, dt->r_index,
dt->r_ob, dt->r_obmat);
}
@@ -1901,18 +2090,18 @@ static bool snapObjectsRay(
SnapObjectContext *sctx, SnapData *snapdata,
const struct SnapObjectParams *params,
/* read/write args */
- float *ray_depth, float *dist_px,
+ float *dist_px,
/* return args */
- float r_loc[3], float r_no[3],
+ float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
struct SnapObjUserData data = {
.snapdata = snapdata,
- .ray_depth = ray_depth,
.dist_px = dist_px,
.r_loc = r_loc,
.r_no = r_no,
.r_ob = r_ob,
+ .r_index = r_index,
.r_obmat = r_obmat,
.ret = false,
};
@@ -2111,53 +2300,25 @@ static bool transform_snap_context_project_view3d_mixed_impl(
const float mval[2], float *dist_px,
float r_co[3], float r_no[3])
{
- float ray_depth = BVH_RAYCAST_DIST_MAX;
- bool is_hit = false;
-
const int elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE};
BLI_assert(snap_to_flag != 0);
BLI_assert((snap_to_flag & ~(1 | 2 | 4)) == 0);
- if (params->use_occlusion_test) {
- const float dist_px_orig = dist_px ? *dist_px : 0;
- for (int i = 2; i >= 0; i--) {
- if (snap_to_flag & (1 << i)) {
- if (i == 0) {
- BLI_assert(dist_px != NULL);
- *dist_px = dist_px_orig;
- }
- if (ED_transform_snap_object_project_view3d(
- sctx,
- elem_type[i], params,
- mval, dist_px, &ray_depth,
- r_co, r_no))
- {
- /* 0.01 is a random but small value to prioritizing
- * the first elements of the loop */
- ray_depth += 0.01f;
- is_hit = true;
- }
- }
- }
- }
- else {
- for (int i = 0; i < 3; i++) {
- if (snap_to_flag & (1 << i)) {
- if (ED_transform_snap_object_project_view3d(
- sctx,
- elem_type[i], params,
- mval, dist_px, &ray_depth,
- r_co, r_no))
- {
- is_hit = true;
- break;
- }
+ for (int i = 0; i < 3; i++) {
+ if (snap_to_flag & (1 << i)) {
+ if (ED_transform_snap_object_project_view3d(
+ sctx,
+ elem_type[i], params,
+ mval, dist_px,
+ r_co, r_no))
+ {
+ return true;
}
}
}
- return is_hit;
+ return false;
}
/**
@@ -2191,55 +2352,98 @@ bool ED_transform_snap_object_project_view3d_ex(
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2], float *dist_px,
- float *ray_depth,
float r_loc[3], float r_no[3], int *r_index,
Object **r_ob, float r_obmat[4][4])
{
- const ARegion *ar = sctx->v3d_data.ar;
- const RegionView3D *rv3d = ar->regiondata;
+ float loc[3], no[3], obmat[4][4];
+ Object *ob = NULL;
- float ray_origin[3], ray_end[3], ray_start[3], ray_normal[3], depth_range[2];
-
- ED_view3d_win_to_origin(ar, mval, ray_origin);
- ED_view3d_win_to_vector(ar, mval, ray_normal);
+ int index_fallback;
+ if (r_index == NULL) {
+ r_index = &index_fallback;
+ }
- ED_view3d_clip_range_get(
- sctx->depsgraph,
- sctx->v3d_data.v3d, sctx->v3d_data.ar->regiondata,
- &depth_range[0], &depth_range[1], false);
+ bool has_hit = false, retval = false;
+ const ARegion *ar = sctx->v3d_data.ar;
+ const RegionView3D *rv3d = ar->regiondata;
- madd_v3_v3v3fl(ray_start, ray_origin, ray_normal, depth_range[0]);
- madd_v3_v3v3fl(ray_end, ray_origin, ray_normal, depth_range[1]);
+ if (snap_to == SCE_SNAP_MODE_FACE || params->use_occlusion_test) {
+ float ray_start[3], ray_normal[3];
- if (!ED_view3d_clip_segment(rv3d, ray_start, ray_end)) {
- return false;
- }
+ if (!ED_view3d_win_to_ray_ex(
+ sctx->depsgraph,
+ sctx->v3d_data.ar, sctx->v3d_data.v3d,
+ mval, NULL, ray_normal, ray_start, true))
+ {
+ return false;
+ }
- float ray_depth_fallback;
- if (ray_depth == NULL) {
- ray_depth_fallback = BVH_RAYCAST_DIST_MAX;
- ray_depth = &ray_depth_fallback;
- }
+ float dummy_ray_depth = BVH_RAYCAST_DIST_MAX;
- if (snap_to == SCE_SNAP_MODE_FACE) {
- return raycastObjects(
+ has_hit = raycastObjects(
sctx, params,
ray_start, ray_normal,
- ray_depth, r_loc, r_no, r_index, r_ob, r_obmat, NULL);
+ &dummy_ray_depth, loc, no,
+ r_index, &ob, obmat, NULL);
+
+ retval = has_hit && (snap_to == SCE_SNAP_MODE_FACE);
}
- else {
+
+ if (ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)) {
SnapData snapdata;
- const enum eViewProj view_proj = rv3d->is_persp ?
- VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
- snap_data_set(
- &snapdata, ar, snap_to, view_proj, mval,
- ray_start, ray_normal, depth_range);
+ copy_m4_m4(snapdata.pmat, rv3d->persmat);
+ snapdata.win_size[0] = ar->winx;
+ snapdata.win_size[1] = ar->winy;
+ copy_v2_v2(snapdata.mval, mval);
+ snapdata.snap_to = snap_to;
+ snapdata.view_proj = rv3d->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO;
+
+ planes_from_projmat(
+ snapdata.pmat,
+ NULL, NULL, NULL, NULL,
+ snapdata.clip_plane[0], snapdata.clip_plane[1]);
+
+ snapdata.clip_plane_len = 2;
+
+ if (has_hit) {
+ /* Compute the new clip_pane but do not add it yet. */
+ float new_clipplane[4];
+ plane_from_point_normal_v3(new_clipplane, loc, no);
+
+ /* Try to snap only to the polygon. */
+ retval |= snapMeshPolygon(
+ sctx, &snapdata, ob, obmat,
+ dist_px, loc, no, r_index);
+
+ /* Add the new clip plane to the beginning of the list. */
+ for (int i = snapdata.clip_plane_len; i != 0; i--) {
+ copy_v4_v4(snapdata.clip_plane[i], snapdata.clip_plane[i - 1]);
+ }
+ copy_v4_v4(snapdata.clip_plane[0], new_clipplane);
+ snapdata.clip_plane_len++;
+ }
- return snapObjectsRay(
+ retval |= snapObjectsRay(
sctx, &snapdata, params,
- ray_depth, dist_px, r_loc, r_no, r_ob, r_obmat);
+ dist_px, loc, no, r_index, &ob, obmat);
+ }
+
+ if (retval) {
+ copy_v3_v3(r_loc, loc);
+ if (r_no) {
+ copy_v3_v3(r_no, no);
+ }
+ if (r_ob) {
+ *r_ob = ob;
+ }
+ if (r_obmat) {
+ copy_m4_m4(r_obmat, obmat);
+ }
+ return true;
}
+
+ return false;
}
bool ED_transform_snap_object_project_view3d(
@@ -2247,7 +2451,6 @@ bool ED_transform_snap_object_project_view3d(
const unsigned short snap_to,
const struct SnapObjectParams *params,
const float mval[2], float *dist_px,
- float *ray_depth,
float r_loc[3], float r_no[3])
{
return ED_transform_snap_object_project_view3d_ex(
@@ -2255,7 +2458,6 @@ bool ED_transform_snap_object_project_view3d(
snap_to,
params,
mval, dist_px,
- ray_depth,
r_loc, r_no, NULL,
NULL, NULL);
}