Merge with trunk r40782
[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 #include "DNA_dynamicpaint_types.h"
22 #include "DNA_modifier_types.h"
23 #include "DNA_object_types.h"
24 #include "DNA_scene_types.h"
25
26 #include "BKE_context.h"
27 #include "BKE_deform.h"
28 #include "BKE_depsgraph.h"
29 #include "BKE_dynamicpaint.h"
30 #include "BKE_modifier.h"
31
32 #include "ED_mesh.h"
33 #include "ED_screen.h"
34
35 #include "RNA_access.h"
36 #include "RNA_define.h"
37 #include "RNA_enum_types.h"
38
39 #include "WM_types.h"
40 #include "WM_api.h"
41
42 static int dynamicpaint_bake_exec(bContext *C, wmOperator *op)
43 {
44         /* Bake dynamic paint */
45         if(!dynamicPaint_initBake(C, op)) {
46                 return OPERATOR_CANCELLED;}
47
48         return OPERATOR_FINISHED;
49 }
50
51 void DPAINT_OT_bake(wmOperatorType *ot)
52 {
53         /* identifiers */
54         ot->name= "Dynamic Paint Bake";
55         ot->description= "Bake dynamic paint image sequence surface";
56         ot->idname= "DPAINT_OT_bake";
57         
58         /* api callbacks */
59         ot->exec= dynamicpaint_bake_exec;
60         ot->poll= ED_operator_object_active_editable;
61 }
62
63 static int surface_slot_add_exec(bContext *C, wmOperator *op)
64 {
65         DynamicPaintModifierData *pmd = 0;
66         Object *cObject = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
67         DynamicPaintSurface *surface;
68
69         /* Make sure we're dealing with a canvas */
70         pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
71         if (!pmd) return OPERATOR_CANCELLED;
72         if (!pmd->canvas) return OPERATOR_CANCELLED;
73
74         surface = dynamicPaint_createNewSurface(pmd->canvas, CTX_data_scene(C));
75
76         if (!surface) return OPERATOR_CANCELLED;
77
78         /* set preview for this surface only and set active */
79         pmd->canvas->active_sur = 0;
80         for(surface=surface->prev; surface; surface=surface->prev) {
81                                 surface->flags &= ~MOD_DPAINT_PREVIEW;
82                                 pmd->canvas->active_sur++;
83         }
84
85         return OPERATOR_FINISHED;
86 }
87
88 /* add surface slot */
89 void DPAINT_OT_surface_slot_add(wmOperatorType *ot)
90 {
91         /* identifiers */
92         ot->name= "Add Surface Slot";
93         ot->idname= "DPAINT_OT_surface_slot_add";
94         ot->description="Add a new Dynamic Paint surface slot";
95         
96         /* api callbacks */
97         ot->exec= surface_slot_add_exec;
98         ot->poll= ED_operator_object_active_editable;
99
100         /* flags */
101         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
102 }
103
104 static int surface_slot_remove_exec(bContext *C, wmOperator *op)
105 {
106         DynamicPaintModifierData *pmd = 0;
107         Object *cObject = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
108         DynamicPaintSurface *surface;
109         int id=0;
110
111         /* Make sure we're dealing with a canvas */
112         pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
113         if (!pmd) return OPERATOR_CANCELLED;
114         if (!pmd->canvas) return OPERATOR_CANCELLED;
115
116         surface = pmd->canvas->surfaces.first;
117
118         /* find active surface and remove it */
119         for(; surface; surface=surface->next) {
120                 if(id == pmd->canvas->active_sur) {
121                                 pmd->canvas->active_sur -= 1;
122                                 dynamicPaint_freeSurface(surface);
123                                 break;
124                         }
125                 id++;
126         }
127
128         dynamicPaint_resetPreview(pmd->canvas);
129         DAG_id_tag_update(&cObject->id, OB_RECALC_DATA);
130         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, cObject);
131
132         return OPERATOR_FINISHED;
133 }
134
135 /* remove surface slot */
136 void DPAINT_OT_surface_slot_remove(wmOperatorType *ot)
137 {
138         /* identifiers */
139         ot->name= "Remove Surface Slot";
140         ot->idname= "DPAINT_OT_surface_slot_remove";
141         ot->description="Remove the selected surface slot";
142         
143         /* api callbacks */
144         ot->exec= surface_slot_remove_exec;
145         ot->poll= ED_operator_object_active_editable;
146
147         /* flags */
148         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
149 }
150
151 static int type_toggle_exec(bContext *C, wmOperator *op)
152 {
153
154         Object *cObject = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
155         Scene *scene = CTX_data_scene(C);
156         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(cObject, eModifierType_DynamicPaint);
157         int type= RNA_enum_get(op->ptr, "type");
158
159         if (!pmd) return OPERATOR_CANCELLED;
160
161         /* if type is already enabled, toggle it off */
162         if (type == MOD_DYNAMICPAINT_TYPE_CANVAS && pmd->canvas) {
163                         dynamicPaint_freeCanvas(pmd);
164         }
165         else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH && pmd->brush) {
166                         dynamicPaint_freeBrush(pmd);
167         }
168         /* else create a new type */
169         else {
170                 if (!dynamicPaint_createType(pmd, type, scene))
171                         return OPERATOR_CANCELLED;
172         }
173         
174         /* update dependancy */
175         DAG_id_tag_update(&cObject->id, OB_RECALC_DATA);
176         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, cObject);
177         DAG_scene_sort(CTX_data_main(C), scene);
178
179         return OPERATOR_FINISHED;
180 }
181
182 void DPAINT_OT_type_toggle(wmOperatorType *ot)
183 {
184         PropertyRNA *prop;
185
186         /* identifiers */
187         ot->name= "Toggle Type Active";
188         ot->idname= "DPAINT_OT_type_toggle";
189         ot->description = "Toggles whether given type is active or not";
190         
191         /* api callbacks */
192         ot->exec= type_toggle_exec;
193         ot->poll= ED_operator_object_active_editable;
194         
195         /* flags */
196         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
197         
198         /* properties */
199         prop= RNA_def_enum(ot->srna, "type", prop_dynamicpaint_type_items, MOD_DYNAMICPAINT_TYPE_CANVAS, "Type", "");
200         ot->prop= prop;
201 }
202
203 static int output_toggle_exec(bContext *C, wmOperator *op)
204 {
205
206         Object *ob = CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
207         Scene *scene = CTX_data_scene(C);
208         DynamicPaintModifierData *pmd = (DynamicPaintModifierData *)modifiers_findByType(ob, eModifierType_DynamicPaint);
209         int index= RNA_int_get(op->ptr, "index");
210
211         if (!pmd) return OPERATOR_CANCELLED;
212
213
214         /* if type is already enabled, toggle it off */
215         if (pmd->canvas) {
216                         DynamicPaintSurface *surface = get_activeSurface(pmd->canvas);
217
218                         if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) {
219                                 int exists = dynamicPaint_outputLayerExists(surface, ob, index);
220                                 char *name;
221                                 
222                                 if (index == 0)
223                                         name = surface->output_name;
224                                 else if (index == 1)
225                                         name = surface->output_name2;
226
227                                 /* Vertex Color Layer */
228                                 if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) {
229                                         if (!exists)
230                                                 ED_mesh_color_add(C, scene, ob, ob->data, name, 1);
231                                         else 
232                                                 ED_mesh_color_remove_named(C, ob, ob->data, name);
233                                 }
234                                 /* Vertex Weight Layer */
235                                 else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
236                                         if (!exists)
237                                                 ED_vgroup_add_name(ob, name);
238                                         else {
239                                                 bDeformGroup *defgroup = defgroup_find_name(ob, name);
240                                                 if (defgroup) ED_vgroup_delete(ob, defgroup);
241                                         }
242                                 }
243                         }
244         }
245
246         return OPERATOR_FINISHED;
247 }
248
249 void DPAINT_OT_output_toggle(wmOperatorType *ot)
250 {
251         PropertyRNA *prop;
252
253         /* identifiers */
254         ot->name= "Toggle Output Layer";
255         ot->idname= "DPAINT_OT_output_toggle";
256         ot->description = "Adds or removes Dynamic Paint output data layer.";
257         
258         /* api callbacks */
259         ot->exec= output_toggle_exec;
260         ot->poll= ED_operator_object_active_editable;
261         
262         /* flags */
263         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
264         
265         /* properties */
266         prop= RNA_def_int(ot->srna, "index", 0, 0, 1, "Index", "", 0, 1);
267         ot->prop= prop;
268 }