Add Chromium-only Blender WebEngine parity work
This commit is contained in:
33
blender-5.2.0/source/blender/editors/lattice/CMakeLists.txt
Normal file
33
blender-5.2.0/source/blender/editors/lattice/CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
# SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
set(INC
|
||||
../include
|
||||
../../makesrna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
)
|
||||
|
||||
set(SRC
|
||||
editlattice_select.cc
|
||||
editlattice_tools.cc
|
||||
editlattice_undo.cc
|
||||
lattice_ops.cc
|
||||
|
||||
lattice_intern.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
PRIVATE bf::blenkernel
|
||||
PRIVATE bf::blenlib
|
||||
PRIVATE bf::depsgraph
|
||||
PRIVATE bf::dna
|
||||
PRIVATE bf::intern::clog
|
||||
PRIVATE bf::intern::guardedalloc
|
||||
PRIVATE bf::render
|
||||
PRIVATE bf::windowmanager
|
||||
)
|
||||
|
||||
blender_add_lib(bf_editor_lattice "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
@@ -0,0 +1,687 @@
|
||||
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edlattice
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "BLI_bitmap.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math_vector.h"
|
||||
#include "BLI_rand.h"
|
||||
#include "BLI_utildefines.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.hh"
|
||||
#include "RNA_define.hh"
|
||||
#include "RNA_enum_types.hh"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_lattice.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_report.hh"
|
||||
|
||||
#include "ED_lattice.hh"
|
||||
#include "ED_object.hh"
|
||||
#include "ED_screen.hh"
|
||||
#include "ED_select_utils.hh"
|
||||
#include "ED_view3d.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
|
||||
#include "lattice_intern.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Utility Functions
|
||||
* \{ */
|
||||
|
||||
static void bpoint_select_set(BPoint *bp, bool select)
|
||||
{
|
||||
if (select) {
|
||||
if (!bp->hide) {
|
||||
bp->f1 |= SELECT;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bp->f1 &= ~SELECT;
|
||||
}
|
||||
}
|
||||
|
||||
static bool lattice_deselect_all_multi(const Span<Base *> bases)
|
||||
{
|
||||
bool changed_multi = false;
|
||||
for (Base *base : bases) {
|
||||
Object *ob_iter = base->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(bContext *C)
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
|
||||
Vector<Base *> bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
|
||||
*vc.bmain, vc.scene, vc.view_layer, vc.v3d);
|
||||
return lattice_deselect_all_multi(bases);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Select Random Operator
|
||||
* \{ */
|
||||
|
||||
static wmOperatorStatus lattice_select_random_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const bool select = (RNA_enum_get(op->ptr, "action") == SEL_SELECT);
|
||||
const float randfac = RNA_float_get(op->ptr, "ratio");
|
||||
const int seed = WM_operator_properties_select_random_seed_increment_get(op);
|
||||
|
||||
const Main *bmain = CTX_data_main(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
*bmain, scene, view_layer, CTX_wm_view3d(C));
|
||||
for (const int ob_index : objects.index_range()) {
|
||||
Object *obedit = objects[ob_index];
|
||||
Lattice *lt = (id_cast<Lattice *>(obedit->data))->editlatt->latt;
|
||||
int seed_iter = seed;
|
||||
|
||||
/* This gives a consistent result regardless of object order. */
|
||||
if (ob_index) {
|
||||
seed_iter += BLI_ghashutil_strhash_p(obedit->id.name);
|
||||
}
|
||||
|
||||
int a = lt->pntsu * lt->pntsv * lt->pntsw;
|
||||
int elem_map_len = 0;
|
||||
BPoint **elem_map = MEM_new_array_uninitialized<BPoint *>(a, __func__);
|
||||
BPoint *bp = lt->def;
|
||||
|
||||
while (a--) {
|
||||
if (!bp->hide) {
|
||||
elem_map[elem_map_len++] = bp;
|
||||
}
|
||||
bp++;
|
||||
}
|
||||
|
||||
BLI_array_randomize(elem_map, sizeof(*elem_map), elem_map_len, seed_iter);
|
||||
const int count_select = elem_map_len * randfac;
|
||||
for (int i = 0; i < count_select; i++) {
|
||||
bpoint_select_set(elem_map[i], select);
|
||||
}
|
||||
MEM_delete(elem_map);
|
||||
|
||||
if (select == false) {
|
||||
lt->actbp = LT_ACTBP_NONE;
|
||||
}
|
||||
|
||||
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
bool flip_uvw[3] = {false};
|
||||
flip_uvw[axis] = true;
|
||||
|
||||
/* we could flip this too */
|
||||
if (!extend) {
|
||||
lt->actbp = LT_ACTBP_NONE;
|
||||
}
|
||||
|
||||
/* store "original" selection */
|
||||
BLI_bitmap *selpoints = BLI_BITMAP_NEW(tot, __func__);
|
||||
BKE_lattice_bitmap_from_flag(lt, selpoints, SELECT, false, false);
|
||||
|
||||
/* actual (de)selection */
|
||||
for (int i = 0; i < tot; i++) {
|
||||
const int i_flip = BKE_lattice_index_flip(lt, i, flip_uvw[0], flip_uvw[1], flip_uvw[2]);
|
||||
BPoint *bp = <->def[i];
|
||||
if (!bp->hide) {
|
||||
if (BLI_BITMAP_TEST(selpoints, i_flip)) {
|
||||
bp->f1 |= SELECT;
|
||||
}
|
||||
else {
|
||||
if (!extend) {
|
||||
bp->f1 &= ~SELECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MEM_delete(selpoints);
|
||||
}
|
||||
|
||||
static wmOperatorStatus 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");
|
||||
|
||||
const Main *bmain = CTX_data_main(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
*bmain, scene, view_layer, CTX_wm_view3d(C));
|
||||
|
||||
for (Object *obedit : objects) {
|
||||
Lattice *lt = (id_cast<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);
|
||||
}
|
||||
|
||||
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(
|
||||
const Lattice *lt, const 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;
|
||||
}
|
||||
|
||||
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 wmOperatorStatus lattice_select_more_less(bContext *C, const bool select)
|
||||
{
|
||||
const Main *bmain = CTX_data_main(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
bool changed = false;
|
||||
|
||||
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
*bmain, scene, view_layer, CTX_wm_view3d(C));
|
||||
for (Object *obedit : objects) {
|
||||
Lattice *lt = (id_cast<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_delete(selpoints);
|
||||
|
||||
changed = true;
|
||||
DEG_id_tag_update(obedit->data, ID_RECALC_SELECT);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
|
||||
}
|
||||
|
||||
return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
static wmOperatorStatus lattice_select_more_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
return lattice_select_more_less(C, true);
|
||||
}
|
||||
|
||||
static wmOperatorStatus lattice_select_less_exec(bContext *C, wmOperator * /*op*/)
|
||||
{
|
||||
return lattice_select_more_less(C, false);
|
||||
}
|
||||
|
||||
void LATTICE_OT_select_more(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Select More";
|
||||
ot->description = "Select vertices 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 = id_cast<Lattice *>(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 wmOperatorStatus lattice_select_all_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const Main *bmain = CTX_data_main(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
int action = RNA_enum_get(op->ptr, "action");
|
||||
|
||||
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
*bmain, scene, view_layer, CTX_wm_view3d(C));
|
||||
|
||||
if (action == SEL_TOGGLE) {
|
||||
action = SEL_SELECT;
|
||||
for (Object *obedit : objects) {
|
||||
Lattice *lt = id_cast<Lattice *>(obedit->data);
|
||||
if (BKE_lattice_is_any_selected(lt->editlatt->latt)) {
|
||||
action = SEL_DESELECT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool changed_multi = false;
|
||||
for (Object *obedit : objects) {
|
||||
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 = id_cast<Lattice *>(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);
|
||||
}
|
||||
}
|
||||
|
||||
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 wmOperatorStatus lattice_select_ungrouped_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const Main *bmain = CTX_data_main(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
const bool is_extend = RNA_boolean_get(op->ptr, "extend");
|
||||
bool changed = false;
|
||||
|
||||
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
*bmain, scene, view_layer, CTX_wm_view3d(C));
|
||||
for (Object *obedit : objects) {
|
||||
Lattice *lt = (id_cast<Lattice *>(obedit->data))->editlatt->latt;
|
||||
MDeformVert *dv;
|
||||
BPoint *bp;
|
||||
int a, tot;
|
||||
|
||||
if (lt->vertex_group_names.is_empty() || lt->dvert == nullptr) {
|
||||
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 == nullptr) {
|
||||
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);
|
||||
}
|
||||
|
||||
if (!changed) {
|
||||
BKE_report(op->reports, RPT_ERROR, "No weights/vertex groups on object(s)");
|
||||
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.
|
||||
* \{ */
|
||||
|
||||
struct NearestLatticeVert_UserData {
|
||||
BPoint *bp;
|
||||
float dist;
|
||||
/** When true, the existing selection gets a disadvantage. */
|
||||
bool select;
|
||||
float mval_fl[2];
|
||||
bool is_changed;
|
||||
};
|
||||
|
||||
static void findnearestLattvert__doClosest(void *user_data, BPoint *bp, const float screen_co[2])
|
||||
{
|
||||
NearestLatticeVert_UserData *data = static_cast<NearestLatticeVert_UserData *>(user_data);
|
||||
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, bool select, Base **r_base)
|
||||
{
|
||||
NearestLatticeVert_UserData data = {nullptr};
|
||||
|
||||
data.dist = ED_view3d_select_dist_px();
|
||||
data.select = select;
|
||||
data.mval_fl[0] = vc->mval[0];
|
||||
data.mval_fl[1] = vc->mval[1];
|
||||
|
||||
Vector<Base *> bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
|
||||
*vc->bmain, vc->scene, vc->view_layer, vc->v3d);
|
||||
for (Base *base : bases) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
return data.bp;
|
||||
}
|
||||
|
||||
bool ED_lattice_select_pick(bContext *C, const int mval[2], const SelectPick_Params ¶ms)
|
||||
{
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
BPoint *bp = nullptr;
|
||||
Base *basact = nullptr;
|
||||
bool changed = false;
|
||||
|
||||
ViewContext vc = ED_view3d_viewcontext_init(C, depsgraph);
|
||||
vc.mval[0] = mval[0];
|
||||
vc.mval[1] = mval[1];
|
||||
|
||||
bp = findnearestLattvert(&vc, true, &basact);
|
||||
bool found = (bp != nullptr);
|
||||
|
||||
if (params.sel_op == SEL_OP_SET) {
|
||||
if ((found && params.select_passthrough) && (bp->f1 & SELECT)) {
|
||||
found = false;
|
||||
}
|
||||
else if (found || params.deselect_all) {
|
||||
/* Deselect everything. */
|
||||
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
*vc.bmain, vc.scene, vc.view_layer, vc.v3d);
|
||||
for (Object *ob : objects) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
ED_view3d_viewcontext_init_object(&vc, basact->object);
|
||||
Lattice *lt = (id_cast<Lattice *>(vc.obedit->data))->editlatt->latt;
|
||||
|
||||
switch (params.sel_op) {
|
||||
case SEL_OP_ADD: {
|
||||
bp->f1 |= SELECT;
|
||||
break;
|
||||
}
|
||||
case SEL_OP_SUB: {
|
||||
bp->f1 &= ~SELECT;
|
||||
break;
|
||||
}
|
||||
case SEL_OP_XOR: {
|
||||
bp->f1 ^= SELECT; /* swap */
|
||||
break;
|
||||
}
|
||||
case SEL_OP_SET: {
|
||||
bp->f1 |= SELECT;
|
||||
break;
|
||||
}
|
||||
case SEL_OP_AND: {
|
||||
BLI_assert_unreachable(); /* Doesn't make sense for picking. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bp->f1 & SELECT) {
|
||||
lt->actbp = bp - lt->def;
|
||||
}
|
||||
else {
|
||||
lt->actbp = LT_ACTBP_NONE;
|
||||
}
|
||||
|
||||
BKE_view_layer_synced_ensure(*vc.bmain, vc.scene, vc.view_layer);
|
||||
if (BKE_view_layer_active_base_get(vc.view_layer) != 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);
|
||||
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed || found;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,368 @@
|
||||
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edlattice
|
||||
*/
|
||||
|
||||
#include "BLI_math_vector.h"
|
||||
|
||||
#include "DNA_curve_types.h"
|
||||
#include "DNA_lattice_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_define.hh"
|
||||
|
||||
#include "BKE_context.hh"
|
||||
#include "BKE_lattice.hh"
|
||||
#include "BKE_layer.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
|
||||
#include "ED_object.hh"
|
||||
#include "ED_screen.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
#include "lattice_intern.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Make Regular Operator
|
||||
* \{ */
|
||||
|
||||
static bool make_regular_poll(bContext *C)
|
||||
{
|
||||
Object *ob;
|
||||
|
||||
if (ED_operator_editlattice(C)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ob = CTX_data_active_object(C);
|
||||
return (ob && ob->type == OB_LATTICE);
|
||||
}
|
||||
|
||||
static wmOperatorStatus make_regular_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const Main *bmain = CTX_data_main(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
View3D *v3d = CTX_wm_view3d(C);
|
||||
const bool is_editmode = CTX_data_edit_object(C) != nullptr;
|
||||
|
||||
if (is_editmode) {
|
||||
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
*bmain, scene, view_layer, CTX_wm_view3d(C));
|
||||
for (Object *ob : objects) {
|
||||
Lattice *lt = id_cast<Lattice *>(ob->data);
|
||||
|
||||
if (lt->editlatt->latt == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ed::object::shape_key_report_if_locked(ob, op->reports)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, nullptr);
|
||||
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
|
||||
if (ob->type != OB_LATTICE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Lattice *lt = id_cast<Lattice *>(ob->data);
|
||||
BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, nullptr);
|
||||
|
||||
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
||||
}
|
||||
FOREACH_SELECTED_OBJECT_END;
|
||||
}
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void LATTICE_OT_make_regular(wmOperatorType *ot)
|
||||
{
|
||||
/* identifiers */
|
||||
ot->name = "Make Regular";
|
||||
ot->description = "Set UVW control points a uniform distance apart";
|
||||
ot->idname = "LATTICE_OT_make_regular";
|
||||
|
||||
/* API callbacks. */
|
||||
ot->exec = make_regular_exec;
|
||||
ot->poll = make_regular_poll;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Flip Verts Operator
|
||||
* \{ */
|
||||
|
||||
/* flipping options */
|
||||
enum eLattice_FlipAxes {
|
||||
LATTICE_FLIP_U = 0,
|
||||
LATTICE_FLIP_V = 1,
|
||||
LATTICE_FLIP_W = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Flip midpoint value so that relative distances between midpoint and neighbor-pair is maintained.
|
||||
* Assumes that UVW <=> XYZ (i.e. axis-aligned index-axes with coordinate-axes).
|
||||
* - Helper for #lattice_flip_exec()
|
||||
*/
|
||||
static void lattice_flip_point_value(
|
||||
Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
|
||||
{
|
||||
BPoint *bp;
|
||||
float diff;
|
||||
|
||||
/* just the point in the middle (unpaired) */
|
||||
bp = <->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
|
||||
|
||||
/* flip over axis */
|
||||
diff = mid - bp->vec[axis];
|
||||
bp->vec[axis] = mid + diff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Swap pairs of lattice points along a specified axis.
|
||||
* - Helper for #lattice_flip_exec()
|
||||
*/
|
||||
static void lattice_swap_point_pairs(
|
||||
Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
|
||||
{
|
||||
BPoint *bpA, *bpB;
|
||||
|
||||
int numU = lt->pntsu;
|
||||
int numV = lt->pntsv;
|
||||
int numW = lt->pntsw;
|
||||
|
||||
int u0 = u, u1 = u;
|
||||
int v0 = v, v1 = v;
|
||||
int w0 = w, w1 = w;
|
||||
|
||||
/* get pair index by just overriding the relevant pair-value
|
||||
* - "-1" else buffer overflow
|
||||
*/
|
||||
switch (axis) {
|
||||
case LATTICE_FLIP_U:
|
||||
u1 = numU - u - 1;
|
||||
break;
|
||||
case LATTICE_FLIP_V:
|
||||
v1 = numV - v - 1;
|
||||
break;
|
||||
case LATTICE_FLIP_W:
|
||||
w1 = numW - w - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* get points to operate on */
|
||||
bpA = <->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
|
||||
bpB = <->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)];
|
||||
|
||||
/* Swap all coordinates, so that flipped coordinates belong to
|
||||
* the indices on the correct side of the lattice.
|
||||
*
|
||||
* Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4)
|
||||
* Indices: (0,L) (1,R) --> (0,L) (1,R)
|
||||
*/
|
||||
swap_v3_v3(bpA->vec, bpB->vec);
|
||||
|
||||
/* However, we need to mirror the coordinate values on the axis we're dealing with,
|
||||
* otherwise we'd have effectively only rotated the points around. If we don't do this,
|
||||
* we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms
|
||||
* such as flipped normals, etc.
|
||||
*
|
||||
* Coords: (3 4) |0| (-2 4) --\
|
||||
* \-> (-3 4) |0| (2 4)
|
||||
* Indices: (0,L) (1,R) --> (0,L) (1,R)
|
||||
*/
|
||||
lattice_flip_point_value(lt, u0, v0, w0, mid, axis);
|
||||
lattice_flip_point_value(lt, u1, v1, w1, mid, axis);
|
||||
}
|
||||
|
||||
static wmOperatorStatus lattice_flip_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const Main *bmain = CTX_data_main(C);
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
bool changed = false;
|
||||
const eLattice_FlipAxes axis = eLattice_FlipAxes(RNA_enum_get(op->ptr, "axis"));
|
||||
|
||||
Vector<Object *> objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
|
||||
*bmain, scene, view_layer, CTX_wm_view3d(C));
|
||||
for (Object *obedit : objects) {
|
||||
Lattice *lt;
|
||||
|
||||
int numU, numV, numW;
|
||||
int totP;
|
||||
|
||||
float mid = 0.0f;
|
||||
short isOdd = 0;
|
||||
|
||||
/* get lattice - we need the "edit lattice" from the lattice... confusing... */
|
||||
lt = id_cast<Lattice *>(obedit->data);
|
||||
lt = lt->editlatt->latt;
|
||||
|
||||
if (ed::object::shape_key_report_if_locked(obedit, op->reports)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
numU = lt->pntsu;
|
||||
numV = lt->pntsv;
|
||||
numW = lt->pntsw;
|
||||
totP = numU * numV * numW;
|
||||
|
||||
/* First Pass: determine midpoint - used for flipping center verts if there
|
||||
* are odd number of points on axis */
|
||||
switch (axis) {
|
||||
case LATTICE_FLIP_U:
|
||||
isOdd = numU & 1;
|
||||
break;
|
||||
case LATTICE_FLIP_V:
|
||||
isOdd = numV & 1;
|
||||
break;
|
||||
case LATTICE_FLIP_W:
|
||||
isOdd = numW & 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("lattice_flip(): Unknown flipping axis (%d)\n", axis);
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
if (isOdd) {
|
||||
BPoint *bp;
|
||||
float avgInv = 1.0f / float(totP);
|
||||
int i;
|
||||
|
||||
/* midpoint calculation - assuming that u/v/w are axis-aligned */
|
||||
for (i = 0, bp = lt->def; i < totP; i++, bp++) {
|
||||
mid += bp->vec[axis] * avgInv;
|
||||
}
|
||||
}
|
||||
|
||||
/* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
|
||||
switch (axis) {
|
||||
case LATTICE_FLIP_U: {
|
||||
int u, v, w;
|
||||
|
||||
/* v/w strips - front to back, top to bottom */
|
||||
for (w = 0; w < numW; w++) {
|
||||
for (v = 0; v < numV; v++) {
|
||||
/* swap coordinates of pairs of vertices on u */
|
||||
for (u = 0; u < (numU / 2); u++) {
|
||||
lattice_swap_point_pairs(lt, u, v, w, mid, axis);
|
||||
}
|
||||
|
||||
/* flip u-coordinate of midpoint (i.e. unpaired point on u) */
|
||||
if (isOdd) {
|
||||
u = (numU / 2);
|
||||
lattice_flip_point_value(lt, u, v, w, mid, axis);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LATTICE_FLIP_V: {
|
||||
int u, v, w;
|
||||
|
||||
/* u/w strips - front to back, left to right */
|
||||
for (w = 0; w < numW; w++) {
|
||||
for (u = 0; u < numU; u++) {
|
||||
/* swap coordinates of pairs of vertices on v */
|
||||
for (v = 0; v < (numV / 2); v++) {
|
||||
lattice_swap_point_pairs(lt, u, v, w, mid, axis);
|
||||
}
|
||||
|
||||
/* flip v-coordinate of midpoint (i.e. unpaired point on v) */
|
||||
if (isOdd) {
|
||||
v = (numV / 2);
|
||||
lattice_flip_point_value(lt, u, v, w, mid, axis);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LATTICE_FLIP_W: {
|
||||
int u, v, w;
|
||||
|
||||
for (v = 0; v < numV; v++) {
|
||||
for (u = 0; u < numU; u++) {
|
||||
/* swap coordinates of pairs of vertices on w */
|
||||
for (w = 0; w < (numW / 2); w++) {
|
||||
lattice_swap_point_pairs(lt, u, v, w, mid, axis);
|
||||
}
|
||||
|
||||
/* flip w-coordinate of midpoint (i.e. unpaired point on w) */
|
||||
if (isOdd) {
|
||||
w = (numW / 2);
|
||||
lattice_flip_point_value(lt, u, v, w, mid, axis);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: /* shouldn't happen, but just in case */
|
||||
break;
|
||||
}
|
||||
|
||||
/* updates */
|
||||
DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
void LATTICE_OT_flip(wmOperatorType *ot)
|
||||
{
|
||||
static const EnumPropertyItem flip_items[] = {
|
||||
{LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""},
|
||||
{LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""},
|
||||
{LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
/* identifiers */
|
||||
ot->name = "Flip (Distortion Free)";
|
||||
ot->description = "Mirror all control points without inverting the lattice deform";
|
||||
ot->idname = "LATTICE_OT_flip";
|
||||
|
||||
/* API callbacks. */
|
||||
ot->poll = ED_operator_editlattice;
|
||||
ot->invoke = WM_menu_invoke;
|
||||
ot->exec = lattice_flip_exec;
|
||||
|
||||
/* flags */
|
||||
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
|
||||
|
||||
/* properties */
|
||||
ot->prop = RNA_def_enum(ot->srna,
|
||||
"axis",
|
||||
flip_items,
|
||||
LATTICE_FLIP_U,
|
||||
"Flip Axis",
|
||||
"Coordinates along this axis get flipped");
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender
|
||||
363
blender-5.2.0/source/blender/editors/lattice/editlattice_undo.cc
Normal file
363
blender-5.2.0/source/blender/editors/lattice/editlattice_undo.cc
Normal file
@@ -0,0 +1,363 @@
|
||||
/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edlattice
|
||||
*/
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
|
||||
#include "CLG_log.h"
|
||||
|
||||
#include "BLI_array_utils.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_string.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 "BKE_context.hh"
|
||||
#include "BKE_deform.hh"
|
||||
#include "BKE_lattice.hh"
|
||||
#include "BKE_layer.hh"
|
||||
#include "BKE_main.hh"
|
||||
#include "BKE_object.hh"
|
||||
#include "BKE_undo_system.hh"
|
||||
|
||||
#include "DEG_depsgraph.hh"
|
||||
|
||||
#include "ED_lattice.hh"
|
||||
#include "ED_object.hh"
|
||||
#include "ED_undo.hh"
|
||||
#include "ED_util.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
#include "WM_types.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
/** We only need this locally. */
|
||||
static CLG_LogRef LOG = {"undo.lattice"};
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Undo Conversion
|
||||
* \{ */
|
||||
|
||||
/* TODO(@ideasman42): this could contain an entire 'Lattice' struct. */
|
||||
struct UndoLattice {
|
||||
BPoint *def;
|
||||
int pntsu, pntsv, pntsw, actbp;
|
||||
char typeu, typev, typew;
|
||||
float fu, fv, fw;
|
||||
float du, dv, dw;
|
||||
MDeformVert *dvert;
|
||||
int shapenr;
|
||||
char vgroup[/*MAX_VGROUP_NAME*/ 64];
|
||||
ListBaseT<bDeformGroup> vertex_group_names;
|
||||
int vertex_group_active_index;
|
||||
size_t undo_size;
|
||||
};
|
||||
|
||||
static void undolatt_to_editlatt(UndoLattice *ult,
|
||||
EditLatt *editlatt,
|
||||
ListBaseT<bDeformGroup> *vertex_group_names,
|
||||
int *vertex_group_active_index)
|
||||
{
|
||||
const int len_src = ult->pntsu * ult->pntsv * ult->pntsw;
|
||||
const int len_dst = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
|
||||
if (len_src != len_dst) {
|
||||
MEM_delete(editlatt->latt->def);
|
||||
editlatt->latt->def = MEM_dupalloc(ult->def);
|
||||
}
|
||||
else {
|
||||
memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len_src);
|
||||
}
|
||||
|
||||
/* Even for the same amount of points we don't just copy memory for MDeformVert,
|
||||
* relations to #MDeformWeight might have changed. */
|
||||
if (editlatt->latt->dvert && ult->dvert) {
|
||||
BKE_defvert_array_free(editlatt->latt->dvert, len_dst);
|
||||
editlatt->latt->dvert = MEM_new_array_uninitialized<MDeformVert>(len_src,
|
||||
"Lattice MDeformVert");
|
||||
BKE_defvert_array_copy(editlatt->latt->dvert, ult->dvert, len_src);
|
||||
}
|
||||
|
||||
editlatt->latt->pntsu = ult->pntsu;
|
||||
editlatt->latt->pntsv = ult->pntsv;
|
||||
editlatt->latt->pntsw = ult->pntsw;
|
||||
editlatt->latt->actbp = ult->actbp;
|
||||
|
||||
editlatt->latt->typeu = ult->typeu;
|
||||
editlatt->latt->typev = ult->typev;
|
||||
editlatt->latt->typew = ult->typew;
|
||||
|
||||
editlatt->latt->fu = ult->fu;
|
||||
editlatt->latt->fv = ult->fv;
|
||||
editlatt->latt->fw = ult->fw;
|
||||
editlatt->latt->du = ult->du;
|
||||
editlatt->latt->dv = ult->dv;
|
||||
editlatt->latt->dw = ult->dw;
|
||||
|
||||
STRNCPY(editlatt->latt->vgroup, ult->vgroup);
|
||||
|
||||
vertex_group_names->free_no_destruct();
|
||||
BKE_defgroup_copy_list(vertex_group_names, &ult->vertex_group_names);
|
||||
*vertex_group_active_index = ult->vertex_group_active_index;
|
||||
|
||||
editlatt->shapenr = ult->shapenr;
|
||||
}
|
||||
|
||||
static void *undolatt_from_editlatt(UndoLattice *ult,
|
||||
EditLatt *editlatt,
|
||||
const ListBaseT<bDeformGroup> *vertex_group_names,
|
||||
int vertex_group_active_index)
|
||||
{
|
||||
BLI_assert(BLI_array_is_zeroed(ult, 1));
|
||||
|
||||
ult->def = MEM_dupalloc(editlatt->latt->def);
|
||||
ult->pntsu = editlatt->latt->pntsu;
|
||||
ult->pntsv = editlatt->latt->pntsv;
|
||||
ult->pntsw = editlatt->latt->pntsw;
|
||||
ult->actbp = editlatt->latt->actbp;
|
||||
|
||||
ult->typeu = editlatt->latt->typeu;
|
||||
ult->typev = editlatt->latt->typev;
|
||||
ult->typew = editlatt->latt->typew;
|
||||
|
||||
ult->fu = editlatt->latt->fu;
|
||||
ult->fv = editlatt->latt->fv;
|
||||
ult->fw = editlatt->latt->fw;
|
||||
ult->du = editlatt->latt->du;
|
||||
ult->dv = editlatt->latt->dv;
|
||||
ult->dw = editlatt->latt->dw;
|
||||
|
||||
STRNCPY(ult->vgroup, editlatt->latt->vgroup);
|
||||
|
||||
BKE_defgroup_copy_list(&ult->vertex_group_names, vertex_group_names);
|
||||
ult->vertex_group_active_index = vertex_group_active_index;
|
||||
|
||||
ult->shapenr = editlatt->shapenr;
|
||||
|
||||
if (editlatt->latt->dvert) {
|
||||
const int tot = ult->pntsu * ult->pntsv * ult->pntsw;
|
||||
ult->dvert = MEM_new_array_uninitialized<MDeformVert>(tot, "Undo Lattice MDeformVert");
|
||||
BKE_defvert_array_copy(ult->dvert, editlatt->latt->dvert, tot);
|
||||
ult->undo_size += sizeof(*ult->dvert) * tot;
|
||||
}
|
||||
|
||||
ult->undo_size += sizeof(*ult->def) * ult->pntsu * ult->pntsv * ult->pntsw;
|
||||
|
||||
return ult;
|
||||
}
|
||||
|
||||
static void undolatt_free_data(UndoLattice *ult)
|
||||
{
|
||||
if (ult->def) {
|
||||
MEM_delete(ult->def);
|
||||
}
|
||||
if (ult->dvert) {
|
||||
BKE_defvert_array_free(ult->dvert, ult->pntsu * ult->pntsv * ult->pntsw);
|
||||
ult->dvert = nullptr;
|
||||
}
|
||||
ult->vertex_group_names.free_no_destruct();
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int validate_undoLatt(void *data, void *edata)
|
||||
{
|
||||
UndoLattice *ult = (UndoLattice *)data;
|
||||
EditLatt *editlatt = (EditLatt *)edata;
|
||||
|
||||
return (ult->pntsu == editlatt->latt->pntsu && ult->pntsv == editlatt->latt->pntsv &&
|
||||
ult->pntsw == editlatt->latt->pntsw);
|
||||
}
|
||||
#endif
|
||||
|
||||
static Object *editlatt_object_from_context(bContext *C)
|
||||
{
|
||||
const Main *bmain = CTX_data_main(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
BKE_view_layer_synced_ensure(*bmain, scene, view_layer);
|
||||
Object *obedit = BKE_view_layer_edit_object_get(view_layer);
|
||||
if (obedit && obedit->type == OB_LATTICE) {
|
||||
Lattice *lt = id_cast<Lattice *>(obedit->data);
|
||||
if (lt->editlatt != nullptr) {
|
||||
return obedit;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Implements ED Undo System
|
||||
*
|
||||
* \note This is similar for all edit-mode types.
|
||||
* \{ */
|
||||
|
||||
struct LatticeUndoStep_Elem {
|
||||
UndoRefID_Object obedit_ref;
|
||||
UndoLattice data;
|
||||
};
|
||||
|
||||
struct LatticeUndoStep {
|
||||
UndoStep step;
|
||||
/** See #ED_undo_object_editmode_validate_scene_from_windows code comment for details. */
|
||||
UndoRefID_Scene scene_ref;
|
||||
LatticeUndoStep_Elem *elems;
|
||||
uint elems_len;
|
||||
};
|
||||
|
||||
static bool lattice_undosys_poll(bContext *C)
|
||||
{
|
||||
return editlatt_object_from_context(C) != nullptr;
|
||||
}
|
||||
|
||||
static bool lattice_undosys_step_encode(bContext *C, Main *bmain, UndoStep *us_p)
|
||||
{
|
||||
LatticeUndoStep *us = reinterpret_cast<LatticeUndoStep *>(us_p);
|
||||
|
||||
/* Important not to use the 3D view when getting objects because all objects
|
||||
* outside of this list will be moved out of edit-mode when reading back undo steps. */
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
Vector<Object *> objects = ED_undo_editmode_objects_from_view_layer(*bmain, scene, view_layer);
|
||||
|
||||
us->scene_ref.ptr = scene;
|
||||
us->elems = MEM_new_array_zeroed<LatticeUndoStep_Elem>(objects.size(), __func__);
|
||||
us->elems_len = objects.size();
|
||||
|
||||
for (uint i = 0; i < objects.size(); i++) {
|
||||
Object *ob = objects[i];
|
||||
LatticeUndoStep_Elem *elem = &us->elems[i];
|
||||
|
||||
elem->obedit_ref.ptr = ob;
|
||||
Lattice *lt = id_cast<Lattice *>(ob->data);
|
||||
undolatt_from_editlatt(
|
||||
&elem->data, lt->editlatt, <->vertex_group_names, lt->vertex_group_active_index);
|
||||
lt->editlatt->needs_flush_to_id = 1;
|
||||
us->step.data_size += elem->data.undo_size;
|
||||
}
|
||||
|
||||
bmain->is_memfile_undo_flush_needed = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void lattice_undosys_step_decode(
|
||||
bContext *C, Main *bmain, UndoStep *us_p, const eUndoStepDir /*dir*/, bool /*is_final*/)
|
||||
{
|
||||
LatticeUndoStep *us = reinterpret_cast<LatticeUndoStep *>(us_p);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
|
||||
ED_undo_object_editmode_validate_scene_from_windows(
|
||||
CTX_wm_manager(C), us->scene_ref.ptr, &scene, &view_layer);
|
||||
ED_undo_object_editmode_restore_helper(
|
||||
scene, view_layer, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
|
||||
|
||||
BLI_assert(BKE_object_is_in_editmode(us->elems[0].obedit_ref.ptr));
|
||||
|
||||
for (uint i = 0; i < us->elems_len; i++) {
|
||||
LatticeUndoStep_Elem *elem = &us->elems[i];
|
||||
Object *obedit = elem->obedit_ref.ptr;
|
||||
Lattice *lt = id_cast<Lattice *>(obedit->data);
|
||||
if (lt->editlatt == nullptr) {
|
||||
/* Should never fail, may not crash but can give odd behavior. */
|
||||
CLOG_ERROR(&LOG,
|
||||
"name='%s', failed to enter edit-mode for object '%s', undo state invalid",
|
||||
us_p->name,
|
||||
obedit->id.name);
|
||||
continue;
|
||||
}
|
||||
undolatt_to_editlatt(
|
||||
&elem->data, lt->editlatt, <->vertex_group_names, <->vertex_group_active_index);
|
||||
BKE_lattice_params_copy(lt, lt->editlatt->latt);
|
||||
|
||||
/* NOTE: only resize the base lattice because this is what the
|
||||
* RNA properties do when the resolution is adjusted.
|
||||
* Failing to do so causes the parameters to show incorrectly.
|
||||
* See: #100651. */
|
||||
{
|
||||
Lattice *lt_em = lt->editlatt->latt;
|
||||
if ((lt->pntsu != lt_em->pntsu) || /* U. */
|
||||
(lt->pntsv != lt_em->pntsv) || /* V. */
|
||||
(lt->pntsw != lt_em->pntsw)) /* W. */
|
||||
{
|
||||
BKE_lattice_resize(lt, lt_em->pntsu, lt_em->pntsv, lt_em->pntsw, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (obedit->shapenr != elem->data.shapenr) {
|
||||
obedit->shapenr = elem->data.shapenr;
|
||||
DEG_id_tag_update(&obedit->id, ID_RECALC_GEOMETRY);
|
||||
}
|
||||
|
||||
lt->editlatt->needs_flush_to_id = 1;
|
||||
DEG_id_tag_update(<->id, ID_RECALC_GEOMETRY);
|
||||
}
|
||||
|
||||
/* The first element is always active */
|
||||
ED_undo_object_set_active_or_warn(
|
||||
*bmain, scene, view_layer, us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
|
||||
|
||||
/* Check after setting active (unless undoing into another scene). */
|
||||
BLI_assert(lattice_undosys_poll(C) || (scene != CTX_data_scene(C)));
|
||||
|
||||
bmain->is_memfile_undo_flush_needed = true;
|
||||
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, nullptr);
|
||||
}
|
||||
|
||||
static void lattice_undosys_step_free(UndoStep *us_p)
|
||||
{
|
||||
LatticeUndoStep *us = reinterpret_cast<LatticeUndoStep *>(us_p);
|
||||
|
||||
for (uint i = 0; i < us->elems_len; i++) {
|
||||
LatticeUndoStep_Elem *elem = &us->elems[i];
|
||||
undolatt_free_data(&elem->data);
|
||||
}
|
||||
MEM_delete(us->elems);
|
||||
}
|
||||
|
||||
static void lattice_undosys_foreach_ID_ref(UndoStep *us_p,
|
||||
UndoTypeForEachIDRefFn foreach_ID_ref_fn,
|
||||
void *user_data)
|
||||
{
|
||||
LatticeUndoStep *us = reinterpret_cast<LatticeUndoStep *>(us_p);
|
||||
|
||||
foreach_ID_ref_fn(user_data, (reinterpret_cast<UndoRefID *>(&us->scene_ref)));
|
||||
for (uint i = 0; i < us->elems_len; i++) {
|
||||
LatticeUndoStep_Elem *elem = &us->elems[i];
|
||||
foreach_ID_ref_fn(user_data, (reinterpret_cast<UndoRefID *>(&elem->obedit_ref)));
|
||||
}
|
||||
}
|
||||
|
||||
void ED_lattice_undosys_type(UndoType *ut)
|
||||
{
|
||||
ut->name = "Edit Lattice";
|
||||
ut->poll = lattice_undosys_poll;
|
||||
ut->step_encode = lattice_undosys_step_encode;
|
||||
ut->step_decode = lattice_undosys_step_decode;
|
||||
ut->step_free = lattice_undosys_step_free;
|
||||
|
||||
ut->step_foreach_ID_ref = lattice_undosys_foreach_ID_ref;
|
||||
|
||||
ut->flags = UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE;
|
||||
|
||||
ut->step_size = sizeof(LatticeUndoStep);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender
|
||||
@@ -0,0 +1,29 @@
|
||||
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edlattice
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace blender {
|
||||
|
||||
struct wmOperatorType;
|
||||
|
||||
/* `editlattice_select.cc` */
|
||||
|
||||
void LATTICE_OT_select_all(wmOperatorType *ot);
|
||||
void LATTICE_OT_select_more(wmOperatorType *ot);
|
||||
void LATTICE_OT_select_less(wmOperatorType *ot);
|
||||
void LATTICE_OT_select_ungrouped(wmOperatorType *ot);
|
||||
void LATTICE_OT_select_random(wmOperatorType *ot);
|
||||
void LATTICE_OT_select_mirror(wmOperatorType *ot);
|
||||
|
||||
/* `editlattice_tools.cc` */
|
||||
|
||||
void LATTICE_OT_make_regular(wmOperatorType *ot);
|
||||
void LATTICE_OT_flip(wmOperatorType *ot);
|
||||
|
||||
} // namespace blender
|
||||
47
blender-5.2.0/source/blender/editors/lattice/lattice_ops.cc
Normal file
47
blender-5.2.0/source/blender/editors/lattice/lattice_ops.cc
Normal file
@@ -0,0 +1,47 @@
|
||||
/* SPDX-FileCopyrightText: 2008 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edlattice
|
||||
*/
|
||||
|
||||
#include "DNA_lattice_types.h"
|
||||
|
||||
#include "BKE_key.hh"
|
||||
|
||||
#include "WM_api.hh"
|
||||
|
||||
#include "ED_lattice.hh"
|
||||
#include "ED_screen.hh"
|
||||
|
||||
#include "lattice_intern.hh"
|
||||
|
||||
namespace blender {
|
||||
|
||||
void ED_operatortypes_lattice()
|
||||
{
|
||||
WM_operatortype_append(LATTICE_OT_select_all);
|
||||
WM_operatortype_append(LATTICE_OT_select_more);
|
||||
WM_operatortype_append(LATTICE_OT_select_less);
|
||||
WM_operatortype_append(LATTICE_OT_select_ungrouped);
|
||||
WM_operatortype_append(LATTICE_OT_select_random);
|
||||
WM_operatortype_append(LATTICE_OT_select_mirror);
|
||||
WM_operatortype_append(LATTICE_OT_make_regular);
|
||||
WM_operatortype_append(LATTICE_OT_flip);
|
||||
}
|
||||
|
||||
void ED_keymap_lattice(wmKeyConfig *keyconf)
|
||||
{
|
||||
wmKeyMap *keymap = WM_keymap_ensure(keyconf, "Lattice", SPACE_EMPTY, RGN_TYPE_WINDOW);
|
||||
keymap->poll = ED_operator_editlattice;
|
||||
}
|
||||
|
||||
KeyBlock *ED_lattice_get_edit_shape_key(const Lattice *latt)
|
||||
{
|
||||
BLI_assert(latt->editlatt);
|
||||
|
||||
return BKE_keyblock_find_by_index(latt->key, latt->editlatt->shapenr - 1);
|
||||
}
|
||||
|
||||
} // namespace blender
|
||||
Reference in New Issue
Block a user