Blender V5.0
particle_edit_undo.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2007 by Janne Karhu. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdlib>
10#include <cstring>
11
12#include "MEM_guardedalloc.h"
13
14#include "CLG_log.h"
15
16#include "DNA_scene_types.h"
18
19#include "BLI_listbase.h"
20#include "BLI_utildefines.h"
21
22#include "BKE_context.hh"
23#include "BKE_layer.hh"
24#include "BKE_particle.h"
25#include "BKE_pointcache.h"
26#include "BKE_undo_system.hh"
27
28#include "DEG_depsgraph.hh"
29
30#include "ED_object.hh"
31#include "ED_particle.hh"
32#include "ED_physics.hh"
33#include "ED_undo.hh"
34
36
38static CLG_LogRef LOG = {"undo.particle"};
39
40/* -------------------------------------------------------------------- */
43
45{
46 PTCacheEditPoint *point;
47
48 size_t mem_used_prev = MEM_get_memory_in_use();
49
50 undo->totpoint = edit->totpoint;
51
52 if (edit->psys) {
53 ParticleData *pa;
54
55 pa = undo->particles = static_cast<ParticleData *>(MEM_dupallocN(edit->psys->particles));
56
57 for (int i = 0; i < edit->totpoint; i++, pa++) {
58 pa->hair = static_cast<HairKey *>(MEM_dupallocN(pa->hair));
59 }
60
61 undo->psys_flag = edit->psys->flag;
62 }
63 else {
64 PTCacheMem *pm;
65
67 pm = static_cast<PTCacheMem *>(undo->mem_cache.first);
68
69 for (; pm; pm = pm->next) {
70 for (int i = 0; i < BPHYS_TOT_DATA; i++) {
71 pm->data[i] = MEM_dupallocN(pm->data[i]);
72 }
73 }
74 }
75
76 point = undo->points = static_cast<PTCacheEditPoint *>(MEM_dupallocN(edit->points));
77 undo->totpoint = edit->totpoint;
78
79 for (int i = 0; i < edit->totpoint; i++, point++) {
80 point->keys = static_cast<PTCacheEditKey *>(MEM_dupallocN(point->keys));
81 /* no need to update edit key->co & key->time pointers here */
82 }
83
84 size_t mem_used_curr = MEM_get_memory_in_use();
85
86 undo->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev :
87 sizeof(PTCacheUndo);
88}
89
91{
92 ParticleSystem *psys = edit->psys;
93 ParticleData *pa;
94 HairKey *hkey;
95 POINT_P;
96 KEY_K;
97
99 if (psys && psys->particles[p].hair) {
100 MEM_freeN(psys->particles[p].hair);
101 }
102
103 if (point->keys) {
104 MEM_freeN(point->keys);
105 }
106 }
107 if (psys && psys->particles) {
108 MEM_freeN(psys->particles);
109 }
110 if (edit->points) {
111 MEM_freeN(edit->points);
112 }
114
115 edit->points = static_cast<PTCacheEditPoint *>(MEM_dupallocN(undo->points));
116 edit->totpoint = undo->totpoint;
117
119 point->keys = static_cast<PTCacheEditKey *>(MEM_dupallocN(point->keys));
120 }
121
122 if (psys) {
123 psys->particles = static_cast<ParticleData *>(MEM_dupallocN(undo->particles));
124
125 psys->totpart = undo->totpoint;
126
128 pa = psys->particles + p;
129 hkey = pa->hair = static_cast<HairKey *>(MEM_dupallocN(pa->hair));
130
131 LOOP_KEYS {
132 key->co = hkey->co;
133 key->time = &hkey->time;
134 hkey++;
135 }
136 }
137
138 psys->flag = undo->psys_flag;
139 }
140 else {
141 PTCacheMem *pm;
142 int i;
143
145
147
148 pm = static_cast<PTCacheMem *>(edit->pid.cache->mem_cache.first);
149
150 for (; pm; pm = pm->next) {
151 for (i = 0; i < BPHYS_TOT_DATA; i++) {
152 pm->data[i] = MEM_dupallocN(pm->data[i]);
153 }
154 void *cur[BPHYS_TOT_DATA];
156
158 LOOP_KEYS {
159 if (int(key->ftime) == int(pm->frame)) {
160 key->co = static_cast<float *>(cur[BPHYS_DATA_LOCATION]);
161 key->vel = static_cast<float *>(cur[BPHYS_DATA_VELOCITY]);
162 key->rot = static_cast<float *>(cur[BPHYS_DATA_ROTATION]);
163 key->time = &key->ftime;
164 }
165 }
167 }
168 }
169 }
170}
171
173{
174 PTCacheEditPoint *point;
175 int i;
176
177 for (i = 0, point = undo->points; i < undo->totpoint; i++, point++) {
178 if (undo->particles && (undo->particles + i)->hair) {
179 MEM_freeN((undo->particles + i)->hair);
180 }
181 if (point->keys) {
182 MEM_freeN(point->keys);
183 }
184 }
185 if (undo->points) {
186 MEM_freeN(undo->points);
187 }
188 if (undo->particles) {
189 MEM_freeN(undo->particles);
190 }
192}
193
195
196/* -------------------------------------------------------------------- */
199
203 UndoRefID_Scene scene_ref;
204 UndoRefID_Object object_ref;
206};
207
209{
211 Scene *scene = CTX_data_scene(C);
212 ViewLayer *view_layer = CTX_data_view_layer(C);
213 BKE_view_layer_synced_ensure(scene, view_layer);
215 PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob);
216
217 return (edit != nullptr);
218}
219
220static bool particle_undosys_step_encode(bContext *C, Main * /*bmain*/, UndoStep *us_p)
221{
224 ViewLayer *view_layer = CTX_data_view_layer(C);
225 us->scene_ref.ptr = CTX_data_scene(C);
226 BKE_view_layer_synced_ensure(us->scene_ref.ptr, view_layer);
227 us->object_ref.ptr = BKE_view_layer_active_object_get(view_layer);
228 PTCacheEdit *edit = PE_get_current(depsgraph, us->scene_ref.ptr, us->object_ref.ptr);
230 return true;
231}
232
234 bContext *C, Main * /*bmain*/, UndoStep *us_p, const eUndoStepDir /*dir*/, bool /*is_final*/)
235{
237
239 Scene *scene = us->scene_ref.ptr;
240 ViewLayer *view_layer = CTX_data_view_layer(C);
241
242 /* Only to correct the `view_layer` which might not match the scene
243 * (in the case of undoing with multiple windows). */
245 CTX_wm_manager(C), us->scene_ref.ptr, &scene, &view_layer);
246
247 Object *ob = us->object_ref.ptr;
249
250 PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob);
251
252 /* While this shouldn't happen, entering particle edit-mode uses a more complex
253 * setup compared to most other modes which we can't ensure succeeds. */
254 if (UNLIKELY(edit == nullptr)) {
255 BLI_assert(0);
256 return;
257 }
258
259 undoptcache_to_editcache(&us->data, edit);
261 if ((pset->flag & PE_DRAW_PART) != 0) {
262 psys_free_path_cache(nullptr, edit);
264 }
266
267 ED_undo_object_set_active_or_warn(scene, view_layer, ob, us_p->name, &LOG);
268
269 /* Check after setting active (unless undoing into another scene). */
271}
272
274{
277}
278
280 UndoTypeForEachIDRefFn foreach_ID_ref_fn,
281 void *user_data)
282{
284 foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->scene_ref));
285 foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->object_ref));
286}
287
302
Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Scene * CTX_data_scene(const bContext *C)
wmWindowManager * CTX_wm_manager(const bContext *C)
ViewLayer * CTX_data_view_layer(const bContext *C)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
Object * BKE_view_layer_active_object_get(const ViewLayer *view_layer)
void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit)
Definition particle.cc:907
void BKE_particle_batch_cache_dirty_tag(struct ParticleSystem *psys, int mode)
Definition particle.cc:5288
@ BKE_PARTICLE_BATCH_DIRTY_ALL
void BKE_ptcache_mem_pointers_incr(void *cur[BPHYS_TOT_DATA])
void BKE_ptcache_free_mem(struct ListBase *mem_cache)
void BKE_ptcache_mem_pointers_init(struct PTCacheMem *pm, void *cur[BPHYS_TOT_DATA])
@ UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE
void(*)(void *user_data, UndoRefID *id_ref) UndoTypeForEachIDRefFn
eUndoStepDir
#define BLI_assert(a)
Definition BLI_assert.h:46
void void void void void void BLI_duplicatelist(ListBase *dst, const ListBase *src) ATTR_NONNULL(1
#define UNLIKELY(x)
void DEG_id_tag_update(ID *id, unsigned int flags)
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:1074
@ BPHYS_DATA_VELOCITY
@ BPHYS_DATA_LOCATION
@ BPHYS_DATA_ROTATION
#define BPHYS_TOT_DATA
@ PE_DRAW_PART
PTCacheEdit * PE_get_current(Depsgraph *depsgraph, Scene *scene, Object *ob)
void ED_object_particle_edit_mode_enter_ex(Depsgraph *depsgraph, Scene *scene, Object *ob)
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:775
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:794
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
#define C
Definition RandGen.cpp:29
BPy_StructRNA * depsgraph
#define LOG(level)
Definition log.h:97
size_t(* MEM_get_memory_in_use)(void)
Definition mallocn.cc:70
void * MEM_dupallocN(const void *vmemh)
Definition mallocn.cc:143
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
static bool particle_undosys_poll(bContext *C)
static void particle_undosys_step_decode(bContext *C, Main *, UndoStep *us_p, const eUndoStepDir, bool)
static void undoptcache_to_editcache(PTCacheUndo *undo, PTCacheEdit *edit)
static bool particle_undosys_step_encode(bContext *C, Main *, UndoStep *us_p)
static void particle_undosys_foreach_ID_ref(UndoStep *us_p, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
static void particle_undosys_step_free(UndoStep *us_p)
static void undoptcache_free_data(PTCacheUndo *undo)
void ED_particle_undosys_type(UndoType *ut)
static void undoptcache_from_editcache(PTCacheUndo *undo, PTCacheEdit *edit)
#define POINT_P
#define LOOP_KEYS
#define KEY_K
#define LOOP_POINTS
void * first
struct PTCacheEditKey * keys
PTCacheEditPoint * points
struct ParticleSystem * psys
struct PTCacheID pid
struct PointCache * cache
unsigned int frame
struct PTCacheMem * next
struct ListBase mem_cache
struct PTCacheEditPoint * points
struct ParticleData * particles
ParticleData * particles
UndoRefID_Object object_ref
UndoRefID_Scene scene_ref
struct ListBase mem_cache
struct ToolSettings * toolsettings
struct ParticleEditSettings particle
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)
i
Definition text_draw.cc:230