Refactor: Select: Use IndexRange for the element selection
This cleanup naming convention and code clarity. There is no functional change. - `elem_ranges` is changed to a `Map` to avoid relying on `sel_data->drawn_index`. - `select_draw_utils.cc` is merged with `select_engine.cc` - `index_drawn_len` is renamed to `max_index_drawn_len` - Remove the usage of `DrawData` Rel #134690 Pull Request: https://projects.blender.org/blender/blender/pulls/134940
This commit is contained in:
committed by
Clément Foucault
parent
c03ee7f6a8
commit
1b902e305c
@@ -142,7 +142,6 @@ set(SRC
|
||||
engines/gpencil/gpencil_render.cc
|
||||
engines/gpencil/gpencil_shader_c.cc
|
||||
engines/gpencil/gpencil_shader_fx.cc
|
||||
engines/select/select_draw_utils.cc
|
||||
engines/select/select_engine.cc
|
||||
engines/select/select_instance.cc
|
||||
engines/overlay/overlay_armature.cc
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_set.hh"
|
||||
#include "DNA_ID.h"
|
||||
|
||||
#include "BLI_array.hh"
|
||||
@@ -23,42 +25,27 @@ struct RegionView3D;
|
||||
struct View3D;
|
||||
struct rcti;
|
||||
|
||||
struct SELECTID_ObjectData {
|
||||
DrawData dd;
|
||||
|
||||
uint drawn_index;
|
||||
|
||||
/* Used to avoid adding to the pass more than once. */
|
||||
bool in_pass;
|
||||
|
||||
/* Used to detect and remove objects that are not included in the array. */
|
||||
bool is_drawn;
|
||||
};
|
||||
|
||||
struct ObjectOffsets {
|
||||
/* For convenience only. */
|
||||
union {
|
||||
uint offset;
|
||||
uint face_start;
|
||||
};
|
||||
union {
|
||||
uint face;
|
||||
uint edge_start;
|
||||
};
|
||||
union {
|
||||
uint edge;
|
||||
uint vert_start;
|
||||
};
|
||||
uint vert;
|
||||
/* Indices inside the selection framebuffer associated with the elements of a mesh. */
|
||||
struct ElemIndexRanges {
|
||||
/* Range for each element type. */
|
||||
blender::IndexRange face;
|
||||
blender::IndexRange edge;
|
||||
blender::IndexRange vert;
|
||||
/* Combined range for the whole object. */
|
||||
blender::IndexRange total;
|
||||
};
|
||||
|
||||
struct SELECTID_Context {
|
||||
/* All context objects */
|
||||
blender::Array<Object *> objects;
|
||||
blender::Array<ObjectOffsets> index_offsets;
|
||||
/* All selectable evaluated objects. */
|
||||
blender::Vector<Object *> objects;
|
||||
/* Map of the selectable objects from `objects` to their indices ranges. */
|
||||
blender::Map<Object *, ElemIndexRanges> elem_ranges;
|
||||
|
||||
/** Total number of element indices `index_offsets[object_drawn_len - 1].vert`. */
|
||||
uint index_drawn_len;
|
||||
/**
|
||||
* Maximum index value that can be contained inside the selection framebuffer.
|
||||
* Each object/element type has different range which are described inside `elem_ranges`.
|
||||
*/
|
||||
uint max_index_drawn_len;
|
||||
|
||||
short select_mode;
|
||||
|
||||
@@ -71,7 +58,12 @@ struct SELECTID_Context {
|
||||
|
||||
/* `draw_select_buffer.cc` */
|
||||
|
||||
bool DRW_select_buffer_elem_get(uint sel_id, uint *r_elem, uint *r_base_index, char *r_elem_type);
|
||||
bool DRW_select_buffer_elem_get(uint sel_id, uint &r_elem, uint &r_base_index, char &r_elem_type);
|
||||
|
||||
/**
|
||||
* Assume it is called right after `DRW_select_buffer_bitmap_from_*` so that the same evaluated
|
||||
* object is used for drawing and as parameter to this function.
|
||||
*/
|
||||
uint DRW_select_buffer_context_offset_for_object_elem(Depsgraph *depsgraph,
|
||||
Object *object,
|
||||
char elem_type);
|
||||
|
||||
@@ -1,226 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2019 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup draw_engine
|
||||
*
|
||||
* Engine for drawing a selection map where the pixels indicate the selection indices.
|
||||
*/
|
||||
|
||||
#include "BKE_editmesh.hh"
|
||||
#include "BKE_mesh.hh"
|
||||
|
||||
#include "DNA_mesh_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "ED_view3d.hh"
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
|
||||
#include "draw_cache_impl.hh"
|
||||
|
||||
#include "select_private.hh"
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Draw Utilities
|
||||
* \{ */
|
||||
|
||||
short select_id_get_object_select_mode(Scene *scene, Object *ob)
|
||||
{
|
||||
short r_select_mode = 0;
|
||||
if (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)) {
|
||||
/* In order to sample flat colors for vertex weights / texture-paint / vertex-paint
|
||||
* we need to be in SCE_SELECT_FACE mode so select_cache_init() correctly sets up
|
||||
* a shgroup with select_id_flat.
|
||||
* Note this is not working correctly for vertex-paint (yet), but has been discussed
|
||||
* in #66645 and there is a solution by @mano-wii in P1032.
|
||||
* So OB_MODE_VERTEX_PAINT is already included here [required for P1032 I guess]. */
|
||||
Mesh *me_orig = static_cast<Mesh *>(DEG_get_original_object(ob)->data);
|
||||
if (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) {
|
||||
r_select_mode = SCE_SELECT_VERTEX;
|
||||
}
|
||||
else {
|
||||
r_select_mode = SCE_SELECT_FACE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
r_select_mode = scene->toolsettings->selectmode;
|
||||
}
|
||||
|
||||
return r_select_mode;
|
||||
}
|
||||
|
||||
static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, eDrawType 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;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void draw_select_id_edit_mesh(SELECTID_Instance &inst,
|
||||
Object *ob,
|
||||
ResourceHandle res_handle,
|
||||
short select_mode,
|
||||
bool draw_facedot,
|
||||
uint initial_offset,
|
||||
uint *r_vert_offset,
|
||||
uint *r_edge_offset,
|
||||
uint *r_face_offset)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
using namespace blender;
|
||||
Mesh &mesh = *static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh.runtime->edit_mesh.get();
|
||||
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
|
||||
|
||||
if (select_mode & SCE_SELECT_FACE) {
|
||||
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
|
||||
PassSimple::Sub *face_sub = inst.select_face_flat;
|
||||
face_sub->push_constant("offset", int(initial_offset));
|
||||
face_sub->draw(geom_faces, res_handle);
|
||||
|
||||
if (draw_facedot) {
|
||||
gpu::Batch *geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(mesh);
|
||||
face_sub->draw(geom_facedots, res_handle);
|
||||
}
|
||||
*r_face_offset = initial_offset + em->bm->totface;
|
||||
}
|
||||
else {
|
||||
if (ob->dt >= OB_SOLID) {
|
||||
#ifdef USE_CAGE_OCCLUSION
|
||||
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
|
||||
#else
|
||||
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_surface(mesh);
|
||||
#endif
|
||||
inst.select_face_uniform->draw(geom_faces, res_handle);
|
||||
}
|
||||
*r_face_offset = initial_offset;
|
||||
}
|
||||
|
||||
/* Unlike faces, only draw edges if edge select mode. */
|
||||
if (select_mode & SCE_SELECT_EDGE) {
|
||||
gpu::Batch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(mesh);
|
||||
inst.select_edge->push_constant("offset", int(*r_face_offset));
|
||||
inst.select_edge->draw(geom_edges, res_handle);
|
||||
*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: #53512. */
|
||||
*r_edge_offset = *r_face_offset;
|
||||
}
|
||||
|
||||
/* Unlike faces, only verts if vert select mode. */
|
||||
if (select_mode & SCE_SELECT_VERTEX) {
|
||||
gpu::Batch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(mesh);
|
||||
inst.select_vert->push_constant("offset", int(*r_edge_offset));
|
||||
inst.select_vert->draw(geom_verts, res_handle);
|
||||
*r_vert_offset = *r_edge_offset + em->bm->totvert;
|
||||
}
|
||||
else {
|
||||
*r_vert_offset = *r_edge_offset;
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_select_id_mesh(SELECTID_Instance &inst,
|
||||
Object *ob,
|
||||
ResourceHandle res_handle,
|
||||
short select_mode,
|
||||
uint initial_offset,
|
||||
uint *r_vert_offset,
|
||||
uint *r_edge_offset,
|
||||
uint *r_face_offset)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
using namespace blender;
|
||||
Mesh &mesh = *static_cast<Mesh *>(ob->data);
|
||||
|
||||
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
|
||||
if (select_mode & SCE_SELECT_FACE) {
|
||||
inst.select_face_flat->push_constant("offset", int(initial_offset));
|
||||
inst.select_face_flat->draw(geom_faces, res_handle);
|
||||
*r_face_offset = initial_offset + mesh.faces_num;
|
||||
}
|
||||
else {
|
||||
/* Only draw faces to mask out verts, we don't want their selection ID's. */
|
||||
inst.select_face_uniform->draw(geom_faces, res_handle);
|
||||
*r_face_offset = initial_offset;
|
||||
}
|
||||
|
||||
if (select_mode & SCE_SELECT_EDGE) {
|
||||
gpu::Batch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(mesh);
|
||||
inst.select_edge->push_constant("offset", int(*r_face_offset));
|
||||
inst.select_edge->draw(geom_edges, res_handle);
|
||||
*r_edge_offset = *r_face_offset + mesh.edges_num;
|
||||
}
|
||||
else {
|
||||
*r_edge_offset = *r_face_offset;
|
||||
}
|
||||
|
||||
if (select_mode & SCE_SELECT_VERTEX) {
|
||||
gpu::Batch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(mesh);
|
||||
inst.select_vert->push_constant("offset", int(*r_edge_offset));
|
||||
inst.select_vert->draw(geom_verts, res_handle);
|
||||
*r_vert_offset = *r_edge_offset + mesh.verts_num;
|
||||
}
|
||||
else {
|
||||
*r_vert_offset = *r_edge_offset;
|
||||
}
|
||||
}
|
||||
|
||||
void select_id_draw_object(SELECTID_Instance &inst,
|
||||
View3D *v3d,
|
||||
Object *ob,
|
||||
ResourceHandle res_handle,
|
||||
short select_mode,
|
||||
uint initial_offset,
|
||||
uint *r_vert_offset,
|
||||
uint *r_edge_offset,
|
||||
uint *r_face_offset)
|
||||
{
|
||||
BLI_assert(initial_offset > 0);
|
||||
|
||||
switch (ob->type) {
|
||||
case OB_MESH: {
|
||||
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
|
||||
if (mesh.runtime->edit_mesh) {
|
||||
bool draw_facedot = check_ob_drawface_dot(select_mode, v3d, eDrawType(ob->dt));
|
||||
draw_select_id_edit_mesh(inst,
|
||||
ob,
|
||||
res_handle,
|
||||
select_mode,
|
||||
draw_facedot,
|
||||
initial_offset,
|
||||
r_vert_offset,
|
||||
r_edge_offset,
|
||||
r_face_offset);
|
||||
}
|
||||
else {
|
||||
draw_select_id_mesh(inst,
|
||||
ob,
|
||||
res_handle,
|
||||
select_mode,
|
||||
initial_offset,
|
||||
r_vert_offset,
|
||||
r_edge_offset,
|
||||
r_face_offset);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OB_CURVES_LEGACY:
|
||||
case OB_SURF:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
#undef SELECT_ENGINE
|
||||
@@ -8,10 +8,13 @@
|
||||
* Engine for drawing a selection map where the pixels indicate the selection indices.
|
||||
*/
|
||||
|
||||
#include "BKE_editmesh.hh"
|
||||
#include "BKE_mesh_types.hh"
|
||||
#include "BLI_math_matrix.h"
|
||||
|
||||
#include "BLT_translation.hh"
|
||||
|
||||
#include "DEG_depsgraph_query.hh"
|
||||
#include "ED_view3d.hh"
|
||||
|
||||
#include "RE_engine.h"
|
||||
@@ -113,6 +116,31 @@ static void select_engine_init(void *vedata)
|
||||
}
|
||||
}
|
||||
|
||||
static short select_id_get_object_select_mode(Scene *scene, Object *ob)
|
||||
{
|
||||
short r_select_mode = 0;
|
||||
if (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT | OB_MODE_TEXTURE_PAINT)) {
|
||||
/* In order to sample flat colors for vertex weights / texture-paint / vertex-paint
|
||||
* we need to be in SCE_SELECT_FACE mode so select_cache_init() correctly sets up
|
||||
* a shgroup with select_id_flat.
|
||||
* Note this is not working correctly for vertex-paint (yet), but has been discussed
|
||||
* in #66645 and there is a solution by @mano-wii in P1032.
|
||||
* So OB_MODE_VERTEX_PAINT is already included here [required for P1032 I guess]. */
|
||||
Mesh *me_orig = static_cast<Mesh *>(DEG_get_original_object(ob)->data);
|
||||
if (me_orig->editflag & ME_EDIT_PAINT_VERT_SEL) {
|
||||
r_select_mode = SCE_SELECT_VERTEX;
|
||||
}
|
||||
else {
|
||||
r_select_mode = SCE_SELECT_FACE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
r_select_mode = scene->toolsettings->selectmode;
|
||||
}
|
||||
|
||||
return r_select_mode;
|
||||
}
|
||||
|
||||
static void select_cache_init(void *vedata)
|
||||
{
|
||||
SELECTID_Instance &inst = *reinterpret_cast<SELECTID_Data *>(vedata)->instance;
|
||||
@@ -199,67 +227,200 @@ static void select_cache_init(void *vedata)
|
||||
}
|
||||
}
|
||||
|
||||
/* Create selection data. */
|
||||
for (uint sel_id : e_data.context.objects.index_range()) {
|
||||
Object *obj_eval = e_data.context.objects[sel_id];
|
||||
DrawData *data = DRW_drawdata_ensure(
|
||||
&obj_eval->id, &draw_engine_select_type, sizeof(SELECTID_ObjectData), nullptr, nullptr);
|
||||
SELECTID_ObjectData *sel_data = reinterpret_cast<SELECTID_ObjectData *>(data);
|
||||
sel_data->drawn_index = sel_id;
|
||||
sel_data->in_pass = false;
|
||||
sel_data->is_drawn = false;
|
||||
}
|
||||
e_data.context.elem_ranges.clear();
|
||||
|
||||
e_data.context.persmat = float4x4(draw_ctx->rv3d->persmat);
|
||||
e_data.context.index_drawn_len = 1;
|
||||
e_data.context.max_index_drawn_len = 1;
|
||||
select_engine_framebuffer_setup();
|
||||
GPU_framebuffer_bind(e_data.framebuffer_select_id);
|
||||
GPU_framebuffer_clear_color_depth(e_data.framebuffer_select_id, blender::float4{0.0f}, 1.0f);
|
||||
}
|
||||
|
||||
static bool check_ob_drawface_dot(short select_mode, const View3D *v3d, eDrawType 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;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* Return a new range if size `n` after `total_range` and grow `total_range` by the same amount. */
|
||||
static IndexRange alloc_range(IndexRange &total_range, uint size)
|
||||
{
|
||||
const IndexRange indices = total_range.after(size);
|
||||
total_range = IndexRange::from_begin_size(total_range.start(), total_range.size() + size);
|
||||
return indices;
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
|
||||
static ElemIndexRanges select_id_edit_mesh_sync(SELECTID_Instance &inst,
|
||||
Object *ob,
|
||||
ResourceHandle res_handle,
|
||||
short select_mode,
|
||||
bool draw_facedot,
|
||||
const uint initial_index)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
using namespace blender;
|
||||
Mesh &mesh = *static_cast<Mesh *>(ob->data);
|
||||
BMEditMesh *em = mesh.runtime->edit_mesh.get();
|
||||
|
||||
ElemIndexRanges ranges{};
|
||||
ranges.total = IndexRange::from_begin_size(initial_index, 0);
|
||||
|
||||
BM_mesh_elem_table_ensure(em->bm, BM_VERT | BM_EDGE | BM_FACE);
|
||||
|
||||
if (select_mode & SCE_SELECT_FACE) {
|
||||
ranges.face = alloc_range(ranges.total, em->bm->totface);
|
||||
|
||||
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
|
||||
PassSimple::Sub *face_sub = inst.select_face_flat;
|
||||
face_sub->push_constant("offset", int(ranges.face.start()));
|
||||
face_sub->draw(geom_faces, res_handle);
|
||||
|
||||
if (draw_facedot) {
|
||||
gpu::Batch *geom_facedots = DRW_mesh_batch_cache_get_facedots_with_select_id(mesh);
|
||||
face_sub->draw(geom_facedots, res_handle);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ob->dt >= OB_SOLID) {
|
||||
#ifdef USE_CAGE_OCCLUSION
|
||||
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
|
||||
#else
|
||||
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_surface(mesh);
|
||||
#endif
|
||||
inst.select_face_uniform->draw(geom_faces, res_handle);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlike faces, only draw edges if edge select mode. */
|
||||
if (select_mode & SCE_SELECT_EDGE) {
|
||||
ranges.edge = alloc_range(ranges.total, em->bm->totedge);
|
||||
|
||||
gpu::Batch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(mesh);
|
||||
inst.select_edge->push_constant("offset", int(ranges.edge.start()));
|
||||
inst.select_edge->draw(geom_edges, res_handle);
|
||||
}
|
||||
|
||||
/* Unlike faces, only verts if vert select mode. */
|
||||
if (select_mode & SCE_SELECT_VERTEX) {
|
||||
ranges.vert = alloc_range(ranges.total, em->bm->totvert);
|
||||
|
||||
gpu::Batch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(mesh);
|
||||
inst.select_vert->push_constant("offset", int(ranges.vert.start()));
|
||||
inst.select_vert->draw(geom_verts, res_handle);
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
|
||||
static ElemIndexRanges select_id_mesh_sync(SELECTID_Instance &inst,
|
||||
Object *ob,
|
||||
ResourceHandle res_handle,
|
||||
short select_mode,
|
||||
const uint initial_index)
|
||||
{
|
||||
using namespace blender::draw;
|
||||
using namespace blender;
|
||||
Mesh &mesh = *static_cast<Mesh *>(ob->data);
|
||||
|
||||
ElemIndexRanges ranges{};
|
||||
ranges.total = IndexRange::from_begin_size(initial_index, 0);
|
||||
|
||||
gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_triangles_with_select_id(mesh);
|
||||
if (select_mode & SCE_SELECT_FACE) {
|
||||
ranges.face = alloc_range(ranges.total, mesh.faces_num);
|
||||
|
||||
inst.select_face_flat->push_constant("offset", int(ranges.face.start()));
|
||||
inst.select_face_flat->draw(geom_faces, res_handle);
|
||||
}
|
||||
else {
|
||||
/* Only draw faces to mask out verts, we don't want their selection ID's. */
|
||||
inst.select_face_uniform->draw(geom_faces, res_handle);
|
||||
}
|
||||
|
||||
if (select_mode & SCE_SELECT_EDGE) {
|
||||
ranges.edge = alloc_range(ranges.total, mesh.edges_num);
|
||||
|
||||
gpu::Batch *geom_edges = DRW_mesh_batch_cache_get_edges_with_select_id(mesh);
|
||||
inst.select_edge->push_constant("offset", int(ranges.edge.start()));
|
||||
inst.select_edge->draw(geom_edges, res_handle);
|
||||
}
|
||||
|
||||
if (select_mode & SCE_SELECT_VERTEX) {
|
||||
ranges.vert = alloc_range(ranges.total, mesh.verts_num);
|
||||
|
||||
gpu::Batch *geom_verts = DRW_mesh_batch_cache_get_verts_with_select_id(mesh);
|
||||
inst.select_vert->push_constant("offset", int(ranges.vert.start()));
|
||||
inst.select_vert->draw(geom_verts, res_handle);
|
||||
}
|
||||
|
||||
return ranges;
|
||||
}
|
||||
|
||||
static ElemIndexRanges select_id_object_sync(SELECTID_Instance &inst,
|
||||
View3D *v3d,
|
||||
Object *ob,
|
||||
ResourceHandle res_handle,
|
||||
short select_mode,
|
||||
uint index_start)
|
||||
{
|
||||
BLI_assert_msg(index_start > 0, "Index 0 is reserved for no selection");
|
||||
|
||||
switch (ob->type) {
|
||||
case OB_MESH: {
|
||||
const Mesh &mesh = *static_cast<const Mesh *>(ob->data);
|
||||
if (mesh.runtime->edit_mesh) {
|
||||
bool draw_facedot = check_ob_drawface_dot(select_mode, v3d, eDrawType(ob->dt));
|
||||
return select_id_edit_mesh_sync(
|
||||
inst, ob, res_handle, select_mode, draw_facedot, index_start);
|
||||
}
|
||||
return select_id_mesh_sync(inst, ob, res_handle, select_mode, index_start);
|
||||
}
|
||||
case OB_CURVES_LEGACY:
|
||||
case OB_SURF:
|
||||
break;
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return ElemIndexRanges{};
|
||||
}
|
||||
|
||||
static void select_cache_populate(void *vedata, Object *ob)
|
||||
{
|
||||
Manager &manager = *DRW_manager_get();
|
||||
ObjectRef ob_ref = DRW_object_ref_get(ob);
|
||||
SelectEngineData &e_data = get_engine_data();
|
||||
SELECTID_Context &sel_ctx = e_data.context;
|
||||
SELECTID_Instance &inst = *reinterpret_cast<SELECTID_Data *>(vedata)->instance;
|
||||
SELECTID_ObjectData *sel_data = (SELECTID_ObjectData *)DRW_drawdata_get(
|
||||
&ob->id, &draw_engine_select_type);
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
|
||||
if (!sel_data || sel_data->is_drawn) {
|
||||
if (sel_data) {
|
||||
/* Remove data, object is not in array. */
|
||||
DrawDataList *drawdata = DRW_drawdatalist_from_id(&ob->id);
|
||||
BLI_freelinkN((ListBase *)drawdata, sel_data);
|
||||
}
|
||||
if (!sel_ctx.objects.contains(ob) && ob->dt >= OB_SOLID) {
|
||||
/* This object is not selectable. It is here to participate in occlusion.
|
||||
* This is the case in retopology mode. */
|
||||
blender::gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_surface(
|
||||
*static_cast<Mesh *>(ob->data));
|
||||
|
||||
/* This object is not in the array. It is here to participate in the depth buffer. */
|
||||
if (ob->dt >= OB_SOLID) {
|
||||
blender::gpu::Batch *geom_faces = DRW_mesh_batch_cache_get_surface(
|
||||
*static_cast<Mesh *>(ob->data));
|
||||
|
||||
inst.depth_occlude->draw(geom_faces, manager.resource_handle(ob_ref));
|
||||
}
|
||||
inst.depth_occlude->draw(geom_faces, manager.resource_handle(ob_ref));
|
||||
return;
|
||||
}
|
||||
else if (!sel_data->in_pass) {
|
||||
|
||||
/* Only sync selectable object once.
|
||||
* This can happen in retopology mode where there is two sync loop. */
|
||||
sel_ctx.elem_ranges.lookup_or_add_cb(ob, [&]() {
|
||||
ResourceHandle res_handle = manager.resource_handle(ob_ref);
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
ObjectOffsets *ob_offsets = &e_data.context.index_offsets[sel_data->drawn_index];
|
||||
uint offset = e_data.context.index_drawn_len;
|
||||
select_id_draw_object(inst,
|
||||
draw_ctx->v3d,
|
||||
ob,
|
||||
res_handle,
|
||||
e_data.context.select_mode,
|
||||
offset,
|
||||
&ob_offsets->vert,
|
||||
&ob_offsets->edge,
|
||||
&ob_offsets->face);
|
||||
|
||||
ob_offsets->offset = offset;
|
||||
sel_data->in_pass = true;
|
||||
e_data.context.index_drawn_len = ob_offsets->vert;
|
||||
}
|
||||
ElemIndexRanges elem_ranges = select_id_object_sync(
|
||||
inst, draw_ctx->v3d, ob, res_handle, sel_ctx.select_mode, sel_ctx.max_index_drawn_len);
|
||||
sel_ctx.max_index_drawn_len = elem_ranges.total.one_after_last();
|
||||
return elem_ranges;
|
||||
});
|
||||
}
|
||||
|
||||
static void select_draw_scene(void *vedata)
|
||||
@@ -297,14 +458,6 @@ static void select_draw_scene(void *vedata)
|
||||
if (e_data.context.select_mode & SCE_SELECT_VERTEX) {
|
||||
manager.submit(inst.select_id_vert_ps, inst.view_verts);
|
||||
}
|
||||
|
||||
/* Mark objects from the array to later identify which ones are not in the array. */
|
||||
for (Object *obj_eval : e_data.context.objects) {
|
||||
DrawData *data = DRW_drawdata_ensure(
|
||||
&obj_eval->id, &draw_engine_select_type, sizeof(SELECTID_ObjectData), nullptr, nullptr);
|
||||
SELECTID_ObjectData *sel_data = reinterpret_cast<SELECTID_ObjectData *>(data);
|
||||
sel_data->is_drawn = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void select_engine_free()
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "draw_view_data.hh"
|
||||
|
||||
#include "DRW_render.hh"
|
||||
#include "DRW_select_buffer.hh"
|
||||
|
||||
using namespace blender::draw;
|
||||
|
||||
@@ -56,16 +57,3 @@ struct SELECTID_Shaders {
|
||||
GPUShader *select_id_flat;
|
||||
GPUShader *select_id_uniform;
|
||||
};
|
||||
|
||||
/* `select_draw_utils.cc` */
|
||||
|
||||
short select_id_get_object_select_mode(Scene *scene, Object *ob);
|
||||
void select_id_draw_object(SELECTID_Instance &inst,
|
||||
View3D *v3d,
|
||||
Object *ob,
|
||||
ResourceHandle res_handle,
|
||||
short select_mode,
|
||||
uint initial_offset,
|
||||
uint *r_vert_offset,
|
||||
uint *r_edge_offset,
|
||||
uint *r_face_offset);
|
||||
|
||||
@@ -2477,7 +2477,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d)
|
||||
if (!viewport) {
|
||||
/* Selection engine requires a viewport.
|
||||
* TODO(@germano): This should be done internally in the engine. */
|
||||
sel_ctx->index_drawn_len = 1;
|
||||
sel_ctx->max_index_drawn_len = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ uint *DRW_select_buffer_read(
|
||||
DRW_draw_select_id(depsgraph, region, v3d);
|
||||
}
|
||||
|
||||
if (select_ctx->index_drawn_len > 1) {
|
||||
if (select_ctx->max_index_drawn_len > 1) {
|
||||
BLI_assert(region->winx == GPU_texture_width(DRW_engine_select_texture_get()) &&
|
||||
region->winy == GPU_texture_height(DRW_engine_select_texture_get()));
|
||||
|
||||
@@ -153,8 +153,8 @@ uint *DRW_select_buffer_bitmap_from_rect(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BLI_assert(select_ctx->index_drawn_len > 0);
|
||||
const uint bitmap_len = select_ctx->index_drawn_len - 1;
|
||||
BLI_assert(select_ctx->max_index_drawn_len > 0);
|
||||
const uint bitmap_len = select_ctx->max_index_drawn_len - 1;
|
||||
|
||||
BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__);
|
||||
const uint *buf_iter = buf;
|
||||
@@ -195,8 +195,8 @@ uint *DRW_select_buffer_bitmap_from_circle(Depsgraph *depsgraph,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BLI_assert(select_ctx->index_drawn_len > 0);
|
||||
const uint bitmap_len = select_ctx->index_drawn_len - 1;
|
||||
BLI_assert(select_ctx->max_index_drawn_len > 0);
|
||||
const uint bitmap_len = select_ctx->max_index_drawn_len - 1;
|
||||
|
||||
BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__);
|
||||
const uint *buf_iter = buf;
|
||||
@@ -270,8 +270,8 @@ uint *DRW_select_buffer_bitmap_from_poly(Depsgraph *depsgraph,
|
||||
drw_select_mask_px_cb,
|
||||
&poly_mask_data);
|
||||
|
||||
BLI_assert(select_ctx->index_drawn_len > 0);
|
||||
const uint bitmap_len = select_ctx->index_drawn_len - 1;
|
||||
BLI_assert(select_ctx->max_index_drawn_len > 0);
|
||||
const uint bitmap_len = select_ctx->max_index_drawn_len - 1;
|
||||
|
||||
BLI_bitmap *bitmap_buf = BLI_BITMAP_NEW(bitmap_len, __func__);
|
||||
const uint *buf_iter = buf;
|
||||
@@ -398,51 +398,38 @@ uint DRW_select_buffer_find_nearest_to_point(Depsgraph *depsgraph,
|
||||
* \{ */
|
||||
|
||||
bool DRW_select_buffer_elem_get(const uint sel_id,
|
||||
uint *r_elem,
|
||||
uint *r_base_index,
|
||||
char *r_elem_type)
|
||||
uint &r_elem,
|
||||
uint &r_base_index,
|
||||
char &r_elem_type)
|
||||
{
|
||||
SELECTID_Context *select_ctx = DRW_select_engine_context_get();
|
||||
|
||||
char elem_type = 0;
|
||||
uint elem_id = 0;
|
||||
uint base_index = 0;
|
||||
|
||||
for (; base_index < select_ctx->objects.size(); base_index++) {
|
||||
ObjectOffsets *base_ofs = &select_ctx->index_offsets[base_index];
|
||||
|
||||
if (base_ofs->face > sel_id) {
|
||||
elem_id = sel_id - base_ofs->face_start;
|
||||
elem_type = SCE_SELECT_FACE;
|
||||
break;
|
||||
for (const auto &item : select_ctx->elem_ranges.items()) {
|
||||
const ElemIndexRanges &ranges = item.value;
|
||||
Object *ob = item.key;
|
||||
if (!ranges.total.contains(sel_id)) {
|
||||
continue;
|
||||
}
|
||||
if (base_ofs->edge > sel_id) {
|
||||
elem_id = sel_id - base_ofs->edge_start;
|
||||
elem_type = SCE_SELECT_EDGE;
|
||||
break;
|
||||
if (ranges.face.contains(sel_id)) {
|
||||
r_elem = sel_id - ranges.face.start();
|
||||
r_elem_type = SCE_SELECT_FACE;
|
||||
r_base_index = select_ctx->objects.first_index_of(ob);
|
||||
return true;
|
||||
}
|
||||
if (base_ofs->vert > sel_id) {
|
||||
elem_id = sel_id - base_ofs->vert_start;
|
||||
elem_type = SCE_SELECT_VERTEX;
|
||||
break;
|
||||
if (ranges.edge.contains(sel_id)) {
|
||||
r_elem = sel_id - ranges.edge.start();
|
||||
r_elem_type = SCE_SELECT_EDGE;
|
||||
r_base_index = select_ctx->objects.first_index_of(ob);
|
||||
return true;
|
||||
}
|
||||
if (ranges.vert.contains(sel_id)) {
|
||||
r_elem = sel_id - ranges.vert.start();
|
||||
r_elem_type = SCE_SELECT_VERTEX;
|
||||
r_base_index = select_ctx->objects.first_index_of(ob);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (base_index == select_ctx->objects.size()) {
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint DRW_select_buffer_context_offset_for_object_elem(Depsgraph *depsgraph,
|
||||
@@ -453,23 +440,17 @@ uint DRW_select_buffer_context_offset_for_object_elem(Depsgraph *depsgraph,
|
||||
|
||||
Object *ob_eval = DEG_get_evaluated_object(depsgraph, object);
|
||||
|
||||
SELECTID_ObjectData *sel_data = (SELECTID_ObjectData *)DRW_drawdata_get(
|
||||
&ob_eval->id, &draw_engine_select_type);
|
||||
|
||||
if (!sel_data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ObjectOffsets *base_ofs = &select_ctx->index_offsets[sel_data->drawn_index];
|
||||
const ElemIndexRanges base_ofs = select_ctx->elem_ranges.lookup_default(ob_eval,
|
||||
ElemIndexRanges{});
|
||||
|
||||
if (elem_type == SCE_SELECT_VERTEX) {
|
||||
return base_ofs->vert_start;
|
||||
return base_ofs.vert.start();
|
||||
}
|
||||
if (elem_type == SCE_SELECT_EDGE) {
|
||||
return base_ofs->edge_start;
|
||||
return base_ofs.edge.start();
|
||||
}
|
||||
if (elem_type == SCE_SELECT_FACE) {
|
||||
return base_ofs->face_start;
|
||||
return base_ofs.face.start();
|
||||
}
|
||||
BLI_assert(0);
|
||||
return 0;
|
||||
@@ -488,7 +469,6 @@ void DRW_select_buffer_context_create(Depsgraph *depsgraph,
|
||||
SELECTID_Context *select_ctx = DRW_select_engine_context_get();
|
||||
|
||||
select_ctx->objects.reinitialize(bases.size());
|
||||
select_ctx->index_offsets.reinitialize(bases.size());
|
||||
|
||||
for (const int i : bases.index_range()) {
|
||||
Object *obj = bases[i]->object;
|
||||
|
||||
@@ -249,14 +249,14 @@ void EDBM_select_mirrored(BMEditMesh *em,
|
||||
|
||||
static BMElem *edbm_select_id_bm_elem_get(const Span<Base *> bases,
|
||||
const uint sel_id,
|
||||
uint *r_base_index)
|
||||
uint &r_base_index)
|
||||
{
|
||||
uint elem_id;
|
||||
char elem_type = 0;
|
||||
bool success = DRW_select_buffer_elem_get(sel_id, &elem_id, r_base_index, &elem_type);
|
||||
bool success = DRW_select_buffer_elem_get(sel_id, elem_id, r_base_index, elem_type);
|
||||
|
||||
if (success) {
|
||||
Object *obedit = bases[*r_base_index]->object;
|
||||
Object *obedit = bases[r_base_index]->object;
|
||||
BMEditMesh *em = BKE_editmesh_from_object(obedit);
|
||||
|
||||
switch (elem_type) {
|
||||
@@ -364,7 +364,7 @@ BMVert *EDBM_vert_find_nearest_ex(ViewContext *vc,
|
||||
vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px_manhattan_test);
|
||||
|
||||
if (index) {
|
||||
eve = (BMVert *)edbm_select_id_bm_elem_get(bases, index, &base_index);
|
||||
eve = (BMVert *)edbm_select_id_bm_elem_get(bases, index, base_index);
|
||||
}
|
||||
else {
|
||||
eve = nullptr;
|
||||
@@ -594,7 +594,7 @@ BMEdge *EDBM_edge_find_nearest_ex(ViewContext *vc,
|
||||
vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px_manhattan_test);
|
||||
|
||||
if (index) {
|
||||
eed = (BMEdge *)edbm_select_id_bm_elem_get(bases, index, &base_index);
|
||||
eed = (BMEdge *)edbm_select_id_bm_elem_get(bases, index, base_index);
|
||||
}
|
||||
else {
|
||||
eed = nullptr;
|
||||
@@ -818,7 +818,7 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
|
||||
}
|
||||
|
||||
if (index) {
|
||||
efa = (BMFace *)edbm_select_id_bm_elem_get(bases, index, &base_index);
|
||||
efa = (BMFace *)edbm_select_id_bm_elem_get(bases, index, base_index);
|
||||
}
|
||||
else {
|
||||
efa = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user