Blender V4.3
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
9#include <cmath>
10#include <cstdlib>
11#include <cstring>
12
13#include "MEM_guardedalloc.h"
14
15#include "CLG_log.h"
16
17#include "DNA_scene_types.h"
19
20#include "BLI_listbase.h"
21#include "BLI_utildefines.h"
22
23#include "BKE_context.hh"
24#include "BKE_layer.hh"
25#include "BKE_particle.h"
26#include "BKE_pointcache.h"
27#include "BKE_undo_system.hh"
28
29#include "DEG_depsgraph.hh"
30
31#include "ED_object.hh"
32#include "ED_particle.hh"
33#include "ED_physics.hh"
34#include "ED_undo.hh"
35
37
39static CLG_LogRef LOG = {"ed.undo.particle_edit"};
40
41/* -------------------------------------------------------------------- */
46{
48
49 size_t mem_used_prev = MEM_get_memory_in_use();
50
51 undo->totpoint = edit->totpoint;
52
53 if (edit->psys) {
54 ParticleData *pa;
55
56 pa = undo->particles = static_cast<ParticleData *>(MEM_dupallocN(edit->psys->particles));
57
58 for (int i = 0; i < edit->totpoint; i++, pa++) {
59 pa->hair = static_cast<HairKey *>(MEM_dupallocN(pa->hair));
60 }
61
62 undo->psys_flag = edit->psys->flag;
63 }
64 else {
65 PTCacheMem *pm;
66
68 pm = static_cast<PTCacheMem *>(undo->mem_cache.first);
69
70 for (; pm; pm = pm->next) {
71 for (int i = 0; i < BPHYS_TOT_DATA; i++) {
72 pm->data[i] = MEM_dupallocN(pm->data[i]);
73 }
74 }
75 }
76
77 point = undo->points = static_cast<PTCacheEditPoint *>(MEM_dupallocN(edit->points));
78 undo->totpoint = edit->totpoint;
79
80 for (int i = 0; i < edit->totpoint; i++, point++) {
81 point->keys = static_cast<PTCacheEditKey *>(MEM_dupallocN(point->keys));
82 /* no need to update edit key->co & key->time pointers here */
83 }
84
85 size_t mem_used_curr = MEM_get_memory_in_use();
86
87 undo->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev :
88 sizeof(PTCacheUndo);
89}
90
92{
93 ParticleSystem *psys = edit->psys;
94 ParticleData *pa;
95 HairKey *hkey;
96 POINT_P;
97 KEY_K;
98
100 if (psys && psys->particles[p].hair) {
101 MEM_freeN(psys->particles[p].hair);
102 }
103
104 if (point->keys) {
105 MEM_freeN(point->keys);
106 }
107 }
108 if (psys && psys->particles) {
109 MEM_freeN(psys->particles);
110 }
111 if (edit->points) {
112 MEM_freeN(edit->points);
113 }
115
116 edit->points = static_cast<PTCacheEditPoint *>(MEM_dupallocN(undo->points));
117 edit->totpoint = undo->totpoint;
118
120 point->keys = static_cast<PTCacheEditKey *>(MEM_dupallocN(point->keys));
121 }
122
123 if (psys) {
124 psys->particles = static_cast<ParticleData *>(MEM_dupallocN(undo->particles));
125
126 psys->totpart = undo->totpoint;
127
129 pa = psys->particles + p;
130 hkey = pa->hair = static_cast<HairKey *>(MEM_dupallocN(pa->hair));
131
132 LOOP_KEYS {
133 key->co = hkey->co;
134 key->time = &hkey->time;
135 hkey++;
136 }
137 }
138
139 psys->flag = undo->psys_flag;
140 }
141 else {
142 PTCacheMem *pm;
143 int i;
144
146
148
149 pm = static_cast<PTCacheMem *>(edit->pid.cache->mem_cache.first);
150
151 for (; pm; pm = pm->next) {
152 for (i = 0; i < BPHYS_TOT_DATA; i++) {
153 pm->data[i] = MEM_dupallocN(pm->data[i]);
154 }
155 void *cur[BPHYS_TOT_DATA];
157
159 LOOP_KEYS {
160 if (int(key->ftime) == int(pm->frame)) {
161 key->co = static_cast<float *>(cur[BPHYS_DATA_LOCATION]);
162 key->vel = static_cast<float *>(cur[BPHYS_DATA_VELOCITY]);
163 key->rot = static_cast<float *>(cur[BPHYS_DATA_ROTATION]);
164 key->time = &key->ftime;
165 }
166 }
168 }
169 }
170 }
171}
172
174{
176 int i;
177
178 for (i = 0, point = undo->points; i < undo->totpoint; i++, point++) {
179 if (undo->particles && (undo->particles + i)->hair) {
180 MEM_freeN((undo->particles + i)->hair);
181 }
182 if (point->keys) {
183 MEM_freeN(point->keys);
184 }
185 }
186 if (undo->points) {
187 MEM_freeN(undo->points);
188 }
189 if (undo->particles) {
190 MEM_freeN(undo->particles);
191 }
193}
194
197/* -------------------------------------------------------------------- */
204 UndoRefID_Scene scene_ref;
205 UndoRefID_Object object_ref;
207};
208
210{
212 Scene *scene = CTX_data_scene(C);
213 ViewLayer *view_layer = CTX_data_view_layer(C);
214 BKE_view_layer_synced_ensure(scene, view_layer);
216 PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob);
217
218 return (edit != nullptr);
219}
220
221static bool particle_undosys_step_encode(bContext *C, Main * /*bmain*/, UndoStep *us_p)
222{
225 ViewLayer *view_layer = CTX_data_view_layer(C);
226 us->scene_ref.ptr = CTX_data_scene(C);
227 BKE_view_layer_synced_ensure(us->scene_ref.ptr, view_layer);
228 us->object_ref.ptr = BKE_view_layer_active_object_get(view_layer);
229 PTCacheEdit *edit = PE_get_current(depsgraph, us->scene_ref.ptr, us->object_ref.ptr);
231 return true;
232}
233
235 bContext *C, Main * /*bmain*/, UndoStep *us_p, const eUndoStepDir /*dir*/, bool /*is_final*/)
236{
238
240 Scene *scene = us->scene_ref.ptr;
241 ViewLayer *view_layer = CTX_data_view_layer(C);
242
243 /* Only to correct the `view_layer` which might not match the scene
244 * (in the case of undoing with multiple windows). */
246 CTX_wm_manager(C), us->scene_ref.ptr, &scene, &view_layer);
247
248 Object *ob = us->object_ref.ptr;
250
251 PTCacheEdit *edit = PE_get_current(depsgraph, scene, ob);
252
253 /* While this shouldn't happen, entering particle edit-mode uses a more complex
254 * setup compared to most other modes which we can't ensure succeeds. */
255 if (UNLIKELY(edit == nullptr)) {
256 BLI_assert(0);
257 return;
258 }
259
260 undoptcache_to_editcache(&us->data, edit);
261 ParticleEditSettings *pset = &scene->toolsettings->particle;
262 if ((pset->flag & PE_DRAW_PART) != 0) {
263 psys_free_path_cache(nullptr, edit);
265 }
267
268 ED_undo_object_set_active_or_warn(scene, view_layer, ob, us_p->name, &LOG);
269
270 /* Check after setting active (unless undoing into another scene). */
272}
273
275{
278}
279
281 UndoTypeForEachIDRefFn foreach_ID_ref_fn,
282 void *user_data)
283{
285 foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->scene_ref));
286 foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->object_ref));
287}
288
303
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:904
void BKE_particle_batch_cache_dirty_tag(struct ParticleSystem *psys, int mode)
Definition particle.cc:5295
@ 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)
struct PTCacheUndo PTCacheUndo
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:50
void void void void void void BLI_duplicatelist(struct ListBase *dst, const struct 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:1041
@ 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:790
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 MEM_SAFE_FREE(v)
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
const Depsgraph * depsgraph
size_t(* MEM_get_memory_in_use)(void)
Definition mallocn.cc:62
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
void *(* MEM_dupallocN)(const void *vmemh)
Definition mallocn.cc:39
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)
static CLG_LogRef LOG
#define POINT_P
#define LOOP_KEYS
#define KEY_K
#define LOOP_POINTS
void * first
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
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)