Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / physics / dynamicpaint_ops.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/editors/physics/dynamicpaint_ops.c
22  *  \ingroup edphys
23  */
24
25 #include <math.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "MEM_guardedalloc.h"
30
31 #include "BLI_blenlib.h"
32 #include "BLI_string.h"
33 #include "BLI_utildefines.h"
34
35 #include "BLT_translation.h"
36
37 #include "DNA_dynamicpaint_types.h"
38 #include "DNA_modifier_types.h"
39 #include "DNA_object_types.h"
40 #include "DNA_scene_types.h"
41
42 #include "BKE_context.h"
43 #include "BKE_deform.h"
44 #include "BKE_object_deform.h"
45 #include "BKE_dynamicpaint.h"
46 #include "BKE_global.h"
47 #include "BKE_main.h"
48 #include "BKE_modifier.h"
49 #include "BKE_report.h"
50 #include "BKE_screen.h"
51
52 #include "DEG_depsgraph.h"
53 #include "DEG_depsgraph_build.h"
54
55 #include "ED_mesh.h"
56 #include "ED_screen.h"
57 #include "ED_object.h"
58
59 #include "RNA_access.h"
60 #include "RNA_define.h"
61 #include "RNA_enum_types.h"
62
63 #include "PIL_time.h"
64
65 #include "WM_types.h"
66 #include "WM_api.h"
67
68 #include "physics_intern.h" /* own include */
69
70 static int surface_slot_add_exec(bContext *C, wmOperator *UNUSED(op))
71 {
72         DynamicPaintModifierData *pmd = NULL;
73         Object *cObject = ED_object_context(C);
74         DynamicPaintCanvasSettings *canvas;
75         DynamicPaintSurface *surface;
76
77         /* Make sure we're dealing with a canvas */
78         pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
79         if (!pmd || !pmd->canvas)
80                 return OPERATOR_CANCELLED;
81
82         canvas = pmd->canvas;
83         surface = dynamicPaint_createNewSurface(canvas, CTX_data_scene(C));
84
85         if (!surface)
86                 return OPERATOR_CANCELLED;
87
88         /* set preview for this surface only and set active */
89         canvas->active_sur = 0;
90         for (surface = surface->prev; surface; surface = surface->prev) {
91                 surface->flags &= ~MOD_DPAINT_PREVIEW;
92                 canvas->active_sur++;
93         }
94
95         return OPERATOR_FINISHED;
96 }
97
98 /* add surface slot */
99 void DPAINT_OT_surface_slot_add(wmOperatorType *ot)
100 {
101         /* identifiers */
102         ot->name = "Add Surface Slot";
103         ot->idname = "DPAINT_OT_surface_slot_add";
104         ot->description = "Add a new Dynamic Paint surface slot";
105         
106         /* api callbacks */
107         ot->exec = surface_slot_add_exec;
108         ot->poll = ED_operator_object_active_editable;
109
110         /* flags */
111         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
112 }
113
114 static int surface_slot_remove_exec(bContext *C, wmOperator *UNUSED(op))
115 {
116         DynamicPaintModifierData *pmd = NULL;
117         Object *obj_ctx = ED_object_context(C);
118         DynamicPaintCanvasSettings *canvas;
119         DynamicPaintSurface *surface;
120         int id = 0;
121
122         /* Make sure we're dealing with a canvas */
123         pmd = (DynamicPaintModifierData *)modifiers_findByType(obj_ctx, eModifierType_DynamicPaint);
124         if (!pmd || !pmd->canvas) return OPERATOR_CANCELLED;
125
126         canvas = pmd->canvas;
127         surface = canvas->surfaces.first;
128
129         /* find active surface and remove it */
130         for (; surface; surface = surface->next) {
131                 if (id == canvas->active_sur) {
132                                 canvas->active_sur -= 1;
133                                 dynamicPaint_freeSurface(surface);
134                                 break;
135                         }
136                 id++;
137         }
138
139         dynamicPaint_resetPreview(canvas);
140         DEG_id_tag_update(&obj_ctx->id, OB_RECALC_DATA);
141         WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, obj_ctx);
142
143         return OPERATOR_FINISHED;
144 }
145
146 /* remove surface slot */
147 void DPAINT_OT_surface_slot_remove(wmOperatorType *ot)
148 {
149         /* identifiers */
150         ot->name = "Remove Surface Slot";
151         ot->idname = "DPAINT_OT_surface_slot_remove";
152         ot->description = "Remove the selected surface slot";
153         
154         /* api callbacks */
155         ot->exec = surface_slot_remove_exec;
156         ot->poll = ED_operator_object_active_editable;
157
158         /* flags */
159         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
160 }
161
162 static int type_toggle_exec(bContext *C, wmOperator *op)
163 {
164
165         Object *cObject = ED_object_context(C);
166         Scene *scene = CTX_data_scene(C);
167         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
168         int type = RNA_enum_get(op->ptr, "type");
169
170         if (!pmd) return OPERATOR_CANCELLED;
171
172         /* if type is already enabled, toggle it off */
173         if (type == MOD_DYNAMICPAINT_TYPE_CANVAS && pmd->canvas) {
174                         dynamicPaint_freeCanvas(pmd);
175         }
176         else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH && pmd->brush) {
177                         dynamicPaint_freeBrush(pmd);
178         }
179         /* else create a new type */
180         else {
181                 if (!dynamicPaint_createType(pmd, type, scene))
182                         return OPERATOR_CANCELLED;
183         }
184         
185         /* update dependency */
186         DEG_id_tag_update(&cObject->id, OB_RECALC_DATA);
187         DEG_relations_tag_update(CTX_data_main(C));
188         WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, cObject);
189
190         return OPERATOR_FINISHED;
191 }
192
193 void DPAINT_OT_type_toggle(wmOperatorType *ot)
194 {
195         PropertyRNA *prop;
196
197         /* identifiers */
198         ot->name = "Toggle Type Active";
199         ot->idname = "DPAINT_OT_type_toggle";
200         ot->description = "Toggle whether given type is active or not";
201         
202         /* api callbacks */
203         ot->exec = type_toggle_exec;
204         ot->poll = ED_operator_object_active_editable;
205         
206         /* flags */
207         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
208         
209         /* properties */
210         prop = RNA_def_enum(ot->srna, "type", rna_enum_prop_dynamicpaint_type_items, MOD_DYNAMICPAINT_TYPE_CANVAS, "Type", "");
211         ot->prop = prop;
212 }
213
214 static int output_toggle_exec(bContext *C, wmOperator *op)
215 {
216         Object *ob = ED_object_context(C);
217         DynamicPaintSurface *surface;
218         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
219         int output = RNA_enum_get(op->ptr, "output");  /* currently only 1/0 */
220
221         if (!pmd || !pmd->canvas) return OPERATOR_CANCELLED;
222         surface = get_activeSurface(pmd->canvas);
223
224         /* if type is already enabled, toggle it off */
225         if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
226                 int exists = dynamicPaint_outputLayerExists(surface, ob, output);
227                 const char *name;
228                 
229                 if (output == 0)
230                         name = surface->output_name;
231                 else
232                         name = surface->output_name2;
233
234                 /* Vertex Color Layer */
235                 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
236                         if (!exists)
237                                 ED_mesh_color_add(ob->data, name, true);
238                         else 
239                                 ED_mesh_color_remove_named(ob->data, name);
240                 }
241                 /* Vertex Weight Layer */
242                 else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
243                         if (!exists) {
244                                 BKE_object_defgroup_add_name(ob, name);
245                         }
246                         else {
247                                 bDeformGroup *defgroup = defgroup_find_name(ob, name);
248                                 if (defgroup) BKE_object_defgroup_remove(ob, defgroup);
249                         }
250                 }
251         }
252
253         return OPERATOR_FINISHED;
254 }
255
256 void DPAINT_OT_output_toggle(wmOperatorType *ot)
257 {
258         static const EnumPropertyItem prop_output_toggle_types[] = {
259                 {0, "A", 0, "Output A", ""},
260                 {1, "B", 0, "Output B", ""},
261                 {0, NULL, 0, NULL, NULL}
262         };
263
264         /* identifiers */
265         ot->name = "Toggle Output Layer";
266         ot->idname = "DPAINT_OT_output_toggle";
267         ot->description = "Add or remove Dynamic Paint output data layer";
268         
269         /* api callbacks */
270         ot->exec = output_toggle_exec;
271         ot->poll = ED_operator_object_active_editable;
272         
273         /* flags */
274         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
275         
276         /* properties */
277         ot->prop = RNA_def_enum(ot->srna, "output", prop_output_toggle_types, 0, "Output Toggle", "");
278 }
279
280
281 /***************************** Image Sequence Baking ******************************/
282
283 typedef struct DynamicPaintBakeJob {
284         /* from wmJob */
285         void *owner;
286         short *stop, *do_update;
287         float *progress;
288
289         struct Main *bmain;
290         Scene *scene;
291         ViewLayer *view_layer;
292         Depsgraph *depsgraph;
293         Object *ob;
294
295         DynamicPaintSurface *surface;
296         DynamicPaintCanvasSettings *canvas;
297
298         EvaluationContext *eval_ctx;
299
300         int success;
301         double start;
302 } DynamicPaintBakeJob;
303
304 static void dpaint_bake_free(void *customdata)
305 {
306         DynamicPaintBakeJob *job = customdata;
307         MEM_freeN(job);
308 }
309
310 static void dpaint_bake_endjob(void *customdata)
311 {
312         DynamicPaintBakeJob *job = customdata;
313         DynamicPaintCanvasSettings *canvas = job->canvas;
314
315         canvas->flags &= ~MOD_DPAINT_BAKING;
316
317         dynamicPaint_freeSurfaceData(job->surface);
318
319         MEM_freeN(job->eval_ctx);
320
321         G.is_rendering = false;
322         BKE_spacedata_draw_locks(false);
323
324         WM_set_locked_interface(G.main->wm.first, false);
325
326         /* Bake was successful:
327          *  Report for ended bake and how long it took */
328         if (job->success) {
329                 /* Show bake info */
330                 WM_reportf(RPT_INFO, "DynamicPaint: Bake complete! (%.2f)", PIL_check_seconds_timer() - job->start);
331         }
332         else {
333                 if (strlen(canvas->error)) { /* If an error occurred */
334                         WM_reportf(RPT_ERROR, "DynamicPaint: Bake failed: %s", canvas->error);
335                 }
336                 else { /* User canceled the bake */
337                         WM_report(RPT_WARNING, "Baking canceled!");
338                 }
339         }
340 }
341
342 /*
343  * Do actual bake operation. Loop through to-be-baked frames.
344  * Returns 0 on failure.
345  */
346 static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
347 {
348         DynamicPaintSurface *surface = job->surface;
349         Object *cObject = job->ob;
350         DynamicPaintCanvasSettings *canvas = surface->canvas;
351         Scene *scene = job->scene;
352         int frame = 1, orig_frame;
353         int frames;
354
355         frames = surface->end_frame - surface->start_frame + 1;
356         if (frames <= 0) {
357                 BLI_strncpy(canvas->error, N_("No frames to bake"), sizeof(canvas->error));
358                 return;
359         }
360
361         /* Show progress bar. */
362         *(job->do_update) = true;
363
364         /* Set frame to start point (also inits modifier data) */
365         frame = surface->start_frame;
366         orig_frame = scene->r.cfra;
367         scene->r.cfra = (int)frame;
368         ED_update_for_newframe(job->bmain, scene, job->view_layer, job->depsgraph);
369
370         /* Init surface */
371         if (!dynamicPaint_createUVSurface(scene, surface, job->progress, job->do_update)) {
372                 job->success = 0;
373                 return;
374         }
375
376         /* Loop through selected frames */
377         for (frame = surface->start_frame; frame <= surface->end_frame; frame++) {
378                 /* The first 10% are for createUVSurface... */
379                 const float progress = 0.1f + 0.9f * (frame - surface->start_frame) / (float)frames;
380                 surface->current_frame = frame;
381
382                 /* If user requested stop, quit baking */
383                 if (G.is_break) {
384                         job->success = 0;
385                         return;
386                 }
387
388                 /* Update progress bar */
389             *(job->do_update) = true;
390             *(job->progress) = progress;
391
392                 /* calculate a frame */
393                 scene->r.cfra = (int)frame;
394                 ED_update_for_newframe(job->bmain, scene, job->view_layer, job->depsgraph);
395                 if (!dynamicPaint_calculateFrame(surface, job->eval_ctx, scene, cObject, frame)) {
396                         job->success = 0;
397                         return;
398                 }
399
400                 /*
401                  * Save output images
402                  */
403                 {
404                         char filename[FILE_MAX];
405
406                         /* primary output layer */
407                         if (surface->flags & MOD_DPAINT_OUT1) {
408                                 /* set filepath */
409                                 BLI_join_dirfile(filename, sizeof(filename), surface->image_output_path, surface->output_name);
410                                 BLI_path_frame(filename, frame, 4);
411
412                                 /* save image */
413                                 dynamicPaint_outputSurfaceImage(surface, filename, 0);
414                         }
415                         /* secondary output */
416                         if (surface->flags & MOD_DPAINT_OUT2 && surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
417                                 /* set filepath */
418                                 BLI_join_dirfile(filename, sizeof(filename), surface->image_output_path, surface->output_name2);
419                                 BLI_path_frame(filename, frame, 4);
420
421                                 /* save image */
422                                 dynamicPaint_outputSurfaceImage(surface, filename, 1);
423                         }
424                 }
425         }
426
427         scene->r.cfra = orig_frame;
428 }
429
430 static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
431 {
432         DynamicPaintBakeJob *job = customdata;
433
434         job->stop = stop;
435         job->do_update = do_update;
436         job->progress = progress;
437         job->start = PIL_check_seconds_timer();
438         job->success = 1;
439
440         G.is_break = false; /* reset BKE_blender_test_break*/
441
442         /* XXX annoying hack: needed to prevent data corruption when changing
443          * scene frame in separate threads
444          */
445         G.is_rendering = true;
446         BKE_spacedata_draw_locks(true);
447
448         dynamicPaint_bakeImageSequence(job);
449
450         *do_update = true;
451         *stop = 0;
452 }
453
454 /*
455  * Bake Dynamic Paint image sequence surface
456  */
457 static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
458 {
459         DynamicPaintModifierData *pmd = NULL;
460         DynamicPaintCanvasSettings *canvas;
461         Object *ob = ED_object_context(C);
462         Scene *scene = CTX_data_scene(C);
463         ViewLayer *view_layer = CTX_data_view_layer(C);
464         EvaluationContext *eval_ctx = MEM_mallocN(sizeof(*eval_ctx), "EvaluationContext");
465
466         CTX_data_eval_ctx(C, eval_ctx);
467
468         DynamicPaintSurface *surface;
469
470         /*
471          * Get modifier data
472          */
473         pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
474         if (!pmd) {
475                 BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found");
476                 return OPERATOR_CANCELLED;
477         }
478
479         /* Make sure we're dealing with a canvas */
480         canvas = pmd->canvas;
481         if (!canvas) {
482                 BKE_report(op->reports, RPT_ERROR, "Bake failed: invalid canvas");
483                 return OPERATOR_CANCELLED;
484         }
485         surface = get_activeSurface(canvas);
486
487         /* Set state to baking and init surface */
488         canvas->error[0] = '\0';
489         canvas->flags |= MOD_DPAINT_BAKING;
490
491         DynamicPaintBakeJob *job = MEM_mallocN(sizeof(DynamicPaintBakeJob), "DynamicPaintBakeJob");
492         job->bmain = CTX_data_main(C);
493         job->scene = scene;
494         job->view_layer = view_layer;
495         job->depsgraph = CTX_data_depsgraph(C);
496         job->ob = ob;
497         job->canvas = canvas;
498         job->surface = surface;
499         job->eval_ctx = eval_ctx;
500
501         wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene,
502                                     "Dynamic Paint Bake", WM_JOB_PROGRESS,
503                                     WM_JOB_TYPE_DPAINT_BAKE);
504
505         WM_jobs_customdata_set(wm_job, job, dpaint_bake_free);
506         WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
507         WM_jobs_callbacks(wm_job, dpaint_bake_startjob, NULL, NULL, dpaint_bake_endjob);
508
509         WM_set_locked_interface(CTX_wm_manager(C), true);
510
511         /*  Bake Dynamic Paint  */
512         WM_jobs_start(CTX_wm_manager(C), wm_job);
513
514         return OPERATOR_FINISHED;
515 }
516
517 void DPAINT_OT_bake(wmOperatorType *ot)
518 {
519         /* identifiers */
520         ot->name = "Dynamic Paint Bake";
521         ot->description = "Bake dynamic paint image sequence surface";
522         ot->idname = "DPAINT_OT_bake";
523         
524         /* api callbacks */
525         ot->exec = dynamicpaint_bake_exec;
526         ot->poll = ED_operator_object_active_editable;
527 }