Blender  V2.93
particle_edit_undo.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2007 by Janne Karhu.
17  * All rights reserved.
18  */
19 
24 #include <math.h>
25 #include <stdlib.h>
26 #include <string.h>
27 
28 #include "MEM_guardedalloc.h"
29 
30 #include "CLG_log.h"
31 
32 #include "DNA_meshdata_types.h"
33 #include "DNA_scene_types.h"
35 
36 #include "BLI_listbase.h"
37 #include "BLI_utildefines.h"
38 
39 #include "BKE_context.h"
40 #include "BKE_particle.h"
41 #include "BKE_pointcache.h"
42 #include "BKE_undo_system.h"
43 
44 #include "DEG_depsgraph.h"
45 
46 #include "ED_object.h"
47 #include "ED_particle.h"
48 #include "ED_physics.h"
49 #include "ED_undo.h"
50 
52 
53 #include "physics_intern.h"
54 
56 static CLG_LogRef LOG = {"ed.undo.particle_edit"};
57 
58 /* -------------------------------------------------------------------- */
63 {
64  PTCacheEditPoint *point;
65 
66  size_t mem_used_prev = MEM_get_memory_in_use();
67 
68  undo->totpoint = edit->totpoint;
69 
70  if (edit->psys) {
71  ParticleData *pa;
72 
73  pa = undo->particles = MEM_dupallocN(edit->psys->particles);
74 
75  for (int i = 0; i < edit->totpoint; i++, pa++) {
76  pa->hair = MEM_dupallocN(pa->hair);
77  }
78 
79  undo->psys_flag = edit->psys->flag;
80  }
81  else {
82  PTCacheMem *pm;
83 
85  pm = undo->mem_cache.first;
86 
87  for (; pm; pm = pm->next) {
88  for (int i = 0; i < BPHYS_TOT_DATA; i++) {
89  pm->data[i] = MEM_dupallocN(pm->data[i]);
90  }
91  }
92  }
93 
94  point = undo->points = MEM_dupallocN(edit->points);
95  undo->totpoint = edit->totpoint;
96 
97  for (int i = 0; i < edit->totpoint; i++, point++) {
98  point->keys = MEM_dupallocN(point->keys);
99  /* no need to update edit key->co & key->time pointers here */
100  }
101 
102  size_t mem_used_curr = MEM_get_memory_in_use();
103 
104  undo->undo_size = mem_used_prev < mem_used_curr ? mem_used_curr - mem_used_prev :
105  sizeof(PTCacheUndo);
106 }
107 
109 {
110  ParticleSystem *psys = edit->psys;
111  ParticleData *pa;
112  HairKey *hkey;
113  POINT_P;
114  KEY_K;
115 
116  LOOP_POINTS {
117  if (psys && psys->particles[p].hair) {
118  MEM_freeN(psys->particles[p].hair);
119  }
120 
121  if (point->keys) {
122  MEM_freeN(point->keys);
123  }
124  }
125  if (psys && psys->particles) {
126  MEM_freeN(psys->particles);
127  }
128  if (edit->points) {
129  MEM_freeN(edit->points);
130  }
131  if (edit->mirror_cache) {
132  MEM_freeN(edit->mirror_cache);
133  edit->mirror_cache = NULL;
134  }
135 
136  edit->points = MEM_dupallocN(undo->points);
137  edit->totpoint = undo->totpoint;
138 
139  LOOP_POINTS {
140  point->keys = MEM_dupallocN(point->keys);
141  }
142 
143  if (psys) {
144  psys->particles = MEM_dupallocN(undo->particles);
145 
146  psys->totpart = undo->totpoint;
147 
148  LOOP_POINTS {
149  pa = psys->particles + p;
150  hkey = pa->hair = MEM_dupallocN(pa->hair);
151 
152  LOOP_KEYS {
153  key->co = hkey->co;
154  key->time = &hkey->time;
155  hkey++;
156  }
157  }
158 
159  psys->flag = undo->psys_flag;
160  }
161  else {
162  PTCacheMem *pm;
163  int i;
164 
166 
167  BLI_duplicatelist(&edit->pid.cache->mem_cache, &undo->mem_cache);
168 
169  pm = edit->pid.cache->mem_cache.first;
170 
171  for (; pm; pm = pm->next) {
172  for (i = 0; i < BPHYS_TOT_DATA; i++) {
173  pm->data[i] = MEM_dupallocN(pm->data[i]);
174  }
175  void *cur[BPHYS_TOT_DATA];
177 
178  LOOP_POINTS {
179  LOOP_KEYS {
180  if ((int)key->ftime == (int)pm->frame) {
181  key->co = cur[BPHYS_DATA_LOCATION];
182  key->vel = cur[BPHYS_DATA_VELOCITY];
183  key->rot = cur[BPHYS_DATA_ROTATION];
184  key->time = &key->ftime;
185  }
186  }
188  }
189  }
190  }
191 }
192 
194 {
195  PTCacheEditPoint *point;
196  int i;
197 
198  for (i = 0, point = undo->points; i < undo->totpoint; i++, point++) {
199  if (undo->particles && (undo->particles + i)->hair) {
200  MEM_freeN((undo->particles + i)->hair);
201  }
202  if (point->keys) {
203  MEM_freeN(point->keys);
204  }
205  }
206  if (undo->points) {
207  MEM_freeN(undo->points);
208  }
209  if (undo->particles) {
210  MEM_freeN(undo->particles);
211  }
213 }
214 
217 /* -------------------------------------------------------------------- */
221 typedef struct ParticleUndoStep {
223  UndoRefID_Scene scene_ref;
224  UndoRefID_Object object_ref;
227 
228 static bool particle_undosys_poll(struct bContext *C)
229 {
232  ViewLayer *view_layer = CTX_data_view_layer(C);
233  Object *ob = OBACT(view_layer);
235 
236  return (edit != NULL);
237 }
238 
240  struct Main *UNUSED(bmain),
241  UndoStep *us_p)
242 {
244  ParticleUndoStep *us = (ParticleUndoStep *)us_p;
245  ViewLayer *view_layer = CTX_data_view_layer(C);
246  us->scene_ref.ptr = CTX_data_scene(C);
247  us->object_ref.ptr = OBACT(view_layer);
248  PTCacheEdit *edit = PE_get_current(depsgraph, us->scene_ref.ptr, us->object_ref.ptr);
249  undoptcache_from_editcache(&us->data, edit);
250  return true;
251 }
252 
254  struct Main *UNUSED(bmain),
255  UndoStep *us_p,
256  const eUndoStepDir UNUSED(dir),
257  bool UNUSED(is_final))
258 {
260 
261  ParticleUndoStep *us = (ParticleUndoStep *)us_p;
262  Scene *scene = us->scene_ref.ptr;
263  Object *ob = us->object_ref.ptr;
264 
266 
268 
269  /* While this shouldn't happen, entering particle edit-mode uses a more complex
270  * setup compared to most other modes which we can't ensure succeeds. */
271  if (UNLIKELY(edit == NULL)) {
272  BLI_assert(0);
273  return;
274  }
275 
276  undoptcache_to_editcache(&us->data, edit);
278  if ((pset->flag & PE_DRAW_PART) != 0) {
279  psys_free_path_cache(NULL, edit);
281  }
283 
285 
287 }
288 
290 {
291  ParticleUndoStep *us = (ParticleUndoStep *)us_p;
293 }
294 
296  UndoTypeForEachIDRefFn foreach_ID_ref_fn,
297  void *user_data)
298 {
299  ParticleUndoStep *us = (ParticleUndoStep *)us_p;
300  foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->scene_ref));
301  foreach_ID_ref_fn(user_data, ((UndoRefID *)&us->object_ref));
302 }
303 
304 /* Export for ED_undo_sys. */
306 {
307  ut->name = "Edit Particle";
312 
314 
316 
317  ut->step_size = sizeof(ParticleUndoStep);
318 }
319 
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1401
void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit)
Definition: particle.c:986
void BKE_particle_batch_cache_dirty_tag(struct ParticleSystem *psys, int mode)
Definition: particle.c:5243
@ BKE_PARTICLE_BATCH_DIRTY_ALL
Definition: BKE_particle.h:620
void BKE_ptcache_mem_pointers_incr(void *cur[BPHYS_TOT_DATA])
Definition: pointcache.c:1792
void BKE_ptcache_free_mem(struct ListBase *mem_cache)
Definition: pointcache.c:3087
struct PTCacheUndo PTCacheUndo
void BKE_ptcache_mem_pointers_init(struct PTCacheMem *pm, void *cur[BPHYS_TOT_DATA])
Definition: pointcache.c:1782
eUndoStepDir
@ UNDOTYPE_FLAG_NEED_CONTEXT_FOR_ENCODE
void(* UndoTypeForEachIDRefFn)(void *user_data, struct UndoRefID *id_ref)
#define BLI_assert(a)
Definition: BLI_assert.h:58
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:51
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
#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:877
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:39
Scene scene
const Depsgraph * depsgraph
void * user_data
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
size_t(* MEM_get_memory_in_use)(void)
Definition: mallocn.c:59
void *(* MEM_dupallocN)(const void *vmemh)
Definition: mallocn.c:42
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:47
Definition: BKE_main.h:116
struct PTCacheEditKey * keys
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, const 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)