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         Depsgraph *depsgraph;
292         Object *ob;
293
294         DynamicPaintSurface *surface;
295         DynamicPaintCanvasSettings *canvas;
296
297         int success;
298         double start;
299 } DynamicPaintBakeJob;
300
301 static void dpaint_bake_free(void *customdata)
302 {
303         DynamicPaintBakeJob *job = customdata;
304         MEM_freeN(job);
305 }
306
307 static void dpaint_bake_endjob(void *customdata)
308 {
309         DynamicPaintBakeJob *job = customdata;
310         DynamicPaintCanvasSettings *canvas = job->canvas;
311
312         canvas->flags &= ~MOD_DPAINT_BAKING;
313
314         dynamicPaint_freeSurfaceData(job->surface);
315
316         G.is_rendering = false;
317         BKE_spacedata_draw_locks(false);
318
319         WM_set_locked_interface(G.main->wm.first, false);
320
321         /* Bake was successful:
322          *  Report for ended bake and how long it took */
323         if (job->success) {
324                 /* Show bake info */
325                 WM_reportf(RPT_INFO, "DynamicPaint: Bake complete! (%.2f)", PIL_check_seconds_timer() - job->start);
326         }
327         else {
328                 if (strlen(canvas->error)) { /* If an error occurred */
329                         WM_reportf(RPT_ERROR, "DynamicPaint: Bake failed: %s", canvas->error);
330                 }
331                 else { /* User canceled the bake */
332                         WM_report(RPT_WARNING, "Baking canceled!");
333                 }
334         }
335 }
336
337 /*
338  * Do actual bake operation. Loop through to-be-baked frames.
339  * Returns 0 on failure.
340  */
341 static void dynamicPaint_bakeImageSequence(DynamicPaintBakeJob *job)
342 {
343         DynamicPaintSurface *surface = job->surface;
344         Object *cObject = job->ob;
345         DynamicPaintCanvasSettings *canvas = surface->canvas;
346         Scene *scene = job->scene;
347         int frame = 1, orig_frame;
348         int frames;
349
350         frames = surface->end_frame - surface->start_frame + 1;
351         if (frames <= 0) {
352                 BLI_strncpy(canvas->error, N_("No frames to bake"), sizeof(canvas->error));
353                 return;
354         }
355
356         /* Show progress bar. */
357         *(job->do_update) = true;
358
359         /* Set frame to start point (also inits modifier data) */
360         frame = surface->start_frame;
361         orig_frame = scene->r.cfra;
362         scene->r.cfra = (int)frame;
363         ED_update_for_newframe(job->bmain, job->depsgraph);
364
365         /* Init surface */
366         if (!dynamicPaint_createUVSurface(scene, surface, job->progress, job->do_update)) {
367                 job->success = 0;
368                 return;
369         }
370
371         /* Loop through selected frames */
372         for (frame = surface->start_frame; frame <= surface->end_frame; frame++) {
373                 /* The first 10% are for createUVSurface... */
374                 const float progress = 0.1f + 0.9f * (frame - surface->start_frame) / (float)frames;
375                 surface->current_frame = frame;
376
377                 /* If user requested stop, quit baking */
378                 if (G.is_break) {
379                         job->success = 0;
380                         return;
381                 }
382
383                 /* Update progress bar */
384             *(job->do_update) = true;
385             *(job->progress) = progress;
386
387                 /* calculate a frame */
388                 scene->r.cfra = (int)frame;
389                 ED_update_for_newframe(job->bmain, job->depsgraph);
390                 if (!dynamicPaint_calculateFrame(surface, job->depsgraph, scene, cObject, frame)) {
391                         job->success = 0;
392                         return;
393                 }
394
395                 /*
396                  * Save output images
397                  */
398                 {
399                         char filename[FILE_MAX];
400
401                         /* primary output layer */
402                         if (surface->flags & MOD_DPAINT_OUT1) {
403                                 /* set filepath */
404                                 BLI_join_dirfile(filename, sizeof(filename), surface->image_output_path, surface->output_name);
405                                 BLI_path_frame(filename, frame, 4);
406
407                                 /* save image */
408                                 dynamicPaint_outputSurfaceImage(surface, filename, 0);
409                         }
410                         /* secondary output */
411                         if (surface->flags & MOD_DPAINT_OUT2 && surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
412                                 /* set filepath */
413                                 BLI_join_dirfile(filename, sizeof(filename), surface->image_output_path, surface->output_name2);
414                                 BLI_path_frame(filename, frame, 4);
415
416                                 /* save image */
417                                 dynamicPaint_outputSurfaceImage(surface, filename, 1);
418                         }
419                 }
420         }
421
422         scene->r.cfra = orig_frame;
423 }
424
425 static void dpaint_bake_startjob(void *customdata, short *stop, short *do_update, float *progress)
426 {
427         DynamicPaintBakeJob *job = customdata;
428
429         job->stop = stop;
430         job->do_update = do_update;
431         job->progress = progress;
432         job->start = PIL_check_seconds_timer();
433         job->success = 1;
434
435         G.is_break = false; /* reset BKE_blender_test_break*/
436
437         /* XXX annoying hack: needed to prevent data corruption when changing
438          * scene frame in separate threads
439          */
440         G.is_rendering = true;
441         BKE_spacedata_draw_locks(true);
442
443         dynamicPaint_bakeImageSequence(job);
444
445         *do_update = true;
446         *stop = 0;
447 }
448
449 /*
450  * Bake Dynamic Paint image sequence surface
451  */
452 static int dynamicpaint_bake_exec(struct bContext *C, struct wmOperator *op)
453 {
454         DynamicPaintModifierData *pmd = NULL;
455         DynamicPaintCanvasSettings *canvas;
456         Object *ob = ED_object_context(C);
457         Scene *scene = CTX_data_scene(C);
458
459         DynamicPaintSurface *surface;
460
461         /*
462          * Get modifier data
463          */
464         pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
465         if (!pmd) {
466                 BKE_report(op->reports, RPT_ERROR, "Bake failed: no Dynamic Paint modifier found");
467                 return OPERATOR_CANCELLED;
468         }
469
470         /* Make sure we're dealing with a canvas */
471         canvas = pmd->canvas;
472         if (!canvas) {
473                 BKE_report(op->reports, RPT_ERROR, "Bake failed: invalid canvas");
474                 return OPERATOR_CANCELLED;
475         }
476         surface = get_activeSurface(canvas);
477
478         /* Set state to baking and init surface */
479         canvas->error[0] = '\0';
480         canvas->flags |= MOD_DPAINT_BAKING;
481
482         DynamicPaintBakeJob *job = MEM_mallocN(sizeof(DynamicPaintBakeJob), "DynamicPaintBakeJob");
483         job->bmain = CTX_data_main(C);
484         job->scene = scene;
485         job->depsgraph = CTX_data_depsgraph(C);
486         job->ob = ob;
487         job->canvas = canvas;
488         job->surface = surface;
489
490         wmJob *wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), scene,
491                                     "Dynamic Paint Bake", WM_JOB_PROGRESS,
492                                     WM_JOB_TYPE_DPAINT_BAKE);
493
494         WM_jobs_customdata_set(wm_job, job, dpaint_bake_free);
495         WM_jobs_timer(wm_job, 0.1, NC_OBJECT | ND_MODIFIER, NC_OBJECT | ND_MODIFIER);
496         WM_jobs_callbacks(wm_job, dpaint_bake_startjob, NULL, NULL, dpaint_bake_endjob);
497
498         WM_set_locked_interface(CTX_wm_manager(C), true);
499
500         /* Bake Dynamic Paint */
501         WM_jobs_start(CTX_wm_manager(C), wm_job);
502
503         return OPERATOR_FINISHED;
504 }
505
506 void DPAINT_OT_bake(wmOperatorType *ot)
507 {
508         /* identifiers */
509         ot->name = "Dynamic Paint Bake";
510         ot->description = "Bake dynamic paint image sequence surface";
511         ot->idname = "DPAINT_OT_bake";
512
513         /* api callbacks */
514         ot->exec = dynamicpaint_bake_exec;
515         ot->poll = ED_operator_object_active_editable;
516 }