Undo revision 23130 which was a merge with 2.5, a messy one because I did something...
[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_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->description= "Add UV texture layer.";
203         ot->idname= "MESH_OT_uv_texture_add";
204         
205         /* api callbacks */
206         ot->exec= uv_texture_add_exec;
207
208         /* flags */
209         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
210 }
211
212 static int uv_texture_remove_exec(bContext *C, wmOperator *op)
213 {
214         Scene *scene= CTX_data_scene(C);
215         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
216         Mesh *me;
217         CustomDataLayer *cdl;
218         int index;
219
220         if(!ob || ob->type!=OB_MESH)
221                 return OPERATOR_CANCELLED;
222         
223         me= (Mesh*)ob->data;
224         index= CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
225         cdl= (index == -1)? NULL: &me->fdata.layers[index];
226
227         if(!cdl)
228                 return OPERATOR_CANCELLED;
229
230         delete_customdata_layer(C, ob, cdl);
231
232         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
233         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
234
235         return OPERATOR_FINISHED;
236 }
237
238 void MESH_OT_uv_texture_remove(wmOperatorType *ot)
239 {
240         /* identifiers */
241         ot->name= "Remove UV Texture";
242         ot->description= "Remove UV texture layer.";
243         ot->idname= "MESH_OT_uv_texture_remove";
244         
245         /* api callbacks */
246         ot->exec= uv_texture_remove_exec;
247
248         /* flags */
249         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
250 }
251
252 /*********************** vertex color operators ************************/
253
254 static int vertex_color_add_exec(bContext *C, wmOperator *op)
255 {
256         Scene *scene= CTX_data_scene(C);
257         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
258         Mesh *me;
259         EditMesh *em;
260         MCol *mcol;
261         int layernum;
262
263         if(!ob || ob->type!=OB_MESH)
264                 return OPERATOR_CANCELLED;
265         
266         me= (Mesh*)ob->data;
267
268         if(scene->obedit == ob) {
269                 em= me->edit_mesh;
270
271                 layernum= CustomData_number_of_layers(&em->fdata, CD_MCOL);
272                 if(layernum >= MAX_MCOL)
273                         return OPERATOR_CANCELLED;
274
275                 EM_add_data_layer(em, &em->fdata, CD_MCOL);
276                 CustomData_set_layer_active(&em->fdata, CD_MCOL, layernum);
277         }
278         else {
279                 layernum= CustomData_number_of_layers(&me->fdata, CD_MCOL);
280                 if(layernum >= MAX_MCOL)
281                         return OPERATOR_CANCELLED;
282
283                 mcol= me->mcol;
284
285                 if(me->mcol)
286                         CustomData_add_layer(&me->fdata, CD_MCOL, CD_DUPLICATE, me->mcol, me->totface);
287                 else
288                         CustomData_add_layer(&me->fdata, CD_MCOL, CD_DEFAULT, NULL, me->totface);
289
290                 CustomData_set_layer_active(&me->fdata, CD_MCOL, layernum);
291                 mesh_update_customdata_pointers(me);
292
293                 if(!mcol)
294                         shadeMeshMCol(scene, ob, me);
295         }
296
297         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
298         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
299
300         return OPERATOR_FINISHED;
301 }
302
303 void MESH_OT_vertex_color_add(wmOperatorType *ot)
304 {
305         /* identifiers */
306         ot->name= "Add Vertex Color";
307         ot->description= "Add vertex color layer.";
308         ot->idname= "MESH_OT_vertex_color_add";
309         
310         /* api callbacks */
311         ot->exec= vertex_color_add_exec;
312
313         /* flags */
314         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
315 }
316
317 static int vertex_color_remove_exec(bContext *C, wmOperator *op)
318 {
319         Scene *scene= CTX_data_scene(C);
320         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
321         Mesh *me;
322         CustomDataLayer *cdl;
323         int index;
324
325         if(!ob || ob->type!=OB_MESH)
326                 return OPERATOR_CANCELLED;
327         
328         me= (Mesh*)ob->data;
329         index= CustomData_get_active_layer_index(&me->fdata, CD_MCOL);
330         cdl= (index == -1)? NULL: &me->fdata.layers[index];
331
332         if(!cdl)
333                 return OPERATOR_CANCELLED;
334
335         delete_customdata_layer(C, ob, cdl);
336
337         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
338         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
339
340         return OPERATOR_FINISHED;
341 }
342
343 void MESH_OT_vertex_color_remove(wmOperatorType *ot)
344 {
345         /* identifiers */
346         ot->name= "Remove Vertex Color";
347         ot->description= "Remove vertex color layer.";
348         ot->idname= "MESH_OT_vertex_color_remove";
349         
350         /* api callbacks */
351         ot->exec= vertex_color_remove_exec;
352
353         /* flags */
354         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
355 }
356
357 /*********************** sticky operators ************************/
358
359 static int sticky_add_exec(bContext *C, wmOperator *op)
360 {
361         Scene *scene= CTX_data_scene(C);
362         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
363         Mesh *me;
364
365         if(!ob || ob->type!=OB_MESH)
366                 return OPERATOR_CANCELLED;
367         
368         me= (Mesh*)ob->data;
369
370         if(me->msticky)
371                 return OPERATOR_CANCELLED;
372
373         // XXX RE_make_sticky();
374
375         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
376         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
377
378         return OPERATOR_FINISHED;
379 }
380
381 void MESH_OT_sticky_add(wmOperatorType *ot)
382 {
383         /* identifiers */
384         ot->name= "Add Sticky";
385         ot->description= "Add sticky UV texture layer.";
386         ot->idname= "MESH_OT_sticky_add";
387         
388         /* api callbacks */
389         ot->exec= sticky_add_exec;
390
391         /* flags */
392         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
393 }
394
395 static int sticky_remove_exec(bContext *C, wmOperator *op)
396 {
397         Scene *scene= CTX_data_scene(C);
398         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
399         Mesh *me;
400
401         if(!ob || ob->type!=OB_MESH)
402                 return OPERATOR_CANCELLED;
403         
404         me= (Mesh*)ob->data;
405
406         if(!me->msticky)
407                 return OPERATOR_CANCELLED;
408
409         CustomData_free_layer_active(&me->vdata, CD_MSTICKY, me->totvert);
410         me->msticky= NULL;
411
412         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
413         WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
414
415         return OPERATOR_FINISHED;
416 }
417
418 void MESH_OT_sticky_remove(wmOperatorType *ot)
419 {
420         /* identifiers */
421         ot->name= "Remove Sticky";
422         ot->description= "Remove sticky UV texture layer.";
423         ot->idname= "MESH_OT_sticky_remove";
424         
425         /* api callbacks */
426         ot->exec= sticky_remove_exec;
427
428         /* flags */
429         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
430 }
431