Blender  V3.3
dynamicpaint_ops.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <math.h>
8 #include <stdio.h>
9 #include <string.h>
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "BLI_blenlib.h"
14 #include "BLI_string.h"
15 #include "BLI_utildefines.h"
16 
17 #include "BLT_translation.h"
18 
19 #include "DNA_dynamicpaint_types.h"
20 #include "DNA_modifier_types.h"
21 #include "DNA_object_types.h"
22 #include "DNA_scene_types.h"
23 
24 #include "BKE_context.h"
25 #include "BKE_deform.h"
26 #include "BKE_dynamicpaint.h"
27 #include "BKE_global.h"
28 #include "BKE_main.h"
29 #include "BKE_modifier.h"
30 #include "BKE_object_deform.h"
31 #include "BKE_report.h"
32 #include "BKE_screen.h"
33 
34 #include "DEG_depsgraph.h"
35 #include "DEG_depsgraph_build.h"
36 #include "DEG_depsgraph_query.h"
37 
38 #include "ED_mesh.h"
39 #include "ED_object.h"
40 #include "ED_screen.h"
41 
42 #include "RNA_access.h"
43 #include "RNA_define.h"
44 #include "RNA_enum_types.h"
45 
46 #include "PIL_time.h"
47 
48 #include "WM_api.h"
49 #include "WM_types.h"
50 
51 #include "physics_intern.h" /* own include */
52 
54 {
56  Object *cObject = ED_object_context(C);
59 
60  /* Make sure we're dealing with a canvas */
62  if (!pmd || !pmd->canvas) {
63  return OPERATOR_CANCELLED;
64  }
65 
66  canvas = pmd->canvas;
68 
69  if (!surface) {
70  return OPERATOR_CANCELLED;
71  }
72 
73  canvas->active_sur = 0;
74  for (surface = surface->prev; surface; surface = surface->prev) {
75  canvas->active_sur++;
76  }
77 
78  return OPERATOR_FINISHED;
79 }
80 
82 {
83  /* identifiers */
84  ot->name = "Add Surface Slot";
85  ot->idname = "DPAINT_OT_surface_slot_add";
86  ot->description = "Add a new Dynamic Paint surface slot";
87 
88  /* api callbacks */
91 
92  /* flags */
94 }
95 
97 {
99  Object *obj_ctx = ED_object_context(C);
102  int id = 0;
103 
104  /* Make sure we're dealing with a canvas */
106  if (!pmd || !pmd->canvas) {
107  return OPERATOR_CANCELLED;
108  }
109 
110  canvas = pmd->canvas;
111  surface = canvas->surfaces.first;
112 
113  /* find active surface and remove it */
114  for (; surface; surface = surface->next) {
115  if (id == canvas->active_sur) {
116  canvas->active_sur -= 1;
118  break;
119  }
120  id++;
121  }
122 
125 
126  return OPERATOR_FINISHED;
127 }
128 
130 {
131  /* identifiers */
132  ot->name = "Remove Surface Slot";
133  ot->idname = "DPAINT_OT_surface_slot_remove";
134  ot->description = "Remove the selected surface slot";
135 
136  /* api callbacks */
139 
140  /* flags */
142 }
143 
145 {
146 
147  Object *cObject = ED_object_context(C);
150  cObject, eModifierType_DynamicPaint);
151  int type = RNA_enum_get(op->ptr, "type");
152 
153  if (!pmd) {
154  return OPERATOR_CANCELLED;
155  }
156 
157  /* if type is already enabled, toggle it off */
158  if (type == MOD_DYNAMICPAINT_TYPE_CANVAS && pmd->canvas) {
160  }
161  else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH && pmd->brush) {
163  }
164  /* else create a new type */
165  else {
166  if (!dynamicPaint_createType(pmd, type, scene)) {
167  return OPERATOR_CANCELLED;
168  }
169  }
170 
171  /* update dependency */
175 
176  return OPERATOR_FINISHED;
177 }
178 
180 {
181  PropertyRNA *prop;
182 
183  /* identifiers */
184  ot->name = "Toggle Type Active";
185  ot->idname = "DPAINT_OT_type_toggle";
186  ot->description = "Toggle whether given type is active or not";
187 
188  /* api callbacks */
191 
192  /* flags */
194 
195  /* properties */
196  prop = RNA_def_enum(ot->srna,
197  "type",
200  "Type",
201  "");
202  ot->prop = prop;
203 }
204 
206 {
207  Object *ob = ED_object_context(C);
211  int output = RNA_enum_get(op->ptr, "output"); /* currently only 1/0 */
212 
213  if (!pmd || !pmd->canvas) {
214  return OPERATOR_CANCELLED;
215  }
217 
218  /* if type is already enabled, toggle it off */
219  if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
220  bool exists = dynamicPaint_outputLayerExists(surface, ob, output);
221  const char *name;
222 
223  if (output == 0) {
224  name = surface->output_name;
225  }
226  else {
227  name = surface->output_name2;
228  }
229 
230  /* Vertex Color Layer */
231  if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
232  if (!exists) {
233  ED_mesh_color_add(ob->data, name, true, true, op->reports);
234  }
235  else {
236  ED_mesh_color_remove_named(ob->data, name);
237  }
238  }
239  /* Vertex Weight Layer */
240  else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
241  if (!exists) {
244  }
245  else {
246  bDeformGroup *defgroup = BKE_object_defgroup_find_name(ob, name);
247  if (defgroup) {
248  BKE_object_defgroup_remove(ob, defgroup);
250  }
251  }
252  }
253  }
254 
255  return OPERATOR_FINISHED;
256 }
257 
259 {
260  static const EnumPropertyItem prop_output_toggle_types[] = {
261  {0, "A", 0, "Output A", ""},
262  {1, "B", 0, "Output B", ""},
263  {0, NULL, 0, NULL, NULL},
264  };
265 
266  /* identifiers */
267  ot->name = "Toggle Output Layer";
268  ot->idname = "DPAINT_OT_output_toggle";
269  ot->description = "Add or remove Dynamic Paint output data layer";
270 
271  /* api callbacks */
274 
275  /* flags */
277 
278  /* properties */
279  ot->prop = RNA_def_enum(ot->srna, "output", prop_output_toggle_types, 0, "Output Toggle", "");
280 }
281 
282 /***************************** Image Sequence Baking ******************************/
283 
284 typedef struct DynamicPaintBakeJob {
285  /* from wmJob */
286  void *owner;
287  short *stop, *do_update;
288  float *progress;
289 
290  struct Main *bmain;
294 
297 
298  int success;
299  double start;
301 
302 static void dpaint_bake_free(void *customdata)
303 {
304  DynamicPaintBakeJob *job = customdata;
305  MEM_freeN(job);
306 }
307 
308 static void dpaint_bake_endjob(void *customdata)
309 {
310  DynamicPaintBakeJob *job = customdata;
311  DynamicPaintCanvasSettings *canvas = job->canvas;
312 
313  canvas->flags &= ~MOD_DPAINT_BAKING;
314 
316 
317  G.is_rendering = false;
319 
320  WM_set_locked_interface(G_MAIN->wm.first, false);
321 
322  /* Bake was successful:
323  * Report for ended bake and how long it took */
324  if (job->success) {
325  /* Show bake info */
326  WM_reportf(
327  RPT_INFO, "DynamicPaint: Bake complete! (%.2f)", PIL_check_seconds_timer() - job->start);
328  }
329  else {
330  if (strlen(canvas->error)) { /* If an error occurred */
331  WM_reportf(RPT_ERROR, "DynamicPaint: Bake failed: %s", canvas->error);
332  }
333  else { /* User canceled the bake */
334  WM_report(RPT_WARNING, "Baking canceled!");
335  }
336  }
337 }
338 
339 /*
340  * Do actual bake operation. Loop through to-be-baked frames.
341  * Returns 0 on failure.
342  */
344 {
346  Object *cObject = job->ob;
347  DynamicPaintCanvasSettings *canvas = surface->canvas;
348  Scene *input_scene = DEG_get_input_scene(job->depsgraph);
349  Scene *scene = job->scene;
350  int frame = 1, orig_frame;
351  int frames;
352 
353  frames = surface->end_frame - surface->start_frame + 1;
354  if (frames <= 0) {
355  BLI_strncpy(canvas->error, N_("No frames to bake"), sizeof(canvas->error));
356  return;
357  }
358 
359  /* Show progress bar. */
360  *(job->do_update) = true;
361 
362  /* Set frame to start point (also initializes modifier data). */
363  frame = surface->start_frame;
364  orig_frame = input_scene->r.cfra;
365  input_scene->r.cfra = (int)frame;
367 
368  /* Init surface */
370  job->success = 0;
371  return;
372  }
373 
374  /* Loop through selected frames */
375  for (frame = surface->start_frame; frame <= surface->end_frame; frame++) {
376  /* The first 10% are for createUVSurface... */
377  const float progress = 0.1f + 0.9f * (frame - surface->start_frame) / (float)frames;
378  surface->current_frame = frame;
379 
380  /* If user requested stop, quit baking */
381  if (G.is_break) {
382  job->success = 0;
383  return;
384  }
385 
386  /* Update progress bar */
387  *(job->do_update) = true;
388  *(job->progress) = progress;
389 
390  /* calculate a frame */
391  input_scene->r.cfra = (int)frame;
393  if (!dynamicPaint_calculateFrame(surface, job->depsgraph, scene, cObject, frame)) {
394  job->success = 0;
395  return;
396  }
397 
398  /*
399  * Save output images
400  */
401  {
402  char filepath[FILE_MAX];
403 
404  /* primary output layer */
405  if (surface->flags & MOD_DPAINT_OUT1) {
406  /* set filepath */
408  filepath, sizeof(filepath), surface->image_output_path, surface->output_name);
409  BLI_path_frame(filepath, frame, 4);
410 
411  /* save image */
413  }
414  /* secondary output */
415  if (surface->flags & MOD_DPAINT_OUT2 && surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
416  /* set filepath */
418  filepath, sizeof(filepath), surface->image_output_path, surface->output_name2);
419  BLI_path_frame(filepath, frame, 4);
420 
421  /* save image */
423  }
424  }
425  }
426 
427  input_scene->r.cfra = orig_frame;
429 }
430 
431 static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
432 {
433  DynamicPaintBakeJob *job = customdata;
434 
435  job->stop = stop;
436  job->do_update = do_update;
437  job->progress = progress;
439  job->success = 1;
440 
441  G.is_break = false;
442 
443  /* XXX annoying hack: needed to prevent data corruption when changing
444  * scene frame in separate threads
445  */
446  G.is_rendering = true;
448 
450 
451  *do_update = true;
452  *stop = 0;
453 }
454 
455 /*
456  * Bake Dynamic Paint image sequence surface
457  */
458 static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
459 {
461  Object *ob_ = ED_object_context(C);
462  Object *object_eval = DEG_get_evaluated_object(depsgraph, ob_);
463  Scene *scene_eval = DEG_get_evaluated_scene(depsgraph);
464 
466 
467  /*
468  * Get modifier data
469  */
471  object_eval, eModifierType_DynamicPaint);
472  if (pmd == NULL) {
473  BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found");
474  return OPERATOR_CANCELLED;
475  }
476 
477  /* Make sure we're dealing with a canvas */
478  DynamicPaintCanvasSettings *canvas = pmd->canvas;
479  if (canvas == NULL) {
480  BKE_report(op->reports, RPT_ERROR, "Bake failed: invalid canvas");
481  return OPERATOR_CANCELLED;
482  }
483  surface = get_activeSurface(canvas);
484 
485  /* Set state to baking and init surface */
486  canvas->error[0] = '\0';
487  canvas->flags |= MOD_DPAINT_BAKING;
488 
489  DynamicPaintBakeJob *job = MEM_mallocN(sizeof(DynamicPaintBakeJob), "DynamicPaintBakeJob");
490  job->bmain = CTX_data_main(C);
491  job->scene = scene_eval;
492  job->depsgraph = depsgraph;
493  job->ob = object_eval;
494  job->canvas = canvas;
495  job->surface = surface;
496 
497  wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C),
498  CTX_wm_window(C),
499  CTX_data_scene(C),
500  "Dynamic Paint Bake",
503 
507 
509 
510  /* Bake Dynamic Paint */
511  WM_jobs_start(CTX_wm_manager(C), wm_job);
512 
513  return OPERATOR_FINISHED;
514 }
515 
517 {
518  /* identifiers */
519  ot->name = "Dynamic Paint Bake";
520  ot->description = "Bake dynamic paint image sequence surface";
521  ot->idname = "DPAINT_OT_bake";
522 
523  /* api callbacks */
526 }
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_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1074
struct wmWindow * CTX_wm_window(const bContext *C)
Definition: context.c:723
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:322
void dynamicPaint_outputSurfaceImage(struct DynamicPaintSurface *surface, const char *filepath, short output_layer)
void dynamicPaint_freeCanvas(struct DynamicPaintModifierData *pmd)
Definition: dynamicpaint.c:979
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:843
struct DynamicPaintSurface * get_activeSurface(struct DynamicPaintCanvasSettings *canvas)
Definition: dynamicpaint.c:317
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:932
void dynamicPaint_freeSurface(const struct DynamicPaintModifierData *pmd, struct DynamicPaintSurface *surface)
#define G_MAIN
Definition: BKE_global.h:267
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)
Definition: object_deform.c:95
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_path_frame(char *path, int frame, int digits) ATTR_NONNULL()
Definition: path_util.c:709
#define FILE_MAX
void BLI_join_dirfile(char *__restrict dst, size_t maxlen, const char *__restrict dir, const char *__restrict file) ATTR_NONNULL()
Definition: path_util.c:1531
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t maxncpy) ATTR_NONNULL()
Definition: string.c:64
#define UNUSED(x)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
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:791
@ MOD_DPAINT_SURFACE_T_WEIGHT
@ MOD_DPAINT_SURFACE_T_PAINT
@ MOD_DPAINT_OUT2
@ MOD_DPAINT_OUT1
@ MOD_DPAINT_BAKING
@ MOD_DPAINT_SURFACE_F_VERTEX
@ MOD_DYNAMICPAINT_TYPE_BRUSH
@ MOD_DYNAMICPAINT_TYPE_CANVAS
@ eModifierType_DynamicPaint
Object is a sort of wrapper for general info.
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
int ED_mesh_color_add(struct Mesh *me, const char *name, bool active_set, bool do_init, struct ReportList *reports)
bool ED_mesh_color_remove_named(struct Mesh *me, const char *name)
Definition: mesh_data.cc:470
struct Object * ED_object_context(const struct bContext *C)
bool ED_operator_object_active_local_editable(struct bContext *C)
Definition: screen_ops.c:407
void ED_update_for_newframe(struct Main *bmain, struct Depsgraph *depsgraph)
Definition: screen_edit.c:1694
_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:25
@ WM_JOB_PROGRESS
Definition: WM_api.h:1339
@ WM_JOB_TYPE_DPAINT_BAKE
Definition: WM_api.h:1365
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define ND_MODIFIER
Definition: WM_types.h:411
#define NC_OBJECT
Definition: WM_types.h:329
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 @211::@212 surface
ccl_global KernelShaderEvalInput ccl_global float * output
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)
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
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:3783
const EnumPropertyItem rna_enum_prop_dynamicpaint_type_items[]
DynamicPaintCanvasSettings * canvas
DynamicPaintSurface * surface
struct DynamicPaintCanvasSettings * canvas
struct DynamicPaintBrushSettings * brush
void * first
Definition: DNA_listBase.h:31
Definition: BKE_main.h:121
char filepath[1024]
Definition: BKE_main.h:124
void * data
struct RenderData r
Definition: wm_jobs.c:57
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
double PIL_check_seconds_timer(void)
Definition: time.c:64
#define N_(msgid)
void WM_report(eReportType type, const char *message)
void WM_reportf(eReportType 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: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
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