Blender  V3.3
physics_fluid.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright Blender Foundation. All rights reserved. */
3 
8 #include <math.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/stat.h>
12 
13 #include "MEM_guardedalloc.h"
14 
15 /* types */
16 #include "DNA_action_types.h"
17 #include "DNA_object_types.h"
18 
19 #include "BLI_blenlib.h"
20 #include "BLI_path_util.h"
21 #include "BLI_utildefines.h"
22 
23 #include "BLT_translation.h"
24 
25 #include "BKE_context.h"
26 #include "BKE_fluid.h"
27 #include "BKE_global.h"
28 #include "BKE_main.h"
29 #include "BKE_modifier.h"
30 #include "BKE_report.h"
31 #include "BKE_screen.h"
32 
33 #include "DEG_depsgraph.h"
34 
35 #include "ED_object.h"
36 #include "ED_screen.h"
37 #include "PIL_time.h"
38 
39 #include "WM_api.h"
40 #include "WM_types.h"
41 
42 #include "physics_intern.h" /* own include */
43 
44 #include "DNA_fluid_types.h"
45 #include "DNA_scene_types.h"
46 
47 #define FLUID_JOB_BAKE_ALL "FLUID_OT_bake_all"
48 #define FLUID_JOB_BAKE_DATA "FLUID_OT_bake_data"
49 #define FLUID_JOB_BAKE_NOISE "FLUID_OT_bake_noise"
50 #define FLUID_JOB_BAKE_MESH "FLUID_OT_bake_mesh"
51 #define FLUID_JOB_BAKE_PARTICLES "FLUID_OT_bake_particles"
52 #define FLUID_JOB_BAKE_GUIDES "FLUID_OT_bake_guides"
53 #define FLUID_JOB_FREE_ALL "FLUID_OT_free_all"
54 #define FLUID_JOB_FREE_DATA "FLUID_OT_free_data"
55 #define FLUID_JOB_FREE_NOISE "FLUID_OT_free_noise"
56 #define FLUID_JOB_FREE_MESH "FLUID_OT_free_mesh"
57 #define FLUID_JOB_FREE_PARTICLES "FLUID_OT_free_particles"
58 #define FLUID_JOB_FREE_GUIDES "FLUID_OT_free_guides"
59 #define FLUID_JOB_BAKE_PAUSE "FLUID_OT_pause_bake"
60 
61 typedef struct FluidJob {
62  /* from wmJob */
63  void *owner;
64  short *stop, *do_update;
65  float *progress;
66  const char *type;
67  const char *name;
68 
69  struct Main *bmain;
73 
75 
76  int success;
77  double start;
78 
81 
82 static inline bool fluid_is_bake_all(FluidJob *job)
83 {
84  return (STREQ(job->type, FLUID_JOB_BAKE_ALL));
85 }
86 static inline bool fluid_is_bake_data(FluidJob *job)
87 {
88  return (STREQ(job->type, FLUID_JOB_BAKE_DATA));
89 }
90 static inline bool fluid_is_bake_noise(FluidJob *job)
91 {
92  return (STREQ(job->type, FLUID_JOB_BAKE_NOISE));
93 }
94 static inline bool fluid_is_bake_mesh(FluidJob *job)
95 {
96  return (STREQ(job->type, FLUID_JOB_BAKE_MESH));
97 }
98 static inline bool fluid_is_bake_particle(FluidJob *job)
99 {
100  return (STREQ(job->type, FLUID_JOB_BAKE_PARTICLES));
101 }
102 static inline bool fluid_is_bake_guiding(FluidJob *job)
103 {
104  return (STREQ(job->type, FLUID_JOB_BAKE_GUIDES));
105 }
106 static inline bool fluid_is_free_all(FluidJob *job)
107 {
108  return (STREQ(job->type, FLUID_JOB_FREE_ALL));
109 }
110 static inline bool fluid_is_free_data(FluidJob *job)
111 {
112  return (STREQ(job->type, FLUID_JOB_FREE_DATA));
113 }
114 static inline bool fluid_is_free_noise(FluidJob *job)
115 {
116  return (STREQ(job->type, FLUID_JOB_FREE_NOISE));
117 }
118 static inline bool fluid_is_free_mesh(FluidJob *job)
119 {
120  return (STREQ(job->type, FLUID_JOB_FREE_MESH));
121 }
122 static inline bool fluid_is_free_particles(FluidJob *job)
123 {
124  return (STREQ(job->type, FLUID_JOB_FREE_PARTICLES));
125 }
126 static inline bool fluid_is_free_guiding(FluidJob *job)
127 {
128  return (STREQ(job->type, FLUID_JOB_FREE_GUIDES));
129 }
130 
131 static bool fluid_initjob(
132  bContext *C, FluidJob *job, wmOperator *op, char *error_msg, int error_size)
133 {
134  FluidModifierData *fmd = NULL;
135  FluidDomainSettings *fds;
137 
139  if (!fmd) {
140  BLI_strncpy(error_msg, N_("Bake failed: no Fluid modifier found"), error_size);
141  return false;
142  }
143  fds = fmd->domain;
144  if (!fds) {
145  BLI_strncpy(error_msg, N_("Bake failed: invalid domain"), error_size);
146  return false;
147  }
148 
149  job->bmain = CTX_data_main(C);
150  job->scene = CTX_data_scene(C);
152  job->ob = ob;
153  job->fmd = fmd;
154  job->type = op->type->idname;
155  job->name = op->type->name;
156 
157  return true;
158 }
159 
160 static bool fluid_validatepaths(FluidJob *job, ReportList *reports)
161 {
162  FluidDomainSettings *fds = job->fmd->domain;
163  char temp_dir[FILE_MAX];
164  temp_dir[0] = '\0';
165  bool is_relative = false;
166 
167  const char *relbase = BKE_modifier_path_relbase(job->bmain, job->ob);
168 
169  /* We do not accept empty paths, they can end in random places silently, see T51176. */
170  if (fds->cache_directory[0] == '\0') {
171  char cache_name[64];
172  BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name);
173  BKE_modifier_path_init(fds->cache_directory, sizeof(fds->cache_directory), cache_name);
174  BKE_reportf(reports,
175  RPT_WARNING,
176  "Fluid: Empty cache path, reset to default '%s'",
177  fds->cache_directory);
178  }
179 
180  BLI_strncpy(temp_dir, fds->cache_directory, FILE_MAXDIR);
181  is_relative = BLI_path_abs(temp_dir, relbase);
182 
183  /* Ensure whole path exists */
184  const bool dir_exists = BLI_dir_create_recursive(temp_dir);
185 
186  /* We change path to some presumably valid default value, but do not allow bake process to
187  * continue, this gives user chance to set manually another path. */
188  if (!dir_exists) {
189  char cache_name[64];
190  BKE_fluid_cache_new_name_for_current_session(sizeof(cache_name), cache_name);
191  BKE_modifier_path_init(fds->cache_directory, sizeof(fds->cache_directory), cache_name);
192 
193  BKE_reportf(reports,
194  RPT_ERROR,
195  "Fluid: Could not create cache directory '%s', reset to default '%s'",
196  temp_dir,
197  fds->cache_directory);
198 
199  /* Ensure whole path exists and is writable. */
200  if (!BLI_dir_create_recursive(temp_dir)) {
201  BKE_reportf(reports,
202  RPT_ERROR,
203  "Fluid: Could not use default cache directory '%s', "
204  "please define a valid cache path manually",
205  temp_dir);
206  return false;
207  }
208  /* Copy final dir back into domain settings */
209  BLI_strncpy(fds->cache_directory, temp_dir, FILE_MAXDIR);
210 
211  return false;
212  }
213 
214  /* Change path back to is original state (ie relative or absolute). */
215  if (is_relative) {
216  BLI_path_rel(temp_dir, relbase);
217  }
218 
219  /* Copy final dir back into domain settings */
220  BLI_strncpy(fds->cache_directory, temp_dir, FILE_MAXDIR);
221  return true;
222 }
223 
224 static void fluid_bake_free(void *customdata)
225 {
226  FluidJob *job = customdata;
227  MEM_freeN(job);
228 }
229 
230 static void fluid_bake_sequence(FluidJob *job)
231 {
232  FluidDomainSettings *fds = job->fmd->domain;
233  Scene *scene = job->scene;
234  int frame = 1, orig_frame;
235  int frames;
236  int *pause_frame = NULL;
237  bool is_first_frame;
238 
239  frames = fds->cache_frame_end - fds->cache_frame_start + 1;
240 
241  if (frames <= 0) {
242  BLI_strncpy(fds->error, N_("No frames to bake"), sizeof(fds->error));
243  return;
244  }
245 
246  /* Show progress bar. */
247  if (job->do_update) {
248  *(job->do_update) = true;
249  }
250 
251  /* Get current pause frame (pointer) - depending on bake type. */
252  pause_frame = job->pause_frame;
253 
254  /* Set frame to start point (depending on current pause frame value). */
255  is_first_frame = ((*pause_frame) == 0);
256  frame = is_first_frame ? fds->cache_frame_start : (*pause_frame);
257 
258  /* Save orig frame and update scene frame. */
259  orig_frame = scene->r.cfra;
260  scene->r.cfra = frame;
261 
262  /* Loop through selected frames. */
263  for (; frame <= fds->cache_frame_end; frame++) {
264  const float progress = (frame - fds->cache_frame_start) / (float)frames;
265 
266  /* Keep track of pause frame - needed to init future loop. */
267  (*pause_frame) = frame;
268 
269  /* If user requested stop, quit baking. */
270  if (G.is_break) {
271  job->success = 0;
272  return;
273  }
274 
275  /* Update progress bar. */
276  if (job->do_update) {
277  *(job->do_update) = true;
278  }
279  if (job->progress) {
280  *(job->progress) = progress;
281  }
282 
283  scene->r.cfra = frame;
284 
285  /* Update animation system. */
287 
288  /* If user requested stop, quit baking. */
289  if (G.is_break) {
290  job->success = 0;
291  return;
292  }
293  }
294 
295  /* Restore frame position that we were on before bake. */
296  scene->r.cfra = orig_frame;
297 }
298 
299 static void fluid_bake_endjob(void *customdata)
300 {
301  FluidJob *job = customdata;
302  FluidDomainSettings *fds = job->fmd->domain;
303 
304  if (fluid_is_bake_noise(job) || fluid_is_bake_all(job)) {
308  }
309  if (fluid_is_bake_mesh(job) || fluid_is_bake_all(job)) {
313  }
314  if (fluid_is_bake_particle(job) || fluid_is_bake_all(job)) {
318  }
319  if (fluid_is_bake_guiding(job) || fluid_is_bake_all(job)) {
323  }
324  if (fluid_is_bake_data(job) || fluid_is_bake_all(job)) {
328  }
330 
331  G.is_rendering = false;
333  WM_set_locked_interface(G_MAIN->wm.first, false);
334 
335  /* Bake was successful:
336  * Report for ended bake and how long it took. */
337  if (job->success) {
338  /* Show bake info. */
339  WM_reportf(
340  RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start);
341  }
342  else {
343  if (fds->error[0] != '\0') {
344  WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, fds->error);
345  }
346  else { /* User canceled the bake. */
347  WM_reportf(RPT_WARNING, "Fluid: %s canceled!", job->name);
348  }
349  }
350 }
351 
352 static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
353 {
354  FluidJob *job = customdata;
355  FluidDomainSettings *fds = job->fmd->domain;
356 
357  char temp_dir[FILE_MAX];
358  const char *relbase = BKE_modifier_path_relbase_from_global(job->ob);
359 
360  job->stop = stop;
361  job->do_update = do_update;
362  job->progress = progress;
364  job->success = 1;
365 
366  G.is_break = false;
367  G.is_rendering = true;
369 
370  if (fluid_is_bake_noise(job) || fluid_is_bake_all(job)) {
371  BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_NOISE, NULL);
372  BLI_path_abs(temp_dir, relbase);
373  BLI_dir_create_recursive(temp_dir); /* Create 'noise' subdir if it does not exist already */
377  }
378  if (fluid_is_bake_mesh(job) || fluid_is_bake_all(job)) {
379  BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_MESH, NULL);
380  BLI_path_abs(temp_dir, relbase);
381  BLI_dir_create_recursive(temp_dir); /* Create 'mesh' subdir if it does not exist already */
384  job->pause_frame = &fds->cache_frame_pause_mesh;
385  }
386  if (fluid_is_bake_particle(job) || fluid_is_bake_all(job)) {
388  temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_PARTICLES, NULL);
389  BLI_path_abs(temp_dir, relbase);
390 
391  /* Create 'particles' subdir if it does not exist already */
392  BLI_dir_create_recursive(temp_dir);
393 
397  }
398  if (fluid_is_bake_guiding(job) || fluid_is_bake_all(job)) {
399  BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_GUIDE, NULL);
400  BLI_path_abs(temp_dir, relbase);
401  BLI_dir_create_recursive(temp_dir); /* Create 'guiding' subdir if it does not exist already */
405  }
406  if (fluid_is_bake_data(job) || fluid_is_bake_all(job)) {
407  BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_CONFIG, NULL);
408  BLI_path_abs(temp_dir, relbase);
409  BLI_dir_create_recursive(temp_dir); /* Create 'config' subdir if it does not exist already */
410 
411  BLI_path_join(temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_DATA, NULL);
412  BLI_path_abs(temp_dir, relbase);
413  BLI_dir_create_recursive(temp_dir); /* Create 'data' subdir if it does not exist already */
416  job->pause_frame = &fds->cache_frame_pause_data;
417 
420  temp_dir, sizeof(temp_dir), fds->cache_directory, FLUID_DOMAIN_DIR_SCRIPT, NULL);
421  BLI_path_abs(temp_dir, relbase);
422  BLI_dir_create_recursive(temp_dir); /* Create 'script' subdir if it does not exist already */
423  }
424  }
426 
427  fluid_bake_sequence(job);
428 
429  if (do_update) {
430  *do_update = true;
431  }
432  if (stop) {
433  *stop = 0;
434  }
435 }
436 
437 static void fluid_free_endjob(void *customdata)
438 {
439  FluidJob *job = customdata;
440  FluidDomainSettings *fds = job->fmd->domain;
441 
442  G.is_rendering = false;
444  WM_set_locked_interface(G_MAIN->wm.first, false);
445 
446  /* Reflect the now empty cache in the viewport too. */
448 
449  /* Free was successful:
450  * Report for ended free job and how long it took */
451  if (job->success) {
452  /* Show free job info */
453  WM_reportf(
454  RPT_INFO, "Fluid: %s complete! (%.2f)", job->name, PIL_check_seconds_timer() - job->start);
455  }
456  else {
457  if (fds->error[0] != '\0') {
458  WM_reportf(RPT_ERROR, "Fluid: %s failed: %s", job->name, fds->error);
459  }
460  else { /* User canceled the free job */
461  WM_reportf(RPT_WARNING, "Fluid: %s canceled!", job->name);
462  }
463  }
464 }
465 
466 static void fluid_free_startjob(void *customdata, short *stop, short *do_update, float *progress)
467 {
468  FluidJob *job = customdata;
469  FluidDomainSettings *fds = job->fmd->domain;
470 
471  job->stop = stop;
472  job->do_update = do_update;
473  job->progress = progress;
475  job->success = 1;
476 
477  G.is_break = false;
478  G.is_rendering = true;
480 
481  int cache_map = 0;
482 
483  if (fluid_is_free_data(job) || fluid_is_free_all(job)) {
486  }
487  if (fluid_is_free_noise(job) || fluid_is_free_all(job)) {
488  cache_map |= FLUID_DOMAIN_OUTDATED_NOISE;
489  }
490  if (fluid_is_free_mesh(job) || fluid_is_free_all(job)) {
491  cache_map |= FLUID_DOMAIN_OUTDATED_MESH;
492  }
493  if (fluid_is_free_particles(job) || fluid_is_free_all(job)) {
494  cache_map |= FLUID_DOMAIN_OUTDATED_PARTICLES;
495  }
496  if (fluid_is_free_guiding(job) || fluid_is_free_all(job)) {
500  }
501 #ifdef WITH_FLUID
502  BKE_fluid_cache_free(fds, job->ob, cache_map);
503 #else
504  UNUSED_VARS(fds);
505 #endif
506 
507  *do_update = true;
508  *stop = 0;
509 
510  /* Update scene so that viewport shows freed up scene */
512 }
513 
514 /***************************** Operators ******************************/
515 
516 static int fluid_bake_exec(struct bContext *C, struct wmOperator *op)
517 {
518  FluidJob *job = MEM_mallocN(sizeof(FluidJob), "FluidJob");
519  char error_msg[256] = "\0";
520 
521  if (!fluid_initjob(C, job, op, error_msg, sizeof(error_msg))) {
522  if (error_msg[0]) {
523  BKE_report(op->reports, RPT_ERROR, error_msg);
524  }
525  fluid_bake_free(job);
526  return OPERATOR_CANCELLED;
527  }
528  if (!fluid_validatepaths(job, op->reports)) {
529  fluid_bake_free(job);
530  return OPERATOR_CANCELLED;
531  }
533 
535  fluid_bake_endjob(job);
536  fluid_bake_free(job);
537 
538  return OPERATOR_FINISHED;
539 }
540 
541 static int fluid_bake_invoke(struct bContext *C,
542  struct wmOperator *op,
543  const wmEvent *UNUSED(_event))
544 {
546  FluidJob *job = MEM_mallocN(sizeof(FluidJob), "FluidJob");
547  char error_msg[256] = "\0";
548 
549  if (!fluid_initjob(C, job, op, error_msg, sizeof(error_msg))) {
550  if (error_msg[0]) {
551  BKE_report(op->reports, RPT_ERROR, error_msg);
552  }
553  fluid_bake_free(job);
554  return OPERATOR_CANCELLED;
555  }
556 
557  if (!fluid_validatepaths(job, op->reports)) {
558  fluid_bake_free(job);
559  return OPERATOR_CANCELLED;
560  }
561 
562  /* Clear existing banners so that the upcoming progress bar from this job has more room. */
564 
565  wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
566  CTX_wm_window(C),
567  scene,
568  "Fluid Bake",
571 
575 
577 
578  WM_jobs_start(CTX_wm_manager(C), wm_job);
580 
581  return OPERATOR_RUNNING_MODAL;
582 }
583 
584 static int fluid_bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
585 {
586  /* no running blender, remove handler and pass through */
589  }
590 
591  switch (event->type) {
592  case EVT_ESCKEY:
593  return OPERATOR_RUNNING_MODAL;
594  }
595  return OPERATOR_PASS_THROUGH;
596 }
597 
598 static int fluid_free_exec(struct bContext *C, struct wmOperator *op)
599 {
600  FluidModifierData *fmd = NULL;
601  FluidDomainSettings *fds;
604 
605  /*
606  * Get modifier data
607  */
609  if (!fmd) {
610  BKE_report(op->reports, RPT_ERROR, "Bake free failed: no Fluid modifier found");
611  return OPERATOR_CANCELLED;
612  }
613  fds = fmd->domain;
614  if (!fds) {
615  BKE_report(op->reports, RPT_ERROR, "Bake free failed: invalid domain");
616  return OPERATOR_CANCELLED;
617  }
618 
619  /* Cannot free data if other bakes currently working */
622  BKE_report(op->reports, RPT_ERROR, "Bake free failed: pending bake jobs found");
623  return OPERATOR_CANCELLED;
624  }
625 
626  FluidJob *job = MEM_mallocN(sizeof(FluidJob), "FluidJob");
627  job->bmain = CTX_data_main(C);
628  job->scene = scene;
630  job->ob = ob;
631  job->fmd = fmd;
632  job->type = op->type->idname;
633  job->name = op->type->name;
634 
635  if (!fluid_validatepaths(job, op->reports)) {
636  fluid_bake_free(job);
637  return OPERATOR_CANCELLED;
638  }
639 
640  /* Clear existing banners so that the upcoming progress bar from this job has more room. */
642 
643  wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
644  CTX_wm_window(C),
645  scene,
646  "Fluid Free",
649 
653 
655 
656  /* Free Fluid Geometry */
657  WM_jobs_start(CTX_wm_manager(C), wm_job);
658 
659  return OPERATOR_FINISHED;
660 }
661 
662 static int fluid_pause_exec(struct bContext *C, struct wmOperator *op)
663 {
664  FluidModifierData *fmd = NULL;
665  FluidDomainSettings *fds;
667 
668  /*
669  * Get modifier data
670  */
672  if (!fmd) {
673  BKE_report(op->reports, RPT_ERROR, "Bake free failed: no Fluid modifier found");
674  return OPERATOR_CANCELLED;
675  }
676  fds = fmd->domain;
677  if (!fds) {
678  BKE_report(op->reports, RPT_ERROR, "Bake free failed: invalid domain");
679  return OPERATOR_CANCELLED;
680  }
681 
682  G.is_break = true;
683 
684  return OPERATOR_FINISHED;
685 }
686 
688 {
689  /* identifiers */
690  ot->name = "Bake All";
691  ot->description = "Bake Entire Fluid Simulation";
693 
694  /* api callbacks */
699 }
700 
702 {
703  /* identifiers */
704  ot->name = "Free All";
705  ot->description = "Free Entire Fluid Simulation";
707 
708  /* api callbacks */
711 }
712 
714 {
715  /* identifiers */
716  ot->name = "Bake Data";
717  ot->description = "Bake Fluid Data";
719 
720  /* api callbacks */
725 }
726 
728 {
729  /* identifiers */
730  ot->name = "Free Data";
731  ot->description = "Free Fluid Data";
733 
734  /* api callbacks */
737 }
738 
740 {
741  /* identifiers */
742  ot->name = "Bake Noise";
743  ot->description = "Bake Fluid Noise";
745 
746  /* api callbacks */
751 }
752 
754 {
755  /* identifiers */
756  ot->name = "Free Noise";
757  ot->description = "Free Fluid Noise";
759 
760  /* api callbacks */
763 }
764 
766 {
767  /* identifiers */
768  ot->name = "Bake Mesh";
769  ot->description = "Bake Fluid Mesh";
771 
772  /* api callbacks */
777 }
778 
780 {
781  /* identifiers */
782  ot->name = "Free Mesh";
783  ot->description = "Free Fluid Mesh";
785 
786  /* api callbacks */
789 }
790 
792 {
793  /* identifiers */
794  ot->name = "Bake Particles";
795  ot->description = "Bake Fluid Particles";
797 
798  /* api callbacks */
803 }
804 
806 {
807  /* identifiers */
808  ot->name = "Free Particles";
809  ot->description = "Free Fluid Particles";
811 
812  /* api callbacks */
815 }
816 
818 {
819  /* identifiers */
820  ot->name = "Bake Guides";
821  ot->description = "Bake Fluid Guiding";
823 
824  /* api callbacks */
829 }
830 
832 {
833  /* identifiers */
834  ot->name = "Free Guides";
835  ot->description = "Free Fluid Guiding";
837 
838  /* api callbacks */
841 }
842 
844 {
845  /* identifiers */
846  ot->name = "Pause Bake";
847  ot->description = "Pause Bake";
849 
850  /* api callbacks */
853 }
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:713
struct Depsgraph * CTX_data_depsgraph_pointer(const bContext *C)
Definition: context.c:1505
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
void BKE_fluid_cache_new_name_for_current_session(int maxlen, char *r_name)
Definition: fluid.c:5110
void BKE_fluid_cache_free(struct FluidDomainSettings *fds, struct Object *ob, int cache_map)
#define G_MAIN
Definition: BKE_global.h:267
void BKE_modifier_path_init(char *path, int path_maxlen, const char *name)
const char * BKE_modifier_path_relbase_from_global(struct Object *ob)
const char * BKE_modifier_path_relbase(struct Main *bmain, struct Object *ob)
struct ModifierData * BKE_modifiers_findby_type(const struct Object *ob, ModifierType type)
void BKE_reportf(ReportList *reports, eReportType type, const char *format,...) ATTR_PRINTF_FORMAT(3
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
void BKE_spacedata_draw_locks(bool set)
Definition: screen.c:516
bool BLI_dir_create_recursive(const char *dir) ATTR_NONNULL()
Definition: fileops.c:1219
#define FILE_MAX
size_t BLI_path_join(char *__restrict dst, size_t dst_len, const char *path_first,...) ATTR_NONNULL(1
void BLI_path_rel(char *file, const char *relfile) ATTR_NONNULL()
Definition: path_util.c:450
#define FILE_MAXDIR
bool BLI_path_abs(char *path, const char *basepath) ATTR_NONNULL()
Definition: path_util.c:897
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define UNUSED_VARS(...)
#define UNUSED(x)
#define STREQ(a, b)
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 FLUID_DOMAIN_DIR_DATA
#define FLUID_DOMAIN_DIR_PARTICLES
#define FLUID_DOMAIN_DIR_MESH
#define FLUID_DOMAIN_DIR_GUIDE
#define FLUID_DOMAIN_DIR_SCRIPT
@ FLUID_DOMAIN_EXPORT_MANTA_SCRIPT
#define FLUID_DOMAIN_DIR_CONFIG
@ FLUID_DOMAIN_BAKED_DATA
@ FLUID_DOMAIN_OUTDATED_GUIDE
@ FLUID_DOMAIN_OUTDATED_PARTICLES
@ FLUID_DOMAIN_BAKING_MESH
@ FLUID_DOMAIN_BAKING_NOISE
@ FLUID_DOMAIN_BAKING_GUIDE
@ FLUID_DOMAIN_OUTDATED_NOISE
@ FLUID_DOMAIN_BAKED_NOISE
@ FLUID_DOMAIN_BAKED_MESH
@ FLUID_DOMAIN_OUTDATED_MESH
@ FLUID_DOMAIN_BAKING_DATA
@ FLUID_DOMAIN_BAKED_GUIDE
@ FLUID_DOMAIN_BAKED_PARTICLES
@ FLUID_DOMAIN_OUTDATED_DATA
@ FLUID_DOMAIN_BAKING_PARTICLES
#define FLUID_DOMAIN_DIR_NOISE
@ eModifierType_Fluid
Object is a sort of wrapper for general info.
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_RUNNING_MODAL
@ OPERATOR_PASS_THROUGH
struct Object * ED_object_active_context(const struct bContext *C)
bool ED_operator_object_active_editable(struct bContext *C)
Definition: screen_ops.c:396
void ED_update_for_newframe(struct Main *bmain, struct Depsgraph *depsgraph)
Definition: screen_edit.c:1694
Read Guarded memory(de)allocation.
Platform independent time functions.
#define C
Definition: RandGen.cpp:25
@ WM_JOB_PROGRESS
Definition: WM_api.h:1339
@ WM_JOB_TYPE_OBJECT_SIM_FLUID
Definition: WM_api.h:1354
#define ND_MODIFIER
Definition: WM_types.h:411
#define NC_OBJECT
Definition: WM_types.h:329
Scene scene
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:33
#define G(x, y, z)
#define FLUID_JOB_FREE_DATA
Definition: physics_fluid.c:54
static int fluid_bake_invoke(struct bContext *C, struct wmOperator *op, const wmEvent *UNUSED(_event))
#define FLUID_JOB_BAKE_GUIDES
Definition: physics_fluid.c:52
#define FLUID_JOB_BAKE_ALL
Definition: physics_fluid.c:47
void FLUID_OT_free_mesh(wmOperatorType *ot)
static void fluid_bake_endjob(void *customdata)
static bool fluid_is_bake_guiding(FluidJob *job)
static bool fluid_is_bake_particle(FluidJob *job)
Definition: physics_fluid.c:98
static bool fluid_is_free_data(FluidJob *job)
static int fluid_bake_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event)
static void fluid_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
static bool fluid_is_bake_noise(FluidJob *job)
Definition: physics_fluid.c:90
static bool fluid_validatepaths(FluidJob *job, ReportList *reports)
#define FLUID_JOB_FREE_MESH
Definition: physics_fluid.c:56
void FLUID_OT_free_particles(wmOperatorType *ot)
static int fluid_pause_exec(struct bContext *C, struct wmOperator *op)
#define FLUID_JOB_FREE_ALL
Definition: physics_fluid.c:53
void FLUID_OT_free_all(wmOperatorType *ot)
void FLUID_OT_bake_guides(wmOperatorType *ot)
static bool fluid_is_free_mesh(FluidJob *job)
void FLUID_OT_free_guides(wmOperatorType *ot)
struct FluidJob FluidJob
#define FLUID_JOB_BAKE_PAUSE
Definition: physics_fluid.c:59
void FLUID_OT_bake_particles(wmOperatorType *ot)
static bool fluid_initjob(bContext *C, FluidJob *job, wmOperator *op, char *error_msg, int error_size)
static void fluid_free_endjob(void *customdata)
static bool fluid_is_free_guiding(FluidJob *job)
static int fluid_bake_exec(struct bContext *C, struct wmOperator *op)
static bool fluid_is_bake_all(FluidJob *job)
Definition: physics_fluid.c:82
static void fluid_bake_free(void *customdata)
#define FLUID_JOB_BAKE_NOISE
Definition: physics_fluid.c:49
#define FLUID_JOB_FREE_PARTICLES
Definition: physics_fluid.c:57
void FLUID_OT_bake_all(wmOperatorType *ot)
#define FLUID_JOB_BAKE_PARTICLES
Definition: physics_fluid.c:51
static bool fluid_is_bake_mesh(FluidJob *job)
Definition: physics_fluid.c:94
static bool fluid_is_free_all(FluidJob *job)
static bool fluid_is_free_noise(FluidJob *job)
static bool fluid_is_free_particles(FluidJob *job)
#define FLUID_JOB_FREE_NOISE
Definition: physics_fluid.c:55
void FLUID_OT_bake_data(wmOperatorType *ot)
static void fluid_free_startjob(void *customdata, short *stop, short *do_update, float *progress)
static int fluid_free_exec(struct bContext *C, struct wmOperator *op)
static bool fluid_is_bake_data(FluidJob *job)
Definition: physics_fluid.c:86
void FLUID_OT_free_noise(wmOperatorType *ot)
#define FLUID_JOB_FREE_GUIDES
Definition: physics_fluid.c:58
#define FLUID_JOB_BAKE_DATA
Definition: physics_fluid.c:48
void FLUID_OT_pause_bake(wmOperatorType *ot)
void FLUID_OT_bake_noise(wmOperatorType *ot)
void FLUID_OT_free_data(wmOperatorType *ot)
#define FLUID_JOB_BAKE_MESH
Definition: physics_fluid.c:50
static void fluid_bake_sequence(FluidJob *job)
void FLUID_OT_bake_mesh(wmOperatorType *ot)
char cache_directory[1024]
int * pause_frame
Definition: physics_fluid.c:79
const char * name
Definition: physics_fluid.c:67
short * stop
Definition: physics_fluid.c:64
FluidModifierData * fmd
Definition: physics_fluid.c:74
Object * ob
Definition: physics_fluid.c:72
Depsgraph * depsgraph
Definition: physics_fluid.c:71
const char * type
Definition: physics_fluid.c:66
double start
Definition: physics_fluid.c:77
float * progress
Definition: physics_fluid.c:65
short * do_update
Definition: physics_fluid.c:64
struct Main * bmain
Definition: physics_fluid.c:69
void * owner
Definition: physics_fluid.c:63
Scene * scene
Definition: physics_fluid.c:70
struct FluidDomainSettings * domain
Definition: BKE_main.h:121
struct RenderData r
short type
Definition: WM_types.h:678
Definition: wm_jobs.c:57
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
int(* modal)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:935
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
struct ReportList * reports
struct wmOperatorType * type
double PIL_check_seconds_timer(void)
Definition: time.c:64
#define N_(msgid)
wmEventHandler_Op * WM_event_add_modal_handler(bContext *C, wmOperator *op)
void WM_report_banners_cancel(Main *bmain)
void WM_reportf(eReportType type, const char *format,...)
void WM_set_locked_interface(wmWindowManager *wm, bool lock)
@ EVT_ESCKEY
wmOperatorType * ot
Definition: wm_files.c:3479
void WM_jobs_start(wmWindowManager *wm, wmJob *wm_job)
Definition: wm_jobs.c:437
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:351
bool WM_jobs_test(const wmWindowManager *wm, const void *owner, int job_type)
Definition: wm_jobs.c:214
void WM_jobs_customdata_set(wmJob *wm_job, void *customdata, void(*free)(void *))
Definition: wm_jobs.c:323
void WM_jobs_timer(wmJob *wm_job, double timestep, unsigned int note, unsigned int endnote)
Definition: wm_jobs.c:339
wmJob * WM_jobs_get(wmWindowManager *wm, wmWindow *win, const void *owner, const char *name, int flag, int job_type)
Definition: wm_jobs.c:184