Blender  V2.93
dynamicpaint_ops.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 
21 #include <math.h>
22 #include <stdio.h>
23 #include <string.h>
24 
25 #include "MEM_guardedalloc.h"
26 
27 #include "BLI_blenlib.h"
28 #include "BLI_string.h"
29 #include "BLI_utildefines.h"
30 
31 #include "BLT_translation.h"
32 
33 #include "DNA_dynamicpaint_types.h"
34 #include "DNA_modifier_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
37 
38 #include "BKE_context.h"
39 #include "BKE_deform.h"
40 #include "BKE_dynamicpaint.h"
41 #include "BKE_global.h"
42 #include "BKE_main.h"
43 #include "BKE_modifier.h"
44 #include "BKE_object_deform.h"
45 #include "BKE_report.h"
46 #include "BKE_screen.h"
47 
48 #include "DEG_depsgraph.h"
49 #include "DEG_depsgraph_build.h"
50 #include "DEG_depsgraph_query.h"
51 
52 #include "ED_mesh.h"
53 #include "ED_object.h"
54 #include "ED_screen.h"
55 
56 #include "RNA_access.h"
57 #include "RNA_define.h"
58 #include "RNA_enum_types.h"
59 
60 #include "PIL_time.h"
61 
62 #include "WM_api.h"
63 #include "WM_types.h"
64 
65 #include "physics_intern.h" /* own include */
66 
68 {
70  Object *cObject = ED_object_context(C);
73 
74  /* Make sure we're dealing with a canvas */
76  if (!pmd || !pmd->canvas) {
77  return OPERATOR_CANCELLED;
78  }
79 
80  canvas = pmd->canvas;
82 
83  if (!surface) {
84  return OPERATOR_CANCELLED;
85  }
86 
87  canvas->active_sur = 0;
88  for (surface = surface->prev; surface; surface = surface->prev) {
89  canvas->active_sur++;
90  }
91 
92  return OPERATOR_FINISHED;
93 }
94 
95 /* add surface slot */
97 {
98  /* identifiers */
99  ot->name = "Add Surface Slot";
100  ot->idname = "DPAINT_OT_surface_slot_add";
101  ot->description = "Add a new Dynamic Paint surface slot";
102 
103  /* api callbacks */
106 
107  /* flags */
109 }
110 
112 {
114  Object *obj_ctx = ED_object_context(C);
117  int id = 0;
118 
119  /* Make sure we're dealing with a canvas */
121  if (!pmd || !pmd->canvas) {
122  return OPERATOR_CANCELLED;
123  }
124 
125  canvas = pmd->canvas;
126  surface = canvas->surfaces.first;
127 
128  /* find active surface and remove it */
129  for (; surface; surface = surface->next) {
130  if (id == canvas->active_sur) {
131  canvas->active_sur -= 1;
133  break;
134  }
135  id++;
136  }
137 
140 
141  return OPERATOR_FINISHED;
142 }
143 
144 /* remove surface slot */
146 {
147  /* identifiers */
148  ot->name = "Remove Surface Slot";
149  ot->idname = "DPAINT_OT_surface_slot_remove";
150  ot->description = "Remove the selected surface slot";
151 
152  /* api callbacks */
155 
156  /* flags */
158 }
159 
161 {
162 
163  Object *cObject = ED_object_context(C);
166  cObject, eModifierType_DynamicPaint);
167  int type = RNA_enum_get(op->ptr, "type");
168 
169  if (!pmd) {
170  return OPERATOR_CANCELLED;
171  }
172 
173  /* if type is already enabled, toggle it off */
174  if (type == MOD_DYNAMICPAINT_TYPE_CANVAS && pmd->canvas) {
176  }
177  else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH && pmd->brush) {
179  }
180  /* else create a new type */
181  else {
182  if (!dynamicPaint_createType(pmd, type, scene)) {
183  return OPERATOR_CANCELLED;
184  }
185  }
186 
187  /* update dependency */
191 
192  return OPERATOR_FINISHED;
193 }
194 
196 {
197  PropertyRNA *prop;
198 
199  /* identifiers */
200  ot->name = "Toggle Type Active";
201  ot->idname = "DPAINT_OT_type_toggle";
202  ot->description = "Toggle whether given type is active or not";
203 
204  /* api callbacks */
207 
208  /* flags */
210 
211  /* properties */
212  prop = RNA_def_enum(ot->srna,
213  "type",
216  "Type",
217  "");
218  ot->prop = prop;
219 }
220 
222 {
223  Object *ob = ED_object_context(C);
227  int output = RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */
228 
229  if (!pmd || !pmd->canvas) {
230  return OPERATOR_CANCELLED;
231  }
233 
234  /* if type is already enabled, toggle it off */
235  if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
236  bool exists = dynamicPaint_outputLayerExists(surface, ob, output);
237  const char *name;
238 
239  if (output == 0) {
240  name = surface->output_name;
241  }
242  else {
243  name = surface->output_name2;
244  }
245 
246  /* Vertex Color Layer */
247  if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
248  if (!exists) {
249  ED_mesh_color_add(ob->data, name, true, true);
250  }
251  else {
252  ED_mesh_color_remove_named(ob->data, name);
253  }
254  }
255  /* Vertex Weight Layer */
256  else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
257  if (!exists) {
260  }
261  else {
262  bDeformGroup *defgroup = BKE_object_defgroup_find_name(ob, name);
263  if (defgroup) {
264  BKE_object_defgroup_remove(ob, defgroup);
266  }
267  }
268  }
269  }
270 
271  return OPERATOR_FINISHED;
272 }
273 
275 {
276  static const EnumPropertyItem prop_output_toggle_types[] = {
277  {0, "A", 0, "Output A", ""},
278  {1, "B", 0, "Output B", ""},
279  {0, NULL, 0, NULL, NULL},
280  };
281 
282  /* identifiers */
283  ot->name = "Toggle Output Layer";
284  ot->idname = "DPAINT_OT_output_toggle";
285  ot->description = "Add or remove Dynamic Paint output data layer";
286 
287  /* api callbacks */
290 
291  /* flags */
293 
294  /* properties */
295  ot->prop = RNA_def_enum(ot->srna, "output", prop_output_toggle_types, 0, "Output Toggle", "");
296 }
297 
298 /***************************** Image Sequence Baking ******************************/
299 
300 typedef struct DynamicPaintBakeJob {
301  /* from wmJob */
302  void *owner;
303  short *stop, *do_update;
304  float *progress;
305 
306  struct Main *bmain;
310 
313 
314  int success;
315  double start;
317 
318 static void dpaint_bake_free(void *customdata)
319 {
320  DynamicPaintBakeJob *job = customdata;
321  MEM_freeN(job);
322 }
323 
324 static void dpaint_bake_endjob(void *customdata)
325 {
326  DynamicPaintBakeJob *job = customdata;
327  DynamicPaintCanvasSettings *canvas = job->canvas;
328 
329  canvas->flags &= ~MOD_DPAINT_BAKING;
330 
332 
333  G.is_rendering = false;
335 
336  WM_set_locked_interface(G_MAIN->wm.first, false);
337 
338  /* Bake was successful:
339  * Report for ended bake and how long it took */
340  if (job->success) {
341  /* Show bake info */
342  WM_reportf(
343  RPT_INFO, "DynamicPaint: Bake complete! (%.2f)", PIL_check_seconds_timer() - job->start);
344  }
345  else {
346  if (strlen(canvas->error)) { /* If an error occurred */
347  WM_reportf(RPT_ERROR, "DynamicPaint: Bake failed: %s", canvas->error);
348  }
349  else { /* User canceled the bake */
350  WM_report(RPT_WARNING, "Baking canceled!");
351  }
352  }
353 }
354 
355 /*
356  * Do actual bake operation. Loop through to-be-baked frames.
357  * Returns 0 on failure.
358  */
360 {
362  Object *cObject = job->ob;
363  DynamicPaintCanvasSettings *canvas = surface->canvas;
364  Scene *input_scene = DEG_get_input_scene(job->depsgraph);
365  Scene *scene = job->scene;
366  int frame = 1, orig_frame;
367  int frames;
368 
369  frames = surface->end_frame - surface->start_frame + 1;
370  if (frames <= 0) {
371  BLI_strncpy(canvas->error, N_("No frames to bake"), sizeof(canvas->error));
372  return;
373  }
374 
375  /* Show progress bar. */
376  *(job->do_update) = true;
377 
378  /* Set frame to start point (also inits modifier data) */
379  frame = surface->start_frame;
380  orig_frame = input_scene->r.cfra;
381  input_scene->r.cfra = (int)frame;
383 
384  /* Init surface */
386  job->success = 0;
387  return;
388  }
389 
390  /* Loop through selected frames */
391  for (frame = surface->start_frame; frame <= surface->end_frame; frame++) {
392  /* The first 10% are for createUVSurface... */
393  const float progress = 0.1f + 0.9f * (frame - surface->start_frame) / (float)frames;
394  surface->current_frame = frame;
395 
396  /* If user requested stop, quit baking */
397  if (G.is_break) {
398  job->success = 0;
399  return;
400  }
401 
402  /* Update progress bar */
403  *(job->do_update) = true;
404  *(job->progress) = progress;
405 
406  /* calculate a frame */
407  input_scene->r.cfra = (int)frame;
409  if (!dynamicPaint_calculateFrame(surface, job->depsgraph, scene, cObject, frame)) {
410  job->success = 0;
411  return;
412  }
413 
414  /*
415  * Save output images
416  */
417  {
418  char filename[FILE_MAX];
419 
420  /* primary output layer */
421  if (surface->flags & MOD_DPAINT_OUT1) {
422  /* set filepath */
424  filename, sizeof(filename), surface->image_output_path, surface->output_name);
425  BLI_path_frame(filename, frame, 4);
426 
427  /* save image */
429  }
430  /* secondary output */
431  if (surface->flags & MOD_DPAINT_OUT2 && surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
432  /* set filepath */
434  filename, sizeof(filename), surface->image_output_path, surface->output_name2);
435  BLI_path_frame(filename, frame, 4);
436 
437  /* save image */
439  }
440  }
441  }
442 
443  input_scene->r.cfra = orig_frame;
445 }
446 
447 static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
448 {
449  DynamicPaintBakeJob *job = customdata;
450 
451  job->stop = stop;
452  job->do_update = do_update;
453  job->progress = progress;
455  job->success = 1;
456 
457  G.is_break = false; /* reset BKE_blender_test_break*/
458 
459  /* XXX annoying hack: needed to prevent data corruption when changing
460  * scene frame in separate threads
461  */
462  G.is_rendering = true;
464 
466 
467  *do_update = true;
468  *stop = 0;
469 }
470 
471 /*
472  * Bake Dynamic Paint image sequence surface
473  */
474 static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
475 {
477  Object *ob_ = ED_object_context(C);
478  Object *object_eval = DEG_get_evaluated_object(depsgraph, ob_);
479  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
480 
482 
483  /*
484  * Get modifier data
485  */
487  object_eval, eModifierType_DynamicPaint);
488  if (pmd == NULL) {
489  BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found");
490  return OPERATOR_CANCELLED;
491  }
492 
493  /* Make sure we're dealing with a canvas */
494  DynamicPaintCanvasSettings *canvas = pmd->canvas;
495  if (canvas == NULL) {
496  BKE_report(op->reports, RPT_ERROR, "Bake failed: invalid canvas");
497  return OPERATOR_CANCELLED;
498  }
499  surface = get_activeSurface(canvas);
500 
501  /* Set state to baking and init surface */
502  canvas->error[0] = '\0';
503  canvas->flags |= MOD_DPAINT_BAKING;
504 
505  DynamicPaintBakeJob *job = MEM_mallocN(sizeof(DynamicPaintBakeJob), "DynamicPaintBakeJob");
506  job->bmain = CTX_data_main(C);
507  job->scene = scene_eval;
508  job->depsgraph = depsgraph;
509  job->ob = object_eval;
510  job->canvas = canvas;
511  job->surface = surface;
512 
513  wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
514  CTX_wm_window(C),
515  CTX_data_scene(C),
516  "Dynamic Paint Bake",
519 
523 
525 
526  /* Bake Dynamic Paint */
527  WM_jobs_start(CTX_wm_manager(C), wm_job);
528 
529  return OPERATOR_FINISHED;
530 }
531 
533 {
534  /* identifiers */
535  ot->name = "Dynamic Paint Bake";
536  ot->description = "Bake dynamic paint image sequence surface";
537  ot->idname = "DPAINT_OT_bake";
538 
539  /* api callbacks */
542 }
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1034
struct wmWindowManager * CTX_wm_manager(const bContext *C)
Definition: context.c:689
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:699
support for deformation groups and hooks.
struct bDeformGroup * BKE_object_defgroup_find_name(const struct Object *ob, const char *name)
bool dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, struct Object *ob, int output)
Definition: dynamicpaint.c:336
void dynamicPaint_outputSurfaceImage(struct DynamicPaintSurface *surface, char *filename, short output_layer)
void dynamicPaint_freeCanvas(struct DynamicPaintModifierData *pmd)
bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, struct Scene *scene)
int dynamicPaint_createUVSurface(struct Scene *scene, struct DynamicPaintSurface *surface, float *progress, short *do_update)
void dynamicPaint_freeBrush(struct DynamicPaintModifierData *pmd)
Definition: dynamicpaint.c:862
struct DynamicPaintSurface * get_activeSurface(struct DynamicPaintCanvasSettings *canvas)
Definition: dynamicpaint.c:331
struct DynamicPaintSurface * dynamicPaint_createNewSurface(struct DynamicPaintCanvasSettings *canvas, struct Scene *scene)
int dynamicPaint_calculateFrame(struct DynamicPaintSurface *surface, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *cObject, int frame)
void dynamicPaint_freeSurfaceData(struct DynamicPaintSurface *surface)
Definition: dynamicpaint.c:951
void dynamicPaint_freeSurface(const struct DynamicPaintModifierData *pmd, struct DynamicPaintSurface *surface)
#define G_MAIN
Definition: BKE_global.h:232
struct ModifierData * BKE_modifiers_findby_type(const struct Object *ob, ModifierType type)
Functions for dealing with objects and deform verts, used by painting and tools.
void BKE_object_defgroup_remove(struct Object *ob, struct bDeformGroup *defgroup)
struct bDeformGroup * BKE_object_defgroup_add_name(struct Object *ob, const char *name)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
void BKE_spacedata_draw_locks(bool set)
Definition: screen.c:547
bool BLI_path_frame(char *path, int frame, int digits) ATTR_NONNULL()
Definition: path_util.c:802
#define FILE_MAX
void BLI_join_dirfile(char *__restrict dst, const size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1737
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, const size_t maxncpy) ATTR_NONNULL()
Definition: string.c:108
#define UNUSED(x)
#define N_(msgid)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
void DEG_relations_tag_update(struct Main *bmain)
struct Scene * DEG_get_input_scene(const Depsgraph *graph)
struct Object * DEG_get_evaluated_object(const struct Depsgraph *depsgraph, struct Object *object)
struct Scene * DEG_get_evaluated_scene(const struct Depsgraph *graph)
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:611
@ MOD_DPAINT_OUT2
@ MOD_DPAINT_OUT1
@ MOD_DPAINT_BAKING
@ MOD_DPAINT_SURFACE_T_WEIGHT
@ MOD_DPAINT_SURFACE_T_PAINT
@ MOD_DPAINT_SURFACE_F_VERTEX
@ eModifierType_DynamicPaint
@ MOD_DYNAMICPAINT_TYPE_BRUSH
@ MOD_DYNAMICPAINT_TYPE_CANVAS
Object is a sort of wrapper for general info.
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
int ED_mesh_color_add(struct Mesh *me, const char *name, const bool active_set, const bool do_init)
Definition: mesh_data.c:382
bool ED_mesh_color_remove_named(struct Mesh *me, const char *name)
Definition: mesh_data.c:475
struct Object * ED_object_context(const struct bContext *C)
bool ED_operator_object_active_local_editable(struct bContext *C)
Definition: screen_ops.c:378
void ED_update_for_newframe(struct Main *bmain, struct Depsgraph *depsgraph)
Definition: screen_edit.c:1617
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
Platform independent time functions.
#define C
Definition: RandGen.cpp:39
@ WM_JOB_TYPE_DPAINT_BAKE
Definition: WM_api.h:750
@ WM_JOB_PROGRESS
Definition: WM_api.h:726
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_MODIFIER
Definition: WM_types.h:363
#define NC_OBJECT
Definition: WM_types.h:280
#define output
Scene scene
const Depsgraph * depsgraph
static int type_toggle_exec(bContext *C, wmOperator *op)
static int surface_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
void DPAINT_OT_type_toggle(wmOperatorType *ot)
void DPAINT_OT_output_toggle(wmOperatorType *ot)
static void dpaint_bake_endjob(void *customdata)
struct DynamicPaintBakeJob DynamicPaintBakeJob
static int output_toggle_exec(bContext *C, wmOperator *op)
static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
void DPAINT_OT_surface_slot_add(wmOperatorType *ot)
static void dpaint_bake_free(void *customdata)
void DPAINT_OT_surface_slot_remove(wmOperatorType *ot)
static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op))
void DPAINT_OT_bake(wmOperatorType *ot)
struct @203::@204 surface
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
void *(* MEM_mallocN)(size_t len, const char *str)
Definition: mallocn.c:47
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3771
const EnumPropertyItem rna_enum_prop_dynamicpaint_type_items[]
DynamicPaintCanvasSettings * canvas
DynamicPaintSurface * surface
struct DynamicPaintCanvasSettings * canvas
struct DynamicPaintBrushSettings * brush
void * first
Definition: DNA_listBase.h:47
Definition: BKE_main.h:116
void * data
struct RenderData r
Definition: wm_jobs.c:73
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
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
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
double PIL_check_seconds_timer(void)
Definition: time.c:80
#define G(x, y, z)
void WM_report(ReportType type, const char *message)
void WM_reportf(ReportType type, const char *format,...)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
void WM_set_locked_interface(wmWindowManager *wm, bool lock)
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
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_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