6755a2be1b7fea4b419984917ec2972eec68380b
[blender-staging.git] / source / blender / editors / space_buttons / buttons_ops.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  * Contributor(s): Blender Foundation
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include "MEM_guardedalloc.h"
32
33 #include "DNA_curve_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_material_types.h"
36 #include "DNA_texture_types.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_world_types.h"
39
40 #include "BKE_context.h"
41 #include "BKE_depsgraph.h"
42 #include "BKE_font.h"
43 #include "BKE_library.h"
44 #include "BKE_material.h"
45 #include "BKE_texture.h"
46 #include "BKE_utildefines.h"
47 #include "BKE_world.h"
48
49 #include "BLI_editVert.h"
50
51 #include "RNA_access.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "ED_curve.h"
57 #include "ED_mesh.h"
58
59 #include "buttons_intern.h"     // own include
60
61 /********************** material slot operators *********************/
62
63 static int material_slot_add_exec(bContext *C, wmOperator *op)
64 {
65         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
66
67         if(!ob)
68                 return OPERATOR_CANCELLED;
69
70         object_add_material_slot(ob);
71         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
72         
73         return OPERATOR_FINISHED;
74 }
75
76 void OBJECT_OT_material_slot_add(wmOperatorType *ot)
77 {
78         /* identifiers */
79         ot->name= "Add Material Slot";
80         ot->idname= "OBJECT_OT_material_slot_add";
81         
82         /* api callbacks */
83         ot->exec= material_slot_add_exec;
84
85         /* flags */
86         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
87 }
88
89 static int material_slot_remove_exec(bContext *C, wmOperator *op)
90 {
91         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
92
93         if(!ob)
94                 return OPERATOR_CANCELLED;
95
96         object_remove_material_slot(ob);
97         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
98         
99         return OPERATOR_FINISHED;
100 }
101
102 void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
103 {
104         /* identifiers */
105         ot->name= "Remove Material Slot";
106         ot->idname= "OBJECT_OT_material_slot_remove";
107         
108         /* api callbacks */
109         ot->exec= material_slot_remove_exec;
110
111         /* flags */
112         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
113 }
114
115 static int material_slot_assign_exec(bContext *C, wmOperator *op)
116 {
117         Scene *scene= CTX_data_scene(C);
118         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
119
120         if(!ob)
121                 return OPERATOR_CANCELLED;
122
123         if(ob && ob->actcol>0) {
124                 if(ob->type == OB_MESH) {
125                         EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
126                         EditFace *efa;
127
128                         if(em) {
129                                 for(efa= em->faces.first; efa; efa=efa->next)
130                                         if(efa->f & SELECT)
131                                                 efa->mat_nr= ob->actcol-1;
132                         }
133                 }
134                 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
135                         ListBase *editnurb= ((Curve*)ob->data)->editnurb;
136                         Nurb *nu;
137
138                         if(editnurb) {
139                                 for(nu= editnurb->first; nu; nu= nu->next)
140                                         if(isNurbsel(nu))
141                                                 nu->mat_nr= nu->charidx= ob->actcol-1;
142                         }
143                 }
144                 else if(ob->type == OB_FONT) {
145                         EditFont *ef= ((Curve*)ob->data)->editfont;
146                 int i, selstart, selend;
147
148                         if(ef && BKE_font_getselection(ob, &selstart, &selend)) {
149                                 for(i=selstart; i<=selend; i++)
150                                         ef->textbufinfo[i].mat_nr = ob->actcol-1;
151                         }
152                 }
153         }
154
155     DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
156     WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
157         
158         return OPERATOR_FINISHED;
159 }
160
161 void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
162 {
163         /* identifiers */
164         ot->name= "Assign Material Slot";
165         ot->idname= "OBJECT_OT_material_slot_assign";
166         
167         /* api callbacks */
168         ot->exec= material_slot_assign_exec;
169
170         /* flags */
171         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
172 }
173
174 static int material_slot_de_select(bContext *C, int select)
175 {
176         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
177
178         if(!ob)
179                 return OPERATOR_CANCELLED;
180
181         if(ob->type == OB_MESH) {
182                 EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
183
184                 if(em) {
185                         if(select)
186                                 EM_select_by_material(em, ob->actcol-1);
187                         else
188                                 EM_deselect_by_material(em, ob->actcol-1);
189                 }
190         }
191         else if ELEM(ob->type, OB_CURVE, OB_SURF) {
192                 ListBase *editnurb= ((Curve*)ob->data)->editnurb;
193                 Nurb *nu;
194                 BPoint *bp;
195                 BezTriple *bezt;
196                 int a;
197
198                 for(nu= editnurb->first; nu; nu=nu->next) {
199                         if(nu->mat_nr==ob->actcol-1) {
200                                 if(nu->bezt) {
201                                         a= nu->pntsu;
202                                         bezt= nu->bezt;
203                                         while(a--) {
204                                                 if(bezt->hide==0) {
205                                                         if(select) {
206                                                                 bezt->f1 |= SELECT;
207                                                                 bezt->f2 |= SELECT;
208                                                                 bezt->f3 |= SELECT;
209                                                         }
210                                                         else {
211                                                                 bezt->f1 &= ~SELECT;
212                                                                 bezt->f2 &= ~SELECT;
213                                                                 bezt->f3 &= ~SELECT;
214                                                         }
215                                                 }
216                                                 bezt++;
217                                         }
218                                 }
219                                 else if(nu->bp) {
220                                         a= nu->pntsu*nu->pntsv;
221                                         bp= nu->bp;
222                                         while(a--) {
223                                                 if(bp->hide==0) {
224                                                         if(select) bp->f1 |= SELECT;
225                                                         else bp->f1 &= ~SELECT;
226                                                 }
227                                                 bp++;
228                                         }
229                                 }
230                         }
231                 }
232         }
233
234     WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
235
236         return OPERATOR_FINISHED;
237 }
238
239 static int material_slot_select_exec(bContext *C, wmOperator *op)
240 {
241         return material_slot_de_select(C, 1);
242 }
243
244 void OBJECT_OT_material_slot_select(wmOperatorType *ot)
245 {
246         /* identifiers */
247         ot->name= "Select Material Slot";
248         ot->idname= "OBJECT_OT_material_slot_select";
249         
250         /* api callbacks */
251         ot->exec= material_slot_select_exec;
252
253         /* flags */
254         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
255 }
256
257 static int material_slot_deselect_exec(bContext *C, wmOperator *op)
258 {
259         return material_slot_de_select(C, 0);
260 }
261
262 void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
263 {
264         /* identifiers */
265         ot->name= "Deselect Material Slot";
266         ot->idname= "OBJECT_OT_material_slot_deselect";
267         
268         /* api callbacks */
269         ot->exec= material_slot_deselect_exec;
270
271         /* flags */
272         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
273 }
274
275 /********************** new material operator *********************/
276
277 static int new_material_exec(bContext *C, wmOperator *op)
278 {
279         Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
280         Object *ob;
281         PointerRNA ptr;
282         int index;
283
284         /* add or copy material */
285         if(ma)
286                 ma= copy_material(ma);
287         else
288                 ma= add_material("Material");
289
290         ma->id.us--; /* compensating for us++ in assign_material */
291
292         /* attempt to assign to material slot */
293         ptr= CTX_data_pointer_get_type(C, "material_slot", &RNA_MaterialSlot);
294
295         if(ptr.data) {
296                 ob= ptr.id.data;
297                 index= (Material**)ptr.data - ob->mat;
298
299                 assign_material(ob, ma, index+1);
300
301                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
302         }
303
304         WM_event_add_notifier(C, NC_MATERIAL|NA_ADDED, ma);
305         
306         return OPERATOR_FINISHED;
307 }
308
309 void MATERIAL_OT_new(wmOperatorType *ot)
310 {
311         /* identifiers */
312         ot->name= "New Material";
313         ot->idname= "MATERIAL_OT_new";
314         
315         /* api callbacks */
316         ot->exec= new_material_exec;
317
318         /* flags */
319         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
320 }
321
322 /********************** new texture operator *********************/
323
324 static int new_texture_exec(bContext *C, wmOperator *op)
325 {
326         Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
327         ID *id;
328         MTex *mtex;
329         PointerRNA ptr;
330
331         /* add or copy texture */
332         if(tex)
333                 tex= copy_texture(tex);
334         else
335                 tex= add_texture("Texture");
336
337         id_us_min(&tex->id);
338
339         /* attempt to assign to texture slot */
340         ptr= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot);
341
342         if(ptr.data) {
343                 id= ptr.id.data;
344                 mtex= ptr.data;
345
346                 if(mtex) {
347                         if(mtex->tex)
348                                 id_us_min(&mtex->tex->id);
349                         mtex->tex= tex;
350                         id_us_plus(&tex->id);
351                 }
352
353                 /* XXX nodes, notifier .. */
354         }
355
356         WM_event_add_notifier(C, NC_TEXTURE|NA_ADDED, tex);
357         
358         return OPERATOR_FINISHED;
359 }
360
361 void TEXTURE_OT_new(wmOperatorType *ot)
362 {
363         /* identifiers */
364         ot->name= "New Texture";
365         ot->idname= "TEXTURE_OT_new";
366         
367         /* api callbacks */
368         ot->exec= new_texture_exec;
369
370         /* flags */
371         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
372 }
373
374 /********************** new world operator *********************/
375
376 static int new_world_exec(bContext *C, wmOperator *op)
377 {
378         Scene *scene= CTX_data_scene(C);
379         World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data;
380
381         /* add or copy world */
382         if(wo)
383                 wo= copy_world(wo);
384         else
385                 wo= add_world("World");
386
387         /* assign to scene */
388         if(scene->world)
389                 id_us_min(&scene->world->id);
390         scene->world= wo;
391
392         WM_event_add_notifier(C, NC_WORLD|NA_ADDED, wo);
393         
394         return OPERATOR_FINISHED;
395 }
396
397 void WORLD_OT_new(wmOperatorType *ot)
398 {
399         /* identifiers */
400         ot->name= "New World";
401         ot->idname= "WORLD_OT_new";
402         
403         /* api callbacks */
404         ot->exec= new_world_exec;
405
406         /* flags */
407         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
408 }
409