Blender  V2.93
physics_pointcache.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 <stdlib.h>
25 #include <string.h>
26 
27 #include "MEM_guardedalloc.h"
28 
29 #include "BLI_blenlib.h"
30 #include "BLI_utildefines.h"
31 
32 #include "DNA_scene_types.h"
33 
34 #include "BKE_context.h"
35 #include "BKE_global.h"
36 #include "BKE_layer.h"
37 #include "BKE_pointcache.h"
38 
39 #include "DEG_depsgraph.h"
40 
41 #include "ED_particle.h"
42 
43 #include "WM_api.h"
44 #include "WM_types.h"
45 
46 #include "RNA_access.h"
47 #include "RNA_define.h"
48 
49 #include "physics_intern.h"
50 
52 {
53  return CTX_data_scene(C) != NULL;
54 }
55 
56 static bool ptcache_poll(bContext *C)
57 {
59 
60  ID *id = ptr.owner_id;
61  PointCache *point_cache = ptr.data;
62 
63  if (id == NULL || point_cache == NULL) {
64  return false;
65  }
66 
67  if (ID_IS_OVERRIDE_LIBRARY_REAL(id) && (point_cache->flag & PTCACHE_DISK_CACHE) == false) {
69  "Library override data-blocks only support Disk Cache storage");
70  return false;
71  }
72 
73  if (ID_IS_LINKED(id) && (point_cache->flag & PTCACHE_DISK_CACHE) == false) {
74  CTX_wm_operator_poll_msg_set(C, "Linked data-blocks do not allow editing caches");
75  return false;
76  }
77 
78  return true;
79 }
80 
82 {
84 
85  ID *id = ptr.owner_id;
86  PointCache *point_cache = ptr.data;
87 
88  if (id == NULL || point_cache == NULL) {
89  return false;
90  }
91 
94  C, "Linked or library override data-blocks do not allow adding or removing caches");
95  return false;
96  }
97 
98  return true;
99 }
100 
101 typedef struct PointCacheJob {
103  void *owner;
104  short *stop, *do_update;
105  float *progress;
106 
109 
110 static void ptcache_job_free(void *customdata)
111 {
112  PointCacheJob *job = customdata;
113  MEM_freeN(job->baker);
114  MEM_freeN(job);
115 }
116 
117 static int ptcache_job_break(void *customdata)
118 {
119  PointCacheJob *job = customdata;
120 
121  if (G.is_break) {
122  return 1;
123  }
124 
125  if (job->stop && *(job->stop)) {
126  return 1;
127  }
128 
129  return 0;
130 }
131 
132 static void ptcache_job_update(void *customdata, float progress, int *cancel)
133 {
134  PointCacheJob *job = customdata;
135 
136  if (ptcache_job_break(job)) {
137  *cancel = 1;
138  }
139 
140  *(job->do_update) = true;
141  *(job->progress) = progress;
142 }
143 
144 static void ptcache_job_startjob(void *customdata, short *stop, short *do_update, float *progress)
145 {
146  PointCacheJob *job = customdata;
147 
148  job->stop = stop;
149  job->do_update = do_update;
150  job->progress = progress;
151 
152  G.is_break = false;
153 
154  /* XXX annoying hack: needed to prevent data corruption when changing
155  * scene frame in separate threads
156  */
157  WM_set_locked_interface(job->wm, true);
158 
159  BKE_ptcache_bake(job->baker);
160 
161  *do_update = true;
162  *stop = 0;
163 }
164 
165 static void ptcache_job_endjob(void *customdata)
166 {
167  PointCacheJob *job = customdata;
168  Scene *scene = job->baker->scene;
169 
170  WM_set_locked_interface(job->wm, false);
171 
174 }
175 
176 static void ptcache_free_bake(PointCache *cache)
177 {
178  if (cache->edit) {
179  if (!cache->edit->edited || 1) { // XXX okee("Lose changes done in particle mode?")) {
180  PE_free_ptcache_edit(cache->edit);
181  cache->edit = NULL;
182  cache->flag &= ~PTCACHE_BAKED;
183  }
184  }
185  else {
186  cache->flag &= ~PTCACHE_BAKED;
187  }
188 }
189 
191 {
192  PTCacheBaker *baker = MEM_callocN(sizeof(PTCacheBaker), "PTCacheBaker");
193 
194  baker->bmain = CTX_data_main(C);
195  baker->scene = CTX_data_scene(C);
196  baker->view_layer = CTX_data_view_layer(C);
197  /* Depsgraph is used to sweep the frame range and evaluate scene at different times. */
199  baker->bake = RNA_boolean_get(op->ptr, "bake");
200  baker->render = 0;
201  baker->anim_init = 0;
202  baker->quick_step = 1;
203 
204  if (!all) {
206  Object *ob = (Object *)ptr.owner_id;
207  PointCache *cache = ptr.data;
208  baker->pid = BKE_ptcache_id_find(ob, baker->scene, cache);
209  }
210 
211  return baker;
212 }
213 
215 {
216  bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
217 
218  PTCacheBaker *baker = ptcache_baker_create(C, op, all);
219  BKE_ptcache_bake(baker);
220  MEM_freeN(baker);
221 
222  return OPERATOR_FINISHED;
223 }
224 
225 static int ptcache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
226 {
227  bool all = STREQ(op->type->idname, "PTCACHE_OT_bake_all");
228 
229  PointCacheJob *job = MEM_mallocN(sizeof(PointCacheJob), "PointCacheJob");
230  job->wm = CTX_wm_manager(C);
231  job->baker = ptcache_baker_create(C, op, all);
232  job->baker->bake_job = job;
234 
235  wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
236  CTX_wm_window(C),
237  CTX_data_scene(C),
238  "Point Cache",
241 
245 
247 
248  WM_jobs_start(CTX_wm_manager(C), wm_job);
249 
251 
252  /* we must run modal until the bake job is done, otherwise the undo push
253  * happens before the job ends, which can lead to race conditions between
254  * the baking and file writing code */
255  return OPERATOR_RUNNING_MODAL;
256 }
257 
258 static int ptcache_bake_modal(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
259 {
260  Scene *scene = (Scene *)op->customdata;
261 
262  /* no running blender, remove handler and pass through */
265  }
266 
267  return OPERATOR_PASS_THROUGH;
268 }
269 
271 {
273  Scene *scene = (Scene *)op->customdata;
274 
275  /* kill on cancel, because job is using op->reports */
277 }
278 
280 {
282  PTCacheID *pid;
283  ListBase pidlist;
284 
287 
288  for (pid = pidlist.first; pid; pid = pid->next) {
289  ptcache_free_bake(pid->cache);
290  }
291 
292  BLI_freelistN(&pidlist);
293 
295  }
297 
299 
300  return OPERATOR_FINISHED;
301 }
302 
304 {
305  /* identifiers */
306  ot->name = "Bake All Physics";
307  ot->description = "Bake all physics";
308  ot->idname = "PTCACHE_OT_bake_all";
309 
310  /* api callbacks */
316 
317  /* flags */
319 
320  RNA_def_boolean(ot->srna, "bake", 1, "Bake", "");
321 }
323 {
324  /* identifiers */
325  ot->name = "Delete All Physics Bakes";
326  ot->idname = "PTCACHE_OT_free_bake_all";
327  ot->description = "Delete all baked caches of all objects in the current scene";
328 
329  /* api callbacks */
332 
333  /* flags */
335 }
336 
338 {
340  PointCache *cache = ptr.data;
341  Object *ob = (Object *)ptr.owner_id;
342 
343  ptcache_free_bake(cache);
344 
346 
347  return OPERATOR_FINISHED;
348 }
350 {
352  PointCache *cache = ptr.data;
353  Object *ob = (Object *)ptr.owner_id;
354 
355  cache->flag |= PTCACHE_BAKED;
356 
358 
359  return OPERATOR_FINISHED;
360 }
362 {
363  /* identifiers */
364  ot->name = "Bake Physics";
365  ot->description = "Bake physics";
366  ot->idname = "PTCACHE_OT_bake";
367 
368  /* api callbacks */
373  ot->poll = ptcache_poll;
374 
375  /* flags */
377 
378  RNA_def_boolean(ot->srna, "bake", 0, "Bake", "");
379 }
381 {
382  /* identifiers */
383  ot->name = "Delete Physics Bake";
384  ot->description = "Delete physics bake";
385  ot->idname = "PTCACHE_OT_free_bake";
386 
387  /* api callbacks */
389  ot->poll = ptcache_poll;
390 
391  /* flags */
393 }
395 {
396  /* identifiers */
397  ot->name = "Bake from Cache";
398  ot->description = "Bake from cache";
399  ot->idname = "PTCACHE_OT_bake_from_cache";
400 
401  /* api callbacks */
403  ot->poll = ptcache_poll;
404 
405  /* flags */
407 }
408 
410 {
413  Object *ob = (Object *)ptr.owner_id;
414  PointCache *cache = ptr.data;
415  PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
416 
417  if (pid.cache) {
418  PointCache *cache_new = BKE_ptcache_add(pid.ptcaches);
419  cache_new->step = pid.default_step;
420  *(pid.cache_ptr) = cache_new;
421 
425  }
426 
427  return OPERATOR_FINISHED;
428 }
430 {
433  Object *ob = (Object *)ptr.owner_id;
434  PointCache *cache = ptr.data;
435  PTCacheID pid = BKE_ptcache_id_find(ob, scene, cache);
436 
437  /* don't delete last cache */
438  if (pid.cache && pid.ptcaches->first != pid.ptcaches->last) {
439  BLI_remlink(pid.ptcaches, pid.cache);
440  BKE_ptcache_free(pid.cache);
441  *(pid.cache_ptr) = pid.ptcaches->first;
442 
445  }
446 
447  return OPERATOR_FINISHED;
448 }
450 {
451  /* identifiers */
452  ot->name = "Add New Cache";
453  ot->description = "Add new cache";
454  ot->idname = "PTCACHE_OT_add";
455 
456  /* api callbacks */
459 
460  /* flags */
462 }
464 {
465  /* identifiers */
466  ot->name = "Delete Current Cache";
467  ot->description = "Delete current cache";
468  ot->idname = "PTCACHE_OT_remove";
469 
470  /* api callbacks */
473 
474  /* flags */
476 }
#define FOREACH_SCENE_OBJECT_END
#define FOREACH_SCENE_OBJECT_BEGIN(scene, _instance)
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
PointerRNA CTX_data_pointer_get_type(const bContext *C, const char *member, StructRNA *type)
Definition: context.c:456
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 CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg)
Definition: context.c:1006
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis)
Definition: pointcache.c:1278
void BKE_ptcache_bake(struct PTCacheBaker *baker)
Definition: pointcache.c:3215
struct PointCache * BKE_ptcache_add(struct ListBase *ptcaches)
Definition: pointcache.c:3072
PTCacheID BKE_ptcache_id_find(struct Object *ob, struct Scene *scene, struct PointCache *cache)
Definition: pointcache.c:1120
void BKE_ptcache_free(struct PointCache *cache)
Definition: pointcache.c:3099
void void BLI_freelistN(struct ListBase *listbase) ATTR_NONNULL(1)
Definition: listbase.c:547
void BLI_remlink(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:133
#define UNUSED(x)
#define STREQ(a, b)
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ ID_RECALC_POINT_CACHE
Definition: DNA_ID.h:642
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition: DNA_ID.h:438
#define ID_IS_LINKED(_id)
Definition: DNA_ID.h:426
#define MAX_DUPLI_RECUR
#define PTCACHE_DISK_CACHE
#define PTCACHE_BAKED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
void PE_free_ptcache_edit(struct PTCacheEdit *edit)
Read Guarded memory(de)allocation.
StructRNA RNA_PointCache
#define C
Definition: RandGen.cpp:39
@ WM_JOB_TYPE_POINTCACHE
Definition: WM_api.h:749
@ WM_JOB_PROGRESS
Definition: WM_api.h:726
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define NC_SCENE
Definition: WM_types.h:279
#define ND_FRAME
Definition: WM_types.h:334
#define ND_POINTCACHE
Definition: WM_types.h:367
#define NC_OBJECT
Definition: WM_types.h:280
Scene scene
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:45
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
static void ptcache_bake_cancel(bContext *C, wmOperator *op)
struct PointCacheJob PointCacheJob
static void ptcache_job_free(void *customdata)
static int ptcache_free_bake_exec(bContext *C, wmOperator *UNUSED(op))
static int ptcache_add_new_exec(bContext *C, wmOperator *UNUSED(op))
static int ptcache_bake_modal(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
static void ptcache_free_bake(PointCache *cache)
static bool ptcache_add_remove_poll(bContext *C)
static int ptcache_job_break(void *customdata)
static bool ptcache_bake_all_poll(bContext *C)
static int ptcache_bake_exec(bContext *C, wmOperator *op)
static int ptcache_bake_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
void PTCACHE_OT_bake(wmOperatorType *ot)
void PTCACHE_OT_free_bake_all(wmOperatorType *ot)
static int ptcache_remove_exec(bContext *C, wmOperator *UNUSED(op))
static bool ptcache_poll(bContext *C)
void PTCACHE_OT_add(wmOperatorType *ot)
static int ptcache_free_bake_all_exec(bContext *C, wmOperator *UNUSED(op))
static PTCacheBaker * ptcache_baker_create(bContext *C, wmOperator *op, bool all)
static void ptcache_job_endjob(void *customdata)
static int ptcache_bake_from_cache_exec(bContext *C, wmOperator *UNUSED(op))
void PTCACHE_OT_remove(wmOperatorType *ot)
void PTCACHE_OT_bake_from_cache(wmOperatorType *ot)
void PTCACHE_OT_bake_all(wmOperatorType *ot)
static void ptcache_job_startjob(void *customdata, short *stop, short *do_update, float *progress)
void PTCACHE_OT_free_bake(wmOperatorType *ot)
static void ptcache_job_update(void *customdata, float progress, int *cancel)
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
Definition: DNA_ID.h:273
void * first
Definition: DNA_listBase.h:47
struct PTCacheID pid
struct Scene * scene
struct Main * bmain
void(* update_progress)(void *data, float progress, int *cancel)
struct Depsgraph * depsgraph
struct ViewLayer * view_layer
struct ID * owner_id
struct PTCacheID * next
struct PointCache * cache
PTCacheBaker * baker
wmWindowManager * wm
struct PTCacheEdit * edit
void * data
Definition: RNA_types.h:52
struct ID * owner_id
Definition: RNA_types.h:50
Definition: wm_jobs.c:73
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:768
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
void(* cancel)(struct bContext *, struct wmOperator *)
Definition: WM_types.h:760
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
struct wmOperatorType * type
struct PointerRNA * ptr
__forceinline bool all(const avxb &b)
Definition: util_avxb.h:214
#define G(x, y, z)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_set_locked_interface(wmWindowManager *wm, bool lock)
PointerRNA * ptr
Definition: wm_files.c:3157
wmOperatorType * ot
Definition: wm_files.c:3156
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition: wm_jobs.c:450
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, void *owner, const char *name, int flag, int job_type)
Definition: wm_jobs.c:196
bool WM_jobs_test(wmWindowManager *wm, void *owner, int job_type)
Definition: wm_jobs.c:223
void WM_jobs_callbacks(wmJob *wm_job, wm_jobs_start_callback startjob, void(*initjob)(void *), void(*update)(void *), void(*endjob)(void *))
Definition: wm_jobs.c:372
void WM_jobs_kill_type(struct wmWindowManager *wm, void *owner, int job_type)
Definition: wm_jobs.c:572
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *))
Definition: wm_jobs.c:344
void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned int endnote)
Definition: wm_jobs.c:360