Particularly noticeable when vertex painting with a subsurf modifier. In some cases every sculpt or paint stroke step would evaluate the dependency graph. This should only happen for redraws. Now more selectively choose if the dependency graph should be evaluated to initialize the view context. Doing it in the view context evaluation is somewhat hidden, now it's more explicit. Differential Revision: https://developer.blender.org/D5844
701 lines
18 KiB
C
701 lines
18 KiB
C
/*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
/** \file
|
|
* \ingroup edlattice
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BLI_listbase.h"
|
|
#include "BLI_math.h"
|
|
#include "BLI_utildefines.h"
|
|
#include "BLI_rand.h"
|
|
#include "BLI_bitmap.h"
|
|
|
|
#include "DNA_curve_types.h"
|
|
#include "DNA_lattice_types.h"
|
|
#include "DNA_meshdata_types.h"
|
|
#include "DNA_object_types.h"
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "RNA_access.h"
|
|
#include "RNA_define.h"
|
|
#include "RNA_enum_types.h"
|
|
|
|
#include "BKE_context.h"
|
|
#include "BKE_lattice.h"
|
|
#include "BKE_report.h"
|
|
#include "BKE_layer.h"
|
|
|
|
#include "ED_object.h"
|
|
#include "ED_screen.h"
|
|
#include "ED_select_utils.h"
|
|
#include "ED_lattice.h"
|
|
#include "ED_view3d.h"
|
|
|
|
#include "WM_api.h"
|
|
#include "WM_types.h"
|
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
#include "lattice_intern.h"
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Utility Functions
|
|
* \{ */
|
|
|
|
static void bpoint_select_set(BPoint *bp, bool select)
|
|
{
|
|
if (select) {
|
|
if (!bp->hide) {
|
|
bp->f1 |= SELECT;
|
|
}
|
|
}
|
|
else {
|
|
bp->f1 &= ~SELECT;
|
|
}
|
|
}
|
|
|
|
bool ED_lattice_deselect_all_multi_ex(struct Base **bases, const uint bases_len)
|
|
{
|
|
bool changed_multi = false;
|
|
for (uint base_index = 0; base_index < bases_len; base_index++) {
|
|
Base *base_iter = bases[base_index];
|
|
Object *ob_iter = base_iter->object;
|
|
changed_multi |= ED_lattice_flags_set(ob_iter, 0);
|
|
DEG_id_tag_update(ob_iter->data, ID_RECALC_SELECT);
|
|
}
|
|
return changed_multi;
|
|
}
|
|
|
|
bool ED_lattice_deselect_all_multi(struct bContext *C)
|
|
{
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
|
ViewContext vc;
|
|
ED_view3d_viewcontext_init(C, &vc, depsgraph);
|
|
uint bases_len = 0;
|
|
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
|
|
vc.view_layer, vc.v3d, &bases_len);
|
|
bool changed_multi = ED_lattice_deselect_all_multi_ex(bases, bases_len);
|
|
MEM_freeN(bases);
|
|
return changed_multi;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Select Random Operator
|
|
* \{ */
|
|
|
|
static int lattice_select_random_exec(bContext *C, wmOperator *op)
|
|
{
|
|
const float randfac = RNA_float_get(op->ptr, "percent") / 100.0f;
|
|
const int seed = WM_operator_properties_select_random_seed_increment_get(op);
|
|
const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
|
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
uint objects_len = 0;
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
view_layer, CTX_wm_view3d(C), &objects_len);
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
Object *obedit = objects[ob_index];
|
|
Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
|
|
|
|
RNG *rng = BLI_rng_new_srandom(seed);
|
|
|
|
int tot;
|
|
BPoint *bp;
|
|
|
|
tot = lt->pntsu * lt->pntsv * lt->pntsw;
|
|
bp = lt->def;
|
|
while (tot--) {
|
|
if (!bp->hide) {
|
|
if (BLI_rng_get_float(rng) < randfac) {
|
|
bpoint_select_set(bp, select);
|
|
}
|
|
}
|
|
bp++;
|
|
}
|
|
|
|
if (select == false) {
|
|
lt->actbp = LT_ACTBP_NONE;
|
|
}
|
|
|
|
BLI_rng_free(rng);
|
|
|
|
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
|
}
|
|
MEM_freeN(objects);
|
|
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
void LATTICE_OT_select_random(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "Select Random";
|
|
ot->description = "Randomly select UVW control points";
|
|
ot->idname = "LATTICE_OT_select_random";
|
|
|
|
/* api callbacks */
|
|
ot->exec = lattice_select_random_exec;
|
|
ot->poll = ED_operator_editlattice;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
/* props */
|
|
WM_operator_properties_select_random(ot);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Select Mirror Operator
|
|
* \{ */
|
|
|
|
static void ed_lattice_select_mirrored(Lattice *lt, const int axis, const bool extend)
|
|
{
|
|
const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
|
|
int i;
|
|
BPoint *bp;
|
|
BLI_bitmap *selpoints;
|
|
|
|
bool flip_uvw[3] = {false};
|
|
flip_uvw[axis] = true;
|
|
|
|
/* we could flip this too */
|
|
if (!extend) {
|
|
lt->actbp = LT_ACTBP_NONE;
|
|
}
|
|
|
|
/* store "original" selection */
|
|
selpoints = BLI_BITMAP_NEW(tot, __func__);
|
|
BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
|
|
|
|
/* actual (de)selection */
|
|
for (i = 0; i < tot; i++) {
|
|
const int i_flip = BKE_lattice_index_flip(lt, i, flip_uvw[0], flip_uvw[1], flip_uvw[2]);
|
|
bp = <->def[i];
|
|
if (!bp->hide) {
|
|
if (BLI_BITMAP_TEST(selpoints, i_flip)) {
|
|
bp->f1 |= SELECT;
|
|
}
|
|
else {
|
|
if (!extend) {
|
|
bp->f1 &= ~SELECT;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
MEM_freeN(selpoints);
|
|
}
|
|
|
|
static int lattice_select_mirror_exec(bContext *C, wmOperator *op)
|
|
{
|
|
const int axis_flag = RNA_enum_get(op->ptr, "axis");
|
|
const bool extend = RNA_boolean_get(op->ptr, "extend");
|
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
uint objects_len = 0;
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
view_layer, CTX_wm_view3d(C), &objects_len);
|
|
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
Object *obedit = objects[ob_index];
|
|
Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
|
|
|
|
for (int axis = 0; axis < 3; axis++) {
|
|
if ((1 << axis) & axis_flag) {
|
|
ed_lattice_select_mirrored(lt, axis, extend);
|
|
}
|
|
}
|
|
|
|
/* TODO, only notify changes */
|
|
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
|
}
|
|
MEM_freeN(objects);
|
|
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
void LATTICE_OT_select_mirror(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "Select Mirror";
|
|
ot->description = "Select mirrored lattice points";
|
|
ot->idname = "LATTICE_OT_select_mirror";
|
|
|
|
/* api callbacks */
|
|
ot->exec = lattice_select_mirror_exec;
|
|
ot->poll = ED_operator_editlattice;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
/* props */
|
|
RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", "");
|
|
|
|
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Select More/Less Operator
|
|
* \{ */
|
|
|
|
static bool lattice_test_bitmap_uvw(
|
|
Lattice *lt, BLI_bitmap *selpoints, int u, int v, int w, const bool selected)
|
|
{
|
|
if ((u < 0 || u >= lt->pntsu) || (v < 0 || v >= lt->pntsv) || (w < 0 || w >= lt->pntsw)) {
|
|
return false;
|
|
}
|
|
else {
|
|
int i = BKE_lattice_index_from_uvw(lt, u, v, w);
|
|
if (lt->def[i].hide == 0) {
|
|
return (BLI_BITMAP_TEST(selpoints, i) != 0) == selected;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static int lattice_select_more_less(bContext *C, const bool select)
|
|
{
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
uint objects_len;
|
|
bool changed = false;
|
|
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
view_layer, CTX_wm_view3d(C), &objects_len);
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
Object *obedit = objects[ob_index];
|
|
Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
|
|
BPoint *bp;
|
|
const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
|
|
int u, v, w;
|
|
BLI_bitmap *selpoints;
|
|
|
|
lt->actbp = LT_ACTBP_NONE;
|
|
|
|
selpoints = BLI_BITMAP_NEW(tot, __func__);
|
|
BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
|
|
|
|
bp = lt->def;
|
|
for (w = 0; w < lt->pntsw; w++) {
|
|
for (v = 0; v < lt->pntsv; v++) {
|
|
for (u = 0; u < lt->pntsu; u++) {
|
|
if ((bp->hide == 0) && (((bp->f1 & SELECT) == 0) == select)) {
|
|
if (lattice_test_bitmap_uvw(lt, selpoints, u + 1, v, w, select) ||
|
|
lattice_test_bitmap_uvw(lt, selpoints, u - 1, v, w, select) ||
|
|
lattice_test_bitmap_uvw(lt, selpoints, u, v + 1, w, select) ||
|
|
lattice_test_bitmap_uvw(lt, selpoints, u, v - 1, w, select) ||
|
|
lattice_test_bitmap_uvw(lt, selpoints, u, v, w + 1, select) ||
|
|
lattice_test_bitmap_uvw(lt, selpoints, u, v, w - 1, select)) {
|
|
SET_FLAG_FROM_TEST(bp->f1, select, SELECT);
|
|
}
|
|
}
|
|
bp++;
|
|
}
|
|
}
|
|
}
|
|
|
|
MEM_freeN(selpoints);
|
|
|
|
changed = true;
|
|
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
|
}
|
|
MEM_freeN(objects);
|
|
|
|
return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
|
}
|
|
|
|
static int lattice_select_more_exec(bContext *C, wmOperator *UNUSED(op))
|
|
{
|
|
return lattice_select_more_less(C, true);
|
|
}
|
|
|
|
static int lattice_select_less_exec(bContext *C, wmOperator *UNUSED(op))
|
|
{
|
|
return lattice_select_more_less(C, false);
|
|
}
|
|
|
|
void LATTICE_OT_select_more(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "Select More";
|
|
ot->description = "Select vertex directly linked to already selected ones";
|
|
ot->idname = "LATTICE_OT_select_more";
|
|
|
|
/* api callbacks */
|
|
ot->exec = lattice_select_more_exec;
|
|
ot->poll = ED_operator_editlattice;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
}
|
|
|
|
void LATTICE_OT_select_less(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "Select Less";
|
|
ot->description = "Deselect vertices at the boundary of each selection region";
|
|
ot->idname = "LATTICE_OT_select_less";
|
|
|
|
/* api callbacks */
|
|
ot->exec = lattice_select_less_exec;
|
|
ot->poll = ED_operator_editlattice;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Select All Operator
|
|
* \{ */
|
|
|
|
bool ED_lattice_flags_set(Object *obedit, int flag)
|
|
{
|
|
Lattice *lt = obedit->data;
|
|
BPoint *bp;
|
|
int a;
|
|
bool changed = false;
|
|
|
|
bp = lt->editlatt->latt->def;
|
|
|
|
a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
|
|
|
|
if (lt->editlatt->latt->actbp != LT_ACTBP_NONE) {
|
|
lt->editlatt->latt->actbp = LT_ACTBP_NONE;
|
|
changed = true;
|
|
}
|
|
|
|
while (a--) {
|
|
if (bp->hide == 0) {
|
|
if (bp->f1 != flag) {
|
|
bp->f1 = flag;
|
|
changed = true;
|
|
}
|
|
}
|
|
bp++;
|
|
}
|
|
return changed;
|
|
}
|
|
|
|
static int lattice_select_all_exec(bContext *C, wmOperator *op)
|
|
{
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
int action = RNA_enum_get(op->ptr, "action");
|
|
|
|
uint objects_len = 0;
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
view_layer, CTX_wm_view3d(C), &objects_len);
|
|
|
|
if (action == SEL_TOGGLE) {
|
|
action = SEL_SELECT;
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
Object *obedit = objects[ob_index];
|
|
Lattice *lt = obedit->data;
|
|
if (BKE_lattice_is_any_selected(lt->editlatt->latt)) {
|
|
action = SEL_DESELECT;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool changed_multi = false;
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
Object *obedit = objects[ob_index];
|
|
Lattice *lt;
|
|
BPoint *bp;
|
|
int a;
|
|
bool changed = false;
|
|
|
|
switch (action) {
|
|
case SEL_SELECT:
|
|
changed = ED_lattice_flags_set(obedit, 1);
|
|
break;
|
|
case SEL_DESELECT:
|
|
changed = ED_lattice_flags_set(obedit, 0);
|
|
break;
|
|
case SEL_INVERT:
|
|
lt = obedit->data;
|
|
bp = lt->editlatt->latt->def;
|
|
a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
|
|
lt->editlatt->latt->actbp = LT_ACTBP_NONE;
|
|
|
|
while (a--) {
|
|
if (bp->hide == 0) {
|
|
bp->f1 ^= SELECT;
|
|
changed = true;
|
|
}
|
|
bp++;
|
|
}
|
|
break;
|
|
}
|
|
if (changed) {
|
|
changed_multi = true;
|
|
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
|
}
|
|
}
|
|
MEM_freeN(objects);
|
|
|
|
if (changed_multi) {
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
return OPERATOR_CANCELLED;
|
|
}
|
|
|
|
void LATTICE_OT_select_all(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "(De)select All";
|
|
ot->description = "Change selection of all UVW control points";
|
|
ot->idname = "LATTICE_OT_select_all";
|
|
|
|
/* api callbacks */
|
|
ot->exec = lattice_select_all_exec;
|
|
ot->poll = ED_operator_editlattice;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
WM_operator_properties_select_all(ot);
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Select Ungrouped Verts Operator
|
|
* \{ */
|
|
|
|
static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
|
|
{
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
uint objects_len;
|
|
const bool is_extend = RNA_boolean_get(op->ptr, "extend");
|
|
bool changed = false;
|
|
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
view_layer, CTX_wm_view3d(C), &objects_len);
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
Object *obedit = objects[ob_index];
|
|
Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
|
|
MDeformVert *dv;
|
|
BPoint *bp;
|
|
int a, tot;
|
|
|
|
if (BLI_listbase_is_empty(&obedit->defbase) || lt->dvert == NULL) {
|
|
continue;
|
|
}
|
|
|
|
if (!is_extend) {
|
|
ED_lattice_flags_set(obedit, 0);
|
|
}
|
|
|
|
dv = lt->dvert;
|
|
tot = lt->pntsu * lt->pntsv * lt->pntsw;
|
|
|
|
for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
|
|
if (bp->hide == 0) {
|
|
if (dv->dw == NULL) {
|
|
bp->f1 |= SELECT;
|
|
}
|
|
}
|
|
}
|
|
|
|
changed = true;
|
|
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
|
}
|
|
MEM_freeN(objects);
|
|
|
|
if (!changed) {
|
|
BKE_report(op->reports,
|
|
RPT_ERROR,
|
|
objects_len > 1 ? "No weights/vertex groups on objects" :
|
|
"No weights/vertex groups on object");
|
|
return OPERATOR_CANCELLED;
|
|
}
|
|
return OPERATOR_FINISHED;
|
|
}
|
|
|
|
void LATTICE_OT_select_ungrouped(wmOperatorType *ot)
|
|
{
|
|
/* identifiers */
|
|
ot->name = "Select Ungrouped";
|
|
ot->idname = "LATTICE_OT_select_ungrouped";
|
|
ot->description = "Select vertices without a group";
|
|
|
|
/* api callbacks */
|
|
ot->exec = lattice_select_ungrouped_exec;
|
|
ot->poll = ED_operator_editlattice;
|
|
|
|
/* flags */
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
|
|
|
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
|
|
}
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Select Picking API
|
|
*
|
|
* Here actual select happens,
|
|
* Gets called via generic mouse select operator.
|
|
* \{ */
|
|
|
|
static void findnearestLattvert__doClosest(void *userData, BPoint *bp, const float screen_co[2])
|
|
{
|
|
struct {
|
|
BPoint *bp;
|
|
float dist;
|
|
int select;
|
|
float mval_fl[2];
|
|
bool is_changed;
|
|
} *data = userData;
|
|
float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
|
|
|
|
if ((bp->f1 & SELECT) && data->select) {
|
|
dist_test += 5.0f;
|
|
}
|
|
|
|
if (dist_test < data->dist) {
|
|
data->dist = dist_test;
|
|
data->bp = bp;
|
|
data->is_changed = true;
|
|
}
|
|
}
|
|
|
|
static BPoint *findnearestLattvert(ViewContext *vc, int sel, Base **r_base)
|
|
{
|
|
/* (sel == 1): selected gets a disadvantage */
|
|
/* in nurb and bezt or bp the nearest is written */
|
|
/* return 0 1 2: handlepunt */
|
|
struct {
|
|
BPoint *bp;
|
|
float dist;
|
|
int select;
|
|
float mval_fl[2];
|
|
bool is_changed;
|
|
} data = {NULL};
|
|
|
|
data.dist = ED_view3d_select_dist_px();
|
|
data.select = sel;
|
|
data.mval_fl[0] = vc->mval[0];
|
|
data.mval_fl[1] = vc->mval[1];
|
|
|
|
uint bases_len;
|
|
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
|
|
vc->view_layer, vc->v3d, &bases_len);
|
|
for (uint base_index = 0; base_index < bases_len; base_index++) {
|
|
Base *base = bases[base_index];
|
|
data.is_changed = false;
|
|
|
|
ED_view3d_viewcontext_init_object(vc, base->object);
|
|
ED_view3d_init_mats_rv3d(base->object, vc->rv3d);
|
|
lattice_foreachScreenVert(
|
|
vc, findnearestLattvert__doClosest, &data, V3D_PROJ_TEST_CLIP_DEFAULT);
|
|
|
|
if (data.is_changed) {
|
|
*r_base = base;
|
|
}
|
|
}
|
|
MEM_freeN(bases);
|
|
return data.bp;
|
|
}
|
|
|
|
bool ED_lattice_select_pick(
|
|
bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
|
|
{
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
|
ViewContext vc;
|
|
BPoint *bp = NULL;
|
|
Base *basact = NULL;
|
|
|
|
ED_view3d_viewcontext_init(C, &vc, depsgraph);
|
|
vc.mval[0] = mval[0];
|
|
vc.mval[1] = mval[1];
|
|
|
|
bp = findnearestLattvert(&vc, true, &basact);
|
|
if (bp) {
|
|
ED_view3d_viewcontext_init_object(&vc, basact->object);
|
|
Lattice *lt = ((Lattice *)vc.obedit->data)->editlatt->latt;
|
|
|
|
if (!extend && !deselect && !toggle) {
|
|
uint objects_len = 0;
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
vc.view_layer, vc.v3d, &objects_len);
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
Object *ob = objects[ob_index];
|
|
if (ED_lattice_flags_set(ob, 0)) {
|
|
DEG_id_tag_update(ob->data, ID_RECALC_SELECT);
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
|
|
}
|
|
}
|
|
MEM_freeN(objects);
|
|
}
|
|
|
|
if (extend) {
|
|
bp->f1 |= SELECT;
|
|
}
|
|
else if (deselect) {
|
|
bp->f1 &= ~SELECT;
|
|
}
|
|
else if (toggle) {
|
|
bp->f1 ^= SELECT; /* swap */
|
|
}
|
|
else {
|
|
ED_lattice_flags_set(vc.obedit, 0);
|
|
bp->f1 |= SELECT;
|
|
}
|
|
|
|
if (bp->f1 & SELECT) {
|
|
lt->actbp = bp - lt->def;
|
|
}
|
|
else {
|
|
lt->actbp = LT_ACTBP_NONE;
|
|
}
|
|
|
|
if (vc.view_layer->basact != basact) {
|
|
ED_object_base_activate(C, basact);
|
|
}
|
|
|
|
DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/** \} */
|