2011-02-23 10:52:22 +00:00
|
|
|
/*
|
2009-01-13 15:18:41 +00:00
|
|
|
* 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,
|
2010-02-12 13:34:04 +00:00
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2009-01-13 15:18:41 +00:00
|
|
|
*
|
|
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
|
|
* All rights reserved.
|
|
|
|
*/
|
|
|
|
|
2019-02-18 08:08:12 +11:00
|
|
|
/** \file
|
|
|
|
* \ingroup edlattice
|
2011-02-27 20:29:51 +00:00
|
|
|
*/
|
|
|
|
|
2009-01-13 15:18:41 +00:00
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_bitmap.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
#include "BLI_listbase.h"
|
2011-11-07 01:38:32 +00:00
|
|
|
#include "BLI_math.h"
|
2013-07-19 10:44:39 +00:00
|
|
|
#include "BLI_rand.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BLI_utildefines.h"
|
2011-01-07 18:36:47 +00:00
|
|
|
|
2009-01-13 15:18:41 +00:00
|
|
|
#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"
|
|
|
|
|
2009-11-29 22:16:29 +00:00
|
|
|
#include "RNA_access.h"
|
2012-10-13 10:42:38 +00:00
|
|
|
#include "RNA_define.h"
|
2013-12-09 15:40:41 +11:00
|
|
|
#include "RNA_enum_types.h"
|
2009-11-29 22:16:29 +00:00
|
|
|
|
2009-01-13 15:18:41 +00:00
|
|
|
#include "BKE_context.h"
|
|
|
|
#include "BKE_lattice.h"
|
2018-04-21 23:52:47 +02:00
|
|
|
#include "BKE_layer.h"
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "BKE_report.h"
|
2009-01-13 15:18:41 +00:00
|
|
|
|
2020-03-19 09:33:03 +01:00
|
|
|
#include "ED_lattice.h"
|
2018-10-26 19:18:49 -03:00
|
|
|
#include "ED_object.h"
|
2009-07-03 15:23:33 +00:00
|
|
|
#include "ED_screen.h"
|
2018-08-14 10:28:41 +10:00
|
|
|
#include "ED_select_utils.h"
|
2009-01-13 15:18:41 +00:00
|
|
|
#include "ED_view3d.h"
|
|
|
|
|
|
|
|
#include "WM_api.h"
|
|
|
|
#include "WM_types.h"
|
|
|
|
|
2018-06-13 15:26:59 +02:00
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
#include "lattice_intern.h"
|
2010-08-10 06:36:42 +00:00
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Utility Functions
|
|
|
|
* \{ */
|
2009-01-13 15:18:41 +00:00
|
|
|
|
2014-01-13 20:36:38 +11:00
|
|
|
static void bpoint_select_set(BPoint *bp, bool select)
|
|
|
|
{
|
|
|
|
if (select) {
|
|
|
|
if (!bp->hide) {
|
|
|
|
bp->f1 |= SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
bp->f1 &= ~SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-26 18:47:55 +11:00
|
|
|
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)
|
|
|
|
{
|
2019-09-18 17:19:07 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
2019-03-26 18:47:55 +11:00
|
|
|
ViewContext vc;
|
2019-09-18 17:19:07 +02:00
|
|
|
ED_view3d_viewcontext_init(C, &vc, depsgraph);
|
2019-03-26 18:47:55 +11:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Select Random Operator
|
|
|
|
* \{ */
|
2013-07-19 10:44:39 +00:00
|
|
|
|
|
|
|
static int lattice_select_random_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2021-01-27 11:19:54 -06:00
|
|
|
const float randfac = RNA_float_get(op->ptr, "ratio");
|
2016-03-29 01:20:45 +11:00
|
|
|
const int seed = WM_operator_properties_select_random_seed_increment_get(op);
|
2014-01-13 20:36:38 +11:00
|
|
|
const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-21 23:52:47 +02:00
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
|
|
uint objects_len = 0;
|
2018-11-25 09:50:34 -02:00
|
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
|
|
view_layer, CTX_wm_view3d(C), &objects_len);
|
2018-04-21 23:52:47 +02:00
|
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
|
|
Object *obedit = objects[ob_index];
|
|
|
|
Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-21 23:52:47 +02:00
|
|
|
RNG *rng = BLI_rng_new_srandom(seed);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-21 23:52:47 +02:00
|
|
|
int tot;
|
|
|
|
BPoint *bp;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-21 23:52:47 +02:00
|
|
|
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);
|
2013-07-19 10:44:39 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-04-21 23:52:47 +02:00
|
|
|
bp++;
|
2013-07-19 10:44:39 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-21 23:52:47 +02:00
|
|
|
if (select == false) {
|
|
|
|
lt->actbp = LT_ACTBP_NONE;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-21 23:52:47 +02:00
|
|
|
BLI_rng_free(rng);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
2018-04-21 23:52:47 +02:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
|
|
|
}
|
|
|
|
MEM_freeN(objects);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-07-19 10:44:39 +00:00
|
|
|
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 */
|
2015-10-10 23:47:41 +11:00
|
|
|
WM_operator_properties_select_random(ot);
|
2013-07-19 10:44:39 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
/** \} */
|
2013-12-09 15:40:41 +11:00
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
2018-03-19 14:49:59 +01:00
|
|
|
/** \name Select Mirror Operator
|
|
|
|
* \{ */
|
2013-12-09 15:40:41 +11:00
|
|
|
|
2016-01-07 20:54:17 +11:00
|
|
|
static void ed_lattice_select_mirrored(Lattice *lt, const int axis, const bool extend)
|
2013-12-09 15:40:41 +11:00
|
|
|
{
|
2016-01-07 20:54:17 +11:00
|
|
|
const int tot = lt->pntsu * lt->pntsv * lt->pntsw;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-07 20:54:17 +11:00
|
|
|
bool flip_uvw[3] = {false};
|
2013-12-09 15:40:41 +11:00
|
|
|
flip_uvw[axis] = true;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2016-01-07 20:54:17 +11:00
|
|
|
/* we could flip this too */
|
2013-12-09 15:40:41 +11:00
|
|
|
if (!extend) {
|
|
|
|
lt->actbp = LT_ACTBP_NONE;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-12-09 15:40:41 +11:00
|
|
|
/* store "original" selection */
|
2020-09-09 18:41:07 +02:00
|
|
|
BLI_bitmap *selpoints = BLI_BITMAP_NEW(tot, __func__);
|
2013-12-09 15:40:41 +11:00
|
|
|
BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-12-09 15:40:41 +11:00
|
|
|
/* actual (de)selection */
|
2020-09-09 18:41:07 +02:00
|
|
|
for (int i = 0; i < tot; i++) {
|
2013-12-09 15:40:41 +11:00
|
|
|
const int i_flip = BKE_lattice_index_flip(lt, i, flip_uvw[0], flip_uvw[1], flip_uvw[2]);
|
2020-09-09 18:41:07 +02:00
|
|
|
BPoint *bp = <->def[i];
|
2013-12-09 15:40:41 +11:00
|
|
|
if (!bp->hide) {
|
2014-06-06 16:05:15 +10:00
|
|
|
if (BLI_BITMAP_TEST(selpoints, i_flip)) {
|
2013-12-09 15:40:41 +11:00
|
|
|
bp->f1 |= SELECT;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!extend) {
|
|
|
|
bp->f1 &= ~SELECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2013-12-09 15:40:41 +11:00
|
|
|
MEM_freeN(selpoints);
|
2016-01-07 20:54:17 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
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");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-21 23:52:47 +02:00
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
|
|
uint objects_len = 0;
|
2018-11-25 09:50:34 -02:00
|
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
|
|
view_layer, CTX_wm_view3d(C), &objects_len);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-21 23:52:47 +02:00
|
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
|
|
Object *obedit = objects[ob_index];
|
|
|
|
Lattice *lt = ((Lattice *)obedit->data)->editlatt->latt;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-21 23:52:47 +02:00
|
|
|
for (int axis = 0; axis < 3; axis++) {
|
|
|
|
if ((1 << axis) & axis_flag) {
|
|
|
|
ed_lattice_select_mirrored(lt, axis, extend);
|
|
|
|
}
|
2016-01-07 20:54:17 +11:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-04-21 23:52:47 +02:00
|
|
|
/* TODO, only notify changes */
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
2018-04-21 23:52:47 +02:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
|
|
|
}
|
|
|
|
MEM_freeN(objects);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-12-09 15:40:41 +11:00
|
|
|
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 */
|
2016-01-07 20:54:17 +11:00
|
|
|
RNA_def_enum_flag(ot->srna, "axis", rna_enum_axis_flag_xyz_items, (1 << 0), "Axis", "");
|
2013-12-09 15:40:41 +11:00
|
|
|
|
|
|
|
RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
|
|
|
|
}
|
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
/** \} */
|
2013-12-09 15:40:41 +11:00
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Select More/Less Operator
|
|
|
|
* \{ */
|
2013-07-19 10:49:23 +00:00
|
|
|
|
2013-07-22 23:20:48 +00:00
|
|
|
static bool lattice_test_bitmap_uvw(
|
2020-07-13 11:27:09 +02:00
|
|
|
Lattice *lt, const BLI_bitmap *selpoints, int u, int v, int w, const bool selected)
|
2013-07-19 10:49:23 +00:00
|
|
|
{
|
|
|
|
if ((u < 0 || u >= lt->pntsu) || (v < 0 || v >= lt->pntsv) || (w < 0 || w >= lt->pntsw)) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-07-03 17:30:31 +02:00
|
|
|
|
|
|
|
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;
|
2013-07-19 10:49:23 +00:00
|
|
|
}
|
2020-07-03 17:30:31 +02:00
|
|
|
return false;
|
2013-07-19 10:49:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int lattice_select_more_less(bContext *C, const bool select)
|
|
|
|
{
|
2018-10-23 20:38:30 -03:00
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
|
|
uint objects_len;
|
|
|
|
bool changed = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-25 09:50:34 -02:00
|
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
|
|
view_layer, CTX_wm_view3d(C), &objects_len);
|
2018-10-23 20:38:30 -03:00
|
|
|
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;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:38:30 -03:00
|
|
|
lt->actbp = LT_ACTBP_NONE;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:38:30 -03:00
|
|
|
selpoints = BLI_BITMAP_NEW(tot, __func__);
|
|
|
|
BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:38:30 -03:00
|
|
|
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) ||
|
2018-10-29 10:24:42 +11:00
|
|
|
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)) {
|
2018-10-23 20:38:30 -03:00
|
|
|
SET_FLAG_FROM_TEST(bp->f1, select, SELECT);
|
|
|
|
}
|
2013-07-19 10:49:23 +00:00
|
|
|
}
|
2018-10-23 20:38:30 -03:00
|
|
|
bp++;
|
2013-07-19 10:49:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:38:30 -03:00
|
|
|
MEM_freeN(selpoints);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:38:30 -03:00
|
|
|
changed = true;
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
2018-10-23 20:38:30 -03:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
|
|
|
}
|
|
|
|
MEM_freeN(objects);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:38:30 -03:00
|
|
|
return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
2013-07-19 10:49:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Select All Operator
|
|
|
|
* \{ */
|
2009-07-03 15:23:33 +00:00
|
|
|
|
2019-03-26 18:47:55 +11:00
|
|
|
bool ED_lattice_flags_set(Object *obedit, int flag)
|
2009-01-13 15:18:41 +00:00
|
|
|
{
|
2012-04-28 15:42:27 +00:00
|
|
|
Lattice *lt = obedit->data;
|
2009-07-03 15:23:33 +00:00
|
|
|
BPoint *bp;
|
|
|
|
int a;
|
2019-03-26 18:47:55 +11:00
|
|
|
bool changed = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 15:42:27 +00:00
|
|
|
bp = lt->editlatt->latt->def;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-04-28 15:42:27 +00:00
|
|
|
a = lt->editlatt->latt->pntsu * lt->editlatt->latt->pntsv * lt->editlatt->latt->pntsw;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-26 18:47:55 +11:00
|
|
|
if (lt->editlatt->latt->actbp != LT_ACTBP_NONE) {
|
|
|
|
lt->editlatt->latt->actbp = LT_ACTBP_NONE;
|
|
|
|
changed = true;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-03-24 06:38:07 +00:00
|
|
|
while (a--) {
|
2012-04-28 15:42:27 +00:00
|
|
|
if (bp->hide == 0) {
|
2019-03-26 18:47:55 +11:00
|
|
|
if (bp->f1 != flag) {
|
|
|
|
bp->f1 = flag;
|
|
|
|
changed = true;
|
|
|
|
}
|
2009-07-03 15:23:33 +00:00
|
|
|
}
|
|
|
|
bp++;
|
|
|
|
}
|
2019-03-26 18:47:55 +11:00
|
|
|
return changed;
|
2009-01-13 15:18:41 +00:00
|
|
|
}
|
|
|
|
|
2011-10-28 03:02:09 +00:00
|
|
|
static int lattice_select_all_exec(bContext *C, wmOperator *op)
|
2009-01-13 15:18:41 +00:00
|
|
|
{
|
2018-05-22 08:11:13 +02:00
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
2009-11-29 22:16:29 +00:00
|
|
|
int action = RNA_enum_get(op->ptr, "action");
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-22 08:11:13 +02:00
|
|
|
uint objects_len = 0;
|
2018-11-25 09:50:34 -02:00
|
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
|
|
view_layer, CTX_wm_view3d(C), &objects_len);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2009-11-29 22:16:29 +00:00
|
|
|
if (action == SEL_TOGGLE) {
|
|
|
|
action = SEL_SELECT;
|
2018-05-22 08:11:13 +02:00
|
|
|
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;
|
2009-01-13 15:18:41 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
|
|
|
|
2019-03-26 18:47:55 +11:00
|
|
|
bool changed_multi = false;
|
2018-05-22 08:11:13 +02:00
|
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
|
|
Object *obedit = objects[ob_index];
|
|
|
|
Lattice *lt;
|
|
|
|
BPoint *bp;
|
|
|
|
int a;
|
2019-03-26 18:47:55 +11:00
|
|
|
bool changed = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-22 08:11:13 +02:00
|
|
|
switch (action) {
|
|
|
|
case SEL_SELECT:
|
2019-03-26 18:47:55 +11:00
|
|
|
changed = ED_lattice_flags_set(obedit, 1);
|
2018-05-22 08:11:13 +02:00
|
|
|
break;
|
|
|
|
case SEL_DESELECT:
|
2019-03-26 18:47:55 +11:00
|
|
|
changed = ED_lattice_flags_set(obedit, 0);
|
2018-05-22 08:11:13 +02:00
|
|
|
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;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-05-22 08:11:13 +02:00
|
|
|
while (a--) {
|
|
|
|
if (bp->hide == 0) {
|
|
|
|
bp->f1 ^= SELECT;
|
2019-03-26 18:47:55 +11:00
|
|
|
changed = true;
|
2018-05-22 08:11:13 +02:00
|
|
|
}
|
|
|
|
bp++;
|
2012-04-28 15:42:27 +00:00
|
|
|
}
|
2018-05-22 08:11:13 +02:00
|
|
|
break;
|
|
|
|
}
|
2019-03-26 18:47:55 +11:00
|
|
|
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);
|
|
|
|
}
|
2009-01-13 15:18:41 +00:00
|
|
|
}
|
2018-05-22 08:11:13 +02:00
|
|
|
MEM_freeN(objects);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-03-26 18:47:55 +11:00
|
|
|
if (changed_multi) {
|
|
|
|
return OPERATOR_FINISHED;
|
|
|
|
}
|
|
|
|
return OPERATOR_CANCELLED;
|
2009-01-13 15:18:41 +00:00
|
|
|
}
|
|
|
|
|
2009-11-29 22:16:29 +00:00
|
|
|
void LATTICE_OT_select_all(wmOperatorType *ot)
|
2009-07-03 15:23:33 +00:00
|
|
|
{
|
|
|
|
/* identifiers */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->name = "(De)select All";
|
|
|
|
ot->description = "Change selection of all UVW control points";
|
|
|
|
ot->idname = "LATTICE_OT_select_all";
|
2018-03-19 14:49:59 +01:00
|
|
|
|
2009-07-03 15:23:33 +00:00
|
|
|
/* api callbacks */
|
2012-03-22 07:26:09 +00:00
|
|
|
ot->exec = lattice_select_all_exec;
|
|
|
|
ot->poll = ED_operator_editlattice;
|
2018-03-19 14:49:59 +01:00
|
|
|
|
2009-07-03 15:23:33 +00:00
|
|
|
/* flags */
|
2012-04-28 15:42:27 +00:00
|
|
|
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
2009-11-29 22:16:29 +00:00
|
|
|
|
|
|
|
WM_operator_properties_select_all(ot);
|
2009-07-03 15:23:33 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
/** \} */
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Select Ungrouped Verts Operator
|
|
|
|
* \{ */
|
2013-03-16 16:11:50 +00:00
|
|
|
|
|
|
|
static int lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
|
|
|
|
{
|
2018-10-23 20:25:57 -03:00
|
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
|
|
uint objects_len;
|
|
|
|
const bool is_extend = RNA_boolean_get(op->ptr, "extend");
|
|
|
|
bool changed = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-11-25 09:50:34 -02:00
|
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
|
|
view_layer, CTX_wm_view3d(C), &objects_len);
|
2018-10-23 20:25:57 -03:00
|
|
|
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;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:25:57 -03:00
|
|
|
if (BLI_listbase_is_empty(&obedit->defbase) || lt->dvert == NULL) {
|
|
|
|
continue;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:25:57 -03:00
|
|
|
if (!is_extend) {
|
|
|
|
ED_lattice_flags_set(obedit, 0);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:25:57 -03:00
|
|
|
dv = lt->dvert;
|
|
|
|
tot = lt->pntsu * lt->pntsv * lt->pntsw;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:25:57 -03:00
|
|
|
for (a = 0, bp = lt->def; a < tot; a++, bp++, dv++) {
|
|
|
|
if (bp->hide == 0) {
|
|
|
|
if (dv->dw == NULL) {
|
|
|
|
bp->f1 |= SELECT;
|
|
|
|
}
|
2013-03-16 16:11:50 +00:00
|
|
|
}
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:25:57 -03:00
|
|
|
changed = true;
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
2018-10-23 20:25:57 -03:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
|
|
|
}
|
|
|
|
MEM_freeN(objects);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-23 20:25:57 -03:00
|
|
|
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;
|
|
|
|
}
|
2013-03-16 16:11:50 +00:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
/** \} */
|
2009-07-03 15:23:33 +00:00
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/** \name Select Picking API
|
|
|
|
*
|
|
|
|
* Here actual select happens,
|
|
|
|
* Gets called via generic mouse select operator.
|
|
|
|
* \{ */
|
2012-10-13 10:42:38 +00:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
static void findnearestLattvert__doClosest(void *userData, BPoint *bp, const float screen_co[2])
|
2009-01-13 15:18:41 +00:00
|
|
|
{
|
2018-10-26 19:18:49 -03:00
|
|
|
struct {
|
|
|
|
BPoint *bp;
|
|
|
|
float dist;
|
|
|
|
int select;
|
|
|
|
float mval_fl[2];
|
|
|
|
bool is_changed;
|
|
|
|
} *data = userData;
|
2012-10-10 01:22:19 +00:00
|
|
|
float dist_test = len_manhattan_v2v2(data->mval_fl, screen_co);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-04-22 09:19:45 +10:00
|
|
|
if ((bp->f1 & SELECT) && data->select) {
|
2012-10-10 01:22:19 +00:00
|
|
|
dist_test += 5.0f;
|
2019-04-22 09:19:45 +10:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-10-10 01:22:19 +00:00
|
|
|
if (dist_test < data->dist) {
|
|
|
|
data->dist = dist_test;
|
2009-01-13 15:18:41 +00:00
|
|
|
data->bp = bp;
|
2018-10-26 19:18:49 -03:00
|
|
|
data->is_changed = true;
|
2009-01-13 15:18:41 +00:00
|
|
|
}
|
|
|
|
}
|
2009-07-03 15:23:33 +00:00
|
|
|
|
2018-10-26 19:18:49 -03:00
|
|
|
static BPoint *findnearestLattvert(ViewContext *vc, int sel, Base **r_base)
|
2009-01-13 15:18:41 +00:00
|
|
|
{
|
2012-10-23 03:38:26 +00:00
|
|
|
/* (sel == 1): selected gets a disadvantage */
|
2012-04-28 15:42:27 +00:00
|
|
|
/* in nurb and bezt or bp the nearest is written */
|
|
|
|
/* return 0 1 2: handlepunt */
|
2018-10-26 19:18:49 -03:00
|
|
|
struct {
|
|
|
|
BPoint *bp;
|
|
|
|
float dist;
|
|
|
|
int select;
|
|
|
|
float mval_fl[2];
|
|
|
|
bool is_changed;
|
|
|
|
} data = {NULL};
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2014-03-11 15:34:19 +11:00
|
|
|
data.dist = ED_view3d_select_dist_px();
|
2009-01-13 15:18:41 +00:00
|
|
|
data.select = sel;
|
2018-10-26 19:18:49 -03:00
|
|
|
data.mval_fl[0] = vc->mval[0];
|
|
|
|
data.mval_fl[1] = vc->mval[1];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-26 19:18:49 -03:00
|
|
|
uint bases_len;
|
2018-11-25 09:50:34 -02:00
|
|
|
Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
|
|
|
|
vc->view_layer, vc->v3d, &bases_len);
|
2018-10-26 19:18:49 -03:00
|
|
|
for (uint base_index = 0; base_index < bases_len; base_index++) {
|
|
|
|
Base *base = bases[base_index];
|
|
|
|
data.is_changed = false;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-26 19:18:49 -03:00
|
|
|
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);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-26 19:18:49 -03:00
|
|
|
if (data.is_changed) {
|
|
|
|
*r_base = base;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-10-26 19:18:49 -03:00
|
|
|
MEM_freeN(bases);
|
2009-01-13 15:18:41 +00:00
|
|
|
return data.bp;
|
|
|
|
}
|
|
|
|
|
2015-11-18 12:20:28 +11:00
|
|
|
bool ED_lattice_select_pick(
|
|
|
|
bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
|
2009-01-13 15:18:41 +00:00
|
|
|
{
|
2019-09-18 17:19:07 +02:00
|
|
|
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
2009-01-13 15:18:41 +00:00
|
|
|
ViewContext vc;
|
2012-04-28 15:42:27 +00:00
|
|
|
BPoint *bp = NULL;
|
2018-10-26 19:18:49 -03:00
|
|
|
Base *basact = NULL;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2019-09-18 17:19:07 +02:00
|
|
|
ED_view3d_viewcontext_init(C, &vc, depsgraph);
|
2018-10-26 19:18:49 -03:00
|
|
|
vc.mval[0] = mval[0];
|
|
|
|
vc.mval[1] = mval[1];
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-26 19:18:49 -03:00
|
|
|
bp = findnearestLattvert(&vc, true, &basact);
|
2012-03-24 06:38:07 +00:00
|
|
|
if (bp) {
|
2018-10-26 19:18:49 -03:00
|
|
|
ED_view3d_viewcontext_init_object(&vc, basact->object);
|
|
|
|
Lattice *lt = ((Lattice *)vc.obedit->data)->editlatt->latt;
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-26 19:18:49 -03:00
|
|
|
if (!extend && !deselect && !toggle) {
|
|
|
|
uint objects_len = 0;
|
2018-11-25 09:50:34 -02:00
|
|
|
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
|
|
|
vc.view_layer, vc.v3d, &objects_len);
|
2018-10-26 19:18:49 -03:00
|
|
|
for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
|
|
|
|
Object *ob = objects[ob_index];
|
2019-03-26 18:47:55 +11:00
|
|
|
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);
|
2018-10-26 19:18:49 -03:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
}
|
2018-10-26 19:18:49 -03:00
|
|
|
MEM_freeN(objects);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2012-06-05 21:54:21 +00:00
|
|
|
if (extend) {
|
|
|
|
bp->f1 |= SELECT;
|
|
|
|
}
|
|
|
|
else if (deselect) {
|
|
|
|
bp->f1 &= ~SELECT;
|
|
|
|
}
|
2012-05-24 21:05:27 +00:00
|
|
|
else if (toggle) {
|
|
|
|
bp->f1 ^= SELECT; /* swap */
|
2009-01-13 15:18:41 +00:00
|
|
|
}
|
2012-06-05 21:54:21 +00:00
|
|
|
else {
|
2015-11-18 12:20:28 +11:00
|
|
|
ED_lattice_flags_set(vc.obedit, 0);
|
2012-05-24 21:05:27 +00:00
|
|
|
bp->f1 |= SELECT;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-06-09 20:28:08 +00:00
|
|
|
if (bp->f1 & SELECT) {
|
|
|
|
lt->actbp = bp - lt->def;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
lt->actbp = LT_ACTBP_NONE;
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-10-26 19:18:49 -03:00
|
|
|
if (vc.view_layer->basact != basact) {
|
|
|
|
ED_object_base_activate(C, basact);
|
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2018-12-06 17:52:37 +01:00
|
|
|
DEG_id_tag_update(vc.obedit->data, ID_RECALC_SELECT);
|
2012-04-28 15:42:27 +00:00
|
|
|
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, vc.obedit->data);
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-19 23:17:44 +00:00
|
|
|
return true;
|
2009-01-13 15:18:41 +00:00
|
|
|
}
|
2019-04-17 06:17:24 +02:00
|
|
|
|
2013-03-19 23:17:44 +00:00
|
|
|
return false;
|
2009-01-13 15:18:41 +00:00
|
|
|
}
|
|
|
|
|
2018-03-19 14:49:59 +01:00
|
|
|
/** \} */
|