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
374 lines
9.7 KiB
C
374 lines
9.7 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_tools.c
|
|
* \ingroup edlattice
|
|
*/
|
|
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BLI_math.h"
|
|
#include "BLI_utildefines.h"
|
|
|
|
#include "DNA_curve_types.h"
|
|
#include "DNA_lattice_types.h"
|
|
#include "DNA_object_types.h"
|
|
#include "DNA_scene_types.h"
|
|
|
|
#include "RNA_access.h"
|
|
#include "RNA_define.h"
|
|
|
|
#include "BKE_context.h"
|
|
#include "BKE_lattice.h"
|
|
#include "BKE_layer.h"
|
|
|
|
#include "DEG_depsgraph.h"
|
|
|
|
#include "ED_screen.h"
|
|
|
|
#include "WM_api.h"
|
|
#include "WM_types.h"
|
|
|
|
#include "lattice_intern.h"
|
|
|
|
/** \} */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/** \name Make Regular Operator
|
|
* \{ */
|
|
|
|
static bool make_regular_poll(bContext *C)
|
|
{
|
|
Object *ob;
|
|
|
|
if (ED_operator_editlattice(C)) return 1;
|
|
|
|
ob = CTX_data_active_object(C);
|
|
return (ob && ob->type == OB_LATTICE);
|
|
}
|
|
|
|
static int make_regular_exec(bContext *C, wmOperator *UNUSED(op))
|
|
{
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
View3D *v3d = CTX_wm_view3d(C);
|
|
const bool is_editmode = CTX_data_edit_object(C) != NULL;
|
|
|
|
if (is_editmode) {
|
|
uint objects_len;
|
|
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 *ob = objects[ob_index];
|
|
Lattice *lt = ob->data;
|
|
|
|
if (lt->editlatt->latt == NULL) {
|
|
continue;
|
|
}
|
|
|
|
BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
|
|
|
|
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
|
|
WM_event_add_notifier(C, NC_GEOM | ND_DATA, ob->data);
|
|
}
|
|
MEM_freeN(objects);
|
|
}
|
|
else {
|
|
FOREACH_SELECTED_OBJECT_BEGIN(view_layer, v3d, ob) {
|
|
if (ob->type != OB_LATTICE) {
|
|
continue;
|
|
}
|
|
|
|
Lattice *lt = ob->data;
|
|
BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, NULL);
|
|
|
|
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 */
|
|
typedef enum eLattice_FlipAxes {
|
|
LATTICE_FLIP_U = 0,
|
|
LATTICE_FLIP_V = 1,
|
|
LATTICE_FLIP_W = 2
|
|
} eLattice_FlipAxes;
|
|
|
|
/**
|
|
* 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 int lattice_flip_exec(bContext *C, wmOperator *op)
|
|
{
|
|
ViewLayer *view_layer = CTX_data_view_layer(C);
|
|
uint objects_len;
|
|
bool changed = false;
|
|
const eLattice_FlipAxes axis = RNA_enum_get(op->ptr, "axis");
|
|
|
|
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;
|
|
|
|
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 = (Lattice *)obedit->data;
|
|
lt = lt->editlatt->latt;
|
|
|
|
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 (%u)\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;
|
|
}
|
|
MEM_freeN(objects);
|
|
|
|
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, NULL, 0, NULL, NULL}};
|
|
|
|
/* 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");
|
|
}
|
|
|
|
/** \} */
|