3D View: Move selection API to a Selection engine.
This commit moves the API of selecting faces, vertices and edges to a DRW manager engine. Reviewers: campbellbarton, fclem Subscribers: jbakker, brecht Differential Revision: https://developer.blender.org/D5090
This commit is contained in:
parent
a85963bed8
commit
651d8bfd98
Notes:
blender-bot
2023-02-14 08:38:11 +01:00
Referenced by issue #68405, Crash when trying to select object
|
@ -126,6 +126,7 @@ set(SRC
|
|||
engines/gpencil/gpencil_engine.h
|
||||
engines/gpencil/gpencil_render.c
|
||||
engines/gpencil/gpencil_shader_fx.c
|
||||
engines/select/select_engine.c
|
||||
|
||||
DRW_engine.h
|
||||
intern/DRW_render.h
|
||||
|
@ -150,6 +151,7 @@ set(SRC
|
|||
engines/external/external_engine.h
|
||||
engines/workbench/workbench_engine.h
|
||||
engines/workbench/workbench_private.h
|
||||
engines/select/select_engine.h
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
@ -363,6 +365,9 @@ data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_shadow_resolve_frag.glsl
|
|||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_swirl_frag.glsl SRC)
|
||||
data_to_c_simple(engines/gpencil/shaders/fx/gpencil_fx_wave_frag.glsl SRC)
|
||||
|
||||
data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC)
|
||||
data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC)
|
||||
|
||||
|
||||
list(APPEND INC
|
||||
)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "BLI_sys_types.h" /* for bool */
|
||||
|
||||
struct ARegion;
|
||||
struct Base;
|
||||
struct DRWInstanceDataList;
|
||||
struct DRWPass;
|
||||
struct Depsgraph;
|
||||
|
@ -136,19 +137,12 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
|
|||
void DRW_draw_depth_object(struct ARegion *ar,
|
||||
struct GPUViewport *viewport,
|
||||
struct Object *object);
|
||||
void DRW_draw_select_id_object(struct Scene *scene,
|
||||
struct RegionView3D *rv3d,
|
||||
struct Object *ob,
|
||||
short select_mode,
|
||||
bool draw_facedot,
|
||||
uint initial_offset,
|
||||
uint *r_vert_offset,
|
||||
uint *r_edge_offset,
|
||||
uint *r_face_offset);
|
||||
|
||||
void DRW_framebuffer_select_id_setup(struct ARegion *ar, const bool clear);
|
||||
void DRW_framebuffer_select_id_release(struct ARegion *ar);
|
||||
void DRW_framebuffer_select_id_read(const struct rcti *rect, uint *r_buf);
|
||||
void DRW_draw_select_id(struct Depsgraph *depsgraph,
|
||||
struct ARegion *ar,
|
||||
struct View3D *v3d,
|
||||
struct Base **bases,
|
||||
const uint bases_len,
|
||||
short select_mode);
|
||||
|
||||
/* grease pencil render */
|
||||
bool DRW_render_check_grease_pencil(struct Depsgraph *depsgraph);
|
||||
|
@ -181,4 +175,20 @@ void DRW_deferred_shader_remove(struct GPUMaterial *mat);
|
|||
struct DrawDataList *DRW_drawdatalist_from_id(struct ID *id);
|
||||
void DRW_drawdata_free(struct ID *id);
|
||||
|
||||
/* select_engine.c */
|
||||
void DRW_select_context_create(struct Depsgraph *depsgraph,
|
||||
struct Base **bases,
|
||||
const uint bases_len,
|
||||
short select_mode);
|
||||
bool DRW_select_elem_get(const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type);
|
||||
uint DRW_select_context_offset_for_object_elem(const uint base_index, char elem_type);
|
||||
uint DRW_select_context_elem_len(void);
|
||||
void DRW_framebuffer_select_id_read(const struct rcti *rect, uint *r_buf);
|
||||
void DRW_draw_select_id_object(struct Depsgraph *depsgraph,
|
||||
struct ViewLayer *view_layer,
|
||||
struct ARegion *ar,
|
||||
struct View3D *v3d,
|
||||
struct Object *ob,
|
||||
short select_mode);
|
||||
|
||||
#endif /* __DRW_ENGINE_H__ */
|
||||
|
|
|
@ -0,0 +1,647 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2019, Blender Foundation.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup draw_engine
|
||||
*
|
||||
* Engine for drawing a selection map where the pixels indicate the selection indices.
|
||||
*/
|
||||
|
||||
#include "BLI_rect.h"
|
||||
|
||||
#include "BKE_editmesh.h"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_screen_types.h"
|
||||
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "GPU_shader.h"
|
||||
#include "GPU_select.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "DRW_engine.h"
|
||||
#include "DRW_render.h"
|
||||
|
||||
#include "draw_cache_impl.h"
|
||||
|
||||
#include "select_engine.h"
|
||||
/* Shaders */
|
||||
|
||||
#define SELECT_ENGINE "SELECT_ENGINE"
|
||||
|
||||
/* *********** LISTS *********** */
|
||||
|
||||
/* GPUViewport.storage
|
||||
* Is freed everytime the viewport engine changes */
|
||||
typedef struct SELECTID_StorageList {
|
||||
struct SELECTID_PrivateData *g_data;
|
||||
} SELECTID_StorageList;
|
||||
|
||||
typedef struct SELECTID_PassList {
|
||||
struct DRWPass *select_id_face_pass;
|
||||
struct DRWPass *select_id_edge_pass;
|
||||
struct DRWPass *select_id_vert_pass;
|
||||
} SELECTID_PassList;
|
||||
|
||||
typedef struct SELECTID_Data {
|
||||
void *engine_type;
|
||||
DRWViewportEmptyList *fbl;
|
||||
DRWViewportEmptyList *txl;
|
||||
SELECTID_PassList *psl;
|
||||
SELECTID_StorageList *stl;
|
||||
} SELECTID_Data;
|
||||
|
||||
typedef struct SELECTID_Shaders {
|
||||
/* Depth Pre Pass */
|
||||
struct GPUShader *select_id_flat;
|
||||
struct GPUShader *select_id_uniform;
|
||||
} SELECTID_Shaders;
|
||||
|
||||
/* *********** STATIC *********** */
|
||||
|
||||
static struct {
|
||||
SELECTID_Shaders sh_data[GPU_SHADER_CFG_LEN];
|
||||
|
||||
struct GPUFrameBuffer *framebuffer_select_id;
|
||||
struct GPUTexture *texture_u32;
|
||||
|
||||
struct {
|
||||
struct BaseOffset *base_array_index_offsets;
|
||||
uint bases_len;
|
||||
uint last_base_drawn;
|
||||
/** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */
|
||||
uint last_index_drawn;
|
||||
|
||||
struct Depsgraph *depsgraph;
|
||||
short select_mode;
|
||||
} context;
|
||||
} e_data = {{{NULL}}}; /* Engine data */
|
||||
|
||||
typedef struct SELECTID_PrivateData {
|
||||
DRWShadingGroup *shgrp_face_unif;
|
||||
DRWShadingGroup *shgrp_face_flat;
|
||||
DRWShadingGroup *shgrp_edge;
|
||||
DRWShadingGroup *shgrp_vert;
|
||||
|
||||
DRWView *view_faces;
|
||||
DRWView *view_edges;
|
||||
DRWView *view_verts;
|
||||
} SELECTID_PrivateData; /* Transient data */
|
||||
|
||||
struct BaseOffset {
|
||||
/* For convenience only. */
|
||||
union {
|
||||
uint offset;
|
||||
uint face_start;
|
||||
};
|
||||
union {
|
||||
uint face;
|
||||
uint edge_start;
|
||||
};
|
||||
union {
|
||||
uint edge;
|
||||
uint vert_start;
|
||||
};
|
||||
uint vert;
|
||||
};
|
||||
|
||||
/* Shaders */
|
||||
extern char datatoc_common_view_lib_glsl[];
|
||||
extern char datatoc_selection_id_3D_vert_glsl[];
|
||||
extern char datatoc_selection_id_frag_glsl[];
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Selection Utilities
|
||||
* \{ */
|
||||
|
||||
static void draw_select_framebuffer_select_id_setup(void)
|
||||
{
|
||||
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
|
||||
int size[2];
|
||||
size[0] = GPU_texture_width(dtxl->depth);
|
||||
size[1] = GPU_texture_height(dtxl->depth);
|
||||
|
||||
if (e_data.framebuffer_select_id == NULL) {
|
||||
e_data.framebuffer_select_id = GPU_framebuffer_create();
|
||||
}
|
||||
|
||||
if ((e_data.texture_u32 != NULL) && ((GPU_texture_width(e_data.texture_u32) != size[0]) ||
|
||||
(GPU_texture_height(e_data.texture_u32) != size[1]))) {
|
||||
|
||||
GPU_texture_free(e_data.texture_u32);
|
||||
e_data.texture_u32 = NULL;
|
||||
}
|
||||
|
||||
if (e_data.texture_u32 == NULL) {
|
||||
e_data.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL);
|
||||
|
||||
GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, dtxl->depth, 0, 0);
|
||||
GPU_framebuffer_texture_attach(e_data.framebuffer_select_id, e_data.texture_u32, 0, 0);
|
||||
GPU_framebuffer_check_valid(e_data.framebuffer_select_id, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_select_id_object(void *vedata,
|
||||
Object *ob,
|
||||
short select_mode,
|
||||
bool draw_facedot,
|
||||
uint initial_offset,
|
||||
uint *r_vert_offset,
|
||||
uint *r_edge_offset,
|
||||
uint *r_face_offset)
|
||||
{
|
||||
SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
|
||||
|
||||
BLI_assert(initial_offset > 0);
|
||||
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
if (ob->mode & OB_MODE_EDIT) {
|
||||
Mesh *me = ob->data;
|
||||
BMEditMesh *em = me->edit_mesh;
|
||||
const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
|
||||
|
||||
DRW_mesh_batch_cache_validate(me);
|
||||
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
|
||||
|
||||
struct 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 (use_faceselect && 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);
|
||||
|
||||
DRWShadingGroup *face_shgrp;
|
||||
if (use_faceselect) {
|
||||
face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat);
|
||||
DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset);
|
||||
|
||||
if (draw_facedot) {
|
||||
DRW_shgroup_call(face_shgrp, geom_facedots, ob);
|
||||
}
|
||||
*r_face_offset = initial_offset + em->bm->totface;
|
||||
}
|
||||
else {
|
||||
face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_unif);
|
||||
DRW_shgroup_uniform_int_copy(face_shgrp, "id", 0);
|
||||
|
||||
*r_face_offset = initial_offset;
|
||||
}
|
||||
DRW_shgroup_call(face_shgrp, geom_faces, ob);
|
||||
|
||||
/* Unlike faces, only draw edges if edge select mode. */
|
||||
if (select_mode & SCE_SELECT_EDGE) {
|
||||
DRWShadingGroup *edge_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_edge);
|
||||
DRW_shgroup_uniform_int_copy(edge_shgrp, "offset", *(int *)r_face_offset);
|
||||
DRW_shgroup_call(edge_shgrp, geom_edges, ob);
|
||||
*r_edge_offset = *r_face_offset + em->bm->totedge;
|
||||
}
|
||||
else {
|
||||
/* Note that `r_vert_offset` is calculated from `r_edge_offset`.
|
||||
* Otherwise the first vertex is never selected, see: T53512. */
|
||||
*r_edge_offset = *r_face_offset;
|
||||
}
|
||||
|
||||
/* Unlike faces, only verts if vert select mode. */
|
||||
if (select_mode & SCE_SELECT_VERTEX) {
|
||||
DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert);
|
||||
DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", *(int *)r_edge_offset);
|
||||
DRW_shgroup_call(vert_shgrp, geom_verts, ob);
|
||||
*r_vert_offset = *r_edge_offset + em->bm->totvert;
|
||||
}
|
||||
else {
|
||||
*r_vert_offset = *r_edge_offset;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Mesh *me_orig = DEG_get_original_object(ob)->data;
|
||||
Mesh *me_eval = ob->data;
|
||||
|
||||
DRW_mesh_batch_cache_validate(me_eval);
|
||||
struct GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval);
|
||||
if ((me_orig->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))) {
|
||||
|
||||
struct GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval);
|
||||
DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true);
|
||||
|
||||
/* Only draw faces to mask out verts, we don't want their selection ID's. */
|
||||
DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_unif);
|
||||
DRW_shgroup_uniform_int_copy(face_shgrp, "id", 0);
|
||||
DRW_shgroup_call(face_shgrp, geom_faces, ob);
|
||||
|
||||
DRWShadingGroup *vert_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_vert);
|
||||
DRW_shgroup_uniform_int_copy(vert_shgrp, "offset", 1);
|
||||
DRW_shgroup_call(vert_shgrp, geom_verts, ob);
|
||||
|
||||
*r_face_offset = *r_edge_offset = initial_offset;
|
||||
*r_vert_offset = me_eval->totvert + 1;
|
||||
}
|
||||
else {
|
||||
const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
|
||||
DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide);
|
||||
|
||||
DRWShadingGroup *face_shgrp = DRW_shgroup_create_sub(stl->g_data->shgrp_face_flat);
|
||||
DRW_shgroup_uniform_int_copy(face_shgrp, "offset", *(int *)&initial_offset);
|
||||
DRW_shgroup_call(face_shgrp, geom_faces, ob);
|
||||
|
||||
*r_face_offset = initial_offset + me_eval->totpoly;
|
||||
*r_edge_offset = *r_vert_offset = *r_face_offset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OB_CURVE:
|
||||
case OB_SURF:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt)
|
||||
{
|
||||
if (select_mode & SCE_SELECT_FACE) {
|
||||
if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) {
|
||||
return true;
|
||||
}
|
||||
if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) {
|
||||
return true;
|
||||
}
|
||||
if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) {
|
||||
/* Since we can't deduce face selection when edges aren't visible - show dots. */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Engine Functions
|
||||
* \{ */
|
||||
|
||||
static void select_engine_init(void *vedata)
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
eGPUShaderConfig sh_cfg = draw_ctx->sh_cfg;
|
||||
|
||||
SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
|
||||
SELECTID_Shaders *sh_data = &e_data.sh_data[sh_cfg];
|
||||
|
||||
/* Prepass */
|
||||
if (!sh_data->select_id_flat) {
|
||||
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
|
||||
sh_data->select_id_flat = GPU_shader_create_from_arrays({
|
||||
.vert = (const char *[]){sh_cfg_data->lib,
|
||||
datatoc_common_view_lib_glsl,
|
||||
datatoc_selection_id_3D_vert_glsl,
|
||||
NULL},
|
||||
.frag = (const char *[]){datatoc_selection_id_frag_glsl, NULL},
|
||||
.defs = (const char *[]){sh_cfg_data->def, NULL},
|
||||
});
|
||||
}
|
||||
if (!sh_data->select_id_uniform) {
|
||||
const GPUShaderConfigData *sh_cfg_data = &GPU_shader_cfg_data[sh_cfg];
|
||||
sh_data->select_id_uniform = GPU_shader_create_from_arrays({
|
||||
.vert = (const char *[]){sh_cfg_data->lib,
|
||||
datatoc_common_view_lib_glsl,
|
||||
datatoc_selection_id_3D_vert_glsl,
|
||||
NULL},
|
||||
.frag = (const char *[]){datatoc_selection_id_frag_glsl, NULL},
|
||||
.defs = (const char *[]){sh_cfg_data->def, "#define UNIFORM_ID\n", NULL},
|
||||
});
|
||||
}
|
||||
|
||||
if (!stl->g_data) {
|
||||
/* Alloc transient pointers */
|
||||
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
|
||||
}
|
||||
|
||||
{
|
||||
/* Create view with depth offset */
|
||||
stl->g_data->view_faces = (DRWView *)DRW_view_default_get();
|
||||
stl->g_data->view_edges = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.0f);
|
||||
stl->g_data->view_verts = DRW_view_create_with_zoffset(draw_ctx->rv3d, 1.1f);
|
||||
}
|
||||
}
|
||||
|
||||
static void select_cache_init(void *vedata)
|
||||
{
|
||||
SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl;
|
||||
SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
|
||||
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
SELECTID_Shaders *sh_data = &e_data.sh_data[draw_ctx->sh_cfg];
|
||||
{
|
||||
psl->select_id_face_pass = DRW_pass_create("Face Pass", DRW_STATE_DEFAULT);
|
||||
stl->g_data->shgrp_face_unif = DRW_shgroup_create(sh_data->select_id_uniform,
|
||||
psl->select_id_face_pass);
|
||||
|
||||
stl->g_data->shgrp_face_flat = DRW_shgroup_create(sh_data->select_id_flat,
|
||||
psl->select_id_face_pass);
|
||||
|
||||
psl->select_id_edge_pass = DRW_pass_create(
|
||||
"Edge Pass", DRW_STATE_DEFAULT | DRW_STATE_FIRST_VERTEX_CONVENTION);
|
||||
|
||||
stl->g_data->shgrp_edge = DRW_shgroup_create(sh_data->select_id_flat,
|
||||
psl->select_id_edge_pass);
|
||||
|
||||
psl->select_id_vert_pass = DRW_pass_create("Vert Pass", DRW_STATE_DEFAULT);
|
||||
stl->g_data->shgrp_vert = DRW_shgroup_create(sh_data->select_id_flat,
|
||||
psl->select_id_vert_pass);
|
||||
|
||||
DRW_shgroup_uniform_float_copy(stl->g_data->shgrp_vert, "sizeVertex", G_draw.block.sizeVertex);
|
||||
|
||||
if (draw_ctx->sh_cfg == GPU_SHADER_CFG_CLIPPED) {
|
||||
DRW_shgroup_state_enable(stl->g_data->shgrp_face_unif, DRW_STATE_CLIP_PLANES);
|
||||
DRW_shgroup_state_enable(stl->g_data->shgrp_face_flat, DRW_STATE_CLIP_PLANES);
|
||||
DRW_shgroup_state_enable(stl->g_data->shgrp_edge, DRW_STATE_CLIP_PLANES);
|
||||
DRW_shgroup_state_enable(stl->g_data->shgrp_vert, DRW_STATE_CLIP_PLANES);
|
||||
}
|
||||
}
|
||||
|
||||
e_data.context.last_base_drawn = 0;
|
||||
e_data.context.last_index_drawn = 1;
|
||||
}
|
||||
|
||||
static void select_cache_populate(void *vedata, Object *ob)
|
||||
{
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
short select_mode = e_data.context.select_mode;
|
||||
|
||||
if (select_mode == -1) {
|
||||
ToolSettings *ts = draw_ctx->scene->toolsettings;
|
||||
select_mode = ts->selectmode;
|
||||
}
|
||||
|
||||
bool draw_facedot = check_ob_drawface_dot(select_mode, draw_ctx->v3d, ob->dt);
|
||||
|
||||
struct BaseOffset *base_ofs =
|
||||
&e_data.context.base_array_index_offsets[e_data.context.last_base_drawn++];
|
||||
|
||||
uint offset = e_data.context.last_index_drawn;
|
||||
|
||||
draw_select_id_object(vedata,
|
||||
ob,
|
||||
select_mode,
|
||||
draw_facedot,
|
||||
offset,
|
||||
&base_ofs->vert,
|
||||
&base_ofs->edge,
|
||||
&base_ofs->face);
|
||||
|
||||
base_ofs->offset = offset;
|
||||
e_data.context.last_index_drawn = base_ofs->vert;
|
||||
}
|
||||
|
||||
static void select_draw_scene(void *vedata)
|
||||
{
|
||||
SELECTID_StorageList *stl = ((SELECTID_Data *)vedata)->stl;
|
||||
SELECTID_PassList *psl = ((SELECTID_Data *)vedata)->psl;
|
||||
|
||||
/* Setup framebuffer */
|
||||
draw_select_framebuffer_select_id_setup();
|
||||
GPU_framebuffer_bind(e_data.framebuffer_select_id);
|
||||
|
||||
/* dithering and AA break color coding, so disable */
|
||||
glDisable(GL_DITHER);
|
||||
|
||||
GPU_framebuffer_clear_color_depth(e_data.framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
|
||||
|
||||
DRW_view_set_active(stl->g_data->view_faces);
|
||||
DRW_draw_pass(psl->select_id_face_pass);
|
||||
|
||||
DRW_view_set_active(stl->g_data->view_edges);
|
||||
DRW_draw_pass(psl->select_id_edge_pass);
|
||||
|
||||
DRW_view_set_active(stl->g_data->view_verts);
|
||||
DRW_draw_pass(psl->select_id_vert_pass);
|
||||
}
|
||||
|
||||
static void select_engine_free(void)
|
||||
{
|
||||
for (int sh_data_index = 0; sh_data_index < ARRAY_SIZE(e_data.sh_data); sh_data_index++) {
|
||||
SELECTID_Shaders *sh_data = &e_data.sh_data[sh_data_index];
|
||||
DRW_SHADER_FREE_SAFE(sh_data->select_id_flat);
|
||||
DRW_SHADER_FREE_SAFE(sh_data->select_id_uniform);
|
||||
}
|
||||
|
||||
DRW_TEXTURE_FREE_SAFE(e_data.texture_u32);
|
||||
GPU_FRAMEBUFFER_FREE_SAFE(e_data.framebuffer_select_id);
|
||||
MEM_SAFE_FREE(e_data.context.base_array_index_offsets);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Exposed `DRW_engine.h` functions
|
||||
* \{ */
|
||||
|
||||
bool DRW_select_elem_get(const uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type)
|
||||
{
|
||||
char elem_type = 0;
|
||||
uint elem_id;
|
||||
uint base_index = 0;
|
||||
|
||||
for (; base_index < e_data.context.bases_len; base_index++) {
|
||||
struct BaseOffset *base_ofs = &e_data.context.base_array_index_offsets[base_index];
|
||||
|
||||
if (base_ofs->face > sel_id) {
|
||||
elem_id = sel_id - base_ofs->face_start;
|
||||
elem_type = SCE_SELECT_FACE;
|
||||
break;
|
||||
}
|
||||
if (base_ofs->edge > sel_id) {
|
||||
elem_id = sel_id - base_ofs->edge_start;
|
||||
elem_type = SCE_SELECT_EDGE;
|
||||
break;
|
||||
}
|
||||
if (base_ofs->vert > sel_id) {
|
||||
elem_id = sel_id - base_ofs->vert_start;
|
||||
elem_type = SCE_SELECT_VERTEX;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (base_index == e_data.context.bases_len) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*r_elem = elem_id;
|
||||
|
||||
if (r_base_index) {
|
||||
*r_base_index = base_index;
|
||||
}
|
||||
|
||||
if (r_elem_type) {
|
||||
*r_elem_type = elem_type;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
uint DRW_select_context_offset_for_object_elem(const uint base_index, char elem_type)
|
||||
{
|
||||
struct BaseOffset *base_ofs = &e_data.context.base_array_index_offsets[base_index];
|
||||
|
||||
if (elem_type == SCE_SELECT_VERTEX) {
|
||||
return base_ofs->vert_start - 1;
|
||||
}
|
||||
if (elem_type == SCE_SELECT_EDGE) {
|
||||
return base_ofs->edge_start - 1;
|
||||
}
|
||||
if (elem_type == SCE_SELECT_FACE) {
|
||||
return base_ofs->face_start - 1;
|
||||
}
|
||||
BLI_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint DRW_select_context_elem_len(void)
|
||||
{
|
||||
return e_data.context.last_index_drawn;
|
||||
}
|
||||
|
||||
/* Read a block of pixels from the select frame buffer. */
|
||||
void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf)
|
||||
{
|
||||
/* clamp rect by texture */
|
||||
rcti r = {
|
||||
.xmin = 0,
|
||||
.xmax = GPU_texture_width(e_data.texture_u32),
|
||||
.ymin = 0,
|
||||
.ymax = GPU_texture_height(e_data.texture_u32),
|
||||
};
|
||||
|
||||
rcti rect_clamp = *rect;
|
||||
if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) {
|
||||
DRW_opengl_context_enable();
|
||||
GPU_framebuffer_bind(e_data.framebuffer_select_id);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glReadPixels(rect_clamp.xmin,
|
||||
rect_clamp.ymin,
|
||||
BLI_rcti_size_x(&rect_clamp),
|
||||
BLI_rcti_size_y(&rect_clamp),
|
||||
GL_RED_INTEGER,
|
||||
GL_UNSIGNED_INT,
|
||||
r_buf);
|
||||
|
||||
GPU_framebuffer_restore();
|
||||
DRW_opengl_context_disable();
|
||||
|
||||
if (!BLI_rcti_compare(rect, &rect_clamp)) {
|
||||
GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t buf_size = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect) * sizeof(*r_buf);
|
||||
|
||||
memset(r_buf, 0, buf_size);
|
||||
}
|
||||
}
|
||||
|
||||
void DRW_select_context_create(Depsgraph *depsgraph,
|
||||
Base **UNUSED(bases),
|
||||
const uint bases_len,
|
||||
short select_mode)
|
||||
{
|
||||
e_data.context.depsgraph = depsgraph;
|
||||
e_data.context.select_mode = select_mode;
|
||||
e_data.context.bases_len = bases_len;
|
||||
|
||||
MEM_SAFE_FREE(e_data.context.base_array_index_offsets);
|
||||
e_data.context.base_array_index_offsets = MEM_mallocN(
|
||||
sizeof(*e_data.context.base_array_index_offsets) * bases_len, __func__);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Legacy
|
||||
* \{ */
|
||||
|
||||
void DRW_draw_select_id_object(Depsgraph *depsgraph,
|
||||
ViewLayer *view_layer,
|
||||
ARegion *ar,
|
||||
View3D *v3d,
|
||||
Object *ob,
|
||||
short select_mode)
|
||||
{
|
||||
Base *base = BKE_view_layer_base_find(view_layer, ob);
|
||||
DRW_draw_select_id(depsgraph, ar, v3d, &base, 1, select_mode);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Engine Type
|
||||
* \{ */
|
||||
|
||||
static const DrawEngineDataSize select_data_size = DRW_VIEWPORT_DATA_SIZE(SELECTID_Data);
|
||||
|
||||
DrawEngineType draw_engine_select_type = {
|
||||
NULL,
|
||||
NULL,
|
||||
N_("Select ID"),
|
||||
&select_data_size,
|
||||
&select_engine_init,
|
||||
&select_engine_free,
|
||||
&select_cache_init,
|
||||
&select_cache_populate,
|
||||
NULL,
|
||||
NULL,
|
||||
&select_draw_scene,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* Note: currently unused, we may want to register so we can see this when debugging the view. */
|
||||
|
||||
RenderEngineType DRW_engine_viewport_select_type = {
|
||||
NULL,
|
||||
NULL,
|
||||
SELECT_ENGINE,
|
||||
N_("Select ID"),
|
||||
RE_INTERNAL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&draw_engine_select_type,
|
||||
{NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
/** \} */
|
||||
|
||||
#undef SELECT_ENGINE
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Copyright 2019, Blender Foundation.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* \ingroup draw_engine
|
||||
*/
|
||||
|
||||
#ifndef __SELECT_ENGINE_H__
|
||||
#define __SELECT_ENGINE_H__
|
||||
|
||||
extern DrawEngineType draw_engine_select_type;
|
||||
extern RenderEngineType DRW_engine_viewport_select_type;
|
||||
|
||||
#endif /* __SELECT_ID_ENGINE_H__ */
|
|
@ -0,0 +1,26 @@
|
|||
|
||||
uniform float sizeVertex;
|
||||
|
||||
in vec3 pos;
|
||||
|
||||
#ifndef UNIFORM_ID
|
||||
uniform int offset;
|
||||
in uint color;
|
||||
|
||||
flat out uint id;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifndef UNIFORM_ID
|
||||
id = floatBitsToUint(intBitsToFloat(offset)) + color;
|
||||
#endif
|
||||
|
||||
vec3 world_pos = point_object_to_world(pos);
|
||||
gl_Position = point_world_to_ndc(world_pos);
|
||||
gl_PointSize = sizeVertex;
|
||||
|
||||
#ifdef USE_WORLD_CLIP_PLANES
|
||||
world_clip_planes_calc_clip_distance(world_pos);
|
||||
#endif
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
#ifdef UNIFORM_ID
|
||||
uniform uint id;
|
||||
uniform int id;
|
||||
# define id floatBitsToUint(intBitsToFloat(id))
|
||||
#else
|
||||
flat in uint id;
|
||||
#endif
|
|
@ -89,6 +89,7 @@
|
|||
#include "engines/workbench/workbench_engine.h"
|
||||
#include "engines/external/external_engine.h"
|
||||
#include "engines/gpencil/gpencil_engine.h"
|
||||
#include "engines/select/select_engine.h"
|
||||
|
||||
#include "GPU_context.h"
|
||||
|
||||
|
@ -2136,16 +2137,13 @@ void DRW_custom_pipeline(DrawEngineType *draw_engine_type,
|
|||
|
||||
static struct DRWSelectBuffer {
|
||||
struct GPUFrameBuffer *framebuffer_depth_only;
|
||||
struct GPUFrameBuffer *framebuffer_select_id;
|
||||
struct GPUTexture *texture_depth;
|
||||
struct GPUTexture *texture_u32;
|
||||
} g_select_buffer = {NULL};
|
||||
|
||||
static void draw_select_framebuffer_depth_only_setup(const int size[2])
|
||||
{
|
||||
if (g_select_buffer.framebuffer_depth_only == NULL) {
|
||||
g_select_buffer.framebuffer_depth_only = GPU_framebuffer_create();
|
||||
g_select_buffer.framebuffer_select_id = GPU_framebuffer_create();
|
||||
}
|
||||
|
||||
if ((g_select_buffer.texture_depth != NULL) &&
|
||||
|
@ -2162,32 +2160,7 @@ static void draw_select_framebuffer_depth_only_setup(const int size[2])
|
|||
GPU_framebuffer_texture_attach(
|
||||
g_select_buffer.framebuffer_depth_only, g_select_buffer.texture_depth, 0, 0);
|
||||
|
||||
GPU_framebuffer_texture_attach(
|
||||
g_select_buffer.framebuffer_select_id, g_select_buffer.texture_depth, 0, 0);
|
||||
|
||||
GPU_framebuffer_check_valid(g_select_buffer.framebuffer_depth_only, NULL);
|
||||
GPU_framebuffer_check_valid(g_select_buffer.framebuffer_select_id, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_select_framebuffer_select_id_setup(const int size[2])
|
||||
{
|
||||
draw_select_framebuffer_depth_only_setup(size);
|
||||
|
||||
if ((g_select_buffer.texture_u32 != NULL) &&
|
||||
((GPU_texture_width(g_select_buffer.texture_u32) != size[0]) ||
|
||||
(GPU_texture_height(g_select_buffer.texture_u32) != size[1]))) {
|
||||
GPU_texture_free(g_select_buffer.texture_u32);
|
||||
g_select_buffer.texture_u32 = NULL;
|
||||
}
|
||||
|
||||
if (g_select_buffer.texture_u32 == NULL) {
|
||||
g_select_buffer.texture_u32 = GPU_texture_create_2d(size[0], size[1], GPU_R32UI, NULL, NULL);
|
||||
|
||||
GPU_framebuffer_texture_attach(
|
||||
g_select_buffer.framebuffer_select_id, g_select_buffer.texture_u32, 0, 0);
|
||||
|
||||
GPU_framebuffer_check_valid(g_select_buffer.framebuffer_select_id, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2575,6 +2548,78 @@ void DRW_draw_depth_loop_gpencil(struct Depsgraph *depsgraph,
|
|||
DRW_opengl_context_disable();
|
||||
}
|
||||
|
||||
void DRW_draw_select_id(Depsgraph *depsgraph,
|
||||
ARegion *ar,
|
||||
View3D *v3d,
|
||||
Base **bases,
|
||||
const uint bases_len,
|
||||
short select_mode)
|
||||
{
|
||||
Scene *scene = DEG_get_evaluated_scene(depsgraph);
|
||||
ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph);
|
||||
|
||||
DRW_select_context_create(depsgraph, bases, bases_len, select_mode);
|
||||
|
||||
DRW_opengl_context_enable();
|
||||
|
||||
/* Reset before using it. */
|
||||
drw_state_prepare_clean_for_draw(&DST);
|
||||
DST.buffer_finish_called = true;
|
||||
|
||||
/* Instead of 'DRW_context_state_init(C, &DST.draw_ctx)', assign from args */
|
||||
DST.draw_ctx = (DRWContextState){
|
||||
.ar = ar,
|
||||
.rv3d = ar->regiondata,
|
||||
.v3d = v3d,
|
||||
.scene = scene,
|
||||
.view_layer = view_layer,
|
||||
.obact = OBACT(view_layer),
|
||||
.depsgraph = depsgraph,
|
||||
};
|
||||
|
||||
use_drw_engine(&draw_engine_select_type);
|
||||
drw_context_state_init();
|
||||
|
||||
/* Setup viewport */
|
||||
DST.viewport = WM_draw_region_get_viewport(ar, 0);
|
||||
drw_viewport_var_init();
|
||||
|
||||
/* Update ubos */
|
||||
DRW_globals_update();
|
||||
|
||||
/* Init engines */
|
||||
drw_engines_init();
|
||||
|
||||
{
|
||||
drw_engines_cache_init();
|
||||
|
||||
/* Keep `base_index` in sync with `e_data.context.last_base_drawn`.
|
||||
* So don't skip objects. */
|
||||
for (uint base_index = 0; base_index < bases_len; base_index++) {
|
||||
Object *obj_eval = DEG_get_evaluated_object(depsgraph, bases[base_index]->object);
|
||||
drw_engines_cache_populate(obj_eval);
|
||||
}
|
||||
|
||||
drw_engines_cache_finish();
|
||||
}
|
||||
|
||||
/* Start Drawing */
|
||||
DRW_state_reset();
|
||||
drw_engines_draw_scene();
|
||||
DRW_state_reset();
|
||||
|
||||
drw_engines_disable();
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Avoid accidental reuse. */
|
||||
drw_state_ensure_not_reused(&DST);
|
||||
#endif
|
||||
|
||||
/* Changin context */
|
||||
GPU_framebuffer_restore();
|
||||
DRW_opengl_context_disable();
|
||||
}
|
||||
|
||||
/** See #DRW_shgroup_world_clip_planes_from_rv3d. */
|
||||
static void draw_world_clip_planes_from_rv3d(GPUBatch *batch, const float world_clip_planes[6][4])
|
||||
{
|
||||
|
@ -2646,294 +2691,6 @@ void DRW_draw_depth_object(ARegion *ar, GPUViewport *viewport, Object *object)
|
|||
DRW_opengl_context_disable();
|
||||
}
|
||||
|
||||
static void draw_mesh_verts(GPUBatch *batch, uint 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) {
|
||||
draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
|
||||
}
|
||||
GPU_batch_draw(batch);
|
||||
}
|
||||
|
||||
static void draw_mesh_edges(GPUBatch *batch, uint 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) {
|
||||
draw_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 draw_mesh_face(GPUBatch *batch,
|
||||
uint offset,
|
||||
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", offset);
|
||||
if (world_clip_planes != NULL) {
|
||||
draw_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) {
|
||||
draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
|
||||
}
|
||||
GPU_batch_draw(batch);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_mesh_face_dot(GPUBatch *batch, uint offset, 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", offset);
|
||||
if (world_clip_planes != NULL) {
|
||||
draw_world_clip_planes_from_rv3d(batch, world_clip_planes);
|
||||
}
|
||||
GPU_batch_draw(batch);
|
||||
}
|
||||
|
||||
void DRW_draw_select_id_object(Scene *scene,
|
||||
RegionView3D *rv3d,
|
||||
Object *ob,
|
||||
short select_mode,
|
||||
bool draw_facedot,
|
||||
uint initial_offset,
|
||||
uint *r_vert_offset,
|
||||
uint *r_edge_offset,
|
||||
uint *r_face_offset)
|
||||
{
|
||||
ToolSettings *ts = scene->toolsettings;
|
||||
if (select_mode == -1) {
|
||||
select_mode = ts->selectmode;
|
||||
}
|
||||
|
||||
/* Init the scene of the draw context. When using face dot selection on
|
||||
* when the subsurf modifier is active on the cage, the scene needs to be
|
||||
* valid. It is read from the context in the
|
||||
* `DRW_mesh_batch_cache_create_requested` and used in the `isDisabled`
|
||||
* method of the SubSurfModifier. */
|
||||
DRWContextState *draw_ctx = &DST.draw_ctx;
|
||||
draw_ctx->scene = scene;
|
||||
|
||||
GPU_matrix_mul(ob->obmat);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
BLI_assert(initial_offset > 0);
|
||||
|
||||
switch (ob->type) {
|
||||
case OB_MESH:
|
||||
if (ob->mode & OB_MODE_EDIT) {
|
||||
Mesh *me = ob->data;
|
||||
BMEditMesh *em = me->edit_mesh;
|
||||
const bool use_faceselect = (select_mode & SCE_SELECT_FACE) != 0;
|
||||
|
||||
DRW_mesh_batch_cache_validate(me);
|
||||
|
||||
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 (use_faceselect && 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);
|
||||
|
||||
draw_mesh_face(geom_faces, initial_offset, use_faceselect, world_clip_planes);
|
||||
|
||||
if (use_faceselect && draw_facedot) {
|
||||
draw_mesh_face_dot(geom_facedots, initial_offset, world_clip_planes);
|
||||
}
|
||||
|
||||
if (select_mode & SCE_SELECT_FACE) {
|
||||
*r_face_offset = initial_offset + em->bm->totface;
|
||||
}
|
||||
else {
|
||||
*r_face_offset = initial_offset;
|
||||
}
|
||||
|
||||
ED_view3d_polygon_offset(rv3d, 1.0);
|
||||
|
||||
/* Unlike faces, only draw edges if edge select mode. */
|
||||
if (select_mode & SCE_SELECT_EDGE) {
|
||||
draw_mesh_edges(geom_edges, *r_face_offset, world_clip_planes);
|
||||
*r_edge_offset = *r_face_offset + em->bm->totedge;
|
||||
}
|
||||
else {
|
||||
/* Note that `r_vert_offset` is calculated from `r_edge_offset`.
|
||||
* Otherwise the first vertex is never selected, see: T53512. */
|
||||
*r_edge_offset = *r_face_offset;
|
||||
}
|
||||
|
||||
ED_view3d_polygon_offset(rv3d, 1.1);
|
||||
|
||||
/* Unlike faces, only verts if vert select mode. */
|
||||
if (select_mode & SCE_SELECT_VERTEX) {
|
||||
draw_mesh_verts(geom_verts, *r_edge_offset, world_clip_planes);
|
||||
*r_vert_offset = *r_edge_offset + em->bm->totvert;
|
||||
}
|
||||
else {
|
||||
*r_vert_offset = *r_edge_offset;
|
||||
}
|
||||
|
||||
ED_view3d_polygon_offset(rv3d, 0.0);
|
||||
}
|
||||
else {
|
||||
Mesh *me_orig = DEG_get_original_object(ob)->data;
|
||||
Mesh *me_eval = ob->data;
|
||||
|
||||
DRW_mesh_batch_cache_validate(me_eval);
|
||||
GPUBatch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(me_eval);
|
||||
if ((me_orig->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))) {
|
||||
|
||||
GPUBatch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(me_eval);
|
||||
DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, true);
|
||||
|
||||
/* Only draw faces to mask out verts, we don't want their selection ID's. */
|
||||
draw_mesh_face(geom_faces, 0, false, world_clip_planes);
|
||||
draw_mesh_verts(geom_verts, 1, world_clip_planes);
|
||||
|
||||
*r_face_offset = *r_edge_offset = initial_offset;
|
||||
*r_vert_offset = me_eval->totvert + 1;
|
||||
}
|
||||
else {
|
||||
const bool use_hide = (me_orig->editflag & ME_EDIT_PAINT_FACE_SEL);
|
||||
DRW_mesh_batch_cache_create_requested(ob, me_eval, NULL, false, use_hide);
|
||||
|
||||
draw_mesh_face(geom_faces, initial_offset, true, world_clip_planes);
|
||||
|
||||
*r_face_offset = initial_offset + me_eval->totpoly;
|
||||
*r_edge_offset = *r_vert_offset = *r_face_offset;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case OB_CURVE:
|
||||
case OB_SURF:
|
||||
break;
|
||||
}
|
||||
|
||||
GPU_matrix_set(rv3d->viewmat);
|
||||
}
|
||||
|
||||
/* Set an opengl context to be used with shaders that draw on U32 colors. */
|
||||
void DRW_framebuffer_select_id_setup(ARegion *ar, const bool clear)
|
||||
{
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
|
||||
DRW_opengl_context_enable();
|
||||
|
||||
/* Setup framebuffer */
|
||||
int viewport_size[2] = {ar->winx, ar->winy};
|
||||
draw_select_framebuffer_select_id_setup(viewport_size);
|
||||
GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id);
|
||||
|
||||
/* dithering and AA break color coding, so disable */
|
||||
glDisable(GL_DITHER);
|
||||
|
||||
GPU_depth_test(true);
|
||||
GPU_program_point_size(false);
|
||||
|
||||
if (clear) {
|
||||
GPU_framebuffer_clear_color_depth(
|
||||
g_select_buffer.framebuffer_select_id, (const float[4]){0.0f}, 1.0f);
|
||||
}
|
||||
|
||||
if (rv3d->rflag & RV3D_CLIPPING) {
|
||||
ED_view3d_clipping_set(rv3d);
|
||||
}
|
||||
}
|
||||
|
||||
/* Ends the context for selection and restoring the previous one. */
|
||||
void DRW_framebuffer_select_id_release(ARegion *ar)
|
||||
{
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
|
||||
if (rv3d->rflag & RV3D_CLIPPING) {
|
||||
ED_view3d_clipping_disable();
|
||||
}
|
||||
|
||||
GPU_depth_test(false);
|
||||
|
||||
GPU_framebuffer_restore();
|
||||
|
||||
DRW_opengl_context_disable();
|
||||
}
|
||||
|
||||
/* Read a block of pixels from the select frame buffer. */
|
||||
void DRW_framebuffer_select_id_read(const rcti *rect, uint *r_buf)
|
||||
{
|
||||
/* clamp rect by texture */
|
||||
rcti r = {
|
||||
.xmin = 0,
|
||||
.xmax = GPU_texture_width(g_select_buffer.texture_u32),
|
||||
.ymin = 0,
|
||||
.ymax = GPU_texture_height(g_select_buffer.texture_u32),
|
||||
};
|
||||
|
||||
rcti rect_clamp = *rect;
|
||||
if (BLI_rcti_isect(&r, &rect_clamp, &rect_clamp)) {
|
||||
DRW_opengl_context_enable();
|
||||
GPU_framebuffer_bind(g_select_buffer.framebuffer_select_id);
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glReadPixels(rect_clamp.xmin,
|
||||
rect_clamp.ymin,
|
||||
BLI_rcti_size_x(&rect_clamp),
|
||||
BLI_rcti_size_y(&rect_clamp),
|
||||
GL_RED_INTEGER,
|
||||
GL_UNSIGNED_INT,
|
||||
r_buf);
|
||||
|
||||
GPU_framebuffer_restore();
|
||||
DRW_opengl_context_disable();
|
||||
|
||||
if (!BLI_rcti_compare(rect, &rect_clamp)) {
|
||||
GPU_select_buffer_stride_realign(rect, &rect_clamp, r_buf);
|
||||
}
|
||||
}
|
||||
else {
|
||||
size_t buf_size = BLI_rcti_size_x(rect) * BLI_rcti_size_y(rect) * sizeof(*r_buf);
|
||||
|
||||
memset(r_buf, 0, buf_size);
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
@ -3089,6 +2846,7 @@ void DRW_engines_register(void)
|
|||
DRW_engine_register(&draw_engine_pose_type);
|
||||
DRW_engine_register(&draw_engine_sculpt_type);
|
||||
DRW_engine_register(&draw_engine_gpencil_type);
|
||||
DRW_engine_register(&draw_engine_select_type);
|
||||
|
||||
/* setup callbacks */
|
||||
{
|
||||
|
@ -3123,9 +2881,7 @@ void DRW_engines_free(void)
|
|||
|
||||
DRW_opengl_context_enable();
|
||||
|
||||
DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_u32);
|
||||
DRW_TEXTURE_FREE_SAFE(g_select_buffer.texture_depth);
|
||||
GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_select_id);
|
||||
GPU_FRAMEBUFFER_FREE_SAFE(g_select_buffer.framebuffer_depth_only);
|
||||
|
||||
DRW_hair_free();
|
||||
|
|
|
@ -512,26 +512,6 @@ int view3d_opengl_select(struct ViewContext *vc,
|
|||
eV3DSelectObjectFilter select_filter);
|
||||
|
||||
/* view3d_select.c */
|
||||
struct EDSelectID_Context;
|
||||
struct EDSelectID_Context *ED_view3d_select_id_context_create(struct ViewContext *vc,
|
||||
struct Base **bases,
|
||||
const uint bases_len,
|
||||
short select_mode);
|
||||
|
||||
void ED_view3d_select_id_context_destroy(struct EDSelectID_Context *sel_id_ctx);
|
||||
void ED_view3d_select_id_validate_view_matrices(struct EDSelectID_Context *sel_id_ctx,
|
||||
struct ViewContext *vc);
|
||||
|
||||
uint ED_view3d_select_id_context_offset_for_object_elem(
|
||||
const struct EDSelectID_Context *sel_id_ctx, int base_index, char elem_type);
|
||||
|
||||
uint ED_view3d_select_id_context_elem_len(const struct EDSelectID_Context *sel_id_ctx);
|
||||
bool ED_view3d_select_id_elem_get(struct EDSelectID_Context *sel_id_ctx,
|
||||
const uint sel_id,
|
||||
uint *r_elem,
|
||||
uint *r_base_index,
|
||||
char *r_elem_type);
|
||||
|
||||
float ED_view3d_select_dist_px(void);
|
||||
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc);
|
||||
void ED_view3d_viewcontext_init_object(struct ViewContext *vc, struct Object *obact);
|
||||
|
|
|
@ -23,6 +23,7 @@ set(INC
|
|||
../../blentranslation
|
||||
../../bmesh
|
||||
../../depsgraph
|
||||
../../draw
|
||||
../../gpu
|
||||
../../imbuf
|
||||
../../makesdna
|
||||
|
|
|
@ -68,6 +68,8 @@
|
|||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "DRW_engine.h"
|
||||
|
||||
#include "mesh_intern.h" /* own include */
|
||||
|
||||
/* use bmesh operator flags for a few operators */
|
||||
|
@ -197,15 +199,11 @@ void EDBM_automerge(Scene *scene, Object *obedit, bool update, const char hflag)
|
|||
/** \name Back-Buffer OpenGL Selection
|
||||
* \{ */
|
||||
|
||||
static BMElem *EDBM_select_id_bm_elem_get(struct EDSelectID_Context *sel_id_ctx,
|
||||
Base **bases,
|
||||
const uint sel_id,
|
||||
uint *r_base_index)
|
||||
static BMElem *edbm_select_id_bm_elem_get(Base **bases, const uint sel_id, uint *r_base_index)
|
||||
{
|
||||
uint elem_id;
|
||||
char elem_type = 0;
|
||||
bool success = ED_view3d_select_id_elem_get(
|
||||
sel_id_ctx, sel_id, &elem_id, r_base_index, &elem_type);
|
||||
bool success = DRW_select_elem_get(sel_id, &elem_id, r_base_index, &elem_type);
|
||||
|
||||
if (success) {
|
||||
Object *obedit = bases[*r_base_index]->object;
|
||||
|
@ -335,20 +333,17 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
|
|||
{
|
||||
FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_VERTEX);
|
||||
|
||||
struct EDSelectID_Context *sel_id_ctx = ED_view3d_select_id_context_create(
|
||||
vc, bases, bases_len, select_mode);
|
||||
DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, select_mode);
|
||||
|
||||
index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px);
|
||||
|
||||
if (index) {
|
||||
eve = (BMVert *)EDBM_select_id_bm_elem_get(sel_id_ctx, bases, index, &base_index);
|
||||
eve = (BMVert *)edbm_select_id_bm_elem_get(bases, index, &base_index);
|
||||
}
|
||||
else {
|
||||
eve = NULL;
|
||||
}
|
||||
|
||||
ED_view3d_select_id_context_destroy(sel_id_ctx);
|
||||
|
||||
FAKE_SELECT_MODE_END(vc, fake_select_mode);
|
||||
}
|
||||
|
||||
|
@ -564,20 +559,17 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
|
|||
{
|
||||
FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_EDGE);
|
||||
|
||||
struct EDSelectID_Context *sel_id_ctx = ED_view3d_select_id_context_create(
|
||||
vc, bases, bases_len, select_mode);
|
||||
DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, select_mode);
|
||||
|
||||
index = ED_select_buffer_find_nearest_to_point(vc->mval, 1, UINT_MAX, &dist_px);
|
||||
|
||||
if (index) {
|
||||
eed = (BMEdge *)EDBM_select_id_bm_elem_get(sel_id_ctx, bases, index, &base_index);
|
||||
eed = (BMEdge *)edbm_select_id_bm_elem_get(bases, index, &base_index);
|
||||
}
|
||||
else {
|
||||
eed = NULL;
|
||||
}
|
||||
|
||||
ED_view3d_select_id_context_destroy(sel_id_ctx);
|
||||
|
||||
FAKE_SELECT_MODE_END(vc, fake_select_mode);
|
||||
}
|
||||
|
||||
|
@ -777,20 +769,17 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
|
|||
{
|
||||
FAKE_SELECT_MODE_BEGIN(vc, fake_select_mode, select_mode, SCE_SELECT_FACE);
|
||||
|
||||
struct EDSelectID_Context *sel_id_ctx = ED_view3d_select_id_context_create(
|
||||
vc, bases, bases_len, select_mode);
|
||||
DRW_draw_select_id(vc->depsgraph, vc->ar, vc->v3d, bases, bases_len, select_mode);
|
||||
|
||||
index = ED_select_buffer_sample_point(vc->mval);
|
||||
|
||||
if (index) {
|
||||
efa = (BMFace *)EDBM_select_id_bm_elem_get(sel_id_ctx, bases, index, &base_index);
|
||||
efa = (BMFace *)edbm_select_id_bm_elem_get(bases, index, &base_index);
|
||||
}
|
||||
else {
|
||||
efa = NULL;
|
||||
}
|
||||
|
||||
ED_view3d_select_id_context_destroy(sel_id_ctx);
|
||||
|
||||
FAKE_SELECT_MODE_END(vc, fake_select_mode);
|
||||
}
|
||||
|
||||
|
|
|
@ -155,11 +155,13 @@ void ED_view3d_clipping_enable(void)
|
|||
/**
|
||||
* \note Only use in object mode.
|
||||
*/
|
||||
static void validate_object_select_id(
|
||||
struct Depsgraph *depsgraph, Scene *scene, ARegion *ar, View3D *v3d, Object *obact)
|
||||
static void validate_object_select_id(struct Depsgraph *depsgraph,
|
||||
Scene *scene,
|
||||
ViewLayer *view_layer,
|
||||
ARegion *ar,
|
||||
View3D *v3d,
|
||||
Object *obact)
|
||||
{
|
||||
RegionView3D *rv3d = ar->regiondata;
|
||||
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(depsgraph, &scene->id);
|
||||
Object *obact_eval = DEG_get_evaluated_object(depsgraph, obact);
|
||||
|
||||
BLI_assert(ar->regiontype == RGN_TYPE_WINDOW);
|
||||
|
@ -186,19 +188,8 @@ static void validate_object_select_id(
|
|||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
DRW_draw_select_id_object(
|
||||
depsgraph, view_layer, ar, v3d, obact, scene->toolsettings->selectmode);
|
||||
}
|
||||
|
||||
/* TODO: Create a flag in `DRW_manager` because the drawing is no longer
|
||||
|
@ -233,7 +224,8 @@ 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);
|
||||
validate_object_select_id(
|
||||
vc->depsgraph, vc->scene, vc->view_layer, vc->ar, vc->v3d, vc->obact);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,192 +110,6 @@
|
|||
|
||||
// #include "PIL_time_utildefines.h"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Selection Utilities
|
||||
* \{ */
|
||||
|
||||
struct EDBaseOffset {
|
||||
/* For convenience only. */
|
||||
union {
|
||||
uint offset;
|
||||
uint face_start;
|
||||
};
|
||||
union {
|
||||
uint face;
|
||||
uint edge_start;
|
||||
};
|
||||
union {
|
||||
uint edge;
|
||||
uint vert_start;
|
||||
};
|
||||
uint vert;
|
||||
};
|
||||
|
||||
struct EDSelectID_Context {
|
||||
struct EDBaseOffset *base_array_index_offsets;
|
||||
/** Borrow from caller (not freed). */
|
||||
struct Base **bases;
|
||||
uint bases_len;
|
||||
/** Total number of items `base_array_index_offsets[bases_len - 1].vert`. */
|
||||
uint base_array_index_len;
|
||||
/** Used to check for changes. (Use depsgraph instead?). */
|
||||
float persmat[4][4];
|
||||
short select_mode;
|
||||
};
|
||||
|
||||
static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, char dt)
|
||||
{
|
||||
if (select_mode & SCE_SELECT_FACE) {
|
||||
if ((dt < OB_SOLID) || XRAY_FLAG_ENABLED(v3d)) {
|
||||
return true;
|
||||
}
|
||||
if (v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_FACE_DOT) {
|
||||
return true;
|
||||
}
|
||||
if ((v3d->overlay.edit_flag & V3D_OVERLAY_EDIT_EDGES) == 0) {
|
||||
/* Since we can't deduce face selection when edges aren't visible - show dots. */
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void ed_select_id_draw_bases(struct EDSelectID_Context *sel_id_ctx,
|
||||
ViewContext *vc,
|
||||
short select_mode)
|
||||
{
|
||||
Scene *scene_eval = (Scene *)DEG_get_evaluated_id(vc->depsgraph, &vc->scene->id);
|
||||
DRW_framebuffer_select_id_setup(vc->ar, true);
|
||||
|
||||
uint offset = 1;
|
||||
for (uint base_index = 0; base_index < sel_id_ctx->bases_len; base_index++) {
|
||||
Object *ob_eval = DEG_get_evaluated_object(vc->depsgraph,
|
||||
sel_id_ctx->bases[base_index]->object);
|
||||
|
||||
struct EDBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index];
|
||||
bool draw_facedot = check_ob_drawface_dot(select_mode, vc->v3d, ob_eval->dt);
|
||||
|
||||
DRW_draw_select_id_object(scene_eval,
|
||||
vc->rv3d,
|
||||
ob_eval,
|
||||
select_mode,
|
||||
draw_facedot,
|
||||
offset,
|
||||
&base_ofs->vert,
|
||||
&base_ofs->edge,
|
||||
&base_ofs->face);
|
||||
|
||||
base_ofs->offset = offset;
|
||||
offset = base_ofs->vert;
|
||||
}
|
||||
|
||||
sel_id_ctx->base_array_index_len = offset;
|
||||
|
||||
DRW_framebuffer_select_id_release(vc->ar);
|
||||
}
|
||||
|
||||
void ED_view3d_select_id_validate_view_matrices(struct EDSelectID_Context *sel_id_ctx,
|
||||
ViewContext *vc)
|
||||
{
|
||||
if (!compare_m4m4(sel_id_ctx->persmat, vc->rv3d->persmat, FLT_EPSILON)) {
|
||||
ed_select_id_draw_bases(sel_id_ctx, vc, sel_id_ctx->select_mode);
|
||||
}
|
||||
}
|
||||
|
||||
uint ED_view3d_select_id_context_offset_for_object_elem(
|
||||
const struct EDSelectID_Context *sel_id_ctx, int base_index, char elem_type)
|
||||
{
|
||||
struct EDBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index];
|
||||
if (elem_type == SCE_SELECT_VERTEX) {
|
||||
return base_ofs->vert_start - 1;
|
||||
}
|
||||
if (elem_type == SCE_SELECT_EDGE) {
|
||||
return base_ofs->edge_start - 1;
|
||||
}
|
||||
if (elem_type == SCE_SELECT_FACE) {
|
||||
return base_ofs->face_start - 1;
|
||||
}
|
||||
BLI_assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint ED_view3d_select_id_context_elem_len(const struct EDSelectID_Context *sel_id_ctx)
|
||||
{
|
||||
return sel_id_ctx->base_array_index_len;
|
||||
}
|
||||
|
||||
struct EDSelectID_Context *ED_view3d_select_id_context_create(ViewContext *vc,
|
||||
Base **bases,
|
||||
const uint bases_len,
|
||||
short select_mode)
|
||||
{
|
||||
struct EDSelectID_Context *sel_id_ctx = MEM_mallocN(sizeof(*sel_id_ctx), __func__);
|
||||
sel_id_ctx->base_array_index_offsets = MEM_mallocN(sizeof(struct EDBaseOffset) * bases_len,
|
||||
__func__);
|
||||
sel_id_ctx->bases = bases;
|
||||
sel_id_ctx->bases_len = bases_len;
|
||||
copy_m4_m4(sel_id_ctx->persmat, vc->rv3d->persmat);
|
||||
sel_id_ctx->select_mode = select_mode;
|
||||
ed_select_id_draw_bases(sel_id_ctx, vc, select_mode);
|
||||
|
||||
return sel_id_ctx;
|
||||
}
|
||||
|
||||
void ED_view3d_select_id_context_destroy(struct EDSelectID_Context *sel_id_ctx)
|
||||
{
|
||||
MEM_freeN(sel_id_ctx->base_array_index_offsets);
|
||||
MEM_freeN(sel_id_ctx);
|
||||
}
|
||||
|
||||
bool ED_view3d_select_id_elem_get(struct EDSelectID_Context *sel_id_ctx,
|
||||
const uint sel_id,
|
||||
uint *r_elem,
|
||||
uint *r_base_index,
|
||||
char *r_elem_type)
|
||||
{
|
||||
char elem_type = 0;
|
||||
uint elem_id;
|
||||
uint base_index = 0;
|
||||
|
||||
while (true) {
|
||||
struct EDBaseOffset *base_ofs = &sel_id_ctx->base_array_index_offsets[base_index];
|
||||
if (base_ofs->face > sel_id) {
|
||||
elem_id = sel_id - base_ofs->face_start;
|
||||
elem_type = SCE_SELECT_FACE;
|
||||
break;
|
||||
}
|
||||
if (base_ofs->edge > sel_id) {
|
||||
elem_id = sel_id - base_ofs->edge_start;
|
||||
elem_type = SCE_SELECT_EDGE;
|
||||
break;
|
||||
}
|
||||
if (base_ofs->vert > sel_id) {
|
||||
elem_id = sel_id - base_ofs->vert_start;
|
||||
elem_type = SCE_SELECT_VERTEX;
|
||||
break;
|
||||
}
|
||||
|
||||
base_index++;
|
||||
if (base_index >= sel_id_ctx->bases_len) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*r_elem = elem_id;
|
||||
|
||||
if (r_base_index) {
|
||||
*r_base_index = base_index;
|
||||
}
|
||||
|
||||
if (r_elem_type) {
|
||||
*r_elem_type = elem_type;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Public Utilities
|
||||
* \{ */
|
||||
|
@ -385,7 +199,6 @@ static bool object_deselect_all_except(ViewLayer *view_layer, Base *b)
|
|||
struct EditSelectBuf_Cache {
|
||||
Base **bases;
|
||||
uint bases_len;
|
||||
struct EDSelectID_Context *sel_id_ctx;
|
||||
BLI_bitmap *select_bitmap;
|
||||
};
|
||||
|
||||
|
@ -407,8 +220,12 @@ static void editselect_buf_cache_init(struct EditSelectBuf_Cache *esel, ViewCont
|
|||
esel->bases_len = 0;
|
||||
}
|
||||
}
|
||||
esel->sel_id_ctx = ED_view3d_select_id_context_create(
|
||||
vc, esel->bases, esel->bases_len, vc->scene->toolsettings->selectmode);
|
||||
DRW_draw_select_id(vc->depsgraph,
|
||||
vc->ar,
|
||||
vc->v3d,
|
||||
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;
|
||||
}
|
||||
|
@ -416,9 +233,6 @@ static void editselect_buf_cache_init(struct EditSelectBuf_Cache *esel, ViewCont
|
|||
|
||||
static void editselect_buf_cache_free(struct EditSelectBuf_Cache *esel)
|
||||
{
|
||||
if (esel->sel_id_ctx) {
|
||||
ED_view3d_select_id_context_destroy(esel->sel_id_ctx);
|
||||
}
|
||||
MEM_SAFE_FREE(esel->select_bitmap);
|
||||
MEM_SAFE_FREE(esel->bases);
|
||||
}
|
||||
|
@ -455,8 +269,7 @@ static bool edbm_backbuf_check_and_select_verts(struct EditSelectBuf_Cache *esel
|
|||
bool changed = false;
|
||||
|
||||
const BLI_bitmap *select_bitmap = esel->select_bitmap;
|
||||
uint index = ED_view3d_select_id_context_offset_for_object_elem(
|
||||
esel->sel_id_ctx, ob->runtime.select_id, SCE_SELECT_VERTEX);
|
||||
uint index = DRW_select_context_offset_for_object_elem(ob->runtime.select_id, SCE_SELECT_VERTEX);
|
||||
|
||||
BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
|
||||
if (!BM_elem_flag_test(eve, BM_ELEM_HIDDEN)) {
|
||||
|
@ -483,8 +296,7 @@ static bool edbm_backbuf_check_and_select_edges(struct EditSelectBuf_Cache *esel
|
|||
bool changed = false;
|
||||
|
||||
const BLI_bitmap *select_bitmap = esel->select_bitmap;
|
||||
uint index = ED_view3d_select_id_context_offset_for_object_elem(
|
||||
esel->sel_id_ctx, ob->runtime.select_id, SCE_SELECT_EDGE);
|
||||
uint index = DRW_select_context_offset_for_object_elem(ob->runtime.select_id, SCE_SELECT_EDGE);
|
||||
|
||||
BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
|
||||
if (!BM_elem_flag_test(eed, BM_ELEM_HIDDEN)) {
|
||||
|
@ -511,8 +323,7 @@ static bool edbm_backbuf_check_and_select_faces(struct EditSelectBuf_Cache *esel
|
|||
bool changed = false;
|
||||
|
||||
const BLI_bitmap *select_bitmap = esel->select_bitmap;
|
||||
uint index = ED_view3d_select_id_context_offset_for_object_elem(
|
||||
esel->sel_id_ctx, ob->runtime.select_id, SCE_SELECT_FACE);
|
||||
uint index = DRW_select_context_offset_for_object_elem(ob->runtime.select_id, SCE_SELECT_FACE);
|
||||
|
||||
BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
|
||||
if (!BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) {
|
||||
|
@ -1017,7 +828,7 @@ static bool do_lasso_select_mesh(ViewContext *vc,
|
|||
if (wm_userdata->data == NULL) {
|
||||
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
|
||||
esel = wm_userdata->data;
|
||||
const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx);
|
||||
const uint buffer_len = DRW_select_context_elem_len();
|
||||
esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect);
|
||||
}
|
||||
}
|
||||
|
@ -1036,10 +847,8 @@ static bool do_lasso_select_mesh(ViewContext *vc,
|
|||
struct LassoSelectUserData_ForMeshEdge data_for_edge = {
|
||||
.data = &data,
|
||||
.esel = use_zbuf ? esel : NULL,
|
||||
.backbuf_offset = use_zbuf ? ED_view3d_select_id_context_offset_for_object_elem(
|
||||
esel->sel_id_ctx,
|
||||
vc->obedit->runtime.select_id,
|
||||
SCE_SELECT_EDGE) :
|
||||
.backbuf_offset = use_zbuf ? DRW_select_context_offset_for_object_elem(
|
||||
vc->obedit->runtime.select_id, SCE_SELECT_EDGE) :
|
||||
0,
|
||||
};
|
||||
mesh_foreachScreenEdge(
|
||||
|
@ -1327,7 +1136,7 @@ static bool do_lasso_select_paintvert(ViewContext *vc,
|
|||
if (wm_userdata->data == NULL) {
|
||||
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
|
||||
esel = wm_userdata->data;
|
||||
const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx);
|
||||
const uint buffer_len = DRW_select_context_elem_len();
|
||||
esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect);
|
||||
}
|
||||
}
|
||||
|
@ -1386,7 +1195,7 @@ static bool do_lasso_select_paintface(ViewContext *vc,
|
|||
if (esel == NULL) {
|
||||
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
|
||||
esel = wm_userdata->data;
|
||||
const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx);
|
||||
const uint buffer_len = DRW_select_context_elem_len();
|
||||
esel->select_bitmap = ED_select_buffer_bitmap_from_poly(buffer_len, mcords, moves, &rect);
|
||||
}
|
||||
|
||||
|
@ -2742,7 +2551,7 @@ static bool do_paintvert_box_select(ViewContext *vc,
|
|||
if (wm_userdata->data == NULL) {
|
||||
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
|
||||
esel = wm_userdata->data;
|
||||
const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx);
|
||||
const uint buffer_len = DRW_select_context_elem_len();
|
||||
esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect);
|
||||
}
|
||||
if (esel->select_bitmap != NULL) {
|
||||
|
@ -2797,7 +2606,7 @@ static bool do_paintface_box_select(ViewContext *vc,
|
|||
if (wm_userdata->data == NULL) {
|
||||
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
|
||||
esel = wm_userdata->data;
|
||||
const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx);
|
||||
const uint buffer_len = DRW_select_context_elem_len();
|
||||
esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect);
|
||||
}
|
||||
if (esel->select_bitmap != NULL) {
|
||||
|
@ -2995,7 +2804,7 @@ static bool do_mesh_box_select(ViewContext *vc,
|
|||
if (wm_userdata->data == NULL) {
|
||||
editselect_buf_cache_init_with_generic_userdata(wm_userdata, vc);
|
||||
esel = wm_userdata->data;
|
||||
const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx);
|
||||
const uint buffer_len = DRW_select_context_elem_len();
|
||||
esel->select_bitmap = ED_select_buffer_bitmap_from_rect(buffer_len, rect);
|
||||
}
|
||||
}
|
||||
|
@ -3014,10 +2823,8 @@ static bool do_mesh_box_select(ViewContext *vc,
|
|||
struct BoxSelectUserData_ForMeshEdge cb_data = {
|
||||
.data = &data,
|
||||
.esel = use_zbuf ? esel : NULL,
|
||||
.backbuf_offset = use_zbuf ? ED_view3d_select_id_context_offset_for_object_elem(
|
||||
esel->sel_id_ctx,
|
||||
vc->obedit->runtime.select_id,
|
||||
SCE_SELECT_EDGE) :
|
||||
.backbuf_offset = use_zbuf ? DRW_select_context_offset_for_object_elem(
|
||||
vc->obedit->runtime.select_id, SCE_SELECT_EDGE) :
|
||||
0,
|
||||
};
|
||||
mesh_foreachScreenEdge(
|
||||
|
@ -3582,8 +3389,7 @@ static bool mesh_circle_select(ViewContext *vc,
|
|||
struct EditSelectBuf_Cache *esel = wm_userdata->data;
|
||||
|
||||
if (use_zbuf) {
|
||||
ED_view3d_select_id_validate_view_matrices(esel->sel_id_ctx, vc);
|
||||
const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx);
|
||||
const uint buffer_len = DRW_select_context_elem_len();
|
||||
esel->select_bitmap = ED_select_buffer_bitmap_from_circle(buffer_len, mval, (int)(rad + 1.0f));
|
||||
}
|
||||
|
||||
|
@ -3660,7 +3466,7 @@ static bool paint_facesel_circle_select(ViewContext *vc,
|
|||
|
||||
{
|
||||
struct EditSelectBuf_Cache *esel = wm_userdata->data;
|
||||
const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx);
|
||||
const uint buffer_len = DRW_select_context_elem_len();
|
||||
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);
|
||||
|
@ -3715,7 +3521,7 @@ static bool paint_vertsel_circle_select(ViewContext *vc,
|
|||
|
||||
if (use_zbuf) {
|
||||
struct EditSelectBuf_Cache *esel = wm_userdata->data;
|
||||
const uint buffer_len = ED_view3d_select_id_context_elem_len(esel->sel_id_ctx);
|
||||
const uint buffer_len = DRW_select_context_elem_len();
|
||||
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);
|
||||
|
|
|
@ -221,9 +221,6 @@ data_to_c_simple(shaders/gpu_shader_2D_edituvs_edges_vert.glsl SRC)
|
|||
data_to_c_simple(shaders/gpu_shader_2D_edituvs_faces_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_2D_edituvs_stretch_vert.glsl SRC)
|
||||
|
||||
data_to_c_simple(shaders/gpu_shader_3D_selection_id_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_selection_id_frag.glsl SRC)
|
||||
|
||||
data_to_c_simple(shaders/gpu_shader_text_simple_vert.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_text_simple_geom.glsl SRC)
|
||||
data_to_c_simple(shaders/gpu_shader_text_vert.glsl SRC)
|
||||
|
|
|
@ -355,11 +355,8 @@ typedef enum eGPUBuiltinShader {
|
|||
GPU_SHADER_2D_UV_FACES,
|
||||
GPU_SHADER_2D_UV_FACES_STRETCH_AREA,
|
||||
GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE,
|
||||
/* Selection */
|
||||
GPU_SHADER_3D_FLAT_SELECT_ID,
|
||||
GPU_SHADER_3D_UNIFORM_SELECT_ID,
|
||||
} eGPUBuiltinShader;
|
||||
#define GPU_SHADER_BUILTIN_LEN (GPU_SHADER_3D_UNIFORM_SELECT_ID + 1)
|
||||
#define GPU_SHADER_BUILTIN_LEN (GPU_SHADER_2D_UV_FACES_STRETCH_ANGLE + 1)
|
||||
|
||||
/** Support multiple configurations. */
|
||||
typedef enum eGPUShaderConfig {
|
||||
|
|
|
@ -139,9 +139,6 @@ extern char datatoc_gpu_shader_2D_edituvs_edges_vert_glsl[];
|
|||
extern char datatoc_gpu_shader_2D_edituvs_faces_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_2D_edituvs_stretch_vert_glsl[];
|
||||
|
||||
extern char datatoc_gpu_shader_3D_selection_id_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_selection_id_frag_glsl[];
|
||||
|
||||
extern char datatoc_gpu_shader_2D_line_dashed_uniform_color_vert_glsl[];
|
||||
extern char datatoc_gpu_shader_2D_line_dashed_frag_glsl[];
|
||||
extern char datatoc_gpu_shader_2D_line_dashed_geom_glsl[];
|
||||
|
@ -1312,18 +1309,6 @@ static const GPUShaderStages builtin_shader_stages[GPU_SHADER_BUILTIN_LEN] = {
|
|||
.defs = "#define STRETCH_ANGLE\n",
|
||||
},
|
||||
|
||||
[GPU_SHADER_3D_FLAT_SELECT_ID] =
|
||||
{
|
||||
.vert = datatoc_gpu_shader_3D_selection_id_vert_glsl,
|
||||
.frag = datatoc_gpu_shader_selection_id_frag_glsl,
|
||||
},
|
||||
[GPU_SHADER_3D_UNIFORM_SELECT_ID] =
|
||||
{
|
||||
.vert = datatoc_gpu_shader_3D_selection_id_vert_glsl,
|
||||
.frag = datatoc_gpu_shader_selection_id_frag_glsl,
|
||||
.defs = "#define UNIFORM_ID\n",
|
||||
},
|
||||
|
||||
[GPU_SHADER_GPENCIL_STROKE] =
|
||||
{
|
||||
.vert = datatoc_gpu_shader_gpencil_stroke_vert_glsl,
|
||||
|
@ -1370,9 +1355,7 @@ GPUShader *GPU_shader_get_builtin_shader_with_config(eGPUBuiltinShader shader,
|
|||
GPU_SHADER_3D_GROUNDLINE,
|
||||
GPU_SHADER_3D_GROUNDPOINT,
|
||||
GPU_SHADER_DISTANCE_LINES,
|
||||
GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR,
|
||||
GPU_SHADER_3D_FLAT_SELECT_ID,
|
||||
GPU_SHADER_3D_UNIFORM_SELECT_ID) ||
|
||||
GPU_SHADER_INSTANCE_EDGES_VARIYING_COLOR) ||
|
||||
ELEM(shader,
|
||||
GPU_SHADER_3D_FLAT_COLOR,
|
||||
GPU_SHADER_3D_LINE_DASHED_UNIFORM_COLOR,
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
|
||||
uniform mat4 ModelViewProjectionMatrix;
|
||||
|
||||
in vec3 pos;
|
||||
|
||||
#ifndef UNIFORM_ID
|
||||
uniform uint offset;
|
||||
in uint color;
|
||||
|
||||
flat out uint id;
|
||||
#endif
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifndef UNIFORM_ID
|
||||
id = offset + color;
|
||||
#endif
|
||||
|
||||
vec4 pos_4d = vec4(pos, 1.0);
|
||||
gl_Position = ModelViewProjectionMatrix * pos_4d;
|
||||
|
||||
#ifdef USE_WORLD_CLIP_PLANES
|
||||
/* Warning: ModelMatrix is typically used but select drawing is different. */
|
||||
world_clip_planes_calc_clip_distance(pos);
|
||||
#endif
|
||||
}
|
Loading…
Reference in New Issue