This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/editors/lattice/editlattice_select.c
Sergey Sharybin 79312c1912 Depsgraph: Remove duplicated sets of recalc/update flags
There were at least three copies of those:

- OB_RECALC* family of flags, which are rudiment of an old
  dependency graph system.
- PSYS_RECALC* which were used by old dependency graph system
  as a separate set since the graph itself did not handle
  particle systems.
- DEG_TAG_* which was used to tag IDs.

Now there is a single set, which defines what can be tagged
and queried for an update. It also has some aggregate flags
to make queries simpler.

Lets once and for all solve the madness of those flags, stick
to a single set, which will not overlap with anything or require
any extra conversion.

Technically, shouldn't be measurable user difference, but some
of the agregate flags for few dependency graph components did
change.

Fixes T58632: Particle don't update rotation settings
2018-12-07 11:37:38 +01:00

649 lines
16 KiB
C

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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.
*
* Contributor(s): Blender Foundation
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/editors/lattice/editlattice_select.c
* \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;
}
}
/** \} */
/* -------------------------------------------------------------------- */
/** \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 = &lt->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
* \{ */
void ED_lattice_flags_set(Object *obedit, int flag)
{
Lattice *lt = obedit->data;
BPoint *bp;
int a;
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 = flag;
}
bp++;
}
}
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;
}
}
}
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
Object *obedit = objects[ob_index];
Lattice *lt;
BPoint *bp;
int a;
switch (action) {
case SEL_SELECT:
ED_lattice_flags_set(obedit, 1);
break;
case SEL_DESELECT:
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;
}
bp++;
}
break;
}
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_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)
{
ViewContext vc;
BPoint *bp = NULL;
Base *basact = NULL;
ED_view3d_viewcontext_init(C, &vc);
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];
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;
}
/** \} */