Selection: Remove limit on number of items which can be selected at once #112491
|
@ -294,24 +294,26 @@ struct Bone *ED_armature_pick_bone(struct bContext *C,
|
|||
bool findunsel,
|
||||
struct Base **r_base);
|
||||
|
||||
struct EditBone *ED_armature_pick_ebone_from_selectbuffer(struct Base **bases,
|
||||
uint bases_len,
|
||||
const struct GPUSelectResult *buffer,
|
||||
short hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
struct Base **r_base);
|
||||
struct bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(struct Base **bases,
|
||||
uint bases_len,
|
||||
const struct GPUSelectResult *buffer,
|
||||
short hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
struct Base **r_base);
|
||||
struct EditBone *ED_armature_pick_ebone_from_selectbuffer(
|
||||
struct Base **bases,
|
||||
uint bases_len,
|
||||
const struct GPUSelectResult *hit_results,
|
||||
int hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
struct Base **r_base);
|
||||
struct bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(
|
||||
struct Base **bases,
|
||||
uint bases_len,
|
||||
const struct GPUSelectResult *hit_results,
|
||||
int hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
struct Base **r_base);
|
||||
struct Bone *ED_armature_pick_bone_from_selectbuffer(struct Base **bases,
|
||||
uint bases_len,
|
||||
const struct GPUSelectResult *buffer,
|
||||
short hits,
|
||||
const struct GPUSelectResult *hit_results,
|
||||
int hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
struct Base **r_base);
|
||||
|
|
|
@ -155,34 +155,33 @@ Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
|
|||
|
||||
/* See if there are any selected bones in this buffer */
|
||||
/* only bones from base are checked on */
|
||||
static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode,
|
||||
Base **bases,
|
||||
uint bases_len,
|
||||
const GPUSelectResult *buffer,
|
||||
const short hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
Base **r_base)
|
||||
static void *ed_armature_pick_bone_from_selectbuffer_impl(
|
||||
const bool is_editmode,
|
||||
Base **bases,
|
||||
uint bases_len,
|
||||
const blender::Span<GPUSelectResult> hit_results,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
Base **r_base)
|
||||
{
|
||||
bPoseChannel *pchan;
|
||||
EditBone *ebone;
|
||||
void *firstunSel = nullptr, *firstSel = nullptr, *data;
|
||||
Base *firstunSel_base = nullptr, *firstSel_base = nullptr;
|
||||
uint hitresult;
|
||||
bool takeNext = false;
|
||||
int minsel = 0xffffffff, minunsel = 0xffffffff;
|
||||
|
||||
for (short i = 0; i < hits; i++) {
|
||||
hitresult = buffer[i].id;
|
||||
for (const GPUSelectResult &result : hit_results) {
|
||||
uint hit_id = result.id;
|
||||
|
||||
if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
|
||||
if (hit_id & BONESEL_ANY) { /* to avoid including objects in selection */
|
||||
Base *base = nullptr;
|
||||
bool sel;
|
||||
|
||||
hitresult &= ~BONESEL_ANY;
|
||||
hit_id &= ~BONESEL_ANY;
|
||||
/* Determine what the current bone is */
|
||||
if (is_editmode == false) {
|
||||
base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, hitresult, &pchan);
|
||||
base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, hit_id, &pchan);
|
||||
if (pchan != nullptr) {
|
||||
if (findunsel) {
|
||||
sel = (pchan->bone->flag & BONE_SELECTED);
|
||||
|
@ -199,7 +198,7 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
|
|||
}
|
||||
}
|
||||
else {
|
||||
base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
|
||||
base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hit_id, &ebone);
|
||||
if (findunsel) {
|
||||
sel = (ebone->flag & BONE_SELECTED);
|
||||
}
|
||||
|
@ -213,10 +212,10 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
|
|||
if (data) {
|
||||
if (sel) {
|
||||
if (do_nearest) {
|
||||
if (minsel > buffer[i].depth) {
|
||||
if (minsel > result.depth) {
|
||||
firstSel = data;
|
||||
firstSel_base = base;
|
||||
minsel = buffer[i].depth;
|
||||
minsel = result.depth;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -229,10 +228,10 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
|
|||
}
|
||||
else {
|
||||
if (do_nearest) {
|
||||
if (minunsel > buffer[i].depth) {
|
||||
if (minunsel > result.depth) {
|
||||
firstunSel = data;
|
||||
firstunSel_base = base;
|
||||
minunsel = buffer[i].depth;
|
||||
minunsel = result.depth;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -260,40 +259,40 @@ static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode
|
|||
|
||||
EditBone *ED_armature_pick_ebone_from_selectbuffer(Base **bases,
|
||||
uint bases_len,
|
||||
const GPUSelectResult *buffer,
|
||||
const short hits,
|
||||
const GPUSelectResult *hit_results,
|
||||
const int hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
Base **r_base)
|
||||
{
|
||||
const bool is_editmode = true;
|
||||
return static_cast<EditBone *>(ed_armature_pick_bone_from_selectbuffer_impl(
|
||||
is_editmode, bases, bases_len, buffer, hits, findunsel, do_nearest, r_base));
|
||||
is_editmode, bases, bases_len, {hit_results, hits}, findunsel, do_nearest, r_base));
|
||||
}
|
||||
|
||||
bPoseChannel *ED_armature_pick_pchan_from_selectbuffer(Base **bases,
|
||||
uint bases_len,
|
||||
const GPUSelectResult *buffer,
|
||||
const short hits,
|
||||
const GPUSelectResult *hit_results,
|
||||
const int hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
Base **r_base)
|
||||
{
|
||||
const bool is_editmode = false;
|
||||
return static_cast<bPoseChannel *>(ed_armature_pick_bone_from_selectbuffer_impl(
|
||||
is_editmode, bases, bases_len, buffer, hits, findunsel, do_nearest, r_base));
|
||||
is_editmode, bases, bases_len, {hit_results, hits}, findunsel, do_nearest, r_base));
|
||||
}
|
||||
|
||||
Bone *ED_armature_pick_bone_from_selectbuffer(Base **bases,
|
||||
uint bases_len,
|
||||
const GPUSelectResult *buffer,
|
||||
const short hits,
|
||||
const GPUSelectResult *hit_results,
|
||||
const int hits,
|
||||
bool findunsel,
|
||||
bool do_nearest,
|
||||
Base **r_base)
|
||||
{
|
||||
bPoseChannel *pchan = ED_armature_pick_pchan_from_selectbuffer(
|
||||
bases, bases_len, buffer, hits, findunsel, do_nearest, r_base);
|
||||
bases, bases_len, hit_results, hits, findunsel, do_nearest, r_base);
|
||||
return pchan ? pchan->bone : nullptr;
|
||||
}
|
||||
|
||||
|
@ -318,8 +317,8 @@ static void *ed_armature_pick_bone_impl(
|
|||
{
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
rcti rect;
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
short hits;
|
||||
GPUSelectBuffer buffer;
|
||||
int hits;
|
||||
|
||||
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
|
||||
BLI_assert((vc.obedit != nullptr) == is_editmode);
|
||||
|
@ -329,13 +328,8 @@ static void *ed_armature_pick_bone_impl(
|
|||
/* Don't use hits with this ID, (armature drawing uses this). */
|
||||
const int select_id_ignore = -1;
|
||||
|
||||
hits = view3d_opengl_select_with_id_filter(&vc,
|
||||
buffer,
|
||||
ARRAY_SIZE(buffer),
|
||||
&rect,
|
||||
VIEW3D_SELECT_PICK_NEAREST,
|
||||
VIEW3D_SELECT_FILTER_NOP,
|
||||
select_id_ignore);
|
||||
hits = view3d_opengl_select_with_id_filter(
|
||||
&vc, &buffer, &rect, VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP, select_id_ignore);
|
||||
|
||||
*r_base = nullptr;
|
||||
|
||||
|
@ -352,7 +346,13 @@ static void *ed_armature_pick_bone_impl(
|
|||
}
|
||||
|
||||
void *bone = ed_armature_pick_bone_from_selectbuffer_impl(
|
||||
is_editmode, bases, bases_len, buffer, hits, findunsel, true, r_base);
|
||||
is_editmode,
|
||||
bases,
|
||||
bases_len,
|
||||
buffer.storage.as_span().take_front(hits),
|
||||
findunsel,
|
||||
true,
|
||||
r_base);
|
||||
|
||||
MEM_freeN(bases);
|
||||
|
||||
|
@ -629,15 +629,18 @@ void ARMATURE_OT_select_linked_pick(wmOperatorType *ot)
|
|||
* \{ */
|
||||
|
||||
/* utility function for get_nearest_editbonepoint */
|
||||
static int selectbuffer_ret_hits_12(GPUSelectResult * /*buffer*/, const int hits12)
|
||||
static int selectbuffer_ret_hits_12(blender::MutableSpan<GPUSelectResult> /*results*/,
|
||||
const int hits12)
|
||||
{
|
||||
return hits12;
|
||||
}
|
||||
|
||||
static int selectbuffer_ret_hits_5(GPUSelectResult *buffer, const int hits12, const int hits5)
|
||||
static int selectbuffer_ret_hits_5(blender::MutableSpan<GPUSelectResult> results,
|
||||
const int hits12,
|
||||
const int hits5)
|
||||
{
|
||||
const int ofs = hits12;
|
||||
memcpy(buffer, buffer + ofs, hits5 * sizeof(*buffer));
|
||||
results.slice(0, hits5).copy_from(results.slice(ofs, hits5)); /* Shift results to beginning. */
|
||||
return hits5;
|
||||
}
|
||||
|
||||
|
@ -646,7 +649,7 @@ static int selectbuffer_ret_hits_5(GPUSelectResult *buffer, const int hits12, co
|
|||
static EditBone *get_nearest_editbonepoint(
|
||||
ViewContext *vc, bool findunsel, bool use_cycle, Base **r_base, int *r_selmask)
|
||||
{
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
GPUSelectBuffer buffer;
|
||||
struct Result {
|
||||
uint hitresult;
|
||||
Base *base;
|
||||
|
@ -688,44 +691,32 @@ static EditBone *get_nearest_editbonepoint(
|
|||
const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
|
||||
const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP;
|
||||
|
||||
GPUSelectStorage &storage = buffer.storage;
|
||||
rcti rect;
|
||||
BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
|
||||
const int hits12 = view3d_opengl_select_with_id_filter(vc,
|
||||
buffer,
|
||||
ARRAY_SIZE(buffer),
|
||||
&rect,
|
||||
eV3DSelectMode(select_mode),
|
||||
select_filter,
|
||||
select_id_ignore);
|
||||
const int hits12 = view3d_opengl_select_with_id_filter(
|
||||
vc, &buffer, &rect, eV3DSelectMode(select_mode), select_filter, select_id_ignore);
|
||||
|
||||
if (hits12 == 1) {
|
||||
hits = selectbuffer_ret_hits_12(buffer, hits12);
|
||||
hits = selectbuffer_ret_hits_12(storage.as_mutable_span(), hits12);
|
||||
goto cache_end;
|
||||
}
|
||||
else if (hits12 > 0) {
|
||||
int ofs;
|
||||
|
||||
ofs = hits12;
|
||||
BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
|
||||
const int hits5 = view3d_opengl_select_with_id_filter(vc,
|
||||
buffer + ofs,
|
||||
ARRAY_SIZE(buffer) - ofs,
|
||||
&rect,
|
||||
eV3DSelectMode(select_mode),
|
||||
select_filter,
|
||||
select_id_ignore);
|
||||
const int hits5 = view3d_opengl_select_with_id_filter(
|
||||
vc, &buffer, &rect, eV3DSelectMode(select_mode), select_filter, select_id_ignore);
|
||||
|
||||
if (hits5 == 1) {
|
||||
hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
|
||||
hits = selectbuffer_ret_hits_5(storage.as_mutable_span(), hits12, hits5);
|
||||
goto cache_end;
|
||||
}
|
||||
|
||||
if (hits5 > 0) {
|
||||
hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
|
||||
hits = selectbuffer_ret_hits_5(storage.as_mutable_span(), hits12, hits5);
|
||||
goto cache_end;
|
||||
}
|
||||
else {
|
||||
hits = selectbuffer_ret_hits_12(buffer, hits12);
|
||||
hits = selectbuffer_ret_hits_12(storage.as_mutable_span(), hits12);
|
||||
goto cache_end;
|
||||
}
|
||||
}
|
||||
|
@ -741,7 +732,7 @@ cache_end:
|
|||
/* See if there are any selected bones in this group */
|
||||
if (hits > 0) {
|
||||
if (hits == 1) {
|
||||
result_bias.hitresult = buffer->id;
|
||||
result_bias.hitresult = buffer.storage[0].id;
|
||||
result_bias.base = ED_armature_base_and_ebone_from_select_buffer(
|
||||
bases, bases_len, result_bias.hitresult, &result_bias.ebone);
|
||||
}
|
||||
|
@ -780,7 +771,7 @@ cache_end:
|
|||
}
|
||||
|
||||
for (int i = 0; i < hits; i++) {
|
||||
const uint hitresult = buffer[i].id;
|
||||
const uint hitresult = buffer.storage[i].id;
|
||||
|
||||
Base *base = nullptr;
|
||||
EditBone *ebone;
|
||||
|
|
|
@ -258,8 +258,8 @@ bool ED_armature_pose_select_pick_with_buffer(const Scene *scene,
|
|||
ViewLayer *view_layer,
|
||||
View3D *v3d,
|
||||
Base *base,
|
||||
const GPUSelectResult *buffer,
|
||||
const short hits,
|
||||
const GPUSelectResult *hit_results,
|
||||
const int hits,
|
||||
const SelectPick_Params *params,
|
||||
bool do_nearest)
|
||||
{
|
||||
|
@ -273,7 +273,7 @@ bool ED_armature_pose_select_pick_with_buffer(const Scene *scene,
|
|||
/* Callers happen to already get the active base */
|
||||
Base *base_dummy = nullptr;
|
||||
nearBone = ED_armature_pick_bone_from_selectbuffer(
|
||||
&base, 1, buffer, hits, true, do_nearest, &base_dummy);
|
||||
&base, 1, hit_results, hits, true, do_nearest, &base_dummy);
|
||||
|
||||
return ED_armature_pose_select_pick_bone(scene, view_layer, v3d, ob, nearBone, params);
|
||||
}
|
||||
|
|
|
@ -300,8 +300,8 @@ bool ED_armature_pose_select_pick_with_buffer(const Scene *scene,
|
|||
ViewLayer *view_layer,
|
||||
View3D *v3d,
|
||||
Base *base,
|
||||
const GPUSelectResult *buffer,
|
||||
short hits,
|
||||
const GPUSelectResult *hit_results,
|
||||
int hits,
|
||||
const SelectPick_Params *params,
|
||||
bool do_nearest);
|
||||
/**
|
||||
|
|
|
@ -27,7 +27,7 @@ struct Camera;
|
|||
struct CustomData_MeshMasks;
|
||||
struct Depsgraph;
|
||||
struct EditBone;
|
||||
struct GPUSelectResult;
|
||||
struct GPUSelectBuffer;
|
||||
struct ID;
|
||||
struct Main;
|
||||
struct MetaElem;
|
||||
|
@ -877,15 +877,6 @@ bool ED_view3d_autodist_simple(ARegion *region,
|
|||
bool ED_view3d_depth_read_cached_seg(
|
||||
const ViewDepths *vd, const int mval_sta[2], const int mval_end[2], int margin, float *depth);
|
||||
|
||||
/**
|
||||
* The default value for the maximum number of elements that can be selected at once
|
||||
* using view-port selection.
|
||||
*
|
||||
* \note in many cases this defines the size of fixed-size stack buffers,
|
||||
* so take care increasing this value.
|
||||
*/
|
||||
#define MAXPICKELEMS 2500
|
||||
|
||||
enum eV3DSelectMode {
|
||||
/* all elements in the region, ignore depth */
|
||||
VIEW3D_SELECT_ALL = 0,
|
||||
|
@ -915,28 +906,21 @@ void view3d_opengl_select_cache_begin();
|
|||
void view3d_opengl_select_cache_end();
|
||||
|
||||
/**
|
||||
* \warning be sure to account for a negative return value
|
||||
* This is an error, "Too many objects in select buffer"
|
||||
* and no action should be taken (can crash blender) if this happens
|
||||
*
|
||||
* \note (vc->obedit == NULL) can be set to explicitly skip edit-object selection.
|
||||
*/
|
||||
int view3d_opengl_select_ex(ViewContext *vc,
|
||||
GPUSelectResult *buffer,
|
||||
unsigned int buffer_len,
|
||||
GPUSelectBuffer *buffer,
|
||||
const rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
bool do_material_slot_selection);
|
||||
int view3d_opengl_select(ViewContext *vc,
|
||||
GPUSelectResult *buffer,
|
||||
unsigned int buffer_len,
|
||||
GPUSelectBuffer *buffer,
|
||||
const rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter);
|
||||
int view3d_opengl_select_with_id_filter(ViewContext *vc,
|
||||
GPUSelectResult *buffer,
|
||||
unsigned int buffer_len,
|
||||
GPUSelectBuffer *buffer,
|
||||
const rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
|
|
|
@ -772,7 +772,7 @@ static bool ed_mball_findnearest_metaelem(bContext *C,
|
|||
{
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
int a, hits;
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
GPUSelectBuffer buffer;
|
||||
rcti rect;
|
||||
bool found = false;
|
||||
|
||||
|
@ -781,8 +781,7 @@ static bool ed_mball_findnearest_metaelem(bContext *C,
|
|||
BLI_rcti_init_pt_radius(&rect, mval, 12);
|
||||
|
||||
hits = view3d_opengl_select(&vc,
|
||||
buffer,
|
||||
ARRAY_SIZE(buffer),
|
||||
&buffer,
|
||||
&rect,
|
||||
use_cycle ? VIEW3D_SELECT_PICK_ALL : VIEW3D_SELECT_PICK_NEAREST,
|
||||
VIEW3D_SELECT_FILTER_NOP);
|
||||
|
@ -809,7 +808,7 @@ static bool ed_mball_findnearest_metaelem(bContext *C,
|
|||
* ensure this steps onto the next meta-element. */
|
||||
a = hits;
|
||||
while (a--) {
|
||||
const int select_id = buffer[a].id;
|
||||
const int select_id = buffer.storage[a].id;
|
||||
if (select_id == -1) {
|
||||
continue;
|
||||
}
|
||||
|
@ -825,7 +824,7 @@ static bool ed_mball_findnearest_metaelem(bContext *C,
|
|||
|
||||
for (a = 0; a < hits; a++) {
|
||||
const int index = (hit_cycle_offset == 0) ? a : ((a + hit_cycle_offset) % hits);
|
||||
const uint select_id = buffer[index].id;
|
||||
const uint select_id = buffer.storage[index].id;
|
||||
if (select_id == -1) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "BLI_math_bits.h"
|
||||
#include "BLI_math_geom.h"
|
||||
#include "BLI_rect.h"
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "BLI_task.hh"
|
||||
#include "BLI_utildefines.h"
|
||||
|
@ -1676,8 +1677,7 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot)
|
|||
*/
|
||||
static bool object_mouse_select_menu(bContext *C,
|
||||
ViewContext *vc,
|
||||
const GPUSelectResult *buffer,
|
||||
const int hits,
|
||||
const blender::Span<GPUSelectResult> hit_results,
|
||||
const int mval[2],
|
||||
const SelectPick_Params *params,
|
||||
Base **r_basact)
|
||||
|
@ -1702,12 +1702,12 @@ static bool object_mouse_select_menu(bContext *C,
|
|||
uint depth_id;
|
||||
|
||||
/* two selection methods, the CTRL select uses max dist of 15 */
|
||||
if (buffer) {
|
||||
for (int a = 0; a < hits; a++) {
|
||||
if (!hit_results.is_empty()) {
|
||||
for (const GPUSelectResult &result : hit_results) {
|
||||
/* index was converted */
|
||||
if (base->object->runtime->select_id == (buffer[a].id & ~0xFFFF0000)) {
|
||||
if (base->object->runtime->select_id == (result.id & ~0xFFFF0000)) {
|
||||
ok = true;
|
||||
depth_id = buffer[a].depth;
|
||||
depth_id = result.depth;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1890,13 +1890,10 @@ void VIEW3D_OT_bone_select_menu(wmOperatorType *ot)
|
|||
* \return True when a menu was activated.
|
||||
*/
|
||||
static bool bone_mouse_select_menu(bContext *C,
|
||||
const GPUSelectResult *buffer,
|
||||
const int hits,
|
||||
const blender::Span<GPUSelectResult> hit_results,
|
||||
const bool is_editmode,
|
||||
const SelectPick_Params *params)
|
||||
{
|
||||
BLI_assert(buffer);
|
||||
|
||||
int bone_count = 0;
|
||||
|
||||
struct BoneRefWithDepth {
|
||||
|
@ -1916,10 +1913,10 @@ static bool bone_mouse_select_menu(bContext *C,
|
|||
|
||||
/* Select logic taken from #ed_armature_pick_bone_from_selectbuffer_impl
|
||||
* in `armature_select.cc`. */
|
||||
for (int a = 0; a < hits; a++) {
|
||||
for (const GPUSelectResult &result : hit_results) {
|
||||
void *bone_ptr = nullptr;
|
||||
Base *bone_base = nullptr;
|
||||
uint hitresult = buffer[a].id;
|
||||
uint hitresult = result.id;
|
||||
|
||||
if (!(hitresult & BONESEL_ANY)) {
|
||||
/* To avoid including objects in selection. */
|
||||
|
@ -1972,7 +1969,7 @@ static bool bone_mouse_select_menu(bContext *C,
|
|||
BoneRefWithDepth *bone_ref = MEM_new<BoneRefWithDepth>(__func__);
|
||||
bone_ref->base = bone_base;
|
||||
bone_ref->bone_ptr = bone_ptr;
|
||||
bone_ref->depth_id = buffer[a].depth;
|
||||
bone_ref->depth_id = result.depth;
|
||||
BLI_addtail(&bone_ref_list, (void *)bone_ref);
|
||||
|
||||
BLI_gset_insert(added_bones, bone_ptr);
|
||||
|
@ -2038,10 +2035,10 @@ static bool bone_mouse_select_menu(bContext *C,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool selectbuffer_has_bones(const GPUSelectResult *buffer, const uint hits)
|
||||
static bool selectbuffer_has_bones(const blender::Span<GPUSelectResult> hit_results)
|
||||
{
|
||||
for (uint i = 0; i < hits; i++) {
|
||||
if (buffer[i].id & 0xFFFF0000) {
|
||||
for (const GPUSelectResult &result : hit_results) {
|
||||
if (result.id & 0xFFFF0000) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -2049,25 +2046,28 @@ static bool selectbuffer_has_bones(const GPUSelectResult *buffer, const uint hit
|
|||
}
|
||||
|
||||
/* utility function for mixed_bones_object_selectbuffer */
|
||||
static int selectbuffer_ret_hits_15(GPUSelectResult * /*buffer*/, const int hits15)
|
||||
static int selectbuffer_ret_hits_15(blender::MutableSpan<GPUSelectResult> /*results*/,
|
||||
const int hits15)
|
||||
{
|
||||
return hits15;
|
||||
}
|
||||
|
||||
static int selectbuffer_ret_hits_9(GPUSelectResult *buffer, const int hits15, const int hits9)
|
||||
static int selectbuffer_ret_hits_9(blender::MutableSpan<GPUSelectResult> results,
|
||||
const int hits15,
|
||||
const int hits9)
|
||||
{
|
||||
const int ofs = hits15;
|
||||
memcpy(buffer, buffer + ofs, hits9 * sizeof(GPUSelectResult));
|
||||
results.slice(0, hits9).copy_from(results.slice(ofs, hits9)); /* Shift results to beginning. */
|
||||
return hits9;
|
||||
}
|
||||
|
||||
static int selectbuffer_ret_hits_5(GPUSelectResult *buffer,
|
||||
static int selectbuffer_ret_hits_5(blender::MutableSpan<GPUSelectResult> results,
|
||||
const int hits15,
|
||||
const int hits9,
|
||||
const int hits5)
|
||||
{
|
||||
const int ofs = hits15 + hits9;
|
||||
memcpy(buffer, buffer + ofs, hits5 * sizeof(GPUSelectResult));
|
||||
results.slice(0, hits5).copy_from(results.slice(ofs, hits5)); /* Shift results to beginning. */
|
||||
return hits5;
|
||||
}
|
||||
|
||||
|
@ -2080,8 +2080,7 @@ static int selectbuffer_ret_hits_5(GPUSelectResult *buffer,
|
|||
* Needed so we can step to the next, non-active object when it's already selected, see: #76445.
|
||||
*/
|
||||
static int mixed_bones_object_selectbuffer(ViewContext *vc,
|
||||
GPUSelectResult *buffer,
|
||||
const int buffer_len,
|
||||
GPUSelectBuffer *buffer,
|
||||
const int mval[2],
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
bool do_nearest,
|
||||
|
@ -2104,64 +2103,63 @@ static int mixed_bones_object_selectbuffer(ViewContext *vc,
|
|||
/* we _must_ end cache before return, use 'goto finally' */
|
||||
view3d_opengl_select_cache_begin();
|
||||
|
||||
GPUSelectStorage &storage = buffer->storage;
|
||||
BLI_rcti_init_pt_radius(&rect, mval, 14);
|
||||
hits15 = view3d_opengl_select_ex(
|
||||
vc, buffer, buffer_len, &rect, select_mode, select_filter, do_material_slot_selection);
|
||||
vc, buffer, &rect, select_mode, select_filter, do_material_slot_selection);
|
||||
if (hits15 == 1) {
|
||||
hits = selectbuffer_ret_hits_15(buffer, hits15);
|
||||
hits = selectbuffer_ret_hits_15(storage.as_mutable_span(), hits15);
|
||||
goto finally;
|
||||
}
|
||||
else if (hits15 > 0) {
|
||||
int ofs;
|
||||
has_bones15 = selectbuffer_has_bones(buffer, hits15);
|
||||
has_bones15 = selectbuffer_has_bones(storage.as_span().slice(0, hits15));
|
||||
|
||||
ofs = hits15;
|
||||
BLI_rcti_init_pt_radius(&rect, mval, 9);
|
||||
hits9 = view3d_opengl_select(
|
||||
vc, buffer + ofs, buffer_len - ofs, &rect, select_mode, select_filter);
|
||||
hits9 = view3d_opengl_select(vc, buffer, &rect, select_mode, select_filter);
|
||||
if (hits9 == 1) {
|
||||
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
|
||||
hits = selectbuffer_ret_hits_9(storage.as_mutable_span(), hits15, hits9);
|
||||
goto finally;
|
||||
}
|
||||
else if (hits9 > 0) {
|
||||
has_bones9 = selectbuffer_has_bones(buffer + ofs, hits9);
|
||||
has_bones9 = selectbuffer_has_bones(storage.as_span().slice(ofs, hits9));
|
||||
|
||||
ofs += hits9;
|
||||
BLI_rcti_init_pt_radius(&rect, mval, 5);
|
||||
hits5 = view3d_opengl_select(
|
||||
vc, buffer + ofs, buffer_len - ofs, &rect, select_mode, select_filter);
|
||||
hits5 = view3d_opengl_select(vc, buffer, &rect, select_mode, select_filter);
|
||||
if (hits5 == 1) {
|
||||
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
|
||||
hits = selectbuffer_ret_hits_5(storage.as_mutable_span(), hits15, hits9, hits5);
|
||||
goto finally;
|
||||
}
|
||||
else if (hits5 > 0) {
|
||||
has_bones5 = selectbuffer_has_bones(buffer + ofs, hits5);
|
||||
has_bones5 = selectbuffer_has_bones(storage.as_span().slice(ofs, hits5));
|
||||
}
|
||||
}
|
||||
|
||||
if (has_bones5) {
|
||||
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
|
||||
hits = selectbuffer_ret_hits_5(storage.as_mutable_span(), hits15, hits9, hits5);
|
||||
goto finally;
|
||||
}
|
||||
else if (has_bones9) {
|
||||
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
|
||||
hits = selectbuffer_ret_hits_9(storage.as_mutable_span(), hits15, hits9);
|
||||
goto finally;
|
||||
}
|
||||
else if (has_bones15) {
|
||||
hits = selectbuffer_ret_hits_15(buffer, hits15);
|
||||
hits = selectbuffer_ret_hits_15(storage.as_mutable_span(), hits15);
|
||||
goto finally;
|
||||
}
|
||||
|
||||
if (hits5 > 0) {
|
||||
hits = selectbuffer_ret_hits_5(buffer, hits15, hits9, hits5);
|
||||
hits = selectbuffer_ret_hits_5(storage.as_mutable_span(), hits15, hits9, hits5);
|
||||
goto finally;
|
||||
}
|
||||
else if (hits9 > 0) {
|
||||
hits = selectbuffer_ret_hits_9(buffer, hits15, hits9);
|
||||
hits = selectbuffer_ret_hits_9(storage.as_mutable_span(), hits15, hits9);
|
||||
goto finally;
|
||||
}
|
||||
else {
|
||||
hits = selectbuffer_ret_hits_15(buffer, hits15);
|
||||
hits = selectbuffer_ret_hits_15(storage.as_mutable_span(), hits15);
|
||||
goto finally;
|
||||
}
|
||||
}
|
||||
|
@ -2172,8 +2170,7 @@ finally:
|
|||
}
|
||||
|
||||
static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
|
||||
GPUSelectResult *buffer,
|
||||
const int buffer_len,
|
||||
GPUSelectBuffer *buffer,
|
||||
const int mval[2],
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
bool use_cycle,
|
||||
|
@ -2204,7 +2201,7 @@ static int mixed_bones_object_selectbuffer_extended(ViewContext *vc,
|
|||
do_nearest = do_nearest && !enumerate;
|
||||
|
||||
int hits = mixed_bones_object_selectbuffer(
|
||||
vc, buffer, buffer_len, mval, select_filter, do_nearest, true, false);
|
||||
vc, buffer, mval, select_filter, do_nearest, true, false);
|
||||
|
||||
return hits;
|
||||
}
|
||||
|
@ -2251,7 +2248,7 @@ static int gpu_select_buffer_depth_id_cmp(const void *sel_a_p, const void *sel_b
|
|||
* \return the active base or nullptr.
|
||||
*/
|
||||
static Base *mouse_select_eval_buffer(ViewContext *vc,
|
||||
const GPUSelectResult *buffer,
|
||||
const GPUSelectBuffer &buffer,
|
||||
int hits,
|
||||
bool do_nearest,
|
||||
bool has_bones,
|
||||
|
@ -2274,8 +2271,8 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
|
|||
if (has_bones && do_bones_get_priotity) {
|
||||
/* we skip non-bone hits */
|
||||
for (a = 0; a < hits; a++) {
|
||||
if (min > buffer[a].depth && (buffer[a].id & 0xFFFF0000)) {
|
||||
min = buffer[a].depth;
|
||||
if (min > buffer.storage[a].depth && (buffer.storage[a].id & 0xFFFF0000)) {
|
||||
min = buffer.storage[a].depth;
|
||||
hit_index = a;
|
||||
}
|
||||
}
|
||||
|
@ -2284,26 +2281,25 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
|
|||
|
||||
for (a = 0; a < hits; a++) {
|
||||
/* Any object. */
|
||||
if (min > buffer[a].depth) {
|
||||
min = buffer[a].depth;
|
||||
if (min > buffer.storage[a].depth) {
|
||||
min = buffer.storage[a].depth;
|
||||
hit_index = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hit_index != -1) {
|
||||
select_id = buffer[hit_index].id & 0xFFFF;
|
||||
select_id_subelem = (buffer[hit_index].id & 0xFFFF0000) >> 16;
|
||||
select_id = buffer.storage[hit_index].id & 0xFFFF;
|
||||
select_id_subelem = (buffer.storage[hit_index].id & 0xFFFF0000) >> 16;
|
||||
found = true;
|
||||
/* No need to set `min` to `buffer[hit_index].depth`, it's not used from now on. */
|
||||
/* No need to set `min` to `buffer.storage[hit_index].depth`, it's not used from now on. */
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
GPUSelectStorage buffer_sorted = buffer.storage;
|
||||
{
|
||||
GPUSelectResult *buffer_sorted = static_cast<GPUSelectResult *>(
|
||||
MEM_mallocN(sizeof(*buffer_sorted) * hits, __func__));
|
||||
memcpy(buffer_sorted, buffer, sizeof(*buffer_sorted) * hits);
|
||||
buffer_sorted.resize(hits);
|
||||
/* Remove non-bone objects. */
|
||||
if (has_bones && do_bones_get_priotity) {
|
||||
/* Loop backwards to reduce re-ordering. */
|
||||
|
@ -2313,8 +2309,7 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
|
|||
}
|
||||
}
|
||||
}
|
||||
qsort(buffer_sorted, hits, sizeof(GPUSelectResult), gpu_select_buffer_depth_id_cmp);
|
||||
buffer = buffer_sorted;
|
||||
qsort(buffer_sorted.data(), hits, sizeof(GPUSelectResult), gpu_select_buffer_depth_id_cmp);
|
||||
}
|
||||
|
||||
int hit_index = -1;
|
||||
|
@ -2327,8 +2322,8 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
|
|||
if (base && (base->flag & BASE_SELECTED)) {
|
||||
const int select_id_active = base->object->runtime->select_id;
|
||||
for (int i_next = 0, i_prev = hits - 1; i_next < hits; i_prev = i_next++) {
|
||||
if ((select_id_active == (buffer[i_prev].id & 0xFFFF)) &&
|
||||
(select_id_active != (buffer[i_next].id & 0xFFFF)))
|
||||
if ((select_id_active == (buffer_sorted[i_prev].id & 0xFFFF)) &&
|
||||
(select_id_active != (buffer_sorted[i_next].id & 0xFFFF)))
|
||||
{
|
||||
hit_index = i_next;
|
||||
break;
|
||||
|
@ -2344,11 +2339,10 @@ static Base *mouse_select_eval_buffer(ViewContext *vc,
|
|||
}
|
||||
|
||||
if (hit_index != -1) {
|
||||
select_id = buffer[hit_index].id & 0xFFFF;
|
||||
select_id_subelem = (buffer[hit_index].id & 0xFFFF0000) >> 16;
|
||||
select_id = buffer_sorted[hit_index].id & 0xFFFF;
|
||||
select_id_subelem = (buffer_sorted[hit_index].id & 0xFFFF0000) >> 16;
|
||||
found = true;
|
||||
}
|
||||
MEM_freeN((void *)buffer);
|
||||
}
|
||||
|
||||
Base *basact = nullptr;
|
||||
|
@ -2423,7 +2417,7 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C,
|
|||
{
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
Base *basact = nullptr;
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
GPUSelectBuffer buffer;
|
||||
|
||||
/* setup view context for argument to callbacks */
|
||||
view3d_operator_needs_opengl(C);
|
||||
|
@ -2433,17 +2427,12 @@ static Base *ed_view3d_give_base_under_cursor_ex(bContext *C,
|
|||
|
||||
const bool do_nearest = !XRAY_ACTIVE(vc.v3d);
|
||||
const bool do_material_slot_selection = r_material_slot != nullptr;
|
||||
const int hits = mixed_bones_object_selectbuffer(&vc,
|
||||
buffer,
|
||||
ARRAY_SIZE(buffer),
|
||||
mval,
|
||||
VIEW3D_SELECT_FILTER_NOP,
|
||||
do_nearest,
|
||||
false,
|
||||
do_material_slot_selection);
|
||||
const int hits = mixed_bones_object_selectbuffer(
|
||||
&vc, &buffer, mval, VIEW3D_SELECT_FILTER_NOP, do_nearest, false, do_material_slot_selection);
|
||||
|
||||
if (hits > 0) {
|
||||
const bool has_bones = (r_material_slot == nullptr) && selectbuffer_has_bones(buffer, hits);
|
||||
const bool has_bones = (r_material_slot == nullptr) &&
|
||||
selectbuffer_has_bones(buffer.storage.as_span().slice(0, hits));
|
||||
basact = mouse_select_eval_buffer(
|
||||
&vc, buffer, hits, do_nearest, has_bones, true, r_material_slot);
|
||||
}
|
||||
|
@ -2494,7 +2483,7 @@ static bool ed_object_select_pick_camera_track(bContext *C,
|
|||
Scene *scene,
|
||||
Base *basact,
|
||||
MovieClip *clip,
|
||||
const GPUSelectResult *buffer,
|
||||
const GPUSelectBuffer &buffer,
|
||||
const short hits,
|
||||
const SelectPick_Params *params)
|
||||
{
|
||||
|
@ -2506,7 +2495,7 @@ static bool ed_object_select_pick_camera_track(bContext *C,
|
|||
MovieTrackingTrack *track = nullptr;
|
||||
|
||||
for (int i = 0; i < hits; i++) {
|
||||
const int hitresult = buffer[i].id;
|
||||
const int hitresult = buffer.storage[i].id;
|
||||
|
||||
/* If there's bundles in buffer select bundles first,
|
||||
* so non-camera elements should be ignored in buffer. */
|
||||
|
@ -2615,7 +2604,7 @@ static bool ed_object_select_pick(bContext *C,
|
|||
|
||||
/* Set for GPU depth buffer picking, leave null when selecting by center. */
|
||||
struct GPUData {
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
GPUSelectBuffer buffer;
|
||||
int hits;
|
||||
bool do_nearest;
|
||||
bool has_bones;
|
||||
|
@ -2637,17 +2626,11 @@ static bool ed_object_select_pick(bContext *C,
|
|||
ED_view3d_select_filter_from_mode(scene,
|
||||
vc.obact) :
|
||||
VIEW3D_SELECT_FILTER_NOP);
|
||||
gpu->hits = mixed_bones_object_selectbuffer_extended(&vc,
|
||||
gpu->buffer,
|
||||
ARRAY_SIZE(gpu->buffer),
|
||||
mval,
|
||||
select_filter,
|
||||
true,
|
||||
enumerate,
|
||||
&gpu->do_nearest);
|
||||
gpu->hits = mixed_bones_object_selectbuffer_extended(
|
||||
&vc, &gpu->buffer, mval, select_filter, true, enumerate, &gpu->do_nearest);
|
||||
gpu->has_bones = (object_only && gpu->hits > 0) ?
|
||||
false :
|
||||
selectbuffer_has_bones(gpu->buffer, gpu->hits);
|
||||
selectbuffer_has_bones(gpu->buffer.storage.as_span().slice(0, gpu->hits));
|
||||
}
|
||||
|
||||
/* First handle menu selection, early exit when a menu was opened.
|
||||
|
@ -2655,17 +2638,18 @@ static bool ed_object_select_pick(bContext *C,
|
|||
if (enumerate) {
|
||||
bool has_menu = false;
|
||||
if (center) {
|
||||
if (object_mouse_select_menu(C, &vc, nullptr, 0, mval, params, &basact_override)) {
|
||||
if (object_mouse_select_menu(C, &vc, {}, mval, params, &basact_override)) {
|
||||
has_menu = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (gpu->hits != 0) {
|
||||
if (gpu->has_bones && bone_mouse_select_menu(C, gpu->buffer, gpu->hits, false, params)) {
|
||||
const blender::Span<GPUSelectResult> hit_results = gpu->buffer.storage.as_span().slice(
|
||||
0, gpu->hits);
|
||||
if (gpu->has_bones && bone_mouse_select_menu(C, hit_results, false, params)) {
|
||||
has_menu = true;
|
||||
}
|
||||
else if (object_mouse_select_menu(
|
||||
C, &vc, gpu->buffer, gpu->hits, mval, params, &basact_override)) {
|
||||
else if (object_mouse_select_menu(C, &vc, hit_results, mval, params, &basact_override)) {
|
||||
has_menu = true;
|
||||
}
|
||||
}
|
||||
|
@ -2784,7 +2768,7 @@ static bool ed_object_select_pick(bContext *C,
|
|||
view_layer,
|
||||
v3d,
|
||||
basact ? basact : (Base *)oldbasact,
|
||||
gpu->buffer,
|
||||
gpu->buffer.storage.data(),
|
||||
gpu->hits,
|
||||
params,
|
||||
gpu->do_nearest))
|
||||
|
@ -3374,10 +3358,11 @@ static int view3d_select_exec(bContext *C, wmOperator *op)
|
|||
}
|
||||
else if (obedit->type == OB_ARMATURE) {
|
||||
if (enumerate) {
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
GPUSelectBuffer buffer;
|
||||
const int hits = mixed_bones_object_selectbuffer(
|
||||
&vc, buffer, ARRAY_SIZE(buffer), mval, VIEW3D_SELECT_FILTER_NOP, false, true, false);
|
||||
changed = bone_mouse_select_menu(C, buffer, hits, true, ¶ms);
|
||||
&vc, &buffer, mval, VIEW3D_SELECT_FILTER_NOP, false, true, false);
|
||||
changed = bone_mouse_select_menu(
|
||||
C, buffer.storage.as_span().take_front(hits), true, ¶ms);
|
||||
}
|
||||
if (!changed) {
|
||||
changed = ED_armature_edit_select_pick(C, mval, ¶ms);
|
||||
|
@ -3933,11 +3918,10 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
|
|||
int a;
|
||||
bool changed = false;
|
||||
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
GPUSelectBuffer buffer;
|
||||
int hits;
|
||||
|
||||
hits = view3d_opengl_select(
|
||||
vc, buffer, MAXPICKELEMS, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
|
||||
hits = view3d_opengl_select(vc, &buffer, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
|
||||
|
||||
if (SEL_OP_USE_PRE_DESELECT(sel_op)) {
|
||||
changed |= BKE_mball_deselect_all(mb);
|
||||
|
@ -3950,7 +3934,7 @@ static bool do_meta_box_select(ViewContext *vc, const rcti *rect, const eSelectO
|
|||
bool is_inside_stiff = false;
|
||||
|
||||
for (a = 0; a < hits; a++) {
|
||||
const int hitresult = buffer[a].id;
|
||||
const int hitresult = buffer.storage[a].id;
|
||||
|
||||
if (hitresult == -1) {
|
||||
continue;
|
||||
|
@ -4001,11 +3985,10 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
|
|||
bool changed = false;
|
||||
int a;
|
||||
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
GPUSelectBuffer buffer;
|
||||
int hits;
|
||||
|
||||
hits = view3d_opengl_select(
|
||||
vc, buffer, MAXPICKELEMS, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
|
||||
hits = view3d_opengl_select(vc, &buffer, rect, VIEW3D_SELECT_ALL, VIEW3D_SELECT_FILTER_NOP);
|
||||
|
||||
uint bases_len = 0;
|
||||
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
|
||||
|
@ -4025,7 +4008,7 @@ static bool do_armature_box_select(ViewContext *vc, const rcti *rect, const eSel
|
|||
|
||||
/* first we only check points inside the border */
|
||||
for (a = 0; a < hits; a++) {
|
||||
const int select_id = buffer[a].id;
|
||||
const int select_id = buffer.storage[a].id;
|
||||
if (select_id != -1) {
|
||||
if ((select_id & 0xFFFF0000) == 0) {
|
||||
continue;
|
||||
|
@ -4082,15 +4065,11 @@ static bool do_object_box_select(bContext *C,
|
|||
const eSelectOp sel_op)
|
||||
{
|
||||
View3D *v3d = vc->v3d;
|
||||
int totobj = MAXPICKELEMS; /* XXX solve later */
|
||||
|
||||
/* Selection buffer has bones potentially too, so we add #MAXPICKELEMS. */
|
||||
GPUSelectResult *buffer = static_cast<GPUSelectResult *>(
|
||||
MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult), __func__));
|
||||
GPUSelectBuffer buffer;
|
||||
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
|
||||
vc->obact);
|
||||
const int hits = view3d_opengl_select(
|
||||
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
|
||||
const int hits = view3d_opengl_select(vc, &buffer, rect, VIEW3D_SELECT_ALL, select_filter);
|
||||
BKE_view_layer_synced_ensure(vc->scene, vc->view_layer);
|
||||
LISTBASE_FOREACH (Base *, base, BKE_view_layer_object_bases_get(vc->view_layer)) {
|
||||
base->object->id.tag &= ~LIB_TAG_DOIT;
|
||||
|
@ -4117,9 +4096,10 @@ static bool do_object_box_select(bContext *C,
|
|||
}
|
||||
|
||||
/* The draw order doesn't always match the order we populate the engine, see: #51695. */
|
||||
qsort(buffer, hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp);
|
||||
qsort(buffer.storage.data(), hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp);
|
||||
|
||||
for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end;
|
||||
for (const GPUSelectResult *buf_iter = buffer.storage.data(), *buf_end = buf_iter + hits;
|
||||
buf_iter < buf_end;
|
||||
buf_iter++)
|
||||
{
|
||||
bPoseChannel *pchan_dummy;
|
||||
|
@ -4144,8 +4124,6 @@ static bool do_object_box_select(bContext *C,
|
|||
|
||||
finally:
|
||||
|
||||
MEM_freeN(buffer);
|
||||
|
||||
if (changed) {
|
||||
DEG_id_tag_update(&vc->scene->id, ID_RECALC_SELECT);
|
||||
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
|
||||
|
@ -4160,15 +4138,11 @@ static bool do_pose_box_select(bContext *C,
|
|||
{
|
||||
blender::Vector<Base *> bases = do_pose_tag_select_op_prepare(vc);
|
||||
|
||||
int totobj = MAXPICKELEMS; /* XXX solve later */
|
||||
|
||||
/* Selection buffer has bones potentially too, so add #MAXPICKELEMS. */
|
||||
GPUSelectResult *buffer = static_cast<GPUSelectResult *>(
|
||||
MEM_mallocN((totobj + MAXPICKELEMS) * sizeof(GPUSelectResult), __func__));
|
||||
/* Selection buffer has bones potentially too. */
|
||||
GPUSelectBuffer buffer;
|
||||
const eV3DSelectObjectFilter select_filter = ED_view3d_select_filter_from_mode(vc->scene,
|
||||
vc->obact);
|
||||
const int hits = view3d_opengl_select(
|
||||
vc, buffer, (totobj + MAXPICKELEMS), rect, VIEW3D_SELECT_ALL, select_filter);
|
||||
const int hits = view3d_opengl_select(vc, &buffer, rect, VIEW3D_SELECT_ALL, select_filter);
|
||||
/*
|
||||
* NOTE(@theeth): Regarding the logic use here.
|
||||
* The buffer and #ListBase have the same relative order, which makes the selection
|
||||
|
@ -4181,9 +4155,10 @@ static bool do_pose_box_select(bContext *C,
|
|||
/* no need to loop if there's no hit */
|
||||
|
||||
/* The draw order doesn't always match the order we populate the engine, see: #51695. */
|
||||
qsort(buffer, hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp);
|
||||
qsort(buffer.storage.data(), hits, sizeof(GPUSelectResult), opengl_bone_select_buffer_cmp);
|
||||
|
||||
for (const GPUSelectResult *buf_iter = buffer, *buf_end = buf_iter + hits; buf_iter < buf_end;
|
||||
for (const GPUSelectResult *buf_iter = buffer.storage.data(), *buf_end = buf_iter + hits;
|
||||
buf_iter < buf_end;
|
||||
buf_iter++)
|
||||
{
|
||||
Bone *bone;
|
||||
|
@ -4228,8 +4203,6 @@ static bool do_pose_box_select(bContext *C,
|
|||
WM_event_add_notifier(C, NC_SCENE | ND_OB_SELECT, vc->scene);
|
||||
}
|
||||
|
||||
MEM_freeN(buffer);
|
||||
|
||||
return changed_multi;
|
||||
}
|
||||
|
||||
|
|
|
@ -479,8 +479,7 @@ void view3d_opengl_select_cache_end()
|
|||
struct DrawSelectLoopUserData {
|
||||
uint pass;
|
||||
uint hits;
|
||||
GPUSelectResult *buffer;
|
||||
uint buffer_len;
|
||||
GPUSelectBuffer *buffer;
|
||||
const rcti *rect;
|
||||
eGPUSelectMode gpu_select_mode;
|
||||
};
|
||||
|
@ -490,8 +489,7 @@ static bool drw_select_loop_pass(eDRWSelectStage stage, void *user_data)
|
|||
bool continue_pass = false;
|
||||
DrawSelectLoopUserData *data = static_cast<DrawSelectLoopUserData *>(user_data);
|
||||
if (stage == DRW_SELECT_PASS_PRE) {
|
||||
GPU_select_begin_next(
|
||||
data->buffer, data->buffer_len, data->rect, data->gpu_select_mode, data->hits);
|
||||
GPU_select_begin_next(data->buffer, data->rect, data->gpu_select_mode, data->hits);
|
||||
/* always run POST after PRE. */
|
||||
continue_pass = true;
|
||||
}
|
||||
|
@ -544,8 +542,7 @@ static bool drw_select_filter_object_mode_lock_for_weight_paint(Object *ob, void
|
|||
}
|
||||
|
||||
int view3d_opengl_select_ex(ViewContext *vc,
|
||||
GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
GPUSelectBuffer *buffer,
|
||||
const rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
|
@ -610,7 +607,7 @@ int view3d_opengl_select_ex(ViewContext *vc,
|
|||
/* Re-use cache (rect must be smaller than the cached)
|
||||
* other context is assumed to be unchanged */
|
||||
if (GPU_select_is_cached()) {
|
||||
GPU_select_begin_next(buffer, buffer_len, &rect, gpu_select_mode, 0);
|
||||
GPU_select_begin_next(buffer, &rect, gpu_select_mode, 0);
|
||||
GPU_select_cache_load_id();
|
||||
hits = GPU_select_end();
|
||||
goto finally;
|
||||
|
@ -691,7 +688,6 @@ int view3d_opengl_select_ex(ViewContext *vc,
|
|||
drw_select_loop_user_data.pass = 0;
|
||||
drw_select_loop_user_data.hits = 0;
|
||||
drw_select_loop_user_data.buffer = buffer;
|
||||
drw_select_loop_user_data.buffer_len = buffer_len;
|
||||
drw_select_loop_user_data.rect = ▭
|
||||
drw_select_loop_user_data.gpu_select_mode = gpu_select_mode;
|
||||
|
||||
|
@ -721,7 +717,6 @@ int view3d_opengl_select_ex(ViewContext *vc,
|
|||
drw_select_loop_user_data.pass = 0;
|
||||
drw_select_loop_user_data.hits = 0;
|
||||
drw_select_loop_user_data.buffer = buffer;
|
||||
drw_select_loop_user_data.buffer_len = buffer_len;
|
||||
drw_select_loop_user_data.rect = ▭
|
||||
drw_select_loop_user_data.gpu_select_mode = gpu_select_mode;
|
||||
|
||||
|
@ -755,38 +750,36 @@ int view3d_opengl_select_ex(ViewContext *vc,
|
|||
UI_Theme_Restore(&theme_state);
|
||||
|
||||
finally:
|
||||
|
||||
if (hits < 0) {
|
||||
printf("Too many objects in select buffer\n"); /* XXX make error message */
|
||||
}
|
||||
|
||||
return hits;
|
||||
}
|
||||
|
||||
int view3d_opengl_select(ViewContext *vc,
|
||||
GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
GPUSelectBuffer *buffer,
|
||||
const rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter)
|
||||
{
|
||||
return view3d_opengl_select_ex(vc, buffer, buffer_len, input, select_mode, select_filter, false);
|
||||
return view3d_opengl_select_ex(vc, buffer, input, select_mode, select_filter, false);
|
||||
}
|
||||
|
||||
int view3d_opengl_select_with_id_filter(ViewContext *vc,
|
||||
GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
GPUSelectBuffer *buffer,
|
||||
const rcti *input,
|
||||
eV3DSelectMode select_mode,
|
||||
eV3DSelectObjectFilter select_filter,
|
||||
uint select_id)
|
||||
{
|
||||
int hits = view3d_opengl_select(vc, buffer, buffer_len, input, select_mode, select_filter);
|
||||
const int64_t start = buffer->storage.size();
|
||||
int hits = view3d_opengl_select(vc, buffer, input, select_mode, select_filter);
|
||||
|
||||
/* Selection sometimes uses -1 for an invalid selection ID, remove these as they
|
||||
* interfere with detection of actual number of hits in the selection. */
|
||||
if (hits > 0) {
|
||||
hits = GPU_select_buffer_remove_by_id(buffer, hits, select_id);
|
||||
hits = GPU_select_buffer_remove_by_id(buffer->storage.as_mutable_span().slice(start, hits),
|
||||
select_id);
|
||||
|
||||
/* Trim buffer to the exact size in case selections were removed. */
|
||||
buffer->storage.resize(start + hits);
|
||||
}
|
||||
return hits;
|
||||
}
|
||||
|
|
|
@ -8,11 +8,9 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BLI_span.hh"
|
||||
#include "BLI_sys_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "BLI_vector.hh"
|
||||
|
||||
struct rcti;
|
||||
|
||||
|
@ -43,11 +41,15 @@ typedef struct GPUSelectResult {
|
|||
unsigned int depth;
|
||||
} GPUSelectResult;
|
||||
|
||||
using GPUSelectStorage = blender::Vector<GPUSelectResult, 2500>;
|
||||
struct GPUSelectBuffer {
|
||||
GPUSelectStorage storage;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize and provide buffer for results.
|
||||
*/
|
||||
void GPU_select_begin(GPUSelectResult *buffer,
|
||||
unsigned int buffer_len,
|
||||
void GPU_select_begin(GPUSelectBuffer *buffer,
|
||||
const struct rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits);
|
||||
|
@ -55,8 +57,7 @@ void GPU_select_begin(GPUSelectResult *buffer,
|
|||
* Initialize and provide buffer for results.
|
||||
* Uses the new Select-Next engine if enabled.
|
||||
*/
|
||||
void GPU_select_begin_next(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
void GPU_select_begin_next(GPUSelectBuffer *buffer,
|
||||
const struct rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits);
|
||||
|
@ -92,13 +93,10 @@ void GPU_select_cache_end(void);
|
|||
*
|
||||
* Note that comparing depth as uint is fine.
|
||||
*/
|
||||
const GPUSelectResult *GPU_select_buffer_near(const GPUSelectResult *buffer, int hits);
|
||||
uint GPU_select_buffer_remove_by_id(GPUSelectResult *buffer, int hits, uint select_id);
|
||||
const GPUSelectResult *GPU_select_buffer_near(const blender::Span<GPUSelectResult> hit_results);
|
||||
uint GPU_select_buffer_remove_by_id(blender::MutableSpan<GPUSelectResult> hit_results,
|
||||
uint select_id);
|
||||
/**
|
||||
* Part of the solution copied from `rect_subregion_stride_calc`.
|
||||
*/
|
||||
void GPU_select_buffer_stride_realign(const struct rcti *src, const struct rcti *dst, uint *r_buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -69,8 +69,7 @@ static GPUSelectState g_select_state = {false};
|
|||
/** \name Public API
|
||||
* \{ */
|
||||
|
||||
static void gpu_select_begin_ex(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
static void gpu_select_begin_ex(GPUSelectBuffer *buffer,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits,
|
||||
|
@ -117,38 +116,32 @@ static void gpu_select_begin_ex(GPUSelectResult *buffer,
|
|||
|
||||
switch (g_select_state.algorithm) {
|
||||
case ALGO_SELECT_NEXT: {
|
||||
gpu_select_next_begin(buffer, buffer_len, input, mode);
|
||||
gpu_select_next_begin(buffer, input, mode);
|
||||
break;
|
||||
}
|
||||
case ALGO_GL_QUERY: {
|
||||
gpu_select_query_begin(buffer, buffer_len, input, mode, oldhits);
|
||||
gpu_select_query_begin(buffer, input, mode, oldhits);
|
||||
break;
|
||||
}
|
||||
default: /* ALGO_GL_PICK */
|
||||
{
|
||||
gpu_select_pick_begin(buffer, buffer_len, input, mode);
|
||||
gpu_select_pick_begin(buffer, input, mode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPU_select_begin_next(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
void GPU_select_begin_next(GPUSelectBuffer *buffer,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits)
|
||||
{
|
||||
gpu_select_begin_ex(
|
||||
buffer, buffer_len, input, mode, oldhits, U.experimental.enable_overlay_next);
|
||||
gpu_select_begin_ex(buffer, input, mode, oldhits, U.experimental.enable_overlay_next);
|
||||
}
|
||||
|
||||
void GPU_select_begin(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits)
|
||||
void GPU_select_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode, int oldhits)
|
||||
{
|
||||
gpu_select_begin_ex(buffer, buffer_len, input, mode, oldhits, false);
|
||||
gpu_select_begin_ex(buffer, input, mode, oldhits, false);
|
||||
}
|
||||
|
||||
bool GPU_select_load_id(uint id)
|
||||
|
@ -249,35 +242,35 @@ bool GPU_select_is_cached()
|
|||
/** \name Utilities
|
||||
* \{ */
|
||||
|
||||
const GPUSelectResult *GPU_select_buffer_near(const GPUSelectResult *buffer, int hits)
|
||||
const GPUSelectResult *GPU_select_buffer_near(const blender::Span<GPUSelectResult> hit_results)
|
||||
{
|
||||
const GPUSelectResult *buffer_near = nullptr;
|
||||
uint depth_min = uint(-1);
|
||||
for (int i = 0; i < hits; i++) {
|
||||
if (buffer->depth < depth_min) {
|
||||
BLI_assert(buffer->id != -1);
|
||||
depth_min = buffer->depth;
|
||||
buffer_near = buffer;
|
||||
for (const GPUSelectResult &result : hit_results) {
|
||||
if (result.depth < depth_min) {
|
||||
BLI_assert(result.id != -1);
|
||||
depth_min = result.depth;
|
||||
buffer_near = &result;
|
||||
}
|
||||
buffer++;
|
||||
}
|
||||
return buffer_near;
|
||||
}
|
||||
|
||||
uint GPU_select_buffer_remove_by_id(GPUSelectResult *buffer, int hits, uint select_id)
|
||||
uint GPU_select_buffer_remove_by_id(blender::MutableSpan<GPUSelectResult> hit_results,
|
||||
uint select_id)
|
||||
{
|
||||
GPUSelectResult *buffer_src = buffer;
|
||||
GPUSelectResult *buffer_dst = buffer;
|
||||
int hits_final = 0;
|
||||
for (int i = 0; i < hits; i++) {
|
||||
if (buffer_src->id != select_id) {
|
||||
if (buffer_dst != buffer_src) {
|
||||
memcpy(buffer_dst, buffer_src, sizeof(GPUSelectResult));
|
||||
uint index_src = 0;
|
||||
uint index_dst = 0;
|
||||
uint hits_final = 0;
|
||||
for (const GPUSelectResult &result : hit_results) {
|
||||
if (result.id != select_id) {
|
||||
if (index_dst != index_src) {
|
||||
hit_results[index_dst] = result;
|
||||
}
|
||||
buffer_dst++;
|
||||
hits_final += 1;
|
||||
index_dst++;
|
||||
hits_final++;
|
||||
}
|
||||
buffer_src++;
|
||||
index_src++;
|
||||
}
|
||||
return hits_final;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,7 @@
|
|||
|
||||
struct GPUSelectNextState {
|
||||
/** Result buffer set on initialization. */
|
||||
GPUSelectResult *buffer;
|
||||
uint buffer_len;
|
||||
GPUSelectBuffer *buffer;
|
||||
/** Area of the viewport to render / select from. */
|
||||
rcti rect;
|
||||
/** Number of hits. Set to -1 if it overflows buffer_len. */
|
||||
|
@ -30,15 +29,11 @@ struct GPUSelectNextState {
|
|||
|
||||
static GPUSelectNextState g_state = {};
|
||||
|
||||
void gpu_select_next_begin(GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode)
|
||||
void gpu_select_next_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode)
|
||||
|
||||
{
|
||||
g_state.buffer = buffer;
|
||||
g_state.rect = *input;
|
||||
g_state.buffer_len = buffer_len;
|
||||
g_state.mode = mode;
|
||||
}
|
||||
|
||||
|
@ -54,32 +49,27 @@ eGPUSelectMode gpu_select_next_get_mode()
|
|||
}
|
||||
|
||||
void gpu_select_next_set_result(GPUSelectResult *hit_buf, uint hit_len)
|
||||
|
||||
{
|
||||
if (hit_len > g_state.buffer_len) {
|
||||
g_state.hits = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
blender::MutableSpan<GPUSelectResult> result(g_state.buffer, g_state.buffer_len);
|
||||
blender::Span<GPUSelectResult> hits(hit_buf, hit_len);
|
||||
g_state.buffer->storage.resize(hit_len);
|
||||
blender::MutableSpan<GPUSelectResult> result = g_state.buffer->storage.as_mutable_span();
|
||||
const blender::Span<GPUSelectResult> hits(hit_buf, hit_len);
|
||||
|
||||
/* TODO(fclem): There might be some conversion to do to align to the other APIs output. */
|
||||
switch (g_state.mode) {
|
||||
case eGPUSelectMode::GPU_SELECT_ALL:
|
||||
result.take_front(hit_len).copy_from(hits);
|
||||
result.copy_from(hits);
|
||||
break;
|
||||
case eGPUSelectMode::GPU_SELECT_NEAREST_FIRST_PASS:
|
||||
result.take_front(hit_len).copy_from(hits);
|
||||
result.copy_from(hits);
|
||||
break;
|
||||
case eGPUSelectMode::GPU_SELECT_NEAREST_SECOND_PASS:
|
||||
result.take_front(hit_len).copy_from(hits);
|
||||
result.copy_from(hits);
|
||||
break;
|
||||
case eGPUSelectMode::GPU_SELECT_PICK_ALL:
|
||||
result.take_front(hit_len).copy_from(hits);
|
||||
result.copy_from(hits);
|
||||
break;
|
||||
case eGPUSelectMode::GPU_SELECT_PICK_NEAREST:
|
||||
result.take_front(hit_len).copy_from(hits);
|
||||
result.copy_from(hits);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -227,8 +227,7 @@ static int depth_cmp(const void *v1, const void *v2)
|
|||
/** Depth sorting. */
|
||||
struct GPUPickState {
|
||||
/** Cache on initialization. */
|
||||
GPUSelectResult *buffer;
|
||||
uint buffer_len;
|
||||
GPUSelectBuffer *buffer;
|
||||
/** Mode of this operation. */
|
||||
eGPUSelectMode mode;
|
||||
|
||||
|
@ -294,10 +293,7 @@ struct GPUPickState {
|
|||
|
||||
static GPUPickState g_pick_state{};
|
||||
|
||||
void gpu_select_pick_begin(GPUSelectResult *buffer,
|
||||
const uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode)
|
||||
void gpu_select_pick_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode)
|
||||
{
|
||||
GPUPickState *ps = &g_pick_state;
|
||||
|
||||
|
@ -312,7 +308,6 @@ void gpu_select_pick_begin(GPUSelectResult *buffer,
|
|||
GPU_debug_group_begin("Selection Pick");
|
||||
|
||||
ps->buffer = buffer;
|
||||
ps->buffer_len = buffer_len;
|
||||
ps->mode = mode;
|
||||
|
||||
const uint rect_len = uint(BLI_rcti_size_x(input) * BLI_rcti_size_y(input));
|
||||
|
@ -577,7 +572,6 @@ uint gpu_select_pick_end()
|
|||
rect_depth_final = ps->gpu.rect_depth;
|
||||
}
|
||||
|
||||
uint maxhits = g_pick_state.buffer_len;
|
||||
DepthID *depth_data;
|
||||
uint depth_data_len = 0;
|
||||
|
||||
|
@ -662,22 +656,16 @@ uint gpu_select_pick_end()
|
|||
* so the final hit-list is sorted by depth (nearest first). */
|
||||
uint hits = 0;
|
||||
|
||||
if (depth_data_len > maxhits) {
|
||||
hits = uint(-1);
|
||||
}
|
||||
else {
|
||||
/* Leave sorting up to the caller. */
|
||||
qsort(depth_data, depth_data_len, sizeof(DepthID), depth_cmp);
|
||||
/* Leave sorting up to the caller. */
|
||||
qsort(depth_data, depth_data_len, sizeof(DepthID), depth_cmp);
|
||||
|
||||
for (uint i = 0; i < depth_data_len; i++) {
|
||||
g_pick_state.buffer->storage.reserve(g_pick_state.buffer->storage.size() + depth_data_len);
|
||||
for (uint i = 0; i < depth_data_len; i++) {
|
||||
#ifdef DEBUG_PRINT
|
||||
printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth);
|
||||
printf(" hit: %u: depth %u\n", depth_data[i].id, depth_data[i].depth);
|
||||
#endif
|
||||
g_pick_state.buffer[hits].depth = depth_data[i].depth;
|
||||
g_pick_state.buffer[hits].id = depth_data[i].id;
|
||||
hits++;
|
||||
}
|
||||
BLI_assert(hits < maxhits);
|
||||
g_pick_state.buffer->storage.append_unchecked({depth_data[i].id, depth_data[i].depth});
|
||||
hits++;
|
||||
}
|
||||
|
||||
MEM_freeN(depth_data);
|
||||
|
|
|
@ -16,10 +16,7 @@ extern "C" {
|
|||
|
||||
/* gpu_select_pick */
|
||||
|
||||
void gpu_select_pick_begin(GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode);
|
||||
void gpu_select_pick_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode);
|
||||
bool gpu_select_pick_load_id(uint id, bool end);
|
||||
uint gpu_select_pick_end(void);
|
||||
|
||||
|
@ -33,17 +30,16 @@ void gpu_select_pick_cache_load_id(void);
|
|||
|
||||
/* gpu_select_sample_query */
|
||||
|
||||
void gpu_select_query_begin(
|
||||
GPUSelectResult *buffer, uint buffer_len, const rcti *input, eGPUSelectMode mode, int oldhits);
|
||||
void gpu_select_query_begin(GPUSelectBuffer *buffer,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode,
|
||||
int oldhits);
|
||||
bool gpu_select_query_load_id(uint id);
|
||||
uint gpu_select_query_end(void);
|
||||
|
||||
/* gpu_select_next */
|
||||
|
||||
void gpu_select_next_begin(GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
const rcti *input,
|
||||
eGPUSelectMode mode);
|
||||
void gpu_select_next_begin(GPUSelectBuffer *buffer, const rcti *input, eGPUSelectMode mode);
|
||||
uint gpu_select_next_end(void);
|
||||
|
||||
/* Return a single offset since picking uses squared viewport. */
|
||||
|
|
|
@ -39,9 +39,7 @@ struct GPUSelectQueryState {
|
|||
/** Array holding the id corresponding id to each query. */
|
||||
Vector<uint, QUERY_MIN_LEN> *ids;
|
||||
/** Cache on initialization. */
|
||||
GPUSelectResult *buffer;
|
||||
/** The capacity of the `buffer` array. */
|
||||
uint buffer_len;
|
||||
GPUSelectBuffer *buffer;
|
||||
/** Mode of operation. */
|
||||
eGPUSelectMode mode;
|
||||
uint index;
|
||||
|
@ -56,8 +54,7 @@ struct GPUSelectQueryState {
|
|||
|
||||
static GPUSelectQueryState g_query_state = {false};
|
||||
|
||||
void gpu_select_query_begin(GPUSelectResult *buffer,
|
||||
uint buffer_len,
|
||||
void gpu_select_query_begin(GPUSelectBuffer *buffer,
|
||||
const rcti *input,
|
||||
const eGPUSelectMode mode,
|
||||
int oldhits)
|
||||
|
@ -66,7 +63,6 @@ void gpu_select_query_begin(GPUSelectResult *buffer,
|
|||
|
||||
g_query_state.query_issued = false;
|
||||
g_query_state.buffer = buffer;
|
||||
g_query_state.buffer_len = buffer_len;
|
||||
g_query_state.mode = mode;
|
||||
g_query_state.index = 0;
|
||||
g_query_state.oldhits = oldhits;
|
||||
|
@ -129,7 +125,7 @@ bool gpu_select_query_load_id(uint id)
|
|||
* can read past `buffer_len` in this case. */
|
||||
BLI_assert(g_query_state.oldhits != -1);
|
||||
if (g_query_state.index < g_query_state.oldhits) {
|
||||
if (g_query_state.buffer[g_query_state.index].id == id) {
|
||||
if (g_query_state.buffer->storage[g_query_state.index].id == id) {
|
||||
g_query_state.index++;
|
||||
return true;
|
||||
}
|
||||
|
@ -142,7 +138,6 @@ bool gpu_select_query_load_id(uint id)
|
|||
uint gpu_select_query_end()
|
||||
{
|
||||
uint hits = 0;
|
||||
const uint maxhits = g_query_state.buffer_len;
|
||||
|
||||
if (g_query_state.query_issued) {
|
||||
g_query_state.queries->end_query();
|
||||
|
@ -155,22 +150,15 @@ uint gpu_select_query_end()
|
|||
for (int i = 0; i < result.size(); i++) {
|
||||
if (result[i] != 0) {
|
||||
if (g_query_state.mode != GPU_SELECT_NEAREST_SECOND_PASS) {
|
||||
if (hits < maxhits) {
|
||||
g_query_state.buffer[hits].depth = 0xFFFF;
|
||||
g_query_state.buffer[hits].id = ids[i];
|
||||
hits++;
|
||||
}
|
||||
else {
|
||||
hits = -1;
|
||||
break;
|
||||
}
|
||||
g_query_state.buffer->storage.append({ids[i], 0xFFFF});
|
||||
hits++;
|
||||
}
|
||||
else {
|
||||
int j;
|
||||
/* search in buffer and make selected object first */
|
||||
for (j = 0; j < g_query_state.oldhits; j++) {
|
||||
if (g_query_state.buffer[j].id == ids[i]) {
|
||||
g_query_state.buffer[j].depth = 0;
|
||||
if (g_query_state.buffer->storage[j].id == ids[i]) {
|
||||
g_query_state.buffer->storage[j].depth = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -569,7 +569,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
|||
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
|
||||
rcti rect;
|
||||
/* Almost certainly overkill, but allow for many custom gizmos. */
|
||||
GPUSelectResult buffer[MAXPICKELEMS];
|
||||
GPUSelectBuffer buffer;
|
||||
short hits;
|
||||
|
||||
BLI_rcti_init_pt_radius(&rect, co, hotspot);
|
||||
|
@ -582,14 +582,14 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
|||
/* TODO: waiting for the GPU in the middle of the event loop for every
|
||||
* mouse move is bad for performance, we need to find a solution to not
|
||||
* use the GPU or draw something once. (see #61474) */
|
||||
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
|
||||
GPU_select_begin(&buffer, &rect, GPU_SELECT_NEAREST_FIRST_PASS, 0);
|
||||
/* do the drawing */
|
||||
gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
|
||||
|
||||
hits = GPU_select_end();
|
||||
|
||||
if (hits > 0) {
|
||||
GPU_select_begin(buffer, ARRAY_SIZE(buffer), &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
|
||||
GPU_select_begin(&buffer, &rect, GPU_SELECT_NEAREST_SECOND_PASS, hits);
|
||||
gizmo_draw_select_3d_loop(C, visible_gizmos, visible_gizmos_len, &use_select_bias);
|
||||
GPU_select_end();
|
||||
}
|
||||
|
@ -597,6 +597,7 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
|||
ED_view3d_draw_setup_view(
|
||||
wm, CTX_wm_window(C), depsgraph, CTX_data_scene(C), region, v3d, nullptr, nullptr, nullptr);
|
||||
|
||||
const blender::Span<GPUSelectResult> hit_results = buffer.storage.as_span().take_front(hits);
|
||||
if (use_select_bias && (hits > 1)) {
|
||||
float co_direction[3];
|
||||
float co_screen[3] = {float(co[0]), float(co[1]), 0.0f};
|
||||
|
@ -608,15 +609,14 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
|||
|
||||
GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d_origin);
|
||||
|
||||
GPUSelectResult *buf_iter = buffer;
|
||||
int hit_found = -1;
|
||||
float dot_best = FLT_MAX;
|
||||
|
||||
for (int i = 0; i < hits; i++, buf_iter++) {
|
||||
BLI_assert(buf_iter->id != -1);
|
||||
wmGizmo *gz = visible_gizmos[buf_iter->id >> 8];
|
||||
for (const GPUSelectResult &result : hit_results) {
|
||||
BLI_assert(result.id != -1);
|
||||
wmGizmo *gz = visible_gizmos[result.id >> 8];
|
||||
float co_3d[3];
|
||||
co_screen[2] = float(double(buf_iter->depth) / double(UINT_MAX));
|
||||
co_screen[2] = float(double(result.depth) / double(UINT_MAX));
|
||||
GPU_matrix_unproject_3fv(co_screen, rv3d->viewinv, rv3d->winmat, viewport, co_3d);
|
||||
float select_bias = gz->select_bias;
|
||||
if ((gz->flag & WM_GIZMO_DRAW_NO_SCALE) == 0) {
|
||||
|
@ -626,13 +626,13 @@ static int gizmo_find_intersected_3d_intern(wmGizmo **visible_gizmos,
|
|||
const float dot_test = dot_v3v3(co_3d, co_direction) - select_bias;
|
||||
if (dot_best > dot_test) {
|
||||
dot_best = dot_test;
|
||||
hit_found = buf_iter->id;
|
||||
hit_found = result.id;
|
||||
}
|
||||
}
|
||||
return hit_found;
|
||||
}
|
||||
|
||||
const GPUSelectResult *hit_near = GPU_select_buffer_near(buffer, hits);
|
||||
const GPUSelectResult *hit_near = GPU_select_buffer_near(hit_results);
|
||||
return hit_near ? hit_near->id : -1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue