Blender V4.3
editlattice_tools.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include "MEM_guardedalloc.h"
10
11#include "BLI_math_vector.h"
12#include "BLI_utildefines.h"
13
14#include "DNA_curve_types.h"
15#include "DNA_lattice_types.h"
16#include "DNA_object_types.h"
17#include "DNA_scene_types.h"
18
19#include "RNA_access.hh"
20#include "RNA_define.hh"
21
22#include "BKE_context.hh"
23#include "BKE_lattice.hh"
24#include "BKE_layer.hh"
25
26#include "DEG_depsgraph.hh"
27
28#include "ED_object.hh"
29#include "ED_screen.hh"
30
31#include "WM_api.hh"
32#include "WM_types.hh"
33
34#include "lattice_intern.hh"
35
36using blender::Vector;
37
38/* -------------------------------------------------------------------- */
43{
44 Object *ob;
45
47 return true;
48 }
49
51 return (ob && ob->type == OB_LATTICE);
52}
53
55{
56 const Scene *scene = CTX_data_scene(C);
57 ViewLayer *view_layer = CTX_data_view_layer(C);
58 View3D *v3d = CTX_wm_view3d(C);
59 const bool is_editmode = CTX_data_edit_object(C) != nullptr;
60
61 if (is_editmode) {
63 scene, view_layer, CTX_wm_view3d(C));
64 for (Object *ob : objects) {
65 Lattice *lt = static_cast<Lattice *>(ob->data);
66
67 if (lt->editlatt->latt == nullptr) {
68 continue;
69 }
70
72 continue;
73 }
74
75 BKE_lattice_resize(lt->editlatt->latt, lt->pntsu, lt->pntsv, lt->pntsw, nullptr);
76
79 }
80 }
81 else {
82 FOREACH_SELECTED_OBJECT_BEGIN (view_layer, v3d, ob) {
83 if (ob->type != OB_LATTICE) {
84 continue;
85 }
86
87 Lattice *lt = static_cast<Lattice *>(ob->data);
88 BKE_lattice_resize(lt, lt->pntsu, lt->pntsv, lt->pntsw, nullptr);
89
92 }
94 }
95 return OPERATOR_FINISHED;
96}
97
99{
100 /* identifiers */
101 ot->name = "Make Regular";
102 ot->description = "Set UVW control points a uniform distance apart";
103 ot->idname = "LATTICE_OT_make_regular";
104
105 /* api callbacks */
108
109 /* flags */
111}
112
115/* -------------------------------------------------------------------- */
119/* flipping options */
125
132 Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
133{
134 BPoint *bp;
135 float diff;
136
137 /* just the point in the middle (unpaired) */
138 bp = &lt->def[BKE_lattice_index_from_uvw(lt, u, v, w)];
139
140 /* flip over axis */
141 diff = mid - bp->vec[axis];
142 bp->vec[axis] = mid + diff;
143}
144
150 Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
151{
152 BPoint *bpA, *bpB;
153
154 int numU = lt->pntsu;
155 int numV = lt->pntsv;
156 int numW = lt->pntsw;
157
158 int u0 = u, u1 = u;
159 int v0 = v, v1 = v;
160 int w0 = w, w1 = w;
161
162 /* get pair index by just overriding the relevant pair-value
163 * - "-1" else buffer overflow
164 */
165 switch (axis) {
166 case LATTICE_FLIP_U:
167 u1 = numU - u - 1;
168 break;
169 case LATTICE_FLIP_V:
170 v1 = numV - v - 1;
171 break;
172 case LATTICE_FLIP_W:
173 w1 = numW - w - 1;
174 break;
175 }
176
177 /* get points to operate on */
178 bpA = &lt->def[BKE_lattice_index_from_uvw(lt, u0, v0, w0)];
179 bpB = &lt->def[BKE_lattice_index_from_uvw(lt, u1, v1, w1)];
180
181 /* Swap all coordinates, so that flipped coordinates belong to
182 * the indices on the correct side of the lattice.
183 *
184 * Coords: (-2 4) |0| (3 4) --> (3 4) |0| (-2 4)
185 * Indices: (0,L) (1,R) --> (0,L) (1,R)
186 */
187 swap_v3_v3(bpA->vec, bpB->vec);
188
189 /* However, we need to mirror the coordinate values on the axis we're dealing with,
190 * otherwise we'd have effectively only rotated the points around. If we don't do this,
191 * we'd just be reimplementing the naive mirroring algorithm, which causes unwanted deforms
192 * such as flipped normals, etc.
193 *
194 * Coords: (3 4) |0| (-2 4) --\
195 * \-> (-3 4) |0| (2 4)
196 * Indices: (0,L) (1,R) --> (0,L) (1,R)
197 */
198 lattice_flip_point_value(lt, u0, v0, w0, mid, axis);
199 lattice_flip_point_value(lt, u1, v1, w1, mid, axis);
200}
201
203{
204 const Scene *scene = CTX_data_scene(C);
205 ViewLayer *view_layer = CTX_data_view_layer(C);
206 bool changed = false;
207 const eLattice_FlipAxes axis = eLattice_FlipAxes(RNA_enum_get(op->ptr, "axis"));
208
210 scene, view_layer, CTX_wm_view3d(C));
211 for (Object *obedit : objects) {
212 Lattice *lt;
213
214 int numU, numV, numW;
215 int totP;
216
217 float mid = 0.0f;
218 short isOdd = 0;
219
220 /* get lattice - we need the "edit lattice" from the lattice... confusing... */
221 lt = (Lattice *)obedit->data;
222 lt = lt->editlatt->latt;
223
225 continue;
226 }
227
228 numU = lt->pntsu;
229 numV = lt->pntsv;
230 numW = lt->pntsw;
231 totP = numU * numV * numW;
232
233 /* First Pass: determine midpoint - used for flipping center verts if there
234 * are odd number of points on axis */
235 switch (axis) {
236 case LATTICE_FLIP_U:
237 isOdd = numU & 1;
238 break;
239 case LATTICE_FLIP_V:
240 isOdd = numV & 1;
241 break;
242 case LATTICE_FLIP_W:
243 isOdd = numW & 1;
244 break;
245
246 default:
247 printf("lattice_flip(): Unknown flipping axis (%d)\n", axis);
248 return OPERATOR_CANCELLED;
249 }
250
251 if (isOdd) {
252 BPoint *bp;
253 float avgInv = 1.0f / float(totP);
254 int i;
255
256 /* midpoint calculation - assuming that u/v/w are axis-aligned */
257 for (i = 0, bp = lt->def; i < totP; i++, bp++) {
258 mid += bp->vec[axis] * avgInv;
259 }
260 }
261
262 /* Second Pass: swap pairs of vertices per axis, assuming they are all sorted */
263 switch (axis) {
264 case LATTICE_FLIP_U: {
265 int u, v, w;
266
267 /* v/w strips - front to back, top to bottom */
268 for (w = 0; w < numW; w++) {
269 for (v = 0; v < numV; v++) {
270 /* swap coordinates of pairs of vertices on u */
271 for (u = 0; u < (numU / 2); u++) {
272 lattice_swap_point_pairs(lt, u, v, w, mid, axis);
273 }
274
275 /* flip u-coordinate of midpoint (i.e. unpaired point on u) */
276 if (isOdd) {
277 u = (numU / 2);
278 lattice_flip_point_value(lt, u, v, w, mid, axis);
279 }
280 }
281 }
282 break;
283 }
284 case LATTICE_FLIP_V: {
285 int u, v, w;
286
287 /* u/w strips - front to back, left to right */
288 for (w = 0; w < numW; w++) {
289 for (u = 0; u < numU; u++) {
290 /* swap coordinates of pairs of vertices on v */
291 for (v = 0; v < (numV / 2); v++) {
292 lattice_swap_point_pairs(lt, u, v, w, mid, axis);
293 }
294
295 /* flip v-coordinate of midpoint (i.e. unpaired point on v) */
296 if (isOdd) {
297 v = (numV / 2);
298 lattice_flip_point_value(lt, u, v, w, mid, axis);
299 }
300 }
301 }
302 break;
303 }
304 case LATTICE_FLIP_W: {
305 int u, v, w;
306
307 for (v = 0; v < numV; v++) {
308 for (u = 0; u < numU; u++) {
309 /* swap coordinates of pairs of vertices on w */
310 for (w = 0; w < (numW / 2); w++) {
311 lattice_swap_point_pairs(lt, u, v, w, mid, axis);
312 }
313
314 /* flip w-coordinate of midpoint (i.e. unpaired point on w) */
315 if (isOdd) {
316 w = (numW / 2);
317 lattice_flip_point_value(lt, u, v, w, mid, axis);
318 }
319 }
320 }
321 break;
322 }
323 default: /* shouldn't happen, but just in case */
324 break;
325 }
326
327 /* updates */
329 WM_event_add_notifier(C, NC_GEOM | ND_DATA, obedit->data);
330 changed = true;
331 }
332
333 return changed ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
334}
335
337{
338 static const EnumPropertyItem flip_items[] = {
339 {LATTICE_FLIP_U, "U", 0, "U (X) Axis", ""},
340 {LATTICE_FLIP_V, "V", 0, "V (Y) Axis", ""},
341 {LATTICE_FLIP_W, "W", 0, "W (Z) Axis", ""},
342 {0, nullptr, 0, nullptr, nullptr},
343 };
344
345 /* identifiers */
346 ot->name = "Flip (Distortion Free)";
347 ot->description = "Mirror all control points without inverting the lattice deform";
348 ot->idname = "LATTICE_OT_flip";
349
350 /* api callbacks */
354
355 /* flags */
357
358 /* properties */
360 "axis",
361 flip_items,
363 "Flip Axis",
364 "Coordinates along this axis get flipped");
365}
366
Object * CTX_data_active_object(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
Object * CTX_data_edit_object(const bContext *C)
View3D * CTX_wm_view3d(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
int BKE_lattice_index_from_uvw(const Lattice *lt, int u, int v, int w)
Definition lattice.cc:195
void BKE_lattice_resize(Lattice *lt, int u_new, int v_new, int w_new, Object *lt_ob)
Definition lattice.cc:273
#define FOREACH_SELECTED_OBJECT_BEGIN(_view_layer, _v3d, _instance)
Definition BKE_layer.hh:298
#define FOREACH_SELECTED_OBJECT_END
Definition BKE_layer.hh:310
blender::Vector< Object * > BKE_view_layer_array_from_objects_in_edit_mode_unique_data(const Scene *scene, ViewLayer *view_layer, const View3D *v3d)
MINLINE void swap_v3_v3(float a[3], float b[3])
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1041
Object is a sort of wrapper for general info.
@ OB_LATTICE
bool ED_operator_editlattice(bContext *C)
Read Guarded memory(de)allocation.
@ OPTYPE_UNDO
Definition WM_types.hh:162
@ OPTYPE_REGISTER
Definition WM_types.hh:160
#define NC_GEOM
Definition WM_types.hh:360
#define ND_DATA
Definition WM_types.hh:475
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
#define printf
eLattice_FlipAxes
@ LATTICE_FLIP_W
@ LATTICE_FLIP_V
@ LATTICE_FLIP_U
static bool make_regular_poll(bContext *C)
static void lattice_flip_point_value(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
void LATTICE_OT_flip(wmOperatorType *ot)
static void lattice_swap_point_pairs(Lattice *lt, int u, int v, int w, float mid, eLattice_FlipAxes axis)
static int lattice_flip_exec(bContext *C, wmOperator *op)
static int make_regular_exec(bContext *C, wmOperator *op)
void LATTICE_OT_make_regular(wmOperatorType *ot)
draw_view in_light_buf[] float
IMETHOD Vector diff(const Vector &a, const Vector &b, double dt)
Definition frames.inl:1166
bool shape_key_report_if_locked(const Object *obedit, ReportList *reports)
int RNA_enum_get(PointerRNA *ptr, const char *name)
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, const int default_value, const char *ui_name, const char *ui_description)
float vec[4]
struct Lattice * latt
struct EditLatt * editlatt
struct BPoint * def
const char * name
Definition WM_types.hh:990
bool(* poll)(bContext *C) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1042
const char * idname
Definition WM_types.hh:992
int(* invoke)(bContext *C, wmOperator *op, const wmEvent *event) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1022
int(* exec)(bContext *C, wmOperator *op) ATTR_WARN_UNUSED_RESULT
Definition WM_types.hh:1006
const char * description
Definition WM_types.hh:996
PropertyRNA * prop
Definition WM_types.hh:1092
StructRNA * srna
Definition WM_types.hh:1080
struct ReportList * reports
struct PointerRNA * ptr
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition wm_files.cc:4125
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *)