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/space_view3d')
-rw-r--r--source/blender/editors/space_view3d/drawobject.c231
-rw-r--r--source/blender/editors/space_view3d/space_view3d.c114
-rw-r--r--source/blender/editors/space_view3d/view3d_draw.c174
-rw-r--r--source/blender/editors/space_view3d/view3d_draw_legacy.c161
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_camera.c6
-rw-r--r--source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c17
-rw-r--r--source/blender/editors/space_view3d/view3d_intern.h7
-rw-r--r--source/blender/editors/space_view3d/view3d_select.c608
-rw-r--r--source/blender/editors/space_view3d/view3d_utils.c15
-rw-r--r--source/blender/editors/space_view3d/view3d_view.c2
10 files changed, 627 insertions, 708 deletions
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index 638c77fc3cb..cc76c151a29 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -41,7 +41,6 @@
#include "GPU_batch.h"
#include "GPU_matrix.h"
#include "GPU_state.h"
-#include "GPU_framebuffer.h"
#include "ED_mesh.h"
@@ -51,8 +50,6 @@
#include "view3d_intern.h" /* bad level include */
-#include "../../draw/intern/draw_cache_impl.h" /* bad level include (temporary) */
-
int view3d_effective_drawtype(const struct View3D *v3d)
{
if (v3d->shading.type == OB_RENDER) {
@@ -61,24 +58,6 @@ int view3d_effective_drawtype(const struct View3D *v3d)
return v3d->shading.type;
}
-static bool check_ob_drawface_dot(Scene *sce, View3D *vd, char dt)
-{
- if ((sce->toolsettings->selectmode & SCE_SELECT_FACE) == 0) {
- return false;
- }
-
- if (G.f & G_FLAG_BACKBUFSEL) {
- return false;
- }
-
- /* if its drawing textures with zbuf sel, then don't draw dots */
- if (dt == OB_TEXTURE && vd->shading.type == OB_TEXTURE) {
- return false;
- }
-
- return true;
-}
-
/* OpenGL Circle Drawing - Tables for Optimized Drawing Speed */
/* 32 values of sin function (still same result!) */
#define CIRCLE_RESOL 32
@@ -138,216 +117,6 @@ bool view3d_camera_border_hack_test = false;
/* ***************** BACKBUF SEL (BBS) ********* */
-/** See #DRW_shgroup_world_clip_planes_from_rv3d, same function for draw manager. */
-static void bbs_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4])
-{
- GPU_batch_uniform_4fv_array(batch, "WorldClipPlanes", 6, world_clip_planes[0]);
-}
-
-static void bbs_mesh_verts(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
-{
- GPU_point_size(UI_GetThemeValuef(TH_VERTEX_SIZE));
-
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-}
-
-static void bbs_mesh_wire(GPUBatch *batch, int offset, const float world_clip_planes[6][4])
-{
- GPU_line_width(1.0f);
- glProvokingVertex(GL_FIRST_VERTEX_CONVENTION);
-
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", offset);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-
- glProvokingVertex(GL_LAST_VERTEX_CONVENTION);
-}
-
-/* two options, facecolors or black */
-static void bbs_mesh_face(GPUBatch *batch,
- const bool use_select,
- const float world_clip_planes[6][4])
-{
- if (use_select) {
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", 1);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
- }
- else {
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_UNIFORM_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "id", 0);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
- }
-}
-
-static void bbs_mesh_face_dot(GPUBatch *batch, const float world_clip_planes[6][4])
-{
- const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
- GPU_SHADER_CFG_DEFAULT;
- GPU_batch_program_set_builtin_with_config(batch, GPU_SHADER_3D_FLAT_SELECT_ID, sh_cfg);
- GPU_batch_uniform_1ui(batch, "offset", 1);
- if (world_clip_planes != NULL) {
- bbs_world_clip_planes_from_rv3d(batch, world_clip_planes);
- }
- GPU_batch_draw(batch);
-}
-
-static void bbs_mesh_solid_verts(Depsgraph *UNUSED(depsgraph),
- Scene *UNUSED(scene),
- Object *ob,
- const float world_clip_planes[6][4])
-{
- Mesh *me = ob->data;
-
- GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
-
- /* Only draw faces to mask out verts, we don't want their selection ID's. */
- bbs_mesh_face(geom_faces, false, world_clip_planes);
- bbs_mesh_verts(geom_verts, 1, world_clip_planes);
-
- bm_vertoffs = me->totvert + 1;
-}
-
-static void bbs_mesh_solid_faces(Scene *UNUSED(scene),
- Object *ob,
- const float world_clip_planes[6][4])
-{
- Mesh *me = ob->data;
- Mesh *me_orig = DEG_get_original_object(ob)->data;
-
- const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
- GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, use_hide);
-
- bbs_mesh_face(geom_faces, true, world_clip_planes);
-}
-
-void draw_object_select_id(Depsgraph *depsgraph,
- Scene *scene,
- View3D *v3d,
- RegionView3D *rv3d,
- Object *ob,
- short select_mode)
-{
- ToolSettings *ts = scene->toolsettings;
- if (select_mode == -1) {
- select_mode = ts->selectmode;
- }
-
- GPU_matrix_mul(ob->obmat);
- GPU_depth_test(true);
-
- const float(*world_clip_planes)[4] = NULL;
- if (rv3d->rflag & RV3D_CLIPPING) {
- ED_view3d_clipping_local(rv3d, ob->obmat);
- world_clip_planes = rv3d->clip_local;
- }
-
- switch (ob->type) {
- case OB_MESH:
- if (ob->mode & OB_MODE_EDIT) {
- Mesh *me = ob->data;
- BMEditMesh *em = me->edit_mesh;
- const bool draw_facedot = check_ob_drawface_dot(scene, v3d, ob->dt);
- const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
-
- BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
-
- GPUBatch *geom_faces, *geom_edges, *geom_verts, *geom_facedots;
- geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me);
- if (select_mode & SCE_SELECT_EDGE) {
- geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(me);
- }
- if (select_mode & SCE_SELECT_VERTEX) {
- geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me);
- }
- if (draw_facedot) {
- geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(me);
- }
- DRW_mesh_batch_cache_create_requested(ob, me, NULL, false, true);
-
- bbs_mesh_face(geom_faces, use_faceselect, world_clip_planes);
-
- if (use_faceselect && draw_facedot) {
- bbs_mesh_face_dot(geom_facedots, world_clip_planes);
- }
-
- if (select_mode & SCE_SELECT_FACE) {
- bm_solidoffs = 1 + em->bm->totface;
- }
- else {
- bm_solidoffs = 1;
- }
-
- ED_view3d_polygon_offset(rv3d, 1.0);
-
- /* we draw edges if edge select mode */
- if (select_mode & SCE_SELECT_EDGE) {
- bbs_mesh_wire(geom_edges, bm_solidoffs, world_clip_planes);
- bm_wireoffs = bm_solidoffs + em->bm->totedge;
- }
- else {
- /* `bm_vertoffs` is calculated from `bm_wireoffs`. (otherwise see T53512) */
- bm_wireoffs = bm_solidoffs;
- }
-
- ED_view3d_polygon_offset(rv3d, 1.1);
-
- /* we draw verts if vert select mode. */
- if (select_mode & SCE_SELECT_VERTEX) {
- bbs_mesh_verts(geom_verts, bm_wireoffs, world_clip_planes);
- bm_vertoffs = bm_wireoffs + em->bm->totvert;
- }
- else {
- bm_vertoffs = bm_wireoffs;
- }
-
- ED_view3d_polygon_offset(rv3d, 0.0);
- }
- else {
- Mesh *me = DEG_get_original_object(ob)->data;
- if ((me->editflag & ME_EDIT_PAINT_VERT_SEL) &&
- /* currently vertex select supports weight paint and vertex paint*/
- ((ob->mode & OB_MODE_WEIGHT_PAINT) || (ob->mode & OB_MODE_VERTEX_PAINT))) {
- bbs_mesh_solid_verts(depsgraph, scene, ob, world_clip_planes);
- }
- else {
- bbs_mesh_solid_faces(scene, ob, world_clip_planes);
- }
- }
- break;
- case OB_CURVE:
- case OB_SURF:
- break;
- }
-
- GPU_matrix_set(rv3d->viewmat);
-}
-
void ED_draw_object_facemap(Depsgraph *depsgraph,
Object *ob,
const float col[4],
diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c
index 9ee7bb3066d..c1891865d6d 100644
--- a/source/blender/editors/space_view3d/space_view3d.c
+++ b/source/blender/editors/space_view3d/space_view3d.c
@@ -1131,6 +1131,9 @@ static void view3d_header_region_listener(wmWindow *UNUSED(win),
ED_region_tag_redraw(ar);
}
break;
+ case NC_BRUSH:
+ ED_region_tag_redraw(ar);
+ break;
}
/* From topbar, which ones are needed? split per header? */
@@ -1200,9 +1203,106 @@ static void view3d_buttons_region_init(wmWindowManager *wm, ARegion *ar)
WM_event_add_keymap_handler(&ar->handlers, keymap);
}
-static void view3d_buttons_region_draw(const bContext *C, ARegion *ar)
+void ED_view3d_buttons_region_layout_ex(const bContext *C,
+ ARegion *ar,
+ const char *category_override)
{
- ED_region_panels_ex(C, ar, (const char *[]){CTX_data_mode_string(C), NULL}, -1, true);
+ const enum eContextObjectMode mode = CTX_data_mode_enum(C);
+
+ const char *contexts_base[4] = {NULL};
+ contexts_base[0] = CTX_data_mode_string(C);
+
+ const char **contexts = &contexts_base[1];
+
+ switch (mode) {
+ case CTX_MODE_EDIT_MESH:
+ ARRAY_SET_ITEMS(contexts, ".mesh_edit");
+ break;
+ case CTX_MODE_EDIT_CURVE:
+ ARRAY_SET_ITEMS(contexts, ".curve_edit");
+ break;
+ case CTX_MODE_EDIT_SURFACE:
+ ARRAY_SET_ITEMS(contexts, ".curve_edit");
+ break;
+ case CTX_MODE_EDIT_TEXT:
+ ARRAY_SET_ITEMS(contexts, ".text_edit");
+ break;
+ case CTX_MODE_EDIT_ARMATURE:
+ ARRAY_SET_ITEMS(contexts, ".armature_edit");
+ break;
+ case CTX_MODE_EDIT_METABALL:
+ ARRAY_SET_ITEMS(contexts, ".mball_edit");
+ break;
+ case CTX_MODE_EDIT_LATTICE:
+ ARRAY_SET_ITEMS(contexts, ".lattice_edit");
+ break;
+ case CTX_MODE_POSE:
+ ARRAY_SET_ITEMS(contexts, ".posemode");
+ break;
+ case CTX_MODE_SCULPT:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".sculpt_mode");
+ break;
+ case CTX_MODE_PAINT_WEIGHT:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".weightpaint");
+ break;
+ case CTX_MODE_PAINT_VERTEX:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".vertexpaint");
+ break;
+ case CTX_MODE_PAINT_TEXTURE:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".imagepaint");
+ break;
+ case CTX_MODE_PARTICLE:
+ ARRAY_SET_ITEMS(contexts, ".paint_common", ".particlemode");
+ break;
+ case CTX_MODE_OBJECT:
+ ARRAY_SET_ITEMS(contexts, ".objectmode");
+ break;
+ case CTX_MODE_PAINT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
+ break;
+ case CTX_MODE_SCULPT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
+ break;
+ case CTX_MODE_WEIGHT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
+ break;
+ default:
+ break;
+ }
+
+ switch (mode) {
+ case CTX_MODE_PAINT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_paint");
+ break;
+ case CTX_MODE_SCULPT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_sculpt");
+ break;
+ case CTX_MODE_WEIGHT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_weight");
+ break;
+ case CTX_MODE_EDIT_GPENCIL:
+ ARRAY_SET_ITEMS(contexts, ".greasepencil_edit");
+ break;
+ default:
+ break;
+ }
+
+ ListBase *paneltypes = &ar->type->paneltypes;
+
+ /* Allow drawing 3D view toolbar from non 3D view space type. */
+ if (category_override != NULL) {
+ SpaceType *st = BKE_spacetype_from_id(SPACE_VIEW3D);
+ ARegionType *art = BKE_regiontype_from_id(st, RGN_TYPE_UI);
+ paneltypes = &art->paneltypes;
+ }
+
+ const bool vertical = true;
+ ED_region_panels_layout_ex(C, ar, paneltypes, contexts_base, -1, vertical, category_override);
+}
+
+static void view3d_buttons_region_layout(const bContext *C, ARegion *ar)
+{
+ ED_view3d_buttons_region_layout_ex(C, ar, NULL);
}
static void view3d_buttons_region_listener(wmWindow *UNUSED(win),
@@ -1507,11 +1607,13 @@ void ED_spacetype_view3d(void)
/* regions: listview/buttons */
art = MEM_callocN(sizeof(ARegionType), "spacetype view3d buttons region");
art->regionid = RGN_TYPE_UI;
- art->prefsizex = 180; /* XXX */
+ art->prefsizex = UI_SIDEBAR_PANEL_WIDTH;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
art->listener = view3d_buttons_region_listener;
+ art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_ui;
art->init = view3d_buttons_region_init;
- art->draw = view3d_buttons_region_draw;
+ art->layout = view3d_buttons_region_layout;
+ art->draw = ED_region_panels_draw;
BLI_addhead(&st->regiontypes, art);
view3d_buttons_register(art);
@@ -1535,9 +1637,9 @@ void ED_spacetype_view3d(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
art->listener = view3d_header_region_listener;
+ art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_header;
art->init = view3d_header_region_init;
art->draw = view3d_header_region_draw;
- art->message_subscribe = view3d_header_region_message_subscribe;
BLI_addhead(&st->regiontypes, art);
/* regions: header */
@@ -1546,9 +1648,9 @@ void ED_spacetype_view3d(void)
art->prefsizey = HEADERY;
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_VIEW2D | ED_KEYMAP_FRAMES | ED_KEYMAP_HEADER;
art->listener = view3d_header_region_listener;
+ art->message_subscribe = view3d_header_region_message_subscribe;
art->init = view3d_header_region_init;
art->draw = view3d_header_region_draw;
- art->message_subscribe = ED_area_do_mgs_subscribe_for_tool_header;
BLI_addhead(&st->regiontypes, art);
/* regions: hud */
diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c
index 8c5f1c16438..2ce67bfbe4c 100644
--- a/source/blender/editors/space_view3d/view3d_draw.c
+++ b/source/blender/editors/space_view3d/view3d_draw.c
@@ -105,7 +105,8 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
ARegion *ar,
float viewmat[4][4],
float winmat[4][4],
- const rcti *rect)
+ const rcti *rect,
+ bool offscreen)
{
RegionView3D *rv3d = ar->regiondata;
@@ -138,7 +139,7 @@ void ED_view3d_update_viewmat(Depsgraph *depsgraph,
/* calculate GLSL view dependent values */
/* store window coordinates scaling/offset */
- if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
+ if (!offscreen && rv3d->persp == RV3D_CAMOB && v3d->camera) {
rctf cameraborder;
ED_view3d_calc_camera_border(scene, depsgraph, ar, v3d, rv3d, &cameraborder, false);
rv3d->viewcamtexcofac[0] = (float)ar->winx / BLI_rctf_size_x(&cameraborder);
@@ -184,7 +185,22 @@ static void view3d_main_region_setup_view(Depsgraph *depsgraph,
{
RegionView3D *rv3d = ar->regiondata;
- ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, rect, false);
+
+ /* set for opengl */
+ GPU_matrix_projection_set(rv3d->winmat);
+ GPU_matrix_set(rv3d->viewmat);
+}
+
+static void view3d_main_region_setup_offscreen(Depsgraph *depsgraph,
+ Scene *scene,
+ View3D *v3d,
+ ARegion *ar,
+ float viewmat[4][4],
+ float winmat[4][4])
+{
+ RegionView3D *rv3d = ar->regiondata;
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, viewmat, winmat, NULL, true);
/* set for opengl */
GPU_matrix_projection_set(rv3d->winmat);
@@ -1480,14 +1496,14 @@ static void view3d_stereo3d_setup_offscreen(Depsgraph *depsgraph,
const bool is_left = STREQ(viewname, STEREO_LEFT_NAME);
BKE_camera_multiview_view_matrix(&scene->r, v3d->camera, is_left, viewmat);
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
+ view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat);
}
else { /* SCE_VIEWS_FORMAT_MULTIVIEW */
float viewmat[4][4];
Object *camera = BKE_camera_multiview_render(scene, v3d->camera, viewname);
BKE_camera_multiview_view_matrix(&scene->r, camera, false, viewmat);
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
+ view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat);
}
}
@@ -1503,7 +1519,6 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
bool do_sky,
bool UNUSED(is_persp),
const char *viewname,
- GPUFXSettings *UNUSED(fx_settings),
const bool do_color_management,
GPUOffScreen *ofs,
GPUViewport *viewport)
@@ -1546,7 +1561,7 @@ void ED_view3d_draw_offscreen(Depsgraph *depsgraph,
view3d_stereo3d_setup_offscreen(depsgraph, scene, v3d, ar, winmat, viewname);
}
else {
- view3d_main_region_setup_view(depsgraph, scene, v3d, ar, viewmat, winmat, NULL);
+ view3d_main_region_setup_offscreen(depsgraph, scene, v3d, ar, viewmat, winmat);
}
/* main drawing call */
@@ -1580,7 +1595,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
int sizex,
int sizey,
uint flag,
- uint draw_flags,
int alpha_mode,
int samples,
const char *viewname,
@@ -1590,10 +1604,8 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
{
RegionView3D *rv3d = ar->regiondata;
const bool draw_sky = (alpha_mode == R_ADDSKY);
- const bool use_full_sample = (draw_flags & V3D_OFSDRAW_USE_FULL_SAMPLE);
/* view state */
- GPUFXSettings fx_settings = v3d->fx_settings;
bool is_ortho = false;
float winmat[4][4];
@@ -1613,7 +1625,7 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
if (own_ofs) {
/* bind */
- ofs = GPU_offscreen_create(sizex, sizey, use_full_sample ? 0 : samples, true, false, err_out);
+ ofs = GPU_offscreen_create(sizex, sizey, samples, true, false, err_out);
if (ofs == NULL) {
DRW_opengl_context_disable();
return NULL;
@@ -1640,8 +1652,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
BKE_camera_params_compute_viewplane(&params, sizex, sizey, scene->r.xasp, scene->r.yasp);
BKE_camera_params_compute_matrix(&params);
- BKE_camera_to_gpu_dof(camera, &fx_settings);
-
is_ortho = params.is_ortho;
copy_m4_m4(winmat, params.winmat);
}
@@ -1671,123 +1681,28 @@ ImBuf *ED_view3d_draw_offscreen_imbuf(Depsgraph *depsgraph,
}
}
- if ((samples && use_full_sample) == 0) {
- const bool do_color_management = (ibuf->rect_float == NULL);
- /* Single-pass render, common case */
- ED_view3d_draw_offscreen(depsgraph,
- scene,
- drawtype,
- v3d,
- ar,
- sizex,
- sizey,
- NULL,
- winmat,
- draw_sky,
- !is_ortho,
- viewname,
- &fx_settings,
- do_color_management,
- ofs,
- NULL);
-
- if (ibuf->rect_float) {
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
- }
- else if (ibuf->rect) {
- GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
- }
- }
- else {
- /* Multi-pass render, use accumulation buffer & jitter for 'full' oversampling.
- * Use because OpenGL may use a lower quality MSAA, and only over-sample edges. */
- static float jit_ofs[32][2];
- float winmat_jitter[4][4];
- float *rect_temp = (ibuf->rect_float) ?
- ibuf->rect_float :
- MEM_mallocN(sizex * sizey * sizeof(float[4]), "rect_temp");
- float *accum_buffer = MEM_mallocN(sizex * sizey * sizeof(float[4]), "accum_buffer");
- GPUViewport *viewport = GPU_viewport_create_from_offscreen(ofs);
-
- BLI_jitter_init(jit_ofs, samples);
-
- /* first sample buffer, also initializes 'rv3d->persmat' */
- ED_view3d_draw_offscreen(depsgraph,
- scene,
- drawtype,
- v3d,
- ar,
- sizex,
- sizey,
- NULL,
- winmat,
- draw_sky,
- !is_ortho,
- viewname,
- &fx_settings,
- false,
- ofs,
- viewport);
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, accum_buffer);
-
- /* skip the first sample */
- for (int j = 1; j < samples; j++) {
- copy_m4_m4(winmat_jitter, winmat);
- window_translate_m4(winmat_jitter,
- rv3d->persmat,
- (jit_ofs[j][0] * 2.0f) / sizex,
- (jit_ofs[j][1] * 2.0f) / sizey);
-
- ED_view3d_draw_offscreen(depsgraph,
- scene,
- drawtype,
- v3d,
- ar,
- sizex,
- sizey,
- NULL,
- winmat_jitter,
- draw_sky,
- !is_ortho,
- viewname,
- &fx_settings,
- false,
- ofs,
- viewport);
- GPU_offscreen_read_pixels(ofs, GL_FLOAT, rect_temp);
-
- uint i = sizex * sizey * 4;
- while (i--) {
- accum_buffer[i] += rect_temp[i];
- }
- }
-
- {
- /* don't free data owned by 'ofs' */
- GPU_viewport_clear_from_offscreen(viewport);
- GPU_viewport_free(viewport);
- }
-
- if (ibuf->rect_float == NULL) {
- MEM_freeN(rect_temp);
- }
-
- if (ibuf->rect_float) {
- float *rect_float = ibuf->rect_float;
- uint i = sizex * sizey * 4;
- while (i--) {
- rect_float[i] = accum_buffer[i] / samples;
- }
- }
- else {
- uchar *rect_ub = (uchar *)ibuf->rect;
- uint i = sizex * sizey * 4;
- while (i--) {
- rect_ub[i] = (uchar)(255.0f * accum_buffer[i] / samples);
- }
- }
+ const bool do_color_management = (ibuf->rect_float == NULL);
+ ED_view3d_draw_offscreen(depsgraph,
+ scene,
+ drawtype,
+ v3d,
+ ar,
+ sizex,
+ sizey,
+ NULL,
+ winmat,
+ draw_sky,
+ !is_ortho,
+ viewname,
+ do_color_management,
+ ofs,
+ NULL);
- MEM_freeN(accum_buffer);
+ if (ibuf->rect_float) {
+ GPU_offscreen_read_pixels(ofs, GL_FLOAT, ibuf->rect_float);
+ }
+ else if (ibuf->rect) {
+ GPU_offscreen_read_pixels(ofs, GL_UNSIGNED_BYTE, ibuf->rect);
}
/* unbind */
@@ -1896,7 +1811,6 @@ ImBuf *ED_view3d_draw_offscreen_imbuf_simple(Depsgraph *depsgraph,
width,
height,
flag,
- draw_flags,
alpha_mode,
samples,
viewname,
diff --git a/source/blender/editors/space_view3d/view3d_draw_legacy.c b/source/blender/editors/space_view3d/view3d_draw_legacy.c
index b0cee18f8e3..755852a2e18 100644
--- a/source/blender/editors/space_view3d/view3d_draw_legacy.c
+++ b/source/blender/editors/space_view3d/view3d_draw_legacy.c
@@ -77,6 +77,7 @@
#include "ED_armature.h"
#include "ED_keyframing.h"
#include "ED_gpencil.h"
+#include "ED_mesh.h"
#include "ED_screen.h"
#include "ED_space_api.h"
#include "ED_screen_types.h"
@@ -151,13 +152,11 @@ void ED_view3d_clipping_enable(void)
/* *********************** backdraw for selection *************** */
-static void validate_object_select_id(struct Depsgraph *depsgraph,
- Scene *scene,
- ARegion *ar,
- View3D *v3d,
- Object *obact,
- Object *obedit,
- short select_mode)
+/**
+ * \note Only use in object mode.
+ */
+static void validate_object_select_id(
+ struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d, Object *obact)
{
RegionView3D *rv3d = ar->regiondata;
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
@@ -177,9 +176,6 @@ static void validate_object_select_id(struct Depsgraph *depsgraph,
else if ((obact_eval && (obact_eval->mode & OB_MODE_PARTICLE_EDIT)) && !XRAY_ENABLED(v3d)) {
/* do nothing */
}
- else if ((obedit && (obedit->mode & OB_MODE_EDIT)) && !XRAY_FLAG_ENABLED(v3d)) {
- /* do nothing */
- }
else {
v3d->flag &= ~V3D_INVALID_BACKBUF;
return;
@@ -189,34 +185,25 @@ static void validate_object_select_id(struct Depsgraph *depsgraph,
return;
}
-#if 0
- if (test) {
- if (qtest()) {
- addafterqueue(ar->win, BACKBUFDRAW, 1);
- return;
- }
- }
-#endif
-
-#if 0 /* v3d->zbuf deprecated */
- if (v3d->shading.type > OB_WIRE) {
- v3d->zbuf = true;
- }
-#endif
-
- G.f |= G_FLAG_BACKBUFSEL;
-
if (obact_eval && ((obact_eval->base_flag & BASE_VISIBLE) != 0)) {
+ uint dummy_vert_ofs, dummy_edge_ofs, dummy_face_ofs;
DRW_framebuffer_select_id_setup(ar, true);
- draw_object_select_id(depsgraph, scene_eval, v3d, rv3d, obact_eval, select_mode);
+ DRW_draw_select_id_object(scene_eval,
+ rv3d,
+ obact_eval,
+ scene->toolsettings->selectmode,
+ false,
+ 1,
+ &dummy_vert_ofs,
+ &dummy_edge_ofs,
+ &dummy_face_ofs);
+
DRW_framebuffer_select_id_release(ar);
}
/* TODO: Create a flag in `DRW_manager` because the drawing is no longer
* made on the backbuffer in this case. */
v3d->flag &= ~V3D_INVALID_BACKBUF;
-
- G.f &= ~G_FLAG_BACKBUFSEL;
}
/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow.
@@ -241,21 +228,15 @@ static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void
GPU_framebuffer_free(tmp_fb);
}
-void ED_view3d_select_id_validate_with_select_mode(ViewContext *vc, short select_mode)
+void ED_view3d_select_id_validate(ViewContext *vc)
{
/* TODO: Create a flag in `DRW_manager` because the drawing is no longer
* made on the backbuffer in this case. */
if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
- validate_object_select_id(
- vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact, vc->obedit, select_mode);
+ validate_object_select_id(vc->depsgraph, vc->scene, vc->ar, vc->v3d, vc->obact);
}
}
-void ED_view3d_select_id_validate(ViewContext *vc)
-{
- ED_view3d_select_id_validate_with_select_mode(vc, -1);
-}
-
void ED_view3d_backbuf_depth_validate(ViewContext *vc)
{
if (vc->v3d->flag & V3D_INVALID_BACKBUF) {
@@ -271,10 +252,8 @@ void ED_view3d_backbuf_depth_validate(ViewContext *vc)
}
}
-uint *ED_view3d_select_id_read_rect(ViewContext *vc, const rcti *clip, uint *r_buf_len)
+uint *ED_view3d_select_id_read_rect(const rcti *clip, uint *r_buf_len)
{
- ED_view3d_select_id_validate(vc);
-
uint width = BLI_rcti_size_x(clip);
uint height = BLI_rcti_size_y(clip);
uint buf_len = width * height;
@@ -298,25 +277,8 @@ int ED_view3d_backbuf_sample_size_clamp(ARegion *ar, const float dist)
return (int)min_ff(ceilf(dist), (float)max_ii(ar->winx, ar->winx));
}
-/* samples a single pixel (copied from vpaint) */
-uint ED_view3d_select_id_sample(ViewContext *vc, int x, int y)
-{
- if (x >= vc->ar->winx || y >= vc->ar->winy) {
- return 0;
- }
-
- uint buf_len;
- uint *buf = ED_view3d_select_id_read(vc, x, y, x, y, &buf_len);
- BLI_assert(0 != buf_len);
- uint ret = buf[0];
- MEM_freeN(buf);
-
- return ret;
-}
-
/* reads full rect, converts indices */
-uint *ED_view3d_select_id_read(
- ViewContext *vc, int xmin, int ymin, int xmax, int ymax, uint *r_buf_len)
+uint *ED_view3d_select_id_read(int xmin, int ymin, int xmax, int ymax, uint *r_buf_len)
{
if (UNLIKELY((xmin > xmax) || (ymin > ymax))) {
return NULL;
@@ -330,7 +292,7 @@ uint *ED_view3d_select_id_read(
};
uint buf_len;
- uint *buf = ED_view3d_select_id_read_rect(vc, &rect, &buf_len);
+ uint *buf = ED_view3d_select_id_read_rect(&rect, &buf_len);
if (r_buf_len) {
*r_buf_len = buf_len;
@@ -339,85 +301,6 @@ uint *ED_view3d_select_id_read(
return buf;
}
-/* smart function to sample a rect spiralling outside, nice for backbuf selection */
-uint ED_view3d_select_id_read_nearest(struct ViewContext *UNUSED(vc),
- const int mval[2],
- const uint id_min,
- const uint id_max,
- uint *r_dist)
-{
- /* Create region around mouse cursor. This must be square and have an odd
- * width, the spiraling algorithm does not work with arbitrary rectangles. */
- rcti rect;
- BLI_rcti_init_pt_radius(&rect, mval, *r_dist);
- rect.xmax += 1;
- rect.ymax += 1;
-
- int width = BLI_rcti_size_x(&rect);
- int height = width;
- BLI_assert(width == height);
-
- /* Read from selection framebuffer. */
- uint *buf = MEM_mallocN(width * height * sizeof(*buf), __func__);
- DRW_framebuffer_select_id_read(&rect, buf);
-
- /* Spiral, starting from center of buffer. */
- int spiral_offset = height * (int)(width / 2) + (height / 2);
- int spiral_direction = 0;
-
- uint index = 0;
-
- for (int nr = 1; nr <= height; nr++) {
- for (int a = 0; a < 2; a++) {
- for (int b = 0; b < nr; b++) {
- /* Find hit within the specified range. */
- uint hit_id = buf[spiral_offset];
-
- if (hit_id && hit_id >= id_min && hit_id < id_max) {
- /* Get x/y from spiral offset. */
- int hit_x = spiral_offset % width;
- int hit_y = spiral_offset / width;
-
- int center_x = width / 2;
- int center_y = height / 2;
-
- /* Manhatten distance in keeping with other screen-based selection. */
- *r_dist = (uint)(abs(hit_x - center_x) + abs(hit_y - center_y));
-
- /* Indices start at 1 here. */
- index = (hit_id - id_min) + 1;
- goto exit;
- }
-
- /* Next spiral step. */
- if (spiral_direction == 0) {
- spiral_offset += 1; /* right */
- }
- else if (spiral_direction == 1) {
- spiral_offset -= width; /* down */
- }
- else if (spiral_direction == 2) {
- spiral_offset -= 1; /* left */
- }
- else {
- spiral_offset += width; /* up */
- }
-
- /* Stop if we are outside the buffer. */
- if (spiral_offset < 0 || spiral_offset >= width * height) {
- goto exit;
- }
- }
-
- spiral_direction = (spiral_direction + 1) % 4;
- }
- }
-
-exit:
- MEM_freeN(buf);
- return index;
-}
-
/* ************************************************************* */
static void view3d_stereo_bgpic_setup(Scene *scene, View3D *v3d, Image *ima, ImageUser *iuser)
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_camera.c b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
index 0b8c3b8cd28..5fe62a74d4b 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_camera.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_camera.c
@@ -154,7 +154,7 @@ static void WIDGETGROUP_camera_refresh(const bContext *C, wmGizmoGroup *gzgroup)
/* need to set property here for undo. TODO would prefer to do this in _init */
WM_gizmo_target_property_def_rna(
- cagzgroup->dop_dist, "offset", &camera_ptr, "dof_distance", -1);
+ cagzgroup->dop_dist, "offset", &camera_ptr, "dof.focus_distance", -1);
}
else {
WM_gizmo_set_flag(cagzgroup->dop_dist, WM_GIZMO_HIDDEN, true);
@@ -262,7 +262,7 @@ static void WIDGETGROUP_camera_message_subscribe(const bContext *C,
};
{
- extern PropertyRNA rna_Camera_dof_distance;
+ extern PropertyRNA rna_CameraDOFSettings_focus_distance;
extern PropertyRNA rna_Camera_display_size;
extern PropertyRNA rna_Camera_ortho_scale;
extern PropertyRNA rna_Camera_sensor_fit;
@@ -273,7 +273,7 @@ static void WIDGETGROUP_camera_message_subscribe(const bContext *C,
extern PropertyRNA rna_Camera_type;
extern PropertyRNA rna_Camera_lens;
const PropertyRNA *props[] = {
- &rna_Camera_dof_distance,
+ &rna_CameraDOFSettings_focus_distance,
&rna_Camera_display_size,
&rna_Camera_ortho_scale,
&rna_Camera_sensor_fit,
diff --git a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
index 6f35c0aa748..9cbf179ab49 100644
--- a/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
+++ b/source/blender/editors/space_view3d/view3d_gizmo_preselect_type.c
@@ -304,15 +304,14 @@ static int gizmo_preselect_edgering_test_select(bContext *C, wmGizmo *gz, const
em_setup_viewcontext(C, &vc);
copy_v2_v2_int(vc.mval, mval);
- for (uint base_index = 0; base_index < gz_ring->bases_len; base_index++) {
- Object *ob_iter = gz_ring->bases[base_index]->object;
- ED_view3d_viewcontext_init_object(&vc, ob_iter);
- BMEdge *eed_test = EDBM_edge_find_nearest_ex(&vc, &best.dist, NULL, false, false, NULL);
- if (eed_test) {
- best.ob = ob_iter;
- best.eed = eed_test;
- best.base_index = base_index;
- }
+ uint base_index;
+ BMEdge *eed_test = EDBM_edge_find_nearest_ex(
+ &vc, &best.dist, NULL, false, false, NULL, gz_ring->bases, gz_ring->bases_len, &base_index);
+
+ if (eed_test) {
+ best.ob = gz_ring->bases[base_index]->object;
+ best.eed = eed_test;
+ best.base_index = base_index;
}
BMesh *bm = NULL;
diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h
index 9075909a6fe..e499672acc1 100644
--- a/source/blender/editors/space_view3d/view3d_intern.h
+++ b/source/blender/editors/space_view3d/view3d_intern.h
@@ -127,13 +127,6 @@ void VIEW3D_OT_fly(struct wmOperatorType *ot);
void VIEW3D_OT_walk(struct wmOperatorType *ot);
/* drawobject.c */
-void draw_object_select_id(struct Depsgraph *depsgraph,
- Scene *scene,
- View3D *v3d,
- RegionView3D *rv3d,
- struct Object *ob,
- short select_mode);
-
int view3d_effective_drawtype(const struct View3D *v3d);
/* view3d_draw.c */
diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c
index 2ce23486476..b3b4910c525 100644
--- a/source/blender/editors/space_view3d/view3d_select.c
+++ b/source/blender/editors/space_view3d/view3d_select.c
@@ -41,6 +41,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_array.h"
+#include "BLI_bitmap.h"
#include "BLI_math.h"
#include "BLI_lasso_2d.h"
#include "BLI_rect.h"
@@ -57,6 +58,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "BKE_global.h"
+#include "BKE_main.h"
#include "BKE_armature.h"
#include "BKE_context.h"
@@ -87,6 +89,7 @@
#include "ED_mesh.h"
#include "ED_object.h"
#include "ED_screen.h"
+#include "ED_select_buffer_utils.h"
#include "ED_select_utils.h"
#include "ED_sculpt.h"
#include "ED_mball.h"
@@ -134,9 +137,6 @@ void ED_view3d_viewcontext_init_object(ViewContext *vc, Object *obact)
if (vc->obedit) {
BLI_assert(BKE_object_is_in_editmode(obact));
vc->obedit = obact;
- /* previous selections are now invalid. */
- vc->v3d->flag |= V3D_INVALID_BACKBUF;
-
if (vc->em) {
vc->em = BKE_editmesh_from_object(vc->obedit);
}
@@ -181,20 +181,96 @@ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Internal Edit-Mesh Select Buffer Wrapper
+ *
+ * Avoid duplicate code when using edit-mode selection,
+ * actual logic is handled outside of this function.
+ *
+ * \note Currently this #EDBMSelectID_Context which is mesh specific
+ * however the logic could also be used for non-meshes too.
+ *
+ * \{ */
+
+struct EditSelectBuf_Cache {
+ Base **bases;
+ uint bases_len;
+ struct EDBMSelectID_Context *sel_id_ctx;
+ BLI_bitmap *select_bitmap;
+};
+
+static void editselect_buf_cache_init(struct EditSelectBuf_Cache *esel, ViewContext *vc)
+{
+ if (vc->obedit) {
+ esel->bases = BKE_view_layer_array_from_bases_in_edit_mode(
+ vc->view_layer, vc->v3d, &esel->bases_len);
+ }
+ else {
+ /* Use for paint modes, currently only a single object at a time. */
+ if (vc->obact) {
+ esel->bases = MEM_mallocN(sizeof(esel->bases), __func__);
+ esel->bases[0] = BKE_view_layer_base_find(vc->view_layer, vc->obact);
+ esel->bases_len = 1;
+ }
+ else {
+ esel->bases = NULL;
+ esel->bases_len = 0;
+ }
+ }
+ esel->sel_id_ctx = EDBM_select_id_context_create(
+ vc, esel->bases, esel->bases_len, vc->scene->toolsettings->selectmode);
+ for (int i = 0; i < esel->bases_len; i++) {
+ esel->bases[i]->object->runtime.select_id = i;
+ }
+}
+
+static void editselect_buf_cache_free(struct EditSelectBuf_Cache *esel)
+{
+ if (esel->sel_id_ctx) {
+ EDBM_select_id_context_destroy(esel->sel_id_ctx);
+ }
+ MEM_SAFE_FREE(esel->select_bitmap);
+ MEM_SAFE_FREE(esel->bases);
+}
+
+static void editselect_buf_cache_free_voidp(void *esel_voidp)
+{
+ editselect_buf_cache_free(esel_voidp);
+ MEM_freeN(esel_voidp);
+}
+
+static void editselect_buf_cache_init_with_generic_userdata(wmGenericUserData *wm_userdata,
+ ViewContext *vc)
+{
+ struct EditSelectBuf_Cache *esel = MEM_callocN(sizeof(*esel), __func__);
+ wm_userdata->data = esel;
+ wm_userdata->free_fn = editselect_buf_cache_free_voidp;
+ wm_userdata->use_free = true;
+ editselect_buf_cache_init(esel, vc);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Internal Edit-Mesh Utilities
* \{ */
-static bool edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp sel_op)
+static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel,
+ Object *ob,
+ BMEditMesh *em,
+ const eSelectOp sel_op)
{
BMVert *eve;
BMIter iter;
- uint index = bm_wireoffs;
bool changed = false;
+ const BLI_bitmap *select_bitmap = esel->select_bitmap;
+ uint index = EDBM_select_id_context_offset_for_object_elem(
+ esel->sel_id_ctx, ob->runtime.select_id, BM_VERT);
+
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
const bool is_select = BM_elem_flag_test(eve, BM_ELEM_SELECT);
- const bool is_inside = EDBM_backbuf_check(index);
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_vert_select_set(em->bm, eve, sel_op_result);
@@ -206,17 +282,23 @@ static bool edbm_backbuf_check_and_select_verts(BMEditMesh *em, const eSelectOp
return changed;
}
-static bool edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp sel_op)
+static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel,
+ Object *ob,
+ BMEditMesh *em,
+ const eSelectOp sel_op)
{
BMEdge *eed;
BMIter iter;
- uint index = bm_solidoffs;
bool changed = false;
+ const BLI_bitmap *select_bitmap = esel->select_bitmap;
+ uint index = EDBM_select_id_context_offset_for_object_elem(
+ esel->sel_id_ctx, ob->runtime.select_id, BM_EDGE);
+
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = EDBM_backbuf_check(index);
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_edge_select_set(em->bm, eed, sel_op_result);
@@ -228,17 +310,23 @@ static bool edbm_backbuf_check_and_select_edges(BMEditMesh *em, const eSelectOp
return changed;
}
-static bool edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp sel_op)
+static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel,
+ Object *ob,
+ BMEditMesh *em,
+ const eSelectOp sel_op)
{
BMFace *efa;
BMIter iter;
- uint index = 1;
bool changed = false;
+ const BLI_bitmap *select_bitmap = esel->select_bitmap;
+ uint index = EDBM_select_id_context_offset_for_object_elem(
+ esel->sel_id_ctx, ob->runtime.select_id, BM_FACE);
+
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
const bool is_select = BM_elem_flag_test(efa, BM_ELEM_SELECT);
- const bool is_inside = EDBM_backbuf_check(index);
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_face_select_set(em->bm, efa, sel_op_result);
@@ -251,17 +339,21 @@ static bool edbm_backbuf_check_and_select_faces(BMEditMesh *em, const eSelectOp
}
/* object mode, edbm_ prefix is confusing here, rename? */
-static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp sel_op)
+static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me,
+ struct EditSelectBuf_Cache *esel,
+ const eSelectOp sel_op)
{
MVert *mv = me->mvert;
uint index;
bool changed = false;
+ const BLI_bitmap *select_bitmap = esel->select_bitmap;
+
if (mv) {
- for (index = 1; index <= me->totvert; index++, mv++) {
+ for (index = 0; index < me->totvert; index++, mv++) {
if (!(mv->flag & ME_HIDE)) {
const bool is_select = mv->flag & SELECT;
- const bool is_inside = EDBM_backbuf_check(index);
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(mv->flag, sel_op_result, SELECT);
@@ -274,17 +366,21 @@ static bool edbm_backbuf_check_and_select_verts_obmode(Mesh *me, const eSelectOp
}
/* object mode, edbm_ prefix is confusing here, rename? */
-static bool edbm_backbuf_check_and_select_tfaces(Mesh *me, const eSelectOp sel_op)
+static bool edbm_backbuf_check_and_select_faces_obmode(Mesh *me,
+ struct EditSelectBuf_Cache *esel,
+ const eSelectOp sel_op)
{
MPoly *mpoly = me->mpoly;
uint index;
bool changed = false;
+ const BLI_bitmap *select_bitmap = esel->select_bitmap;
+
if (mpoly) {
- for (index = 1; index <= me->totpoly; index++, mpoly++) {
+ for (index = 0; index < me->totpoly; index++, mpoly++) {
if (!(mpoly->flag & ME_HIDE)) {
const bool is_select = mpoly->flag & ME_FACE_SEL;
- const bool is_inside = EDBM_backbuf_check(index);
+ const bool is_inside = BLI_BITMAP_TEST_BOOL(select_bitmap, index);
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(mpoly->flag, sel_op_result, ME_FACE_SEL);
@@ -623,14 +719,26 @@ static void do_lasso_select_mesh__doSelectVert(void *userData,
data->is_changed = true;
}
}
-static void do_lasso_select_mesh__doSelectEdge_pass0(
- void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
-{
- LassoSelectUserData *data = userData;
+struct LassoSelectUserData_ForMeshEdge {
+ LassoSelectUserData *data;
+ struct EditSelectBuf_Cache *esel;
+ uint backbuf_offset;
+};
+static void do_lasso_select_mesh__doSelectEdge_pass0(void *user_data,
+ BMEdge *eed,
+ const float screen_co_a[2],
+ const float screen_co_b[2],
+ int index)
+{
+ struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data;
+ LassoSelectUserData *data = data_for_edge->data;
+ const bool is_visible = (data_for_edge->esel ?
+ BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap,
+ data_for_edge->backbuf_offset + index) :
+ true);
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
const bool is_inside =
- (EDBM_backbuf_check(bm_solidoffs + index) &&
- edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
+ (is_visible && edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b) &&
BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_a), IS_CLIPPED) &&
BLI_lasso_is_point_inside(data->mcords, data->moves, UNPACK2(screen_co_b), IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
@@ -640,15 +748,24 @@ static void do_lasso_select_mesh__doSelectEdge_pass0(
data->is_changed = true;
}
}
-static void do_lasso_select_mesh__doSelectEdge_pass1(
- void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
+static void do_lasso_select_mesh__doSelectEdge_pass1(void *user_data,
+ BMEdge *eed,
+ const float screen_co_a[2],
+ const float screen_co_b[2],
+ int index)
{
- LassoSelectUserData *data = userData;
+ struct LassoSelectUserData_ForMeshEdge *data_for_edge = user_data;
+ LassoSelectUserData *data = data_for_edge->data;
+ const bool is_visible = (data_for_edge->esel ?
+ BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap,
+ data_for_edge->backbuf_offset + index) :
+ true);
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside =
- (EDBM_backbuf_check(bm_solidoffs + index) &&
- BLI_lasso_is_edge_inside(
- data->mcords, data->moves, UNPACK2(screen_co_a), UNPACK2(screen_co_b), IS_CLIPPED));
+ const bool is_inside = (is_visible && BLI_lasso_is_edge_inside(data->mcords,
+ data->moves,
+ UNPACK2(screen_co_a),
+ UNPACK2(screen_co_b),
+ IS_CLIPPED));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
@@ -674,6 +791,7 @@ static void do_lasso_select_mesh__doSelectFace(void *userData,
}
static bool do_lasso_select_mesh(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const int mcords[][2],
short moves,
const eSelectOp sel_op)
@@ -681,7 +799,6 @@ static bool do_lasso_select_mesh(ViewContext *vc,
LassoSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
rcti rect;
- int bbsel;
/* set editmesh */
vc->em = BKE_editmesh_from_object(vc->obedit);
@@ -701,12 +818,22 @@ static bool do_lasso_select_mesh(ViewContext *vc,
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
GPU_matrix_set(vc->rv3d->viewmat);
- bbsel = EDBM_backbuf_border_mask_init(
- vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
+
+ const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d);
+
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ if (use_zbuf) {
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect);
+ }
+ }
if (ts->selectmode & SCE_SELECT_VERTEX) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op);
+ if (use_zbuf) {
+ data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op);
}
else {
mesh_foreachScreenVert(
@@ -714,18 +841,26 @@ static bool do_lasso_select_mesh(ViewContext *vc,
}
}
if (ts->selectmode & SCE_SELECT_EDGE) {
- /* Does both bbsel and non-bbsel versions (need screen cos for both) */
+ /* Does both use_zbuf and non-use_zbuf versions (need screen cos for both) */
+ struct LassoSelectUserData_ForMeshEdge data_for_edge = {
+ .data = &data,
+ .esel = use_zbuf ? esel : NULL,
+ .backbuf_offset = use_zbuf ?
+ EDBM_select_id_context_offset_for_object_elem(
+ esel->sel_id_ctx, vc->obedit->runtime.select_id, BM_EDGE) :
+ 0,
+ };
mesh_foreachScreenEdge(
- vc, do_lasso_select_mesh__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ vc, do_lasso_select_mesh__doSelectEdge_pass0, &data_for_edge, V3D_PROJ_TEST_CLIP_NEAR);
if (data.is_done == false) {
mesh_foreachScreenEdge(
- vc, do_lasso_select_mesh__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ vc, do_lasso_select_mesh__doSelectEdge_pass1, &data_for_edge, V3D_PROJ_TEST_CLIP_NEAR);
}
}
if (ts->selectmode & SCE_SELECT_FACE) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op);
+ if (use_zbuf) {
+ data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op);
}
else {
mesh_foreachScreenFace(
@@ -733,8 +868,6 @@ static bool do_lasso_select_mesh(ViewContext *vc,
}
}
- EDBM_backbuf_free();
-
if (data.is_changed) {
EDBM_selectmode_flush(vc->em);
}
@@ -975,6 +1108,7 @@ static void do_lasso_select_meshobject__doSelectVert(void *userData,
}
}
static bool do_lasso_select_paintvert(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const int mcords[][2],
short moves,
const eSelectOp sel_op)
@@ -996,14 +1130,20 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
BLI_lasso_boundbox(&rect, mcords, moves);
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
if (use_zbuf) {
- bm_vertoffs = me->totvert + 1; /* max index array */
-
- EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
-
- changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op);
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect);
+ }
+ }
- EDBM_backbuf_free();
+ if (use_zbuf) {
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op);
+ }
}
else {
LassoSelectUserData data;
@@ -1025,9 +1165,11 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
paintvert_flush_flags(ob);
paintvert_tag_select_update(vc->C, ob);
}
+
return changed;
}
static bool do_lasso_select_paintface(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const int mcords[][2],
short moves,
const eSelectOp sel_op)
@@ -1040,19 +1182,25 @@ static bool do_lasso_select_paintface(ViewContext *vc,
return false;
}
- bm_vertoffs = me->totpoly + 1; /* max index array */
-
- BLI_lasso_boundbox(&rect, mcords, moves);
- EDBM_backbuf_border_mask_init(vc, mcords, moves, rect.xmin, rect.ymin, rect.xmax, rect.ymax);
-
bool changed = false;
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
/* flush selection at the end */
changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
}
- changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op);
- EDBM_backbuf_free();
+ BLI_lasso_boundbox(&rect, mcords, moves);
+
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ if (esel == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect);
+ }
+
+ if (esel->select_bitmap) {
+ changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op);
+ }
if (changed) {
paintface_flush_flags(vc->C, ob, SELECT);
@@ -1100,12 +1248,15 @@ static bool view3d_lasso_select(
Object *ob = CTX_data_active_object(C);
bool changed_multi = false;
+ wmGenericUserData wm_userdata_buf = {0};
+ wmGenericUserData *wm_userdata = &wm_userdata_buf;
+
if (vc->obedit == NULL) { /* Object Mode */
if (BKE_paint_select_face_test(ob)) {
- changed_multi |= do_lasso_select_paintface(vc, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_paintface(vc, wm_userdata, mcords, moves, sel_op);
}
else if (BKE_paint_select_vert_test(ob)) {
- changed_multi |= do_lasso_select_paintvert(vc, mcords, moves, sel_op);
+ changed_multi |= do_lasso_select_paintvert(vc, wm_userdata, mcords, moves, sel_op);
}
else if (ob &&
(ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) {
@@ -1122,14 +1273,13 @@ static bool view3d_lasso_select(
}
}
else { /* Edit Mode */
-
FOREACH_OBJECT_IN_MODE_BEGIN (vc->view_layer, vc->v3d, ob->type, ob->mode, ob_iter) {
ED_view3d_viewcontext_init_object(vc, ob_iter);
bool changed = false;
switch (vc->obedit->type) {
case OB_MESH:
- changed = do_lasso_select_mesh(vc, mcords, moves, sel_op);
+ changed = do_lasso_select_mesh(vc, wm_userdata, mcords, moves, sel_op);
break;
case OB_CURVE:
case OB_SURF:
@@ -1157,6 +1307,9 @@ static bool view3d_lasso_select(
}
FOREACH_OBJECT_IN_MODE_END;
}
+
+ WM_generic_user_data_free(wm_userdata);
+
return changed_multi;
}
@@ -1170,6 +1323,7 @@ static int view3d_lasso_select_exec(bContext *C, wmOperator *op)
if (mcords) {
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
@@ -1337,7 +1491,7 @@ static Base *object_mouse_select_menu(
if (buffer) {
for (int a = 0; a < hits; a++) {
/* index was converted */
- if (base->object->select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
+ if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & ~0xFFFF0000)) {
ok = true;
break;
}
@@ -1609,7 +1763,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
else {
/* only exclude active object when it is selected... */
if (BASACT(view_layer) && (BASACT(view_layer)->flag & BASE_SELECTED) && hits > 1) {
- notcol = BASACT(view_layer)->object->select_id;
+ notcol = BASACT(view_layer)->object->runtime.select_id;
}
for (a = 0; a < hits; a++) {
@@ -1623,7 +1777,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
base = FIRSTBASE(view_layer);
while (base) {
if (BASE_SELECTABLE(v3d, base)) {
- if (base->object->select_id == selcol) {
+ if (base->object->runtime.select_id == selcol) {
break;
}
}
@@ -1654,13 +1808,13 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
if (has_bones) {
/* skip non-bone objects */
if ((buffer[4 * a + 3] & 0xFFFF0000)) {
- if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
+ if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
basact = base;
}
}
}
else {
- if (base->object->select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
+ if (base->object->runtime.select_id == (buffer[(4 * a) + 3] & 0xFFFF)) {
basact = base;
}
}
@@ -1693,6 +1847,7 @@ Base *ED_view3d_give_base_under_cursor(bContext *C, const int mval[2])
/* setup view context for argument to callbacks */
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
ED_view3d_viewcontext_init(C, &vc);
@@ -1878,7 +2033,7 @@ static bool ed_object_select_pick(bContext *C,
/* if there's bundles in buffer select bundles first,
* so non-camera elements should be ignored in buffer */
- if (basact->object->select_id != (hitresult & 0xFFFF)) {
+ if (basact->object->runtime.select_id != (hitresult & 0xFFFF)) {
continue;
}
@@ -2129,6 +2284,7 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
RNA_int_get_array(op->ptr, "location", location);
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
if (object) {
obedit = NULL;
@@ -2335,9 +2491,13 @@ static void do_paintvert_box_select__doSelectVert(void *userData,
data->is_changed = true;
}
}
-static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSelectOp sel_op)
+static bool do_paintvert_box_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
+ const rcti *rect,
+ const eSelectOp sel_op)
{
const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
+
Mesh *me;
me = vc->obact->data;
@@ -2354,48 +2514,16 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe
/* pass */
}
else if (use_zbuf) {
- MVert *mvert;
- unsigned int *rt;
- int a, index;
- char *selar;
-
- selar = MEM_callocN(me->totvert + 1, "selar");
-
- uint buf_len;
- uint *buf = ED_view3d_select_id_read_rect(vc, rect, &buf_len);
-
- rt = buf;
-
- a = buf_len;
- while (a--) {
- if (*rt) {
- index = *rt;
- if (index <= me->totvert) {
- selar[index] = 1;
- }
- }
- rt++;
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect);
}
-
- mvert = me->mvert;
- for (a = 1; a <= me->totvert; a++, mvert++) {
- if ((mvert->flag & ME_HIDE) == 0) {
- const bool is_select = mvert->flag & SELECT;
- const bool is_inside = (selar[a] != 0);
- const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
- if (sel_op_result != -1) {
- SET_FLAG_FROM_TEST(mvert->flag, sel_op_result, SELECT);
- changed = true;
- }
- }
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op);
}
-
- MEM_freeN(buf);
- MEM_freeN(selar);
-
-#ifdef __APPLE__
- glReadBuffer(GL_BACK);
-#endif
}
else {
BoxSelectUserData data;
@@ -2419,6 +2547,46 @@ static bool do_paintvert_box_select(ViewContext *vc, const rcti *rect, const eSe
return changed;
}
+static bool do_paintface_box_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
+ const rcti *rect,
+ int sel_op)
+{
+ Object *ob = vc->obact;
+ Mesh *me;
+
+ me = BKE_mesh_from_object(ob);
+ if ((me == NULL) || (me->totpoly == 0)) {
+ return false;
+ }
+
+ bool changed = false;
+ if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
+ changed |= paintface_deselect_all_visible(vc->C, vc->obact, SEL_DESELECT, false);
+ }
+
+ if (BLI_rcti_is_empty(rect)) {
+ /* pass */
+ }
+ else {
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect);
+ }
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op);
+ }
+ }
+
+ if (changed) {
+ paintface_flush_flags(vc->C, vc->obact, SELECT);
+ }
+ return changed;
+}
+
static void do_nurbs_box_select__doSelect(void *userData,
Nurb *UNUSED(nu),
BPoint *bp,
@@ -2519,12 +2687,22 @@ static void do_mesh_box_select__doSelectVert(void *userData,
data->is_changed = true;
}
}
+struct BoxSelectUserData_ForMeshEdge {
+ BoxSelectUserData *data;
+ struct EditSelectBuf_Cache *esel;
+ uint backbuf_offset;
+};
static void do_mesh_box_select__doSelectEdge_pass0(
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
- BoxSelectUserData *data = userData;
+ struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData;
+ BoxSelectUserData *data = data_for_edge->data;
+ const bool is_visible = (data_for_edge->esel ?
+ BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap,
+ data_for_edge->backbuf_offset + index) :
+ true);
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) &&
+ const bool is_inside = (is_visible &&
edge_fully_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
@@ -2536,10 +2714,14 @@ static void do_mesh_box_select__doSelectEdge_pass0(
static void do_mesh_box_select__doSelectEdge_pass1(
void *userData, BMEdge *eed, const float screen_co_a[2], const float screen_co_b[2], int index)
{
- BoxSelectUserData *data = userData;
+ struct BoxSelectUserData_ForMeshEdge *data_for_edge = userData;
+ BoxSelectUserData *data = data_for_edge->data;
+ const bool is_visible = (data_for_edge->esel ?
+ BLI_BITMAP_TEST_BOOL(data_for_edge->esel->select_bitmap,
+ data_for_edge->backbuf_offset + index) :
+ true);
const bool is_select = BM_elem_flag_test(eed, BM_ELEM_SELECT);
- const bool is_inside = (EDBM_backbuf_check(bm_solidoffs + index) &&
- edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
+ const bool is_inside = (is_visible && edge_inside_rect(data->rect_fl, screen_co_a, screen_co_b));
const int sel_op_result = ED_select_op_action_deselected(data->sel_op, is_select, is_inside);
if (sel_op_result != -1) {
BM_edge_select_set(data->vc->em->bm, eed, sel_op_result);
@@ -2560,11 +2742,13 @@ static void do_mesh_box_select__doSelectFace(void *userData,
data->is_changed = true;
}
}
-static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_op)
+static bool do_mesh_box_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
+ const rcti *rect,
+ const eSelectOp sel_op)
{
BoxSelectUserData data;
ToolSettings *ts = vc->scene->toolsettings;
- int bbsel;
view3d_userdata_boxselect_init(&data, vc, rect, sel_op);
@@ -2579,11 +2763,22 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d);
GPU_matrix_set(vc->rv3d->viewmat);
- bbsel = EDBM_backbuf_border_init(vc, rect->xmin, rect->ymin, rect->xmax, rect->ymax);
+
+ const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d);
+
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ if (use_zbuf) {
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect);
+ }
+ }
if (ts->selectmode & SCE_SELECT_VERTEX) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_verts(vc->em, sel_op);
+ if (use_zbuf) {
+ data.is_changed |= edbm_backbuf_check_and_select_verts(esel, vc->obedit, vc->em, sel_op);
}
else {
mesh_foreachScreenVert(
@@ -2591,18 +2786,26 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_
}
}
if (ts->selectmode & SCE_SELECT_EDGE) {
- /* Does both bbsel and non-bbsel versions (need screen cos for both) */
+ /* Does both use_zbuf and non-use_zbuf versions (need screen cos for both) */
+ struct BoxSelectUserData_ForMeshEdge cb_data = {
+ .data = &data,
+ .esel = use_zbuf ? esel : NULL,
+ .backbuf_offset = use_zbuf ?
+ EDBM_select_id_context_offset_for_object_elem(
+ esel->sel_id_ctx, vc->obedit->runtime.select_id, BM_EDGE) :
+ 0,
+ };
mesh_foreachScreenEdge(
- vc, do_mesh_box_select__doSelectEdge_pass0, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ vc, do_mesh_box_select__doSelectEdge_pass0, &cb_data, V3D_PROJ_TEST_CLIP_NEAR);
if (data.is_done == false) {
mesh_foreachScreenEdge(
- vc, do_mesh_box_select__doSelectEdge_pass1, &data, V3D_PROJ_TEST_CLIP_NEAR);
+ vc, do_mesh_box_select__doSelectEdge_pass1, &cb_data, V3D_PROJ_TEST_CLIP_NEAR);
}
}
if (ts->selectmode & SCE_SELECT_FACE) {
- if (bbsel) {
- data.is_changed |= edbm_backbuf_check_and_select_faces(vc->em, sel_op);
+ if (use_zbuf) {
+ data.is_changed |= edbm_backbuf_check_and_select_faces(esel, vc->obedit, vc->em, sel_op);
}
else {
mesh_foreachScreenFace(
@@ -2610,8 +2813,6 @@ static bool do_mesh_box_select(ViewContext *vc, rcti *rect, const eSelectOp sel_
}
}
- EDBM_backbuf_free();
-
if (data.is_changed) {
EDBM_selectmode_flush(vc->em);
}
@@ -2652,7 +2853,7 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
}
const uint hit_object = hitresult & 0xFFFF;
- if (vc->obedit->select_id != hit_object) {
+ if (vc->obedit->runtime.select_id != hit_object) {
continue;
}
@@ -2803,7 +3004,7 @@ static bool do_object_box_select(bContext *C, ViewContext *vc, rcti *rect, const
for (Base *base = vc->view_layer->object_bases.first; base; base = base->next) {
if (BASE_SELECTABLE(v3d, base)) {
- if ((base->object->select_id & 0x0000FFFF) != 0) {
+ if ((base->object->runtime.select_id & 0x0000FFFF) != 0) {
BLI_array_append(bases, base);
}
}
@@ -2893,7 +3094,7 @@ static bool do_pose_box_select(bContext *C, ViewContext *vc, rcti *rect, const e
/* Select the next bone if we're not switching bases. */
if (col + 4 != col_end) {
- if ((base->object->select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
+ if ((base->object->runtime.select_id & 0x0000FFFF) != (col[4] & 0x0000FFFF)) {
break;
}
if (base->object->pose != NULL) {
@@ -2929,7 +3130,11 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
rcti rect;
bool changed_multi = false;
+ wmGenericUserData wm_userdata_buf = {0};
+ wmGenericUserData *wm_userdata = &wm_userdata_buf;
+
view3d_operator_needs_opengl(C);
+ BKE_object_update_select_id(CTX_data_main(C));
/* setup view context for argument to callbacks */
ED_view3d_viewcontext_init(C, &vc);
@@ -2938,7 +3143,6 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
WM_operator_properties_border_to_rcti(op, &rect);
if (vc.obedit) {
-
FOREACH_OBJECT_IN_MODE_BEGIN (
vc.view_layer, vc.v3d, vc.obedit->type, vc.obedit->mode, ob_iter) {
ED_view3d_viewcontext_init_object(&vc, ob_iter);
@@ -2947,7 +3151,7 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
switch (vc.obedit->type) {
case OB_MESH:
vc.em = BKE_editmesh_from_object(vc.obedit);
- changed = do_mesh_box_select(&vc, &rect, sel_op);
+ changed = do_mesh_box_select(&vc, wm_userdata, &rect, sel_op);
if (changed) {
DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
@@ -2997,10 +3201,10 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
C, &vc, &rect, sel_op == SEL_OP_ADD ? true : false);
}
else if (vc.obact && BKE_paint_select_face_test(vc.obact)) {
- changed_multi = do_paintface_box_select(&vc, &rect, sel_op);
+ changed_multi = do_paintface_box_select(&vc, wm_userdata, &rect, sel_op);
}
else if (vc.obact && BKE_paint_select_vert_test(vc.obact)) {
- changed_multi = do_paintvert_box_select(&vc, &rect, sel_op);
+ changed_multi = do_paintvert_box_select(&vc, wm_userdata, &rect, sel_op);
}
else if (vc.obact && vc.obact->mode & OB_MODE_PARTICLE_EDIT) {
changed_multi = PE_box_select(C, &rect, sel_op);
@@ -3013,6 +3217,8 @@ static int view3d_box_select_exec(bContext *C, wmOperator *op)
}
}
+ WM_generic_user_data_free(wm_userdata);
+
if (changed_multi) {
return OPERATOR_FINISHED;
}
@@ -3118,10 +3324,13 @@ static void mesh_circle_doSelectFace(void *userData,
}
}
-static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval[2], float rad)
+static bool mesh_circle_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
+ eSelectOp sel_op,
+ const int mval[2],
+ float rad)
{
ToolSettings *ts = vc->scene->toolsettings;
- int bbsel;
CircleSelectUserData data;
vc->em = BKE_editmesh_from_object(vc->obedit);
@@ -3134,14 +3343,30 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval
}
const bool select = (sel_op != SEL_OP_SUB);
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
ED_view3d_init_mats_rv3d(vc->obedit, vc->rv3d); /* for foreach's screen/vert projection */
view3d_userdata_circleselect_init(&data, vc, select, mval, rad);
+ const bool use_zbuf = !XRAY_FLAG_ENABLED(vc->v3d);
+
+ if (use_zbuf) {
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ }
+ }
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+
+ if (use_zbuf) {
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f));
+ }
+
if (ts->selectmode & SCE_SELECT_VERTEX) {
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_verts(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ if (use_zbuf) {
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_verts(
+ esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ }
}
else {
mesh_foreachScreenVert(vc, mesh_circle_doSelectVert, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
@@ -3149,8 +3374,11 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval
}
if (ts->selectmode & SCE_SELECT_EDGE) {
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_edges(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ if (use_zbuf) {
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_edges(
+ esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ }
}
else {
mesh_foreachScreenEdge(vc, mesh_circle_doSelectEdge, &data, V3D_PROJ_TEST_CLIP_NEAR);
@@ -3158,17 +3386,25 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval
}
if (ts->selectmode & SCE_SELECT_FACE) {
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_faces(vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ if (use_zbuf) {
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_faces(
+ esel, vc->obedit, vc->em, select ? SEL_OP_ADD : SEL_OP_SUB);
+ }
}
else {
mesh_foreachScreenFace(vc, mesh_circle_doSelectFace, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
}
}
- changed |= data.is_changed;
+ if (use_zbuf) {
+ if (esel->select_bitmap != NULL) {
+ MEM_freeN(esel->select_bitmap);
+ esel->select_bitmap = NULL;
+ }
+ }
- EDBM_backbuf_free();
+ changed |= data.is_changed;
if (changed) {
EDBM_selectmode_flush(vc->em);
@@ -3177,6 +3413,7 @@ static bool mesh_circle_select(ViewContext *vc, eSelectOp sel_op, const int mval
}
static bool paint_facesel_circle_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const eSelectOp sel_op,
const int mval[2],
float rad)
@@ -3184,7 +3421,6 @@ static bool paint_facesel_circle_select(ViewContext *vc,
BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
Object *ob = vc->obact;
Mesh *me = ob->data;
- bool bbsel;
bool changed = false;
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
@@ -3192,13 +3428,21 @@ static bool paint_facesel_circle_select(ViewContext *vc,
changed |= paintface_deselect_all_visible(vc->C, ob, SEL_DESELECT, false);
}
- bm_vertoffs = me->totpoly + 1; /* max index array */
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ }
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_tfaces(me, sel_op);
- EDBM_backbuf_free();
+ {
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f));
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_faces_obmode(me, esel, sel_op);
+ MEM_freeN(esel->select_bitmap);
+ esel->select_bitmap = NULL;
+ }
}
+
if (changed) {
paintface_flush_flags(vc->C, ob, SELECT);
}
@@ -3218,6 +3462,7 @@ static void paint_vertsel_circle_select_doSelectVert(void *userData,
}
}
static bool paint_vertsel_circle_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const eSelectOp sel_op,
const int mval[2],
float rad)
@@ -3226,7 +3471,6 @@ static bool paint_vertsel_circle_select(ViewContext *vc,
const bool use_zbuf = !XRAY_ENABLED(vc->v3d);
Object *ob = vc->obact;
Mesh *me = ob->data;
- bool bbsel;
/* CircleSelectUserData data = {NULL}; */ /* UNUSED */
bool changed = false;
@@ -3238,12 +3482,19 @@ static bool paint_vertsel_circle_select(ViewContext *vc,
const bool select = (sel_op != SEL_OP_SUB);
if (use_zbuf) {
- bm_vertoffs = me->totvert + 1; /* max index array */
+ if (wm_userdata->data == NULL) {
+ editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
+ }
+ }
- bbsel = EDBM_backbuf_circle_init(vc, mval[0], mval[1], (short)(rad + 1.0f));
- if (bbsel) {
- changed |= edbm_backbuf_check_and_select_verts_obmode(me, sel_op);
- EDBM_backbuf_free();
+ if (use_zbuf) {
+ struct EditSelectBuf_Cache *esel = wm_userdata->data;
+ const uint buffer_len = EDBM_select_id_context_elem_len(esel->sel_id_ctx);
+ esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f));
+ if (esel->select_bitmap != NULL) {
+ changed |= edbm_backbuf_check_and_select_verts_obmode(me, esel, sel_op);
+ MEM_freeN(esel->select_bitmap);
+ esel->select_bitmap = NULL;
}
}
else {
@@ -3591,27 +3842,40 @@ static bool mball_circle_select(ViewContext *vc,
/** Callbacks for circle selection in Editmode */
static bool obedit_circle_select(ViewContext *vc,
+ wmGenericUserData *wm_userdata,
const eSelectOp sel_op,
const int mval[2],
float rad)
{
+ bool changed = false;
BLI_assert(ELEM(sel_op, SEL_OP_SET, SEL_OP_ADD, SEL_OP_SUB));
switch (vc->obedit->type) {
case OB_MESH:
- return mesh_circle_select(vc, sel_op, mval, rad);
+ changed = mesh_circle_select(vc, wm_userdata, sel_op, mval, rad);
+ break;
case OB_CURVE:
case OB_SURF:
- return nurbscurve_circle_select(vc, sel_op, mval, rad);
+ changed = nurbscurve_circle_select(vc, sel_op, mval, rad);
+ break;
case OB_LATTICE:
- return lattice_circle_select(vc, sel_op, mval, rad);
+ changed = lattice_circle_select(vc, sel_op, mval, rad);
+ break;
case OB_ARMATURE:
- return armature_circle_select(vc, sel_op, mval, rad);
+ changed = armature_circle_select(vc, sel_op, mval, rad);
+ break;
case OB_MBALL:
- return mball_circle_select(vc, sel_op, mval, rad);
+ changed = mball_circle_select(vc, sel_op, mval, rad);
+ break;
default:
BLI_assert(0);
- return false;
+ break;
}
+
+ if (changed) {
+ DEG_id_tag_update(vc->obact->data, ID_RECALC_SELECT);
+ WM_main_add_notifier(NC_GEOM | ND_SELECT, vc->obact->data);
+ }
+ return changed;
}
static bool object_circle_select(ViewContext *vc,
@@ -3660,8 +3924,13 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
const int radius = RNA_int_get(op->ptr, "radius");
const int mval[2] = {RNA_int_get(op->ptr, "x"), RNA_int_get(op->ptr, "y")};
+ /* Allow each selection type to allocate their own data thats used between executions. */
+ wmGesture *gesture = op->customdata; /* NULL when non-modal. */
+ wmGenericUserData wm_userdata_buf = {0};
+ wmGenericUserData *wm_userdata = gesture ? &gesture->user_data : &wm_userdata_buf;
+
const eSelectOp sel_op = ED_select_op_modal(RNA_enum_get(op->ptr, "mode"),
- WM_gesture_is_modal_first(op->customdata));
+ WM_gesture_is_modal_first(gesture));
ED_view3d_viewcontext_init(C, &vc);
@@ -3670,6 +3939,9 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
if (obedit || BKE_paint_select_elem_test(obact) || (obact && (obact->mode & OB_MODE_POSE))) {
view3d_operator_needs_opengl(C);
+ if (obedit == NULL) {
+ BKE_object_update_select_id(CTX_data_main(C));
+ }
FOREACH_OBJECT_IN_MODE_BEGIN (vc.view_layer, vc.v3d, obact->type, obact->mode, ob_iter) {
ED_view3d_viewcontext_init_object(&vc, ob_iter);
@@ -3678,16 +3950,13 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
obedit = vc.obedit;
if (obedit) {
- if (obedit_circle_select(&vc, sel_op, mval, (float)radius)) {
- DEG_id_tag_update(obact->data, ID_RECALC_SELECT);
- WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obact->data);
- }
+ obedit_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius);
}
else if (BKE_paint_select_face_test(obact)) {
- paint_facesel_circle_select(&vc, sel_op, mval, (float)radius);
+ paint_facesel_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius);
}
else if (BKE_paint_select_vert_test(obact)) {
- paint_vertsel_circle_select(&vc, sel_op, mval, (float)radius);
+ paint_vertsel_circle_select(&vc, wm_userdata, sel_op, mval, (float)radius);
}
else if (obact->mode & OB_MODE_POSE) {
pose_circle_select(&vc, sel_op, mval, (float)radius);
@@ -3714,6 +3983,11 @@ static int view3d_circle_select_exec(bContext *C, wmOperator *op)
}
}
+ /* Otherwise this is freed by the gesture. */
+ if (wm_userdata == &wm_userdata_buf) {
+ WM_generic_user_data_free(wm_userdata);
+ }
+
return OPERATOR_FINISHED;
}
diff --git a/source/blender/editors/space_view3d/view3d_utils.c b/source/blender/editors/space_view3d/view3d_utils.c
index 91313657f59..bb8c1a40a05 100644
--- a/source/blender/editors/space_view3d/view3d_utils.c
+++ b/source/blender/editors/space_view3d/view3d_utils.c
@@ -86,21 +86,6 @@ void ED_view3d_background_color_get(const Scene *scene, const View3D *v3d, float
UI_GetThemeColor3fv(TH_BACK, r_color);
}
-void ED_view3d_cursor3d_calc_mat3(const Scene *scene, float mat[3][3])
-{
- const View3DCursor *cursor = &scene->cursor;
- BKE_scene_cursor_rot_to_mat3(cursor, mat);
-}
-
-void ED_view3d_cursor3d_calc_mat4(const Scene *scene, float mat[4][4])
-{
- const View3DCursor *cursor = &scene->cursor;
- float mat3[3][3];
- BKE_scene_cursor_rot_to_mat3(cursor, mat3);
- copy_m4_m3(mat, mat3);
- copy_v3_v3(mat[3], cursor->location);
-}
-
Camera *ED_view3d_camera_data_get(View3D *v3d, RegionView3D *rv3d)
{
/* establish the camera object,
diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c
index 2454358b687..5865efa0ffa 100644
--- a/source/blender/editors/space_view3d/view3d_view.c
+++ b/source/blender/editors/space_view3d/view3d_view.c
@@ -428,7 +428,7 @@ void ED_view3d_smooth_view_force_finish(bContext *C, View3D *v3d, ARegion *ar)
* can use them without redrawing first */
Depsgraph *depsgraph = CTX_data_depsgraph(C);
Scene *scene = CTX_data_scene(C);
- ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL);
+ ED_view3d_update_viewmat(depsgraph, scene, v3d, ar, NULL, NULL, NULL, false);
}
}