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;
|
||||
deadpin marked this conversation as resolved
Outdated
|
||||
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(
|
||||
deadpin marked this conversation as resolved
Outdated
Clément Foucault
commented
Warning: Unused variable Warning: Unused variable
|
||||
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;
|
||||
deadpin marked this conversation as resolved
Outdated
Campbell Barton
commented
These can be These can be `int`, the range is easily enough and used elsewhere with selection indices.
|
||||
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
|
||||
deadpin marked this conversation as resolved
Outdated
Campbell Barton
commented
Since the size is known ahead of time, reserve then use Since the size is known ahead of time, reserve then use `append_unchecked` to avoid re-allocation.
|
||||
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);
|
||||
deadpin marked this conversation as resolved
Outdated
Clément Foucault
commented
Should be Should be `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
These are incorrect. It should be
results.slice(0, hits5).copy_from(results.slice(ofs, hits5));
Same goes for the other 2
copy_from
in this patch.