NLA SoC: Merge from 2.5
[blender.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_particle.h"
46 #include "BKE_texture.h"
47 #include "BKE_utildefines.h"
48 #include "BKE_world.h"
49
50 #include "BLI_editVert.h"
51
52 #include "RNA_access.h"
53
54 #include "WM_api.h"
55 #include "WM_types.h"
56
57 #include "ED_curve.h"
58 #include "ED_mesh.h"
59
60 #include "buttons_intern.h"     // own include
61
62 /********************** material slot operators *********************/
63
64 static int material_slot_add_exec(bContext *C, wmOperator *op)
65 {
66         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
67
68         if(!ob)
69                 return OPERATOR_CANCELLED;
70
71         object_add_material_slot(ob);
72         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
73         
74         return OPERATOR_FINISHED;
75 }
76
77 void OBJECT_OT_material_slot_add(wmOperatorType *ot)
78 {
79         /* identifiers */
80         ot->name= "Add Material Slot";
81         ot->idname= "OBJECT_OT_material_slot_add";
82         
83         /* api callbacks */
84         ot->exec= material_slot_add_exec;
85
86         /* flags */
87         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
88 }
89
90 static int material_slot_remove_exec(bContext *C, wmOperator *op)
91 {
92         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
93
94         if(!ob)
95                 return OPERATOR_CANCELLED;
96
97         object_remove_material_slot(ob);
98         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
99         
100         return OPERATOR_FINISHED;
101 }
102
103 void OBJECT_OT_material_slot_remove(wmOperatorType *ot)
104 {
105         /* identifiers */
106         ot->name= "Remove Material Slot";
107         ot->idname= "OBJECT_OT_material_slot_remove";
108         
109         /* api callbacks */
110         ot->exec= material_slot_remove_exec;
111
112         /* flags */
113         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
114 }
115
116 static int material_slot_assign_exec(bContext *C, wmOperator *op)
117 {
118         Scene *scene= CTX_data_scene(C);
119         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
120
121         if(!ob)
122                 return OPERATOR_CANCELLED;
123
124         if(ob && ob->actcol>0) {
125                 if(ob->type == OB_MESH) {
126                         EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
127                         EditFace *efa;
128
129                         if(em) {
130                                 for(efa= em->faces.first; efa; efa=efa->next)
131                                         if(efa->f & SELECT)
132                                                 efa->mat_nr= ob->actcol-1;
133                         }
134                 }
135                 else if(ELEM(ob->type, OB_CURVE, OB_SURF)) {
136                         ListBase *editnurb= ((Curve*)ob->data)->editnurb;
137                         Nurb *nu;
138
139                         if(editnurb) {
140                                 for(nu= editnurb->first; nu; nu= nu->next)
141                                         if(isNurbsel(nu))
142                                                 nu->mat_nr= nu->charidx= ob->actcol-1;
143                         }
144                 }
145                 else if(ob->type == OB_FONT) {
146                         EditFont *ef= ((Curve*)ob->data)->editfont;
147                 int i, selstart, selend;
148
149                         if(ef && BKE_font_getselection(ob, &selstart, &selend)) {
150                                 for(i=selstart; i<=selend; i++)
151                                         ef->textbufinfo[i].mat_nr = ob->actcol-1;
152                         }
153                 }
154         }
155
156     DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
157     WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
158         
159         return OPERATOR_FINISHED;
160 }
161
162 void OBJECT_OT_material_slot_assign(wmOperatorType *ot)
163 {
164         /* identifiers */
165         ot->name= "Assign Material Slot";
166         ot->idname= "OBJECT_OT_material_slot_assign";
167         
168         /* api callbacks */
169         ot->exec= material_slot_assign_exec;
170
171         /* flags */
172         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
173 }
174
175 static int material_slot_de_select(bContext *C, int select)
176 {
177         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
178
179         if(!ob)
180                 return OPERATOR_CANCELLED;
181
182         if(ob->type == OB_MESH) {
183                 EditMesh *em= ((Mesh*)ob->data)->edit_mesh;
184
185                 if(em) {
186                         if(select)
187                                 EM_select_by_material(em, ob->actcol-1);
188                         else
189                                 EM_deselect_by_material(em, ob->actcol-1);
190                 }
191         }
192         else if ELEM(ob->type, OB_CURVE, OB_SURF) {
193                 ListBase *editnurb= ((Curve*)ob->data)->editnurb;
194                 Nurb *nu;
195                 BPoint *bp;
196                 BezTriple *bezt;
197                 int a;
198
199                 for(nu= editnurb->first; nu; nu=nu->next) {
200                         if(nu->mat_nr==ob->actcol-1) {
201                                 if(nu->bezt) {
202                                         a= nu->pntsu;
203                                         bezt= nu->bezt;
204                                         while(a--) {
205                                                 if(bezt->hide==0) {
206                                                         if(select) {
207                                                                 bezt->f1 |= SELECT;
208                                                                 bezt->f2 |= SELECT;
209                                                                 bezt->f3 |= SELECT;
210                                                         }
211                                                         else {
212                                                                 bezt->f1 &= ~SELECT;
213                                                                 bezt->f2 &= ~SELECT;
214                                                                 bezt->f3 &= ~SELECT;
215                                                         }
216                                                 }
217                                                 bezt++;
218                                         }
219                                 }
220                                 else if(nu->bp) {
221                                         a= nu->pntsu*nu->pntsv;
222                                         bp= nu->bp;
223                                         while(a--) {
224                                                 if(bp->hide==0) {
225                                                         if(select) bp->f1 |= SELECT;
226                                                         else bp->f1 &= ~SELECT;
227                                                 }
228                                                 bp++;
229                                         }
230                                 }
231                         }
232                 }
233         }
234
235     WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob);
236
237         return OPERATOR_FINISHED;
238 }
239
240 static int material_slot_select_exec(bContext *C, wmOperator *op)
241 {
242         return material_slot_de_select(C, 1);
243 }
244
245 void OBJECT_OT_material_slot_select(wmOperatorType *ot)
246 {
247         /* identifiers */
248         ot->name= "Select Material Slot";
249         ot->idname= "OBJECT_OT_material_slot_select";
250         
251         /* api callbacks */
252         ot->exec= material_slot_select_exec;
253
254         /* flags */
255         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
256 }
257
258 static int material_slot_deselect_exec(bContext *C, wmOperator *op)
259 {
260         return material_slot_de_select(C, 0);
261 }
262
263 void OBJECT_OT_material_slot_deselect(wmOperatorType *ot)
264 {
265         /* identifiers */
266         ot->name= "Deselect Material Slot";
267         ot->idname= "OBJECT_OT_material_slot_deselect";
268         
269         /* api callbacks */
270         ot->exec= material_slot_deselect_exec;
271
272         /* flags */
273         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
274 }
275
276 /********************** new material operator *********************/
277
278 static int new_material_exec(bContext *C, wmOperator *op)
279 {
280         Material *ma= CTX_data_pointer_get_type(C, "material", &RNA_Material).data;
281         Object *ob;
282         PointerRNA ptr;
283         int index;
284
285         /* add or copy material */
286         if(ma)
287                 ma= copy_material(ma);
288         else
289                 ma= add_material("Material");
290
291         ma->id.us--; /* compensating for us++ in assign_material */
292
293         /* attempt to assign to material slot */
294         ptr= CTX_data_pointer_get_type(C, "material_slot", &RNA_MaterialSlot);
295
296         if(ptr.data) {
297                 ob= ptr.id.data;
298                 index= (Material**)ptr.data - ob->mat;
299
300                 assign_material(ob, ma, index+1);
301
302                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
303         }
304
305         WM_event_add_notifier(C, NC_MATERIAL|NA_ADDED, ma);
306         
307         return OPERATOR_FINISHED;
308 }
309
310 void MATERIAL_OT_new(wmOperatorType *ot)
311 {
312         /* identifiers */
313         ot->name= "New Material";
314         ot->idname= "MATERIAL_OT_new";
315         
316         /* api callbacks */
317         ot->exec= new_material_exec;
318
319         /* flags */
320         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
321 }
322
323 /********************** new texture operator *********************/
324
325 static int new_texture_exec(bContext *C, wmOperator *op)
326 {
327         Tex *tex= CTX_data_pointer_get_type(C, "texture", &RNA_Texture).data;
328         ID *id;
329         MTex *mtex;
330         PointerRNA ptr;
331
332         /* add or copy texture */
333         if(tex)
334                 tex= copy_texture(tex);
335         else
336                 tex= add_texture("Texture");
337
338         id_us_min(&tex->id);
339
340         /* attempt to assign to texture slot */
341         ptr= CTX_data_pointer_get_type(C, "texture_slot", &RNA_TextureSlot);
342
343         if(ptr.data) {
344                 id= ptr.id.data;
345                 mtex= ptr.data;
346
347                 if(mtex) {
348                         if(mtex->tex)
349                                 id_us_min(&mtex->tex->id);
350                         mtex->tex= tex;
351                         id_us_plus(&tex->id);
352                 }
353
354                 /* XXX nodes, notifier .. */
355         }
356
357         WM_event_add_notifier(C, NC_TEXTURE|NA_ADDED, tex);
358         
359         return OPERATOR_FINISHED;
360 }
361
362 void TEXTURE_OT_new(wmOperatorType *ot)
363 {
364         /* identifiers */
365         ot->name= "New Texture";
366         ot->idname= "TEXTURE_OT_new";
367         
368         /* api callbacks */
369         ot->exec= new_texture_exec;
370
371         /* flags */
372         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
373 }
374
375 /********************** new world operator *********************/
376
377 static int new_world_exec(bContext *C, wmOperator *op)
378 {
379         Scene *scene= CTX_data_scene(C);
380         World *wo= CTX_data_pointer_get_type(C, "world", &RNA_World).data;
381
382         /* add or copy world */
383         if(wo)
384                 wo= copy_world(wo);
385         else
386                 wo= add_world("World");
387
388         /* assign to scene */
389         if(scene->world)
390                 id_us_min(&scene->world->id);
391         scene->world= wo;
392
393         WM_event_add_notifier(C, NC_WORLD|NA_ADDED, wo);
394         
395         return OPERATOR_FINISHED;
396 }
397
398 void WORLD_OT_new(wmOperatorType *ot)
399 {
400         /* identifiers */
401         ot->name= "New World";
402         ot->idname= "WORLD_OT_new";
403         
404         /* api callbacks */
405         ot->exec= new_world_exec;
406
407         /* flags */
408         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
409 }
410
411
412
413 /********************** particle system slot operators *********************/
414
415 static int particle_system_add_exec(bContext *C, wmOperator *op)
416 {
417         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
418         Scene *scene = CTX_data_scene(C);
419
420         if(!scene || !ob)
421                 return OPERATOR_CANCELLED;
422
423         object_add_particle_system(scene, ob);
424         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
425         
426         return OPERATOR_FINISHED;
427 }
428
429 void OBJECT_OT_particle_system_add(wmOperatorType *ot)
430 {
431         /* identifiers */
432         ot->name= "Add Particle System Slot";
433         ot->idname= "OBJECT_OT_particle_system_add";
434         
435         /* api callbacks */
436         ot->exec= particle_system_add_exec;
437
438         /* flags */
439         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
440 }
441
442 static int particle_system_remove_exec(bContext *C, wmOperator *op)
443 {
444         Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
445         Scene *scene = CTX_data_scene(C);
446
447         if(!scene || !ob)
448                 return OPERATOR_CANCELLED;
449
450         object_remove_particle_system(scene, ob);
451         WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
452         
453         return OPERATOR_FINISHED;
454 }
455
456 void OBJECT_OT_particle_system_remove(wmOperatorType *ot)
457 {
458         /* identifiers */
459         ot->name= "Remove Particle System Slot";
460         ot->idname= "OBJECT_OT_particle_system_remove";
461         
462         /* api callbacks */
463         ot->exec= particle_system_remove_exec;
464
465         /* flags */
466         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
467 }
468
469 /********************** new particle settings operator *********************/
470
471 static int new_particle_settings_exec(bContext *C, wmOperator *op)
472 {
473         Scene *scene = CTX_data_scene(C);
474         ParticleSettings *part= CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings).data;
475         Object *ob;
476         PointerRNA ptr;
477
478         /* add or copy particle setting */
479         if(part)
480                 part= psys_copy_settings(part);
481         else
482                 part= psys_new_settings("PSys", NULL);
483
484         /* attempt to assign to material slot */
485         ptr= CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
486
487         if(ptr.data) {
488                 ParticleSystem *psys = (ParticleSystem*)ptr.data;
489                 ob= ptr.id.data;
490
491                 if(psys->part)
492                         psys->part->id.us--;
493
494                 psys->part = part;
495
496                 DAG_scene_sort(scene);
497                 DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
498
499                 WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
500         }
501         
502         return OPERATOR_FINISHED;
503 }
504
505 void PARTICLE_OT_new(wmOperatorType *ot)
506 {
507         /* identifiers */
508         ot->name= "New Particle Settings";
509         ot->idname= "PARTICLE_OT_new";
510         
511         /* api callbacks */
512         ot->exec= new_particle_settings_exec;
513
514         /* flags */
515         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
516 }