Blender V4.3
editlattice_undo.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 <cmath>
10#include <cstdlib>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "CLG_log.h"
16
17#include "BLI_array_utils.h"
18#include "BLI_utildefines.h"
19
20#include "DNA_curve_types.h"
21#include "DNA_lattice_types.h"
22#include "DNA_meshdata_types.h"
23#include "DNA_object_types.h"
24#include "DNA_scene_types.h"
25
26#include "BKE_context.hh"
27#include "BKE_deform.hh"
28#include "BKE_layer.hh"
29#include "BKE_main.hh"
30#include "BKE_object.hh"
31#include "BKE_undo_system.hh"
32
33#include "DEG_depsgraph.hh"
34
35#include "ED_lattice.hh"
36#include "ED_object.hh"
37#include "ED_undo.hh"
38#include "ED_util.hh"
39
40#include "WM_api.hh"
41#include "WM_types.hh"
42
43#include "lattice_intern.hh"
44
46static CLG_LogRef LOG = {"ed.undo.lattice"};
47
48/* -------------------------------------------------------------------- */
52/* TODO(@ideasman42): this could contain an entire 'Lattice' struct. */
57 float fu, fv, fw;
58 float du, dv, dw;
60 size_t undo_size;
61};
62
63static void undolatt_to_editlatt(UndoLattice *ult, EditLatt *editlatt)
64{
65 const int len_src = ult->pntsu * ult->pntsv * ult->pntsw;
66 const int len_dst = editlatt->latt->pntsu * editlatt->latt->pntsv * editlatt->latt->pntsw;
67 if (len_src != len_dst) {
68 MEM_freeN(editlatt->latt->def);
69 editlatt->latt->def = static_cast<BPoint *>(MEM_dupallocN(ult->def));
70 }
71 else {
72 memcpy(editlatt->latt->def, ult->def, sizeof(BPoint) * len_src);
73 }
74
75 /* Even for the same amount of points we don't just copy memory for MDeformVert,
76 * relations to #MDeformWeight might have changed. */
77 if (editlatt->latt->dvert && ult->dvert) {
78 BKE_defvert_array_free(editlatt->latt->dvert, len_dst);
79 editlatt->latt->dvert = static_cast<MDeformVert *>(
80 MEM_mallocN(sizeof(MDeformVert) * len_src, "Lattice MDeformVert"));
81 BKE_defvert_array_copy(editlatt->latt->dvert, ult->dvert, len_src);
82 }
83
84 editlatt->latt->pntsu = ult->pntsu;
85 editlatt->latt->pntsv = ult->pntsv;
86 editlatt->latt->pntsw = ult->pntsw;
87 editlatt->latt->actbp = ult->actbp;
88
89 editlatt->latt->typeu = ult->typeu;
90 editlatt->latt->typev = ult->typev;
91 editlatt->latt->typew = ult->typew;
92
93 editlatt->latt->fu = ult->fu;
94 editlatt->latt->fv = ult->fv;
95 editlatt->latt->fw = ult->fw;
96 editlatt->latt->du = ult->du;
97 editlatt->latt->dv = ult->dv;
98 editlatt->latt->dw = ult->dw;
99}
100
101static void *undolatt_from_editlatt(UndoLattice *ult, EditLatt *editlatt)
102{
104
105 ult->def = static_cast<BPoint *>(MEM_dupallocN(editlatt->latt->def));
106 ult->pntsu = editlatt->latt->pntsu;
107 ult->pntsv = editlatt->latt->pntsv;
108 ult->pntsw = editlatt->latt->pntsw;
109 ult->actbp = editlatt->latt->actbp;
110
111 ult->typeu = editlatt->latt->typeu;
112 ult->typev = editlatt->latt->typev;
113 ult->typew = editlatt->latt->typew;
114
115 ult->fu = editlatt->latt->fu;
116 ult->fv = editlatt->latt->fv;
117 ult->fw = editlatt->latt->fw;
118 ult->du = editlatt->latt->du;
119 ult->dv = editlatt->latt->dv;
120 ult->dw = editlatt->latt->dw;
121
122 if (editlatt->latt->dvert) {
123 const int tot = ult->pntsu * ult->pntsv * ult->pntsw;
124 ult->dvert = static_cast<MDeformVert *>(
125 MEM_mallocN(sizeof(MDeformVert) * tot, "Undo Lattice MDeformVert"));
126 BKE_defvert_array_copy(ult->dvert, editlatt->latt->dvert, tot);
127 ult->undo_size += sizeof(*ult->dvert) * tot;
128 }
129
130 ult->undo_size += sizeof(*ult->def) * ult->pntsu * ult->pntsv * ult->pntsw;
131
132 return ult;
133}
134
136{
137 if (ult->def) {
138 MEM_freeN(ult->def);
139 }
140 if (ult->dvert) {
141 BKE_defvert_array_free(ult->dvert, ult->pntsu * ult->pntsv * ult->pntsw);
142 ult->dvert = nullptr;
143 }
144}
145
146#if 0
147static int validate_undoLatt(void *data, void *edata)
148{
149 UndoLattice *ult = (UndoLattice *)data;
150 EditLatt *editlatt = (EditLatt *)edata;
151
152 return (ult->pntsu == editlatt->latt->pntsu && ult->pntsv == editlatt->latt->pntsv &&
153 ult->pntsw == editlatt->latt->pntsw);
154}
155#endif
156
158{
159 Scene *scene = CTX_data_scene(C);
160 ViewLayer *view_layer = CTX_data_view_layer(C);
161 BKE_view_layer_synced_ensure(scene, view_layer);
162 Object *obedit = BKE_view_layer_edit_object_get(view_layer);
163 if (obedit && obedit->type == OB_LATTICE) {
164 Lattice *lt = static_cast<Lattice *>(obedit->data);
165 if (lt->editlatt != nullptr) {
166 return obedit;
167 }
168 }
169
170 return nullptr;
171}
172
175/* -------------------------------------------------------------------- */
182 UndoRefID_Object obedit_ref;
184};
185
193
195{
196 return editlatt_object_from_context(C) != nullptr;
197}
198
199static bool lattice_undosys_step_encode(bContext *C, Main *bmain, UndoStep *us_p)
200{
201 LatticeUndoStep *us = (LatticeUndoStep *)us_p;
202
203 /* Important not to use the 3D view when getting objects because all objects
204 * outside of this list will be moved out of edit-mode when reading back undo steps. */
205 Scene *scene = CTX_data_scene(C);
206 ViewLayer *view_layer = CTX_data_view_layer(C);
208
209 us->scene_ref.ptr = scene;
210 us->elems = static_cast<LatticeUndoStep_Elem *>(
211 MEM_callocN(sizeof(*us->elems) * objects.size(), __func__));
212 us->elems_len = objects.size();
213
214 for (uint i = 0; i < objects.size(); i++) {
215 Object *ob = objects[i];
216 LatticeUndoStep_Elem *elem = &us->elems[i];
217
218 elem->obedit_ref.ptr = ob;
219 Lattice *lt = static_cast<Lattice *>(ob->data);
222 us->step.data_size += elem->data.undo_size;
223 }
224
225 bmain->is_memfile_undo_flush_needed = true;
226
227 return true;
228}
229
231 bContext *C, Main *bmain, UndoStep *us_p, const eUndoStepDir /*dir*/, bool /*is_final*/)
232{
233 LatticeUndoStep *us = (LatticeUndoStep *)us_p;
234 Scene *scene = CTX_data_scene(C);
235 ViewLayer *view_layer = CTX_data_view_layer(C);
236
238 CTX_wm_manager(C), us->scene_ref.ptr, &scene, &view_layer);
240 scene, view_layer, &us->elems[0].obedit_ref.ptr, us->elems_len, sizeof(*us->elems));
241
243
244 for (uint i = 0; i < us->elems_len; i++) {
245 LatticeUndoStep_Elem *elem = &us->elems[i];
246 Object *obedit = elem->obedit_ref.ptr;
247 Lattice *lt = static_cast<Lattice *>(obedit->data);
248 if (lt->editlatt == nullptr) {
249 /* Should never fail, may not crash but can give odd behavior. */
251 "name='%s', failed to enter edit-mode for object '%s', undo state invalid",
252 us_p->name,
253 obedit->id.name);
254 continue;
255 }
259 }
260
261 /* The first element is always active */
263 scene, view_layer, us->elems[0].obedit_ref.ptr, us_p->name, &LOG);
264
265 /* Check after setting active (unless undoing into another scene). */
267
268 bmain->is_memfile_undo_flush_needed = true;
269
271}
272
274{
275 LatticeUndoStep *us = (LatticeUndoStep *)us_p;
276
277 for (uint i = 0; i < us->elems_len; i++) {
278 LatticeUndoStep_Elem *elem = &us->elems[i];
279 undolatt_free_data(&elem->data);
280 }
281 MEM_freeN(us->elems);
282}
283
285 UndoTypeForEachIDRefFn foreach_ID_ref_fn,
286 void *user_data)
287{
288 LatticeUndoStep *us = (LatticeUndoStep *)us_p;
289
290 foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->scene_ref));
291 for (uint i = 0; i < us->elems_len; i++) {
292 LatticeUndoStep_Elem *elem = &us->elems[i];
293 foreach_ID_ref_fn(user_data, ((UndoRefID *)&elem->obedit_ref));
294 }
295}
296
311
Scene * CTX_data_scene(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
support for deformation groups and hooks.
void BKE_defvert_array_free(MDeformVert *dvert, int totvert)
Definition deform.cc:1066
void BKE_defvert_array_copy(MDeformVert *dst, const MDeformVert *src, int totvert)
Definition deform.cc:1029
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_edit_object_get(const ViewLayer *view_layer)
General operations, lookup, etc. for blender objects.
bool BKE_object_is_in_editmode(const Object *ob)
@ UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE
void(*)(void *user_data, UndoRefID *id_ref) UndoTypeForEachIDRefFn
eUndoStepDir
Generic array manipulation API.
#define BLI_array_is_zeroed(arr, arr_len)
#define BLI_assert(a)
Definition BLI_assert.h:50
unsigned int uint
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:182
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
void ED_undo_object_set_active_or_warn(Scene *scene, ViewLayer *view_layer, Object *ob, const char *info, CLG_LogRef *log)
Definition ed_undo.cc:790
void ED_undo_object_editmode_restore_helper(Scene *scene, ViewLayer *view_layer, Object **object_array, uint object_array_len, uint object_array_stride)
Definition ed_undo.cc:826
blender::Vector< Object * > ED_undo_editmode_objects_from_view_layer(const Scene *scene, ViewLayer *view_layer)
Definition ed_undo.cc:871
void ED_undo_object_editmode_validate_scene_from_windows(wmWindowManager *wm, const Scene *scene_ref, Scene **scene_p, ViewLayer **view_layer_p)
Definition ed_undo.cc:809
Read Guarded memory(de)allocation.
#define NC_GEOM
Definition WM_types.hh:360
#define ND_DATA
Definition WM_types.hh:475
static void undolatt_to_editlatt(UndoLattice *ult, EditLatt *editlatt)
static bool lattice_undosys_poll(bContext *C)
static void lattice_undosys_step_decode(bContext *C, Main *bmain, UndoStep *us_p, const eUndoStepDir, bool)
static void lattice_undosys_step_free(UndoStep *us_p)
void ED_lattice_undosys_type(UndoType *ut)
static void undolatt_free_data(UndoLattice *ult)
static void lattice_undosys_foreach_ID_ref(UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
static bool lattice_undosys_step_encode(bContext *C, Main *bmain, UndoStep *us_p)
static CLG_LogRef LOG
static void * undolatt_from_editlatt(UndoLattice *ult, EditLatt *editlatt)
static Object * editlatt_object_from_context(bContext *C)
void *(* MEM_mallocN)(size_t len, const char *str)
Definition mallocn.cc:44
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_callocN)(size_t len, const char *str)
Definition mallocn.cc:42
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
char needs_flush_to_id
struct Lattice * latt
char name[66]
Definition DNA_ID.h:425
UndoRefID_Object obedit_ref
UndoRefID_Scene scene_ref
LatticeUndoStep_Elem * elems
struct MDeformVert * dvert
struct EditLatt * editlatt
struct BPoint * def
bool is_memfile_undo_flush_needed
Definition BKE_main.hh:165
MDeformVert * dvert
size_t data_size
char name[64]
void(* step_foreach_ID_ref)(UndoStep *us, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
const char * name
void(* step_free)(UndoStep *us)
bool(* poll)(struct bContext *C)
void(* step_decode)(bContext *C, Main *bmain, UndoStep *us, eUndoStepDir dir, bool is_final)
bool(* step_encode)(bContext *C, Main *bmain, UndoStep *us)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)