NLA SoC: Merge from 2.5
[blender.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_view3d.h"
58
59 #include "mesh_intern.h"
60
61 static void delete_customdata_layer(Mesh *me, CustomDataLayer *layer)
62 {
63         CustomData *data= (me->edit_mesh)? &me->edit_mesh->fdata: &me->fdata;
64         void *actlayerdata, *rndlayerdata, *clonelayerdata, *masklayerdata, *layerdata=layer->data;
65         int type= layer->type;
66         int index= CustomData_get_layer_index(data, type);
67         int i, actindex, rndindex, cloneindex, maskindex;
68         
69         /* ok, deleting a non-active layer needs to preserve the active layer indices.
70           to do this, we store a pointer to the .data member of both layer and the active layer,
71           (to detect if we're deleting the active layer or not), then use the active
72           layer data pointer to find where the active layer has ended up.
73           
74           this is necassary because the deletion functions only support deleting the active
75           layer. */
76         actlayerdata = data->layers[CustomData_get_active_layer_index(data, type)].data;
77         rndlayerdata = data->layers[CustomData_get_render_layer_index(data, type)].data;
78         clonelayerdata = data->layers[CustomData_get_clone_layer_index(data, type)].data;
79         masklayerdata = data->layers[CustomData_get_mask_layer_index(data, type)].data;
80         CustomData_set_layer_active(data, type, layer - &data->layers[index]);
81
82         if(me->edit_mesh) {
83                 EM_free_data_layer(me->edit_mesh, data, type);
84         }
85         else {
86                 CustomData_free_layer_active(data, type, me->totface);
87                 mesh_update_customdata_pointers(me);
88         }
89
90         if(!CustomData_has_layer(data, type))
91                 if(type == CD_MCOL && (G.f & G_VERTEXPAINT))
92                         G.f &= ~G_VERTEXPAINT; /* get out of vertexpaint mode */
93
94         /* reconstruct active layer */
95         if (actlayerdata != layerdata) {
96                 /* find index */
97                 actindex = CustomData_get_layer_index(data, type);
98                 for (i=actindex; i<data->totlayer; i++) {
99                         if (data->layers[i].data == actlayerdata) {
100                                 actindex = i - actindex;
101                                 break;
102                         }
103                 }
104                 
105                 /* set index */
106                 CustomData_set_layer_active(data, type, actindex);
107         }
108         
109         if (rndlayerdata != layerdata) {
110                 /* find index */
111                 rndindex = CustomData_get_layer_index(data, type);
112                 for (i=rndindex; i<data->totlayer; i++) {
113                         if (data->layers[i].data == rndlayerdata) {
114                                 rndindex = i - rndindex;
115                                 break;
116                         }
117                 }
118                 
119                 /* set index */
120                 CustomData_set_layer_render(data, type, rndindex);
121         }
122         
123         if (clonelayerdata != layerdata) {
124                 /* find index */
125                 cloneindex = CustomData_get_layer_index(data, type);
126                 for (i=cloneindex; i<data->totlayer; i++) {
127                         if (data->layers[i].data == clonelayerdata) {
128                                 cloneindex = i - cloneindex;
129                                 break;
130                         }
131                 }
132                 
133                 /* set index */
134                 CustomData_set_layer_clone(data, type, cloneindex);
135         }
136         
137         if (masklayerdata != layerdata) {
138                 /* find index */
139                 maskindex = CustomData_get_layer_index(data, type);
140                 for (i=maskindex; i<data->totlayer; i++) {
141                         if (data->layers[i].data == masklayerdata) {
142                                 maskindex = i - maskindex;
143                                 break;
144                         }
145                 }
146                 
147                 /* set index */
148                 CustomData_set_layer_mask(data, type, maskindex);
149         }
150 }
151
152 /*********************** UV texture operators ************************/
153
154 static int uv_texture_add_exec(bContext *C, wmOperator *op)
155 {
156         Scene *scene= CTX_data_scene(C);
157         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
158         Mesh *me;
159         EditMesh *em;
160         int layernum;
161
162         if(!ob || ob->type!=OB_MESH)
163                 return OPERATOR_CANCELLED;
164         
165         me= (Mesh*)ob->data;
166
167         if(scene->obedit == ob) {
168                 em= me->edit_mesh;
169
170                 layernum= CustomData_number_of_layers(&em->fdata, CD_MTFACE);
171                 if(layernum >= MAX_MTFACE)
172                         return OPERATOR_CANCELLED;
173
174                 EM_add_data_layer(em, &em->fdata, CD_MTFACE);
175                 CustomData_set_layer_active(&em->fdata, CD_MTFACE, layernum);
176         }
177         else if(ob) {
178                 layernum= CustomData_number_of_layers(&me->fdata, CD_MTFACE);
179                 if(layernum >= MAX_MTFACE)
180                         return OPERATOR_CANCELLED;
181
182                 if(me->mtface)
183                         CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DUPLICATE, me->mtface, me->totface);
184                 else
185                         CustomData_add_layer(&me->fdata, CD_MTFACE, CD_DEFAULT, NULL, me->totface);
186
187                 CustomData_set_layer_active(&me->fdata, CD_MTFACE, layernum);
188                 mesh_update_customdata_pointers(me);
189         }
190
191         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
192         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
193
194         return OPERATOR_FINISHED;
195 }
196
197 void MESH_OT_uv_texture_add(wmOperatorType *ot)
198 {
199         /* identifiers */
200         ot->name= "Add UV Texture";
201         ot->idname= "MESH_OT_uv_texture_add";
202         
203         /* api callbacks */
204         ot->exec= uv_texture_add_exec;
205
206         /* flags */
207         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
208 }
209
210 static int uv_texture_remove_exec(bContext *C, wmOperator *op)
211 {
212         Scene *scene= CTX_data_scene(C);
213         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
214         Mesh *me;
215         CustomDataLayer *cdl;
216         int index;
217
218         if(!ob || ob->type!=OB_MESH)
219                 return OPERATOR_CANCELLED;
220         
221         me= (Mesh*)ob->data;
222         index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
223         cdl= (index == -1)? NULL: &me->fdata.layers[index];
224
225         if(!cdl)
226                 return OPERATOR_CANCELLED;
227
228         delete_customdata_layer(me, cdl);
229
230         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
231         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
232
233         return OPERATOR_FINISHED;
234 }
235
236 void MESH_OT_uv_texture_remove(wmOperatorType *ot)
237 {
238         /* identifiers */
239         ot->name= "Remove UV Texture";
240         ot->idname= "MESH_OT_uv_texture_remove";
241         
242         /* api callbacks */
243         ot->exec= uv_texture_remove_exec;
244
245         /* flags */
246         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
247 }
248
249 /*********************** vertex color operators ************************/
250
251 static int vertex_color_add_exec(bContext *C, wmOperator *op)
252 {
253         Scene *scene= CTX_data_scene(C);
254         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
255         Mesh *me;
256         EditMesh *em;
257         MCol *mcol;
258         int layernum;
259
260         if(!ob || ob->type!=OB_MESH)
261                 return OPERATOR_CANCELLED;
262         
263         me= (Mesh*)ob->data;
264
265         if(scene->obedit == ob) {
266                 em= me->edit_mesh;
267
268                 layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
269                 if(layernum >= MAX_MCOL)
270                         return OPERATOR_CANCELLED;
271
272                 EM_add_data_layer(em, &em->fdata, CD_MCOL);
273                 CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
274         }
275         else {
276                 layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
277                 if(layernum >= MAX_MCOL)
278                         return OPERATOR_CANCELLED;
279
280                 mcol= me->mcol;
281
282                 if(me->mcol)
283                         CustomData_add_layer(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface);
284                 else
285                         CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
286
287                 CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
288                 mesh_update_customdata_pointers(me);
289
290                 if(!mcol)
291                         shadeMeshMCol(scene, ob, me);
292         }
293
294         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
295         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
296
297         return OPERATOR_FINISHED;
298 }
299
300 void MESH_OT_vertex_color_add(wmOperatorType *ot)
301 {
302         /* identifiers */
303         ot->name= "Add Vertex Color";
304         ot->idname= "MESH_OT_vertex_color_add";
305         
306         /* api callbacks */
307         ot->exec= vertex_color_add_exec;
308
309         /* flags */
310         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
311 }
312
313 static int vertex_color_remove_exec(bContext *C, wmOperator *op)
314 {
315         Scene *scene= CTX_data_scene(C);
316         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
317         Mesh *me;
318         CustomDataLayer *cdl;
319         int index;
320
321         if(!ob || ob->type!=OB_MESH)
322                 return OPERATOR_CANCELLED;
323         
324         me= (Mesh*)ob->data;
325         index= CustomData_get_active_layer_index(&me->fdata, CD_MCOL);
326         cdl= (index == -1)? NULL: &me->fdata.layers[index];
327
328         if(!cdl)
329                 return OPERATOR_CANCELLED;
330
331         delete_customdata_layer(me, cdl);
332
333         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
334         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
335
336         return OPERATOR_FINISHED;
337 }
338
339 void MESH_OT_vertex_color_remove(wmOperatorType *ot)
340 {
341         /* identifiers */
342         ot->name= "Remove Vertex Color";
343         ot->idname= "MESH_OT_vertex_color_remove";
344         
345         /* api callbacks */
346         ot->exec= vertex_color_remove_exec;
347
348         /* flags */
349         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
350 }
351
352 /*********************** sticky operators ************************/
353
354 static int sticky_add_exec(bContext *C, wmOperator *op)
355 {
356         Scene *scene= CTX_data_scene(C);
357         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
358         Mesh *me;
359
360         if(!ob || ob->type!=OB_MESH)
361                 return OPERATOR_CANCELLED;
362         
363         me= (Mesh*)ob->data;
364
365         if(me->msticky)
366                 return OPERATOR_CANCELLED;
367
368         // XXX RE_make_sticky();
369
370         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
371         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
372
373         return OPERATOR_FINISHED;
374 }
375
376 void MESH_OT_sticky_add(wmOperatorType *ot)
377 {
378         /* identifiers */
379         ot->name= "Add Sticky";
380         ot->idname= "MESH_OT_sticky_add";
381         
382         /* api callbacks */
383         ot->exec= sticky_add_exec;
384
385         /* flags */
386         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
387 }
388
389 static int sticky_remove_exec(bContext *C, wmOperator *op)
390 {
391         Scene *scene= CTX_data_scene(C);
392         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
393         Mesh *me;
394
395         if(!ob || ob->type!=OB_MESH)
396                 return OPERATOR_CANCELLED;
397         
398         me= (Mesh*)ob->data;
399
400         if(!me->msticky)
401                 return OPERATOR_CANCELLED;
402
403         CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
404         me->msticky= NULL;
405
406         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
407         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
408
409         return OPERATOR_FINISHED;
410 }
411
412 void MESH_OT_sticky_remove(wmOperatorType *ot)
413 {
414         /* identifiers */
415         ot->name= "Remove Sticky";
416         ot->idname= "MESH_OT_sticky_remove";
417         
418         /* api callbacks */
419         ot->exec= sticky_remove_exec;
420
421         /* flags */
422         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
423 }
424