e06381780db8627d1394b29c6a34ee3e971ab5c1
[blender-staging.git] / source / blender / editors / mesh / mesh_layers.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2009 Blender Foundation.
21  * All rights reserved.
22  *
23  * 
24  * Contributor(s): Blender Foundation
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <stdlib.h>
30 #include <math.h>
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_customdata_types.h"
35 #include "DNA_mesh_types.h"
36 #include "DNA_meshdata_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_windowmanager_types.h"
40
41 #include "BKE_context.h"
42 #include "BKE_customdata.h"
43 #include "BKE_depsgraph.h"
44 #include "BKE_displist.h"
45 #include "BKE_global.h"
46 #include "BKE_mesh.h"
47
48 #include "BLI_editVert.h"
49
50 #include "RNA_access.h"
51 #include "RNA_define.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "ED_mesh.h"
57 #include "ED_object.h"
58 #include "ED_view3d.h"
59
60 #include "mesh_intern.h"
61
62 static void delete_customdata_layer(bContext *C, Object *ob, CustomDataLayer *layer)
63 {
64         Mesh *me = ob->data;
65         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
66         void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data;
67         int type= layer->type;
68         int index= CustomData_get_layer_index(data, type);
69         int i, actindex, rndindex, cloneindex, maskindex;
70         
71         /* ok, deleting a non-active layer needs to preserve the active layer indices.
72           to do this, we store a pointer to the .data member of both layer and the active layer,
73           (to detect if we're deleting the active layer or not), then use the active
74           layer data pointer to find where the active layer has ended up.
75           
76           this is necassary because the deletion functions only support deleting the active
77           layer. */
78         actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
79         rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
80         clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
81         masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data;
82         CustomData_set_layer_active(data, type, layer - &data->layers[index]);
83
84         if(me->edit_mesh) {
85                 EM_free_data_layer(me->edit_mesh, data, type);
86         }
87         else {
88                 CustomData_free_layer_active(data, type, me->totface);
89                 mesh_update_customdata_pointers(me);
90         }
91
92         if(!CustomData_has_layer(data, type) && (type == CD_MCOL && (ob->mode & OB_MODE_VERTEX_PAINT)))
93                 ED_object_toggle_modes(C, OB_MODE_VERTEX_PAINT);
94
95         /* reconstruct active layer */
96         if (actlayerdata != layerdata) {
97                 /* find index */
98                 actindex = CustomData_get_layer_index(data, type);
99                 for (i=actindex; i<data->totlayer; i++) {
100                         if (data->layers[i].data == actlayerdata) {
101                                 actindex = i - actindex;
102                                 break;
103                         }
104                 }
105                 
106                 /* set index */
107                 CustomData_set_layer_active(data, type, actindex);
108         }
109         
110         if (rndlayerdata != layerdata) {
111                 /* find index */
112                 rndindex = CustomData_get_layer_index(data, type);
113                 for (i=rndindex; i<data->totlayer; i++) {
114                         if (data->layers[i].data == rndlayerdata) {
115                                 rndindex = i - rndindex;
116                                 break;
117                         }
118                 }
119                 
120                 /* set index */
121                 CustomData_set_layer_render(data, type, rndindex);
122         }
123         
124         if (clonelayerdata != layerdata) {
125                 /* find index */
126                 cloneindex = CustomData_get_layer_index(data, type);
127                 for (i=cloneindex; i<data->totlayer; i++) {
128                         if (data->layers[i].data == clonelayerdata) {
129                                 cloneindex = i - cloneindex;
130                                 break;
131                         }
132                 }
133                 
134                 /* set index */
135                 CustomData_set_layer_clone(data, type, cloneindex);
136         }
137         
138         if (masklayerdata != layerdata) {
139                 /* find index */
140                 maskindex = CustomData_get_layer_index(data, type);
141                 for (i=maskindex; i<data->totlayer; i++) {
142                         if (data->layers[i].data == masklayerdata) {
143                                 maskindex = i - maskindex;
144                                 break;
145                         }
146                 }
147                 
148                 /* set index */
149                 CustomData_set_layer_mask(data, type, maskindex);
150         }
151 }
152
153 /*********************** UV texture operators ************************/
154
155 static int uv_texture_add_exec(bContext *C, wmOperator *op)
156 {
157         Scene *scene= CTX_data_scene(C);
158         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
159         Mesh *me;
160         EditMesh *em;
161         int layernum;
162
163         if(!ob || ob->type!=OB_MESH)
164                 return OPERATOR_CANCELLED;
165         
166         me= (Mesh*)ob->data;
167
168         if(scene->obedit == ob) {
169                 em= me->edit_mesh;
170
171                 layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
172                 if(layernum >= MAX_MTFACE)
173                         return OPERATOR_CANCELLED;
174
175                 EM_add_data_layer(em, &em->fdata, CD_MTFACE);
176                 CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
177         }
178         else if(ob) {
179                 layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
180                 if(layernum >= MAX_MTFACE)
181                         return OPERATOR_CANCELLED;
182
183                 if(me->mtface)
184                         CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface);
185                 else
186                         CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface);
187
188                 CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
189                 mesh_update_customdata_pointers(me);
190         }
191
192         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
193         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
194
195         return OPERATOR_FINISHED;
196 }
197
198 void MESH_OT_uv_texture_add(wmOperatorType *ot)
199 {
200         /* identifiers */
201         ot->name= "Add UV Texture";
202         ot->idname= "MESH_OT_uv_texture_add";
203         
204         /* api callbacks */
205         ot->exec= uv_texture_add_exec;
206
207         /* flags */
208         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
209 }
210
211 static int uv_texture_remove_exec(bContext *C, wmOperator *op)
212 {
213         Scene *scene= CTX_data_scene(C);
214         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
215         Mesh *me;
216         CustomDataLayer *cdl;
217         int index;
218
219         if(!ob || ob->type!=OB_MESH)
220                 return OPERATOR_CANCELLED;
221         
222         me= (Mesh*)ob->data;
223         index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
224         cdl= (index == -1)? NULL: &me->fdata.layers[index];
225
226         if(!cdl)
227                 return OPERATOR_CANCELLED;
228
229         delete_customdata_layer(C, ob, cdl);
230
231         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
232         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
233
234         return OPERATOR_FINISHED;
235 }
236
237 void MESH_OT_uv_texture_remove(wmOperatorType *ot)
238 {
239         /* identifiers */
240         ot->name= "Remove UV Texture";
241         ot->idname= "MESH_OT_uv_texture_remove";
242         
243         /* api callbacks */
244         ot->exec= uv_texture_remove_exec;
245
246         /* flags */
247         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
248 }
249
250 /*********************** vertex color operators ************************/
251
252 static int vertex_color_add_exec(bContext *C, wmOperator *op)
253 {
254         Scene *scene= CTX_data_scene(C);
255         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
256         Mesh *me;
257         EditMesh *em;
258         MCol *mcol;
259         int layernum;
260
261         if(!ob || ob->type!=OB_MESH)
262                 return OPERATOR_CANCELLED;
263         
264         me= (Mesh*)ob->data;
265
266         if(scene->obedit == ob) {
267                 em= me->edit_mesh;
268
269                 layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
270                 if(layernum >= MAX_MCOL)
271                         return OPERATOR_CANCELLED;
272
273                 EM_add_data_layer(em, &em->fdata, CD_MCOL);
274                 CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
275         }
276         else {
277                 layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
278                 if(layernum >= MAX_MCOL)
279                         return OPERATOR_CANCELLED;
280
281                 mcol= me->mcol;
282
283                 if(me->mcol)
284                         CustomData_add_layer(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface);
285                 else
286                         CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
287
288                 CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
289                 mesh_update_customdata_pointers(me);
290
291                 if(!mcol)
292                         shadeMeshMCol(scene, ob, me);
293         }
294
295         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
296         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
297
298         return OPERATOR_FINISHED;
299 }
300
301 void MESH_OT_vertex_color_add(wmOperatorType *ot)
302 {
303         /* identifiers */
304         ot->name= "Add Vertex Color";
305         ot->idname= "MESH_OT_vertex_color_add";
306         
307         /* api callbacks */
308         ot->exec= vertex_color_add_exec;
309
310         /* flags */
311         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
312 }
313
314 static int vertex_color_remove_exec(bContext *C, wmOperator *op)
315 {
316         Scene *scene= CTX_data_scene(C);
317         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
318         Mesh *me;
319         CustomDataLayer *cdl;
320         int index;
321
322         if(!ob || ob->type!=OB_MESH)
323                 return OPERATOR_CANCELLED;
324         
325         me= (Mesh*)ob->data;
326         index= CustomData_get_active_layer_index(&me->fdata, CD_MCOL);
327         cdl= (index == -1)? NULL: &me->fdata.layers[index];
328
329         if(!cdl)
330                 return OPERATOR_CANCELLED;
331
332         delete_customdata_layer(C, ob, cdl);
333
334         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
335         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
336
337         return OPERATOR_FINISHED;
338 }
339
340 void MESH_OT_vertex_color_remove(wmOperatorType *ot)
341 {
342         /* identifiers */
343         ot->name= "Remove Vertex Color";
344         ot->idname= "MESH_OT_vertex_color_remove";
345         
346         /* api callbacks */
347         ot->exec= vertex_color_remove_exec;
348
349         /* flags */
350         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
351 }
352
353 /*********************** sticky operators ************************/
354
355 static int sticky_add_exec(bContext *C, wmOperator *op)
356 {
357         Scene *scene= CTX_data_scene(C);
358         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
359         Mesh *me;
360
361         if(!ob || ob->type!=OB_MESH)
362                 return OPERATOR_CANCELLED;
363         
364         me= (Mesh*)ob->data;
365
366         if(me->msticky)
367                 return OPERATOR_CANCELLED;
368
369         // XXX RE_make_sticky();
370
371         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
372         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
373
374         return OPERATOR_FINISHED;
375 }
376
377 void MESH_OT_sticky_add(wmOperatorType *ot)
378 {
379         /* identifiers */
380         ot->name= "Add Sticky";
381         ot->idname= "MESH_OT_sticky_add";
382         
383         /* api callbacks */
384         ot->exec= sticky_add_exec;
385
386         /* flags */
387         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
388 }
389
390 static int sticky_remove_exec(bContext *C, wmOperator *op)
391 {
392         Scene *scene= CTX_data_scene(C);
393         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
394         Mesh *me;
395
396         if(!ob || ob->type!=OB_MESH)
397                 return OPERATOR_CANCELLED;
398         
399         me= (Mesh*)ob->data;
400
401         if(!me->msticky)
402                 return OPERATOR_CANCELLED;
403
404         CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
405         me->msticky= NULL;
406
407         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
408         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
409
410         return OPERATOR_FINISHED;
411 }
412
413 void MESH_OT_sticky_remove(wmOperatorType *ot)
414 {
415         /* identifiers */
416         ot->name= "Remove Sticky";
417         ot->idname= "MESH_OT_sticky_remove";
418         
419         /* api callbacks */
420         ot->exec= sticky_remove_exec;
421
422         /* flags */
423         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
424 }
425