Blender  V3.3
particle_edit_undo.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2007 by Janne Karhu. All rights reserved. */
3 
8 #include <math.h>
9 #include <stdlib.h>
10 #include <string.h>
11 
12 #include "MEM_guardedalloc.h"
13 
14 #include "CLG_log.h"
15 
16 #include "DNA_meshdata_types.h"
17 #include "DNA_scene_types.h"
19 
20 #include "BLI_listbase.h"
21 #include "BLI_utildefines.h"
22 
23 #include "BKE_context.h"
24 #include "BKE_particle.h"
25 #include "BKE_pointcache.h"
26 #include "BKE_undo_system.h"
27 
28 #include "DEG_depsgraph.h"
29 
30 #include "ED_object.h"
31 #include "ED_particle.h"
32 #include "ED_physics.h"
33 #include "ED_undo.h"
34 
36 
37 #include "physics_intern.h"
38 
40 static CLG_LogRef LOG = {"ed.undo.particle_edit"};
41 
42 /* -------------------------------------------------------------------- */
47 {
49 
50  size_t mem_used_prev = MEM_get_memory_in_use();
51 
52  undo->totpoint = edit->totpoint;
53 
54  if (edit->psys) {
55  ParticleData *pa;
56 
57  pa = undo->particles = MEM_dupallocN(edit->psys->particles);
58 
59  for (int i = 0; i < edit->totpoint; i++, pa++) {
60  pa->hair = MEM_dupallocN(pa->hair);
61  }
62 
63  undo->psys_flag = edit->psys->flag;
64  }
65  else {
66  PTCacheMem *pm;
67 
69  pm = undo->mem_cache.first;
70 
71  for (; pm; pm = pm->next) {
72  for (int i = 0; i < BPHYS_TOT_DATA; i++) {
73  pm->data[i] = MEM_dupallocN(pm->data[i]);
74  }
75  }
76  }
77 
78  point = undo->points = MEM_dupallocN(edit->points);
79  undo->totpoint = edit->totpoint;
80 
81  for (int i = 0; i < edit->totpoint; i++, point++) {
82  point->keys = MEM_dupallocN(point->keys);
83  /* no need to update edit key->co & key->time pointers here */
84  }
85 
86  size_t mem_used_curr = MEM_get_memory_in_use();
87 
88  undo->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev :
89  sizeof(PTCacheUndo);
90 }
91 
93 {
94  ParticleSystem *psys = edit->psys;
95  ParticleData *pa;
96  HairKey *hkey;
97  POINT_P;
98  KEY_K;
99 
100  LOOP_POINTS {
101  if (psys && psys->particles[p].hair) {
102  MEM_freeN(psys->particles[p].hair);
103  }
104 
105  if (point->keys) {
106  MEM_freeN(point->keys);
107  }
108  }
109  if (psys && psys->particles) {
110  MEM_freeN(psys->particles);
111  }
112  if (edit->points) {
113  MEM_freeN(edit->points);
114  }
116 
117  edit->points = MEM_dupallocN(undo->points);
118  edit->totpoint = undo->totpoint;
119 
120  LOOP_POINTS {
121  point->keys = MEM_dupallocN(point->keys);
122  }
123 
124  if (psys) {
125  psys->particles = MEM_dupallocN(undo->particles);
126 
127  psys->totpart = undo->totpoint;
128 
129  LOOP_POINTS {
130  pa = psys->particles + p;
131  hkey = pa->hair = MEM_dupallocN(pa->hair);
132 
133  LOOP_KEYS {
134  key->co = hkey->co;
135  key->time = &hkey->time;
136  hkey++;
137  }
138  }
139 
140  psys->flag = undo->psys_flag;
141  }
142  else {
143  PTCacheMem *pm;
144  int i;
145 
147 
148  BLI_duplicatelist(&edit->pid.cache->mem_cache, &undo->mem_cache);
149 
150  pm = edit->pid.cache->mem_cache.first;
151 
152  for (; pm; pm = pm->next) {
153  for (i = 0; i < BPHYS_TOT_DATA; i++) {
154  pm->data[i] = MEM_dupallocN(pm->data[i]);
155  }
156  void *cur[BPHYS_TOT_DATA];
158 
159  LOOP_POINTS {
160  LOOP_KEYS {
161  if ((int)key->ftime == (int)pm->frame) {
162  key->co = cur[BPHYS_DATA_LOCATION];
163  key->vel = cur[BPHYS_DATA_VELOCITY];
164  key->rot = cur[BPHYS_DATA_ROTATION];
165  key->time = &key->ftime;
166  }
167  }
169  }
170  }
171  }
172 }
173 
175 {
177  int i;
178 
179  for (i = 0, point = undo->points; i < undo->totpoint; i++, point++) {
180  if (undo->particles && (undo->particles + i)->hair) {
181  MEM_freeN((undo->particles + i)->hair);
182  }
183  if (point->keys) {
184  MEM_freeN(point->keys);
185  }
186  }
187  if (undo->points) {
188  MEM_freeN(undo->points);
189  }
190  if (undo->particles) {
191  MEM_freeN(undo->particles);
192  }
194 }
195 
198 /* -------------------------------------------------------------------- */
202 typedef struct ParticleUndoStep {
204  UndoRefID_Scene scene_ref;
205  UndoRefID_Object object_ref;
208 
209 static bool particle_undosys_poll(struct bContext *C)
210 {
213  ViewLayer *view_layer = CTX_data_view_layer(C);
214  Object *ob = OBACT(view_layer);
216 
217  return (edit != NULL);
218 }
219 
221  struct Main *UNUSED(bmain),
222  UndoStep *us_p)
223 {
225  ParticleUndoStep *us = (ParticleUndoStep *)us_p;
226  ViewLayer *view_layer = CTX_data_view_layer(C);
227  us->scene_ref.ptr = CTX_data_scene(C);
228  us->object_ref.ptr = OBACT(view_layer);
229  PTCacheEdit *edit = PE_get_current(depsgraph, us->scene_ref.ptr, us->object_ref.ptr);
230  undoptcache_from_editcache(&us->data, edit);
231  return true;
232 }
233 
235  struct Main *UNUSED(bmain),
236  UndoStep *us_p,
237  const eUndoStepDir UNUSED(dir),
238  bool UNUSED(is_final))
239 {
241 
242  ParticleUndoStep *us = (ParticleUndoStep *)us_p;
243  Scene *scene = us->scene_ref.ptr;
244  Object *ob = us->object_ref.ptr;
245 
247 
249 
250  /* While this shouldn't happen, entering particle edit-mode uses a more complex
251  * setup compared to most other modes which we can't ensure succeeds. */
252  if (UNLIKELY(edit == NULL)) {
253  BLI_assert(0);
254  return;
255  }
256 
257  undoptcache_to_editcache(&us->data, edit);
259  if ((pset->flag & PE_DRAW_PART) != 0) {
260  psys_free_path_cache(NULL, edit);
262  }
264 
266 
268 }
269 
271 {
272  ParticleUndoStep *us = (ParticleUndoStep *)us_p;
274 }
275 
277  UndoTypeForEachIDRefFn foreach_ID_ref_fn,
278  void *user_data)
279 {
280  ParticleUndoStep *us = (ParticleUndoStep *)us_p;
281  foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->scene_ref));
282  foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->object_ref));
283 }
284 
286 {
287  ut->name = "Edit Particle";
292 
294 
296 
297  ut->step_size = sizeof(ParticleUndoStep);
298 }
299 
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit)
Definition: particle.c:997
@ BKE_PARTICLE_BATCH_DIRTY_ALL
Definition: BKE_particle.h:686
void BKE_particle_batch_cache_dirty_tag(struct ParticleSystem *psys, int mode)
Definition: particle.c:5274
void BKE_ptcache_mem_pointers_incr(void *cur[BPHYS_TOT_DATA])
Definition: pointcache.c:1772
void BKE_ptcache_free_mem(struct ListBase *mem_cache)
Definition: pointcache.c:3029
struct PTCacheUndo PTCacheUndo
void BKE_ptcache_mem_pointers_init(struct PTCacheMem *pm, void *cur[BPHYS_TOT_DATA])
Definition: pointcache.c:1762
@ UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE
eUndoStepDir
void(* UndoTypeForEachIDRefFn)(void *user_data, struct UndoRefID *id_ref)
#define BLI_assert(a)
Definition: BLI_assert.h:46
void void void void void BLI_duplicatelist(struct ListBase *dst, const struct ListBase *src) ATTR_NONNULL(1
#define UNUSED(x)
#define UNLIKELY(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
#define BPHYS_DATA_LOCATION
#define BPHYS_DATA_VELOCITY
#define BPHYS_DATA_ROTATION
#define BPHYS_TOT_DATA
#define PE_DRAW_PART
#define OBACT(_view_layer)
void ED_object_particle_edit_mode_enter_ex(struct Depsgraph *depsgraph, struct Scene *scene, Object *ob)
struct PTCacheEdit * PE_get_current(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob)
void ED_undo_object_set_active_or_warn(struct Scene *scene, struct ViewLayer *view_layer, struct Object *ob, const char *info, struct CLG_LogRef *log)
Definition: ed_undo.c:800
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 Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise 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
#define C
Definition: RandGen.cpp:25
Scene scene
const Depsgraph * depsgraph
void * user_data
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
size_t(* MEM_get_memory_in_use)(void)
Definition: mallocn.c:45
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:28
static bool particle_undosys_poll(struct bContext *C)
static void undoptcache_to_editcache(PTCacheUndo *undo, PTCacheEdit *edit)
static void particle_undosys_step_decode(struct bContext *C, struct Main *UNUSED(bmain), UndoStep *us_p, const eUndoStepDir UNUSED(dir), bool UNUSED(is_final))
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 bool particle_undosys_step_encode(struct bContext *C, struct Main *UNUSED(bmain), 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
struct ParticleUndoStep ParticleUndoStep
#define POINT_P
#define LOOP_KEYS
#define KEY_K
#define LOOP_POINTS
float co[3]
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
int * mirror_cache
PTCacheEditPoint * points
struct ParticleSystem * psys
struct PTCacheID pid
struct PointCache * cache
unsigned int frame
struct PTCacheMem * next
size_t undo_size
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]
size_t step_size
void(* step_decode)(struct bContext *C, struct Main *bmain, UndoStep *us, eUndoStepDir dir, bool is_final)
bool(* step_encode)(struct bContext *C, struct Main *bmain, UndoStep *us)
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)