Image Panels
[blender.git] / source / blender / editors / interface / interface_templates.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  * Contributor(s): Blender Foundation 2009.
21  *
22  * ***** END GPL LICENSE BLOCK *****
23  */
24
25 #include <stdlib.h>
26 #include <string.h>
27
28 #include "MEM_guardedalloc.h"
29
30 #include "DNA_scene_types.h"
31 #include "DNA_screen_types.h"
32
33 #include "BLI_string.h"
34
35 #include "BKE_context.h"
36 #include "BKE_icons.h"
37 #include "BKE_global.h"
38 #include "BKE_library.h"
39 #include "BKE_main.h"
40 #include "BKE_utildefines.h"
41
42 #include "ED_screen.h"
43 #include "ED_previewrender.h"
44
45 #include "RNA_access.h"
46
47 #include "WM_api.h"
48 #include "WM_types.h"
49
50 #include "UI_interface.h"
51 #include "UI_resources.h"
52 #include "interface_intern.h"
53
54 void ui_template_fix_linking()
55 {
56 }
57
58 /********************** Header Template *************************/
59
60 void uiTemplateHeader(uiLayout *layout, bContext *C, int menus)
61 {
62         uiBlock *block;
63         
64         block= uiLayoutFreeBlock(layout);
65         if(menus) ED_area_header_standardbuttons(C, block, 0);
66         else ED_area_header_switchbutton(C, block, 0);
67 }
68
69 /********************** Search Callbacks *************************/
70
71 typedef struct TemplateID {
72         PointerRNA ptr;
73         PropertyRNA *prop;
74
75         ListBase *idlb;
76 } TemplateID;
77
78 /* Search browse menu, assign  */
79 static void id_search_call_cb(bContext *C, void *arg_template, void *item)
80 {
81         TemplateID *template= (TemplateID*)arg_template;
82
83         /* ID */
84         if(item) {
85                 PointerRNA idptr;
86
87                 RNA_id_pointer_create(item, &idptr);
88                 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
89                 RNA_property_update(C, &template->ptr, template->prop);
90         }
91 }
92
93 /* ID Search browse menu, do the search */
94 static void id_search_cb(const bContext *C, void *arg_template, char *str, uiSearchItems *items)
95 {
96         TemplateID *template= (TemplateID*)arg_template;
97         Scene *scene= CTX_data_scene(C);
98         ListBase *lb= template->idlb;
99         ID *id;
100         int iconid;
101
102         /* ID listbase */
103         for(id= lb->first; id; id= id->next) {
104                 if(BLI_strcasestr(id->name+2, str)) {
105                         iconid= ui_id_icon_get(scene, id);
106
107                         if(!uiSearchItemAdd(items, id->name+2, id, iconid))
108                                 break;
109                 }
110         }
111 }
112
113 /* ID Search browse menu, open */
114 static uiBlock *search_menu(bContext *C, ARegion *ar, void *arg_litem)
115 {
116         static char search[256];
117         static TemplateID template;
118         PointerRNA idptr;
119         wmEvent event;
120         wmWindow *win= CTX_wm_window(C);
121         uiBlock *block;
122         uiBut *but;
123         
124         /* clear initial search string, then all items show */
125         search[0]= 0;
126         /* arg_litem is malloced, can be freed by parent button */
127         template= *((TemplateID*)arg_litem);
128         
129         /* get active id for showing first item */
130         idptr= RNA_property_pointer_get(&template.ptr, template.prop);
131
132         block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
133         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
134         
135         /* fake button, it holds space for search items */
136         uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
137         
138         but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, "");
139         uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
140         
141         uiBoundsBlock(block, 6);
142         uiBlockSetDirection(block, UI_DOWN);    
143         uiEndBlock(C, block);
144         
145         event= *(win->eventstate);      /* XXX huh huh? make api call */
146         event.type= EVT_BUT_OPEN;
147         event.val= KM_PRESS;
148         event.customdata= but;
149         event.customdatafree= FALSE;
150         wm_event_add(win, &event);
151         
152         return block;
153 }
154
155 /************************ ID Template ***************************/
156
157 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
158 {
159         TemplateID *template= (TemplateID*)arg_litem;
160         PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
161         ID *id= idptr.data, *newid;
162         int event= GET_INT_FROM_POINTER(arg_event);
163         
164         switch(event) {
165                 case UI_ID_BROWSE:
166                 case UI_ID_PIN:
167                         printf("warning, id event %d shouldnt come here\n", event);
168                         break;
169                 case UI_ID_OPEN:
170                 case UI_ID_ADD_NEW:
171                         if(template->idlb->last) {
172                                 RNA_id_pointer_create(template->idlb->last, &idptr);
173                                 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
174                                 RNA_property_update(C, &template->ptr, template->prop);
175                         }
176                         break;
177                 case UI_ID_DELETE:
178                         memset(&idptr, 0, sizeof(idptr));
179                         RNA_property_pointer_set(&template->ptr, template->prop, idptr);
180                         RNA_property_update(C, &template->ptr, template->prop);
181                         break;
182                 case UI_ID_FAKE_USER:
183                         if(id) {
184                                 if(id->flag & LIB_FAKEUSER) id->us++;
185                                 else id->us--;
186                         }
187                         else return;
188                         break;
189                 case UI_ID_LOCAL:
190                         if(id) {
191                                 if(id_make_local(id, 0)) {
192                                         /* reassign to get get proper updates/notifiers */
193                                         idptr= RNA_property_pointer_get(&template->ptr, template->prop);
194                                         RNA_property_pointer_set(&template->ptr, template->prop, idptr);
195                                         RNA_property_update(C, &template->ptr, template->prop);
196                                 }
197                         }
198                         break;
199                 case UI_ID_ALONE:
200                         if(id) {
201                                 /* make copy */
202                                 if(id_copy(id, &newid, 0) && newid) {
203                                         /* us is 1 by convention, but RNA_property_pointer_set
204                                            will also incremement it, so set it to zero */
205                                         newid->us= 0;
206
207                                         /* assign copy */
208                                         RNA_id_pointer_create(newid, &idptr);
209                                         RNA_property_pointer_set(&template->ptr, template->prop, idptr);
210                                         RNA_property_update(C, &template->ptr, template->prop);
211                                 }
212                         }
213                         break;
214 #if 0
215                 case UI_ID_AUTO_NAME:
216                         break;
217 #endif
218         }
219 }
220
221 static void template_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type, int flag, char *newop, char *openop, char *unlinkop)
222 {
223         uiBut *but;
224         PointerRNA idptr;
225         ListBase *lb;
226         ID *id, *idfrom;
227
228         idptr= RNA_property_pointer_get(&template->ptr, template->prop);
229         id= idptr.data;
230         idfrom= template->ptr.id.data;
231         lb= template->idlb;
232
233         uiBlockBeginAlign(block);
234
235         if(idptr.type)
236                 type= idptr.type;
237
238         if(flag & UI_ID_BROWSE) {
239                 but= uiDefBlockButN(block, search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y, "Browse ID data");
240                 if(type) {
241                         but->icon= RNA_struct_ui_icon(type);
242                         but->flag|= UI_HAS_ICON;
243                         but->flag|= UI_ICON_LEFT;
244                 }
245
246                 if((idfrom && idfrom->lib))
247                         uiButSetFlag(but, UI_BUT_DISABLED);
248         }
249
250         /* text button with name */
251         if(id) {
252                 char name[64];
253
254                 //text_idbutton(id, name);
255                 name[0]= '\0';
256                 but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
257                 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
258
259                 if(id->lib) {
260                         if(id->flag & LIB_INDIRECT) {
261                                 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0,
262                                         "Indirect library datablock, cannot change.");
263                                 uiButSetFlag(but, UI_BUT_DISABLED);
264                         }
265                         else {
266                                 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0,
267                                         "Direct linked library datablock, click to make local.");
268                                 if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib))
269                                         uiButSetFlag(but, UI_BUT_DISABLED);
270                         }
271
272                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
273                 }
274
275                 if(id->us > 1) {
276                         char str[32];
277
278                         sprintf(str, "%d", id->us);
279
280                         if(id->us<10)
281                                 but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
282                         else
283                                 but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X+10,UI_UNIT_Y, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
284
285                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
286                         if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib))
287                                 uiButSetFlag(but, UI_BUT_DISABLED);
288                 }
289         }
290         
291         if(flag & UI_ID_ADD_NEW) {
292                 int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
293                 
294                 if(newop) {
295                         but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
296                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
297                 }
298                 else {
299                         but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
300                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
301                 }
302
303                 if((idfrom && idfrom->lib))
304                         uiButSetFlag(but, UI_BUT_DISABLED);
305         }
306
307         if(flag & UI_ID_OPEN) {
308                 int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
309                 
310                 if(openop) {
311                         but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_REGION_WIN, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
312                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
313                 }
314                 else {
315                         but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
316                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
317                 }
318
319                 if((idfrom && idfrom->lib))
320                         uiButSetFlag(but, UI_BUT_DISABLED);
321         }
322         
323         /* delete button */
324         if(id && (flag & UI_ID_DELETE)) {
325                 if(unlinkop) {
326                         but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
327                 }
328                 else {
329                         but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
330                         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
331                 }
332
333                 if((idfrom && idfrom->lib))
334                         uiButSetFlag(but, UI_BUT_DISABLED);
335         }
336         
337         uiBlockEndAlign(block);
338 }
339
340 void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop)
341 {
342         TemplateID *template;
343         uiBlock *block;
344         PropertyRNA *prop;
345         StructRNA *type;
346         int flag;
347
348         prop= RNA_struct_find_property(ptr, propname);
349
350         if(!prop || RNA_property_type(prop) != PROP_POINTER) {
351                 printf("uiTemplateID: pointer property not found: %s\n", propname);
352                 return;
353         }
354
355         template= MEM_callocN(sizeof(TemplateID), "TemplateID");
356         template->ptr= *ptr;
357         template->prop= prop;
358
359         flag= UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE;
360
361         if(newop)
362                 flag |= UI_ID_ADD_NEW;
363         if(openop)
364                 flag |= UI_ID_OPEN;
365
366         type= RNA_property_pointer_type(ptr, prop);
367         template->idlb= wich_libbase(CTX_data_main(C), RNA_type_to_ID_code(type));
368
369         if(template->idlb) {
370                 uiLayoutRow(layout, 1);
371                 block= uiLayoutGetBlock(layout);
372                 template_ID(C, block, template, type, flag, newop, openop, unlinkop);
373         }
374
375         MEM_freeN(template);
376 }
377
378 /************************ Modifier Template *************************/
379
380 #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
381
382 #include <string.h>
383
384 #include "DNA_object_force.h"
385 #include "DNA_object_types.h"
386 #include "DNA_modifier_types.h"
387 #include "DNA_scene_types.h"
388
389 #include "BKE_depsgraph.h"
390 #include "BKE_DerivedMesh.h"
391 #include "BKE_global.h"
392 #include "BKE_modifier.h"
393 #include "BKE_object.h"
394 #include "BKE_particle.h"
395 #include "BKE_report.h"
396
397 #include "UI_resources.h"
398 #include "ED_util.h"
399
400 #include "BLI_arithb.h"
401 #include "BLI_listbase.h"
402
403 #include "ED_object.h"
404
405 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
406 {
407         Object *ob = ob_v;
408         ModifierData *md;
409         
410         int i, cageIndex = modifiers_getCageIndex(ob, NULL );
411
412         for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) {
413                 if(md == md_v) {
414                         if(i >= cageIndex)
415                                 md->mode ^= eModifierMode_OnCage;
416                         break;
417                 }
418         }
419
420         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
421         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
422 }
423
424 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
425 {
426         Object *ob = ob_v;
427         ModifierData *md = md_v;
428         ModifierData *nmd = modifier_new(md->type);
429
430         modifier_copyData(md, nmd);
431         nmd->mode &= ~eModifierMode_Virtual;
432
433         BLI_addhead(&ob->modifiers, nmd);
434
435         ob->partype = PAROBJECT;
436
437         WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
438         DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
439
440         ED_undo_push(C, "Modifier convert to real");
441 }
442
443 static int modifier_can_delete(ModifierData *md)
444 {
445         // fluid particle modifier can't be deleted here
446         if(md->type == eModifierType_ParticleSystem)
447                 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
448                         return 0;
449
450         return 1;
451 }
452
453 static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, int index, int cageIndex, int lastCageIndex)
454 {
455         ModifierTypeInfo *mti = modifierType_getInfo(md->type);
456         PointerRNA ptr;
457         uiBut *but;
458         uiBlock *block;
459         uiLayout *column, *row, *result= NULL;
460         int isVirtual = md->mode & eModifierMode_Virtual;
461         // XXX short color = md->error?TH_REDALERT:TH_BUT_NEUTRAL;
462         char str[128];
463
464         /* create RNA pointer */
465         RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
466
467         column= uiLayoutColumn(layout, 1);
468         uiLayoutSetContextPointer(column, "modifier", &ptr);
469
470         /* rounded header */
471         /* XXX uiBlockSetCol(block, color); */
472                 /* roundbox 4 free variables: corner-rounding, nop, roundbox type, shade */
473
474         row= uiLayoutRow(uiLayoutBox(column), 0);
475         uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
476
477         block= uiLayoutGetBlock(row);
478
479         //uiDefBut(block, ROUNDBOX, 0, "", x-10, y-4, width, 25, NULL, 7.0, 0.0, 
480         //               (!isVirtual && (md->mode & eModifierMode_Expanded))?3:15, 20, ""); 
481         /* XXX uiBlockSetCol(block, TH_AUTO); */
482         
483         /* open/close icon */
484         if(!isVirtual) {
485                 uiBlockSetEmboss(block, UI_EMBOSSN);
486                 uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, 0, ICON_TRIA_RIGHT, 0, 0, UI_UNIT_X, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier");
487         }
488         
489         /* modifier-type icon */
490         uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
491         
492         uiBlockSetEmboss(block, UI_EMBOSS);
493         
494         if(isVirtual) {
495                 /* virtual modifier */
496                 sprintf(str, "%s parent deform", md->name);
497                 uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
498
499                 but = uiDefBut(block, BUT, 0, "Make Real", 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Convert virtual modifier to a real modifier");
500                 uiButSetFunc(but, modifiers_convertToReal, ob, md);
501         }
502         else {
503                 /* real modifier */
504                 uiBlockBeginAlign(block);
505                 uiItemR(row, "", 0, &ptr, "name", 0);
506
507                 /* Softbody not allowed in this situation, enforce! */
508                 if(((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) && (md->type!=eModifierType_Surface)) {
509                         uiItemR(row, "", ICON_SCENE, &ptr, "render", 0);
510                         uiItemR(row, "", ICON_RESTRICT_VIEW_OFF, &ptr, "realtime", 0);
511
512                         if(mti->flags & eModifierTypeFlag_SupportsEditmode)
513                                 uiItemR(row, "", ICON_EDITMODE_HLT, &ptr, "editmode", 0);
514                 }
515                 
516
517                 /* XXX uiBlockSetEmboss(block, UI_EMBOSSR); */
518
519                 if(ob->type==OB_MESH && modifier_couldBeCage(md) && index<=lastCageIndex) {
520
521                         /* XXX uiBlockSetCol(block, color); */
522                         but = uiDefIconBut(block, BUT, 0, ICON_MESH_DATA, 0, 0, 16, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode");
523                         uiButSetFunc(but, modifiers_setOnCage, ob, md);
524                         uiBlockEndAlign(block);
525                         /* XXX uiBlockSetCol(block, TH_AUTO); */
526                 }
527         }
528
529         /* up/down/delete */
530         if(!isVirtual) {
531                 /* XXX uiBlockSetCol(block, TH_BUT_ACTION); */
532                 uiBlockBeginAlign(block);
533                 uiItemO(row, "", VICON_MOVE_UP, "OBJECT_OT_modifier_move_up");
534                 uiItemO(row, "", VICON_MOVE_DOWN, "OBJECT_OT_modifier_move_down");
535                 uiBlockEndAlign(block);
536                 
537                 uiBlockSetEmboss(block, UI_EMBOSSN);
538
539                 if(modifier_can_delete(md))
540                         uiItemO(row, "", VICON_X, "OBJECT_OT_modifier_remove");
541
542                 /* XXX uiBlockSetCol(block, TH_AUTO); */
543         }
544
545         uiBlockSetEmboss(block, UI_EMBOSS);
546
547         if(!isVirtual && (md->mode & eModifierMode_Expanded)) {
548                 /* apply/convert/copy */
549                 uiLayout *box;
550
551                 box= uiLayoutBox(column);
552                 row= uiLayoutRow(box, 1);
553
554                 if(!isVirtual && (md->type!=eModifierType_Collision) && (md->type!=eModifierType_Surface)) {
555                         /* only here obdata, the rest of modifiers is ob level */
556                         uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
557
558                         if(md->type==eModifierType_ParticleSystem) {
559                         ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
560
561                         if(!(ob->mode & OB_MODE_PARTICLE_EDIT))
562                                         if(ELEM3(psys->part->ren_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache)
563                                                 uiItemO(row, "Convert", 0, "OBJECT_OT_modifier_convert");
564                         }
565                         else
566                                 uiItemO(row, "Apply", 0, "OBJECT_OT_modifier_apply");
567                         
568                         uiBlockClearButLock(block);
569                         uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
570
571                         if(!ELEM4(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth))
572                                 uiItemO(row, "Copy", 0, "OBJECT_OT_modifier_copy");
573                 }
574
575                 result= uiLayoutColumn(box, 0);
576                 block= uiLayoutFreeBlock(box);
577         }
578
579         if(md->error) {
580                 row = uiLayoutRow(uiLayoutBox(column), 0);
581
582                 /* XXX uiBlockSetCol(block, color); */
583                 uiItemL(row, md->error, ICON_ERROR);
584                 /* XXX uiBlockSetCol(block, TH_AUTO); */
585         }
586
587         return result;
588 }
589
590 uiLayout *uiTemplateModifier(uiLayout *layout, PointerRNA *ptr)
591 {
592         Object *ob;
593         ModifierData *md, *vmd;
594         int i, lastCageIndex, cageIndex;
595
596         /* verify we have valid data */
597         if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
598                 printf("uiTemplateModifier: expected modifier on object.\n");
599                 return NULL;
600         }
601
602         ob= ptr->id.data;
603         md= ptr->data;
604
605         if(!ob || !(GS(ob->id.name) == ID_OB)) {
606                 printf("uiTemplateModifier: expected modifier on object.\n");
607                 return NULL;
608         }
609         
610         uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
611         
612         /* find modifier and draw it */
613         cageIndex = modifiers_getCageIndex(ob, &lastCageIndex);
614
615         // XXX virtual modifiers are not accesible for python
616         vmd = modifiers_getVirtualModifierList(ob);
617
618         for(i=0; vmd; i++, vmd=vmd->next) {
619                 if(md == vmd)
620                         return draw_modifier(layout, ob, md, i, cageIndex, lastCageIndex);
621                 else if(vmd->mode & eModifierMode_Virtual)
622                         i--;
623         }
624
625         return NULL;
626 }
627
628 /************************ Constraint Template *************************/
629
630 #include "DNA_action_types.h"
631 #include "DNA_constraint_types.h"
632
633 #include "BKE_action.h"
634 #include "BKE_constraint.h"
635
636 #define REDRAWIPO                                       1
637 #define REDRAWNLA                                       2
638 #define REDRAWBUTSOBJECT                        3               
639 #define REDRAWACTION                            4
640 #define B_CONSTRAINT_TEST                       5
641 #define B_CONSTRAINT_CHANGETARGET       6
642 #define B_CONSTRAINT_INF                        7
643 #define REMAKEIPO                                       8
644 #define B_DIFF                                          9
645
646 void do_constraint_panels(bContext *C, void *arg, int event)
647 {
648         Scene *scene= CTX_data_scene(C);
649         Object *ob= CTX_data_active_object(C);
650         
651         switch(event) {
652         case B_CONSTRAINT_TEST:
653                 // XXX allqueue(REDRAWVIEW3D, 0);
654                 // XXX allqueue(REDRAWBUTSOBJECT, 0);
655                 // XXX allqueue(REDRAWBUTSEDIT, 0);
656                 break;  // no handling
657         case B_CONSTRAINT_INF:
658                 /* influence; do not execute actions for 1 dag_flush */
659                 if (ob->pose)
660                         ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
661                 break;
662         case B_CONSTRAINT_CHANGETARGET:
663                 if (ob->pose) ob->pose->flag |= POSE_RECALC;    // checks & sorts pose channels
664                 DAG_scene_sort(scene);
665                 break;
666         default:
667                 break;
668         }
669
670         object_test_constraints(ob);
671         
672         if(ob->pose) update_pose_constraint_flags(ob->pose);
673         
674         if(ob->type==OB_ARMATURE) DAG_id_flush_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB);
675         else DAG_id_flush_update(&ob->id, OB_RECALC_OB);
676         
677         // XXX allqueue(REDRAWVIEW3D, 0);
678         // XXX allqueue(REDRAWBUTSOBJECT, 0);
679         // XXX allqueue(REDRAWBUTSEDIT, 0);
680 }
681
682 static void constraint_active_func(bContext *C, void *ob_v, void *con_v)
683 {
684         ED_object_constraint_set_active(ob_v, con_v);
685 }
686
687 static void verify_constraint_name_func (bContext *C, void *con_v, void *name_v)
688 {
689         Object *ob= CTX_data_active_object(C);
690         bConstraint *con= con_v;
691         char oldname[32];       
692         
693         if (!con)
694                 return;
695         
696         /* put on the stack */
697         BLI_strncpy(oldname, (char *)name_v, 32);
698         
699         ED_object_constraint_rename(ob, con, oldname);
700         ED_object_constraint_set_active(ob, con);
701         // XXX allqueue(REDRAWACTION, 0); 
702 }
703
704 /* some commonly used macros in the constraints drawing code */
705 #define is_armature_target(target) (target && target->type==OB_ARMATURE)
706 #define is_armature_owner(ob) ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE))
707 #define is_geom_target(target) (target && (ELEM(target->type, OB_MESH, OB_LATTICE)) )
708
709 /* Helper function for draw constraint - draws constraint space stuff 
710  * This function should not be called if no menus are required 
711  * owner/target: -1 = don't draw menu; 0= not posemode, 1 = posemode 
712  */
713 static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short xco, short yco, short owner, short target)
714 {
715         short tarx, ownx, iconx;
716         short bwidth;
717         short iconwidth = 20;
718         
719         /* calculate sizes and placement of menus */
720         if (owner == -1) {
721                 bwidth = 125;
722                 tarx = 120;
723                 ownx = 0;
724         }
725         else if (target == -1) {
726                 bwidth = 125;
727                 tarx = 0;
728                 ownx = 120;
729         }
730         else {
731                 bwidth = 100;
732                 tarx = 85;
733                 iconx = tarx + bwidth + 5;
734                 ownx = tarx + bwidth + iconwidth + 10;
735         }
736         
737         
738         uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Convert:", xco, yco, 80,18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
739
740         /* Target-Space */
741         if (target == 1) {
742                 uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Pose Space %x2|Local with Parent %x3|Local Space %x1", 
743                                                                                                 tarx, yco, bwidth, 18, &con->tarspace, 0, 0, 0, 0, "Choose space that target is evaluated in"); 
744         }
745         else if (target == 0) {
746                 uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Local (Without Parent) Space %x1", 
747                                                                                 tarx, yco, bwidth, 18, &con->tarspace, 0, 0, 0, 0, "Choose space that target is evaluated in"); 
748         }
749         
750         if ((target != -1) && (owner != -1))
751                 uiDefIconBut(block, LABEL, 0, ICON_ARROW_LEFTRIGHT,
752                         iconx, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "");
753         
754         /* Owner-Space */
755         if (owner == 1) {
756                 uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Owner Space %t|World Space %x0|Pose Space %x2|Local with Parent %x3|Local Space %x1", 
757                                                                                                 ownx, yco, bwidth, 18, &con->ownspace, 0, 0, 0, 0, "Choose space that owner is evaluated in");  
758         }
759         else if (owner == 0) {
760                 uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Owner Space %t|World Space %x0|Local (Without Parent) Space %x1", 
761                                                                                 ownx, yco, bwidth, 18, &con->ownspace, 0, 0, 0, 0, "Choose space that owner is evaluated in");  
762         }
763 }
764
765 /* draw panel showing settings for a constraint */
766 static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
767 {
768         bPoseChannel *pchan= get_active_posechannel(ob);
769         bConstraintTypeInfo *cti;
770         uiBlock *block;
771         uiLayout *result= NULL, *col, *box, *row, *subrow;
772         uiBut *but;
773         PointerRNA ptr;
774         char typestr[32];
775         short width = 265;
776         short proxy_protected, xco=0, yco=0;
777         int rb_col;
778
779         /* get constraint typeinfo */
780         cti= constraint_get_typeinfo(con);
781         if (cti == NULL) {
782                 /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
783                 if (con->type == CONSTRAINT_TYPE_NULL)
784                         strcpy(typestr, "Null");
785                 else
786                         strcpy(typestr, "Unknown");
787         }
788         else
789                 strcpy(typestr, cti->name);
790                 
791         /* determine whether constraint is proxy protected or not */
792         if (proxylocked_constraints_owner(ob, pchan))
793                 proxy_protected= (con->flag & CONSTRAINT_PROXY_LOCAL)==0;
794         else
795                 proxy_protected= 0;
796
797         /* unless button has own callback, it adds this callback to button */
798         block= uiLayoutGetBlock(layout);
799         uiBlockSetHandleFunc(block, do_constraint_panels, NULL);
800         uiBlockSetFunc(block, constraint_active_func, ob, con);
801
802         RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
803
804         col= uiLayoutColumn(layout, 1);
805         uiLayoutSetContextPointer(col, "constraint", &ptr);
806
807         box= uiLayoutBox(col);
808         row= uiLayoutRow(box, 0);
809
810         block= uiLayoutGetBlock(box);
811
812         subrow= uiLayoutRow(row, 0);
813         uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT);
814
815         /* Draw constraint header */
816         uiBlockSetEmboss(block, UI_EMBOSSN);
817         
818         /* rounded header */
819         rb_col= (con->flag & CONSTRAINT_ACTIVE)?50:20;
820         
821         /* open/close */
822         uiDefIconButBitS(block, ICONTOG, CONSTRAINT_EXPAND, B_CONSTRAINT_TEST, ICON_TRIA_RIGHT, xco-10, yco, 20, 20, &con->flag, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Constraint");
823         
824         /* name */      
825         uiBlockSetEmboss(block, UI_EMBOSS);
826         
827         /* XXX if (con->flag & CONSTRAINT_DISABLE)
828                 uiBlockSetCol(block, TH_REDALERT);*/
829         
830         uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
831         
832         if(proxy_protected == 0) {
833                 but = uiDefBut(block, TEX, B_CONSTRAINT_TEST, "", xco+120, yco, 85, 18, con->name, 0.0, 29.0, 0.0, 0.0, "Constraint name"); 
834                 uiButSetFunc(but, verify_constraint_name_func, con, con->name);
835         }
836         else
837                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, con->name, xco+120, yco-1, 135, 19, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
838
839         // XXX uiBlockSetCol(block, TH_AUTO);   
840
841         subrow= uiLayoutRow(row, 0);
842         uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
843         
844         /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
845         if (proxy_protected) {
846                 uiBlockSetEmboss(block, UI_EMBOSSN);
847                 
848                 /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */
849                 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco+244, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
850                 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco+262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
851                 
852                 uiBlockSetEmboss(block, UI_EMBOSS);
853         }
854         else {
855                 short prev_proxylock, show_upbut, show_downbut;
856                 
857                 /* Up/Down buttons: 
858                  *      Proxy-constraints are not allowed to occur after local (non-proxy) constraints
859                  *      as that poses problems when restoring them, so disable the "up" button where
860                  *      it may cause this situation. 
861                  *
862                  *      Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose. 
863                  */
864                 if (proxylocked_constraints_owner(ob, pchan)) {
865                         if (con->prev) {
866                                 prev_proxylock= (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
867                         }
868                         else
869                                 prev_proxylock= 0;
870                 }
871                 else
872                         prev_proxylock= 0;
873                         
874                 show_upbut= ((prev_proxylock == 0) && (con->prev));
875                 show_downbut= (con->next) ? 1 : 0;
876                 
877                 if (show_upbut || show_downbut) {
878                         uiBlockBeginAlign(block);
879                                 uiBlockSetEmboss(block, UI_EMBOSS);
880                                 
881                                 if (show_upbut)
882                                         uiDefIconButO(block, BUT, "CONSTRAINT_OT_move_up", WM_OP_INVOKE_DEFAULT, VICON_MOVE_UP, xco+width-50, yco, 16, 18, "Move constraint up in constraint stack");
883                                 
884                                 if (show_downbut)
885                                         uiDefIconButO(block, BUT, "CONSTRAINT_OT_move_down", WM_OP_INVOKE_DEFAULT, VICON_MOVE_DOWN, xco+width-50+18, yco, 16, 18, "Move constraint down in constraint stack");
886                         uiBlockEndAlign(block);
887                 }
888                 
889                 
890                 /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
891                 uiBlockSetEmboss(block, UI_EMBOSSN);
892                         uiDefIconButO(block, BUT, "CONSTRAINT_OT_delete", WM_OP_INVOKE_DEFAULT, ICON_X, xco+262, yco, 19, 19, "Delete constraint");
893                 uiBlockSetEmboss(block, UI_EMBOSS);
894         }
895         
896         /* Set but-locks for protected settings (magic numbers are used here!) */
897         if (proxy_protected)
898                 uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint");
899         
900         /* Draw constraint data */
901         if ((con->flag & CONSTRAINT_EXPAND) == 0) {
902                 (yco) -= 21;
903         }
904         else {
905                 box= uiLayoutBox(col);
906                 block= uiLayoutFreeBlock(box);
907
908                 switch (con->type) {
909 #ifndef DISABLE_PYTHON
910                 case CONSTRAINT_TYPE_PYTHON:
911                         {
912                                 bPythonConstraint *data = con->data;
913                                 bConstraintTarget *ct;
914                                 // uiBut *but2;
915                                 int tarnum, theight;
916                                 // static int pyconindex=0;
917                                 // char *menustr;
918                                 
919                                 theight = (data->tarnum)? (data->tarnum * 38) : (38);
920                                 
921                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Script:", xco+60, yco-24, 55, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
922                                 
923                                 /* do the scripts menu */
924                                 /* XXX menustr = buildmenu_pyconstraints(data->text, &pyconindex);
925                                 but2 = uiDefButI(block, MENU, B_CONSTRAINT_TEST, menustr,
926                                       xco+120, yco-24, 150, 20, &pyconindex,
927                                       0, 0, 0, 0, "Set the Script Constraint to use");
928                                 uiButSetFunc(but2, validate_pyconstraint_cb, data, &pyconindex);
929                                 MEM_freeN(menustr);      */
930                                 
931                                 /* draw target(s) */
932                                 if (data->flag & PYCON_USETARGETS) {
933                                         /* Draw target parameters */ 
934                                         for (ct=data->targets.first, tarnum=1; ct; ct=ct->next, tarnum++) {
935                                                 char tarstr[32];
936                                                 short yoffset= ((tarnum-1) * 38);
937         
938                                                 /* target label */
939                                                 sprintf(tarstr, "Target %d:", tarnum);
940                                                 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, tarstr, xco+45, yco-(48+yoffset), 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
941                                                 
942                                                 /* target space-selector - per target */
943                                                 if (is_armature_target(ct->tar)) {
944                                                         uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Pose Space %x3|Local with Parent %x4|Local Space %x1", 
945                                                                                                                         xco+10, yco-(66+yoffset), 100, 18, &ct->space, 0, 0, 0, 0, "Choose space that target is evaluated in"); 
946                                                 }
947                                                 else {
948                                                         uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Local (Without Parent) Space %x1", 
949                                                                                                                         xco+10, yco-(66+yoffset), 100, 18, &ct->space, 0, 0, 0, 0, "Choose space that target is evaluated in"); 
950                                                 }
951                                                 
952                                                 uiBlockBeginAlign(block);
953                                                         /* target object */
954                                                         uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", xco+120, yco-(48+yoffset), 150, 18, &ct->tar, "Target Object"); 
955                                                         
956                                                         /* subtarget */
957                                                         if (is_armature_target(ct->tar)) {
958                                                                 but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", xco+120, yco-(66+yoffset),150,18, &ct->subtarget, 0, 24, 0, 0, "Subtarget Bone");
959                                                                 uiButSetCompleteFunc(but, autocomplete_bone, (void *)ct->tar);
960                                                         }
961                                                         else if (is_geom_target(ct->tar)) {
962                                                                 but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", xco+120, yco-(66+yoffset),150,18, &ct->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
963                                                                 uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ct->tar);
964                                                         }
965                                                         else {
966                                                                 strcpy(ct->subtarget, "");
967                                                         }
968                                                 uiBlockEndAlign(block);
969                                         }
970                                 }
971                                 else {
972                                         /* Draw indication that no target needed */
973                                         uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", xco+60, yco-48, 55, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
974                                         uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Not Applicable", xco+120, yco-48, 150, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
975                                 }
976                                 
977                                 /* settings */
978                                 uiBlockBeginAlign(block);
979                                         but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Options", xco, yco-(52+theight), (width/2),18, NULL, 0, 24, 0, 0, "Change some of the constraint's settings.");
980                                         // XXX uiButSetFunc(but, BPY_pyconstraint_settings, data, NULL);
981                                         
982                                         but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Refresh", xco+((width/2)+10), yco-(52+theight), (width/2),18, NULL, 0, 24, 0, 0, "Force constraint to refresh it's settings");
983                                 uiBlockEndAlign(block);
984                                 
985                                 /* constraint space settings */
986                                 draw_constraint_spaceselect(block, con, xco, yco-(73+theight), is_armature_owner(ob), -1);
987                         }
988                         break;
989 #endif 
990
991                 case CONSTRAINT_TYPE_NULL:
992                         {
993                                 uiItemL(box, "", 0);
994                         }
995                         break;
996                 default:
997                         result= box;
998                         break;
999                 }
1000         }
1001         
1002         /* clear any locks set up for proxies/lib-linking */
1003         uiBlockClearButLock(block);
1004
1005         return result;
1006 }
1007
1008 uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
1009 {
1010         Object *ob;
1011         bConstraint *con;
1012
1013         /* verify we have valid data */
1014         if(!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
1015                 printf("uiTemplateConstraint: expected constraint on object.\n");
1016                 return NULL;
1017         }
1018
1019         ob= ptr->id.data;
1020         con= ptr->data;
1021
1022         if(!ob || !(GS(ob->id.name) == ID_OB)) {
1023                 printf("uiTemplateConstraint: expected constraint on object.\n");
1024                 return NULL;
1025         }
1026         
1027         uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
1028
1029         /* hrms, the temporal constraint should not draw! */
1030         if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
1031                 bKinematicConstraint *data= con->data;
1032                 if(data->flag & CONSTRAINT_IK_TEMP)
1033                         return NULL;
1034         }
1035
1036         return draw_constraint(layout, ob, con);
1037 }
1038
1039 /************************* Group Template ***************************/
1040
1041 #if 0
1042 static void do_add_groupmenu(void *arg, int event)
1043 {
1044         Object *ob= OBACT;
1045         
1046         if(ob) {
1047                 
1048                 if(event== -1) {
1049                         Group *group= add_group( "Group" );
1050                         add_to_group(group, ob);
1051                 }
1052                 else
1053                         add_to_group(BLI_findlink(&G.main->group, event), ob);
1054                         
1055                 ob->flag |= OB_FROMGROUP;
1056                 BASACT->flag |= OB_FROMGROUP;
1057                 allqueue(REDRAWBUTSOBJECT, 0);
1058                 allqueue(REDRAWVIEW3D, 0);
1059         }               
1060 }
1061
1062 static uiBlock *add_groupmenu(void *arg_unused)
1063 {
1064         uiBlock *block;
1065         Group *group;
1066         short xco=0, yco= 0, index=0;
1067         char str[32];
1068         
1069         block= uiNewBlock(&curarea->uiblocks, "add_constraintmenu", UI_EMBOSSP, UI_HELV, curarea->win);
1070         uiBlockSetButmFunc(block, do_add_groupmenu, NULL);
1071
1072         uiDefBut(block, BUTM, B_NOP, "ADD NEW",         0, 20, 160, 19, NULL, 0.0, 0.0, 1, -1, "");
1073         for(group= G.main->group.first; group; group= group->id.next, index++) {
1074                 
1075                 /*if(group->id.lib) strcpy(str, "L  ");*/ /* we cant allow adding objects inside linked groups, it wont be saved anyway */
1076                 if(group->id.lib==0) {
1077                         strcpy(str, "   ");
1078                         strcat(str, group->id.name+2);
1079                         uiDefBut(block, BUTM, B_NOP, str,       xco*160, -20*yco, 160, 19, NULL, 0.0, 0.0, 1, index, "");
1080                         
1081                         yco++;
1082                         if(yco>24) {
1083                                 yco= 0;
1084                                 xco++;
1085                         }
1086                 }
1087         }
1088         
1089         uiTextBoundsBlock(block, 50);
1090         uiBlockSetDirection(block, UI_DOWN);    
1091         
1092         return block;
1093 }
1094
1095 static void group_ob_rem(void *gr_v, void *ob_v)
1096 {
1097         Object *ob= OBACT;
1098         
1099         if(rem_from_group(gr_v, ob) && find_group(ob, NULL)==NULL) {
1100                 ob->flag &= ~OB_FROMGROUP;
1101                 BASACT->flag &= ~OB_FROMGROUP;
1102         }
1103         allqueue(REDRAWBUTSOBJECT, 0);
1104         allqueue(REDRAWVIEW3D, 0);
1105
1106 }
1107
1108 static void group_local(void *gr_v, void *unused)
1109 {
1110         Group *group= gr_v;
1111         
1112         group->id.lib= NULL;
1113         
1114         allqueue(REDRAWBUTSOBJECT, 0);
1115         allqueue(REDRAWVIEW3D, 0);
1116         
1117 }
1118
1119 uiLayout *uiTemplateGroup(uiLayout *layout, Object *ob, Group *group)
1120 {
1121         uiSetButLock(1, NULL);
1122         uiDefBlockBut(block, add_groupmenu, NULL, "Add to Group", 10,150,150,20, "Add Object to a new Group");
1123
1124         /* all groups */
1125         if(group->id.lib) {
1126                 uiLayoutRow()
1127                 uiBlockBeginAlign(block);
1128                 uiSetButLock(GET_INT_FROM_POINTER(group->id.lib), ERROR_LIBDATA_MESSAGE); /* We cant actually use this button */
1129                 uiDefBut(block, TEX, B_IDNAME, "GR:",   10, 120-yco, 100, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change.");
1130                 uiClearButLock();
1131                 
1132                 but= uiDefIconBut(block, BUT, B_NOP, ICON_PARLIB, 110, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Make Group local");
1133                 uiButSetFunc(but, group_local, group, NULL);
1134                 uiBlockEndAlign(block);
1135         } else {
1136                 but = uiDefBut(block, TEX, B_IDNAME, "GR:",     10, 120-yco, 120, 20, group->id.name+2, 0.0, 21.0, 0, 0, "Displays Group name. Click to change.");
1137                 uiButSetFunc(but, test_idbutton_cb, group->id.name, NULL);
1138         }
1139         
1140         xco = 290;
1141         if(group->id.lib==0) { /* cant remove objects from linked groups */
1142                 but = uiDefIconBut(block, BUT, B_NOP, VICON_X, xco, 120-yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "Remove Group membership");
1143                 uiButSetFunc(but, group_ob_rem, group, ob);
1144         }
1145 }
1146 #endif
1147
1148 /************************* Preview Template ***************************/
1149
1150 #include "DNA_lamp_types.h"
1151 #include "DNA_material_types.h"
1152 #include "DNA_world_types.h"
1153
1154 #define B_MATPRV 1
1155
1156 static void do_preview_buttons(bContext *C, void *arg, int event)
1157 {
1158         switch(event) {
1159                 case B_MATPRV:
1160                         WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, arg);
1161                         break;
1162         }
1163 }
1164
1165 void uiTemplatePreview(uiLayout *layout, ID *id, ID *parent, MTex *slot)
1166 {
1167         uiLayout *row, *col;
1168         uiBlock *block;
1169         Material *ma= NULL;
1170         ID *pid, *pparent;
1171         short *pr_texture= NULL;
1172
1173         if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
1174                 printf("uiTemplatePreview: expected ID of type material, texture, lamp or world.\n");
1175                 return;
1176         }
1177
1178         /* decide what to render */
1179         pid= id;
1180         pparent= NULL;
1181
1182         if(id && (GS(id->name) == ID_TE)) {
1183                 if(parent && (GS(parent->name) == ID_MA))
1184                         pr_texture= &((Material*)parent)->pr_texture;
1185                 else if(parent && (GS(parent->name) == ID_WO))
1186                         pr_texture= &((World*)parent)->pr_texture;
1187                 else if(parent && (GS(parent->name) == ID_LA))
1188                         pr_texture= &((Lamp*)parent)->pr_texture;
1189
1190                 if(pr_texture) {
1191                         if(*pr_texture == TEX_PR_OTHER)
1192                                 pid= parent;
1193                         else if(*pr_texture == TEX_PR_BOTH)
1194                                 pparent= parent;
1195                 }
1196         }
1197
1198         /* layout */
1199         block= uiLayoutGetBlock(layout);
1200         row= uiLayoutRow(layout, 0);
1201         col= uiLayoutColumn(row, 0);
1202         uiLayoutSetKeepAspect(col, 1);
1203         
1204         /* add preview */
1205         uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, pid, 0.0, 0.0, 0, 0, "");
1206         uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot);
1207         uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
1208         
1209         /* add buttons */
1210         if(pid) {
1211                 if(GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
1212                         if(GS(pid->name) == ID_MA) ma= (Material*)pid;
1213                         else ma= (Material*)pparent;
1214
1215                         uiLayoutColumn(row, 1);
1216
1217                         uiDefIconButC(block, ROW, B_MATPRV, ICON_MATPLANE,  0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_FLAT, 0, 0, "Preview type: Flat XY plane");
1218                         uiDefIconButC(block, ROW, B_MATPRV, ICON_MATSPHERE, 0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_SPHERE, 0, 0, "Preview type: Sphere");
1219                         uiDefIconButC(block, ROW, B_MATPRV, ICON_MATCUBE,   0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_CUBE, 0, 0, "Preview type: Cube");
1220                         uiDefIconButC(block, ROW, B_MATPRV, ICON_MONKEY,    0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_MONKEY, 0, 0, "Preview type: Monkey");
1221                         uiDefIconButC(block, ROW, B_MATPRV, ICON_HAIR,      0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_HAIR, 0, 0, "Preview type: Hair strands");
1222                         uiDefIconButC(block, ROW, B_MATPRV, ICON_MAT_SPHERE_SKY, 0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_SPHERE_A, 0, 0, "Preview type: Large sphere with sky");
1223                 }
1224
1225                 if(pr_texture) {
1226                         uiLayoutRow(layout, 1);
1227
1228                         uiDefButS(block, ROW, B_MATPRV, "Texture",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
1229                         if(GS(parent->name) == ID_MA)
1230                                 uiDefButS(block, ROW, B_MATPRV, "Material",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1231                         else if(GS(parent->name) == ID_LA)
1232                                 uiDefButS(block, ROW, B_MATPRV, "Lamp",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1233                         else if(GS(parent->name) == ID_WO)
1234                                 uiDefButS(block, ROW, B_MATPRV, "World",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1235                         uiDefButS(block, ROW, B_MATPRV, "Both",  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
1236                 }
1237         }
1238 }
1239
1240 /********************** ColorRamp Template **************************/
1241
1242 #include "BKE_texture.h"
1243
1244 typedef struct RNAUpdateCb {
1245         PointerRNA ptr;
1246         PropertyRNA *prop;
1247 } RNAUpdateCb;
1248
1249 static void rna_update_cb(bContext *C, void *arg_cb, void *arg_unused)
1250 {
1251         RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
1252
1253         /* we call update here on the pointer property, this way the
1254            owner of the curve mapping can still define it's own update
1255            and notifier, even if the CurveMapping struct is shared. */
1256         RNA_property_update(C, &cb->ptr, cb->prop);
1257 }
1258
1259 #define B_BANDCOL 1
1260
1261 static int vergcband(const void *a1, const void *a2)
1262 {
1263         const CBData *x1=a1, *x2=a2;
1264
1265         if( x1->pos > x2->pos ) return 1;
1266         else if( x1->pos < x2->pos) return -1;
1267         return 0;
1268 }
1269
1270 static void colorband_pos_cb(bContext *C, void *cb_v, void *coba_v)
1271 {
1272         ColorBand *coba= coba_v;
1273         int a;
1274
1275         if(coba->tot<2) return;
1276
1277         for(a=0; a<coba->tot; a++) coba->data[a].cur= a;
1278         qsort(coba->data, coba->tot, sizeof(CBData), vergcband);
1279         for(a=0; a<coba->tot; a++) {
1280                 if(coba->data[a].cur==coba->cur) {
1281                         coba->cur= a;
1282                         break;
1283                 }
1284         }
1285
1286         rna_update_cb(C, cb_v, NULL);
1287 }
1288
1289 static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
1290 {
1291         ColorBand *coba= coba_v;
1292
1293         if(coba->tot < MAXCOLORBAND-1) coba->tot++;
1294         coba->cur= coba->tot-1;
1295
1296         colorband_pos_cb(C, cb_v, coba_v);
1297
1298         ED_undo_push(C, "Add colorband");
1299 }
1300
1301 static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v)
1302 {
1303         ColorBand *coba= coba_v;
1304         int a;
1305
1306         if(coba->tot<2) return;
1307
1308         for(a=coba->cur; a<coba->tot; a++) {
1309                 coba->data[a]= coba->data[a+1];
1310         }
1311         if(coba->cur) coba->cur--;
1312         coba->tot--;
1313
1314         ED_undo_push(C, "Delete colorband");
1315
1316         rna_update_cb(C, cb_v, NULL);
1317 }
1318
1319
1320 /* offset aligns from bottom, standard width 300, height 115 */
1321 static void colorband_buttons_large(uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb)
1322 {
1323         CBData *cbd;
1324         uiBut *bt;
1325
1326         if(coba==NULL) return;
1327
1328         bt= uiDefBut(block, BUT, 0,     "Add",                  0+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Add a new color stop to the colorband");
1329         uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1330
1331         bt= uiDefBut(block, BUT, 0,     "Delete",               60+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Delete the active position");
1332         uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1333
1334         uiDefButS(block, NUM, 0,                "",                             120+xoffs,100+yoffs,80, 20, &coba->cur, 0.0, (float)(coba->tot-1), 0, 0, "Choose active color stop");
1335
1336         bt= uiDefButS(block, MENU, 0,           "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1337                         210+xoffs, 100+yoffs, 90, 20,           &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1338         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1339         uiBlockEndAlign(block);
1340
1341         bt= uiDefBut(block, BUT_COLORBAND, 0, "",       xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, "");
1342         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1343
1344         cbd= coba->data + coba->cur;
1345
1346         bt= uiDefButF(block, NUM, 0, "Pos:",                    0+xoffs,40+yoffs,100, 20, &cbd->pos, 0.0, 1.0, 10, 0, "The position of the active color stop");
1347         uiButSetNFunc(bt, colorband_pos_cb, MEM_dupallocN(cb), coba);
1348         bt= uiDefButF(block, COL, 0,            "",                             110+xoffs,40+yoffs,80,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop");
1349         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1350         bt= uiDefButF(block, NUMSLI, 0, "A ",                   200+xoffs,40+yoffs,100,20, &cbd->a, 0.0, 1.0, 10, 0, "The alpha value of the active color stop");
1351         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1352
1353 }
1354
1355 static void colorband_buttons_small(uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
1356 {
1357         CBData *cbd;
1358         uiBut *bt;
1359         float unit= (butr->xmax-butr->xmin)/14.0f;
1360         float xs= butr->xmin;
1361
1362         cbd= coba->data + coba->cur;
1363
1364
1365         bt= uiDefBut(block, BUT, 0,     "Add",                  xs,butr->ymin+20.0f,2.0f*unit,20,       NULL, 0, 0, 0, 0, "Add a new color stop to the colorband");
1366         uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1367         bt= uiDefBut(block, BUT, 0,     "Delete",               xs+2.0f*unit,butr->ymin+20.0f,2.0f*unit,20,     NULL, 0, 0, 0, 0, "Delete the active position");
1368         uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1369
1370         bt= uiDefButF(block, COL, 0,            "",                     xs+4.0f*unit,butr->ymin+20.0f,2.0f*unit,20,                             &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop");
1371         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1372         bt= uiDefButF(block, NUMSLI, 0,         "A:",           xs+6.0f*unit,butr->ymin+20.0f,4.0f*unit,20,     &(cbd->a), 0.0f, 1.0f, 10, 2, "The alpha value of the active color stop");
1373         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1374
1375         bt= uiDefButS(block, MENU, 0,           "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1376                         xs+10.0f*unit, butr->ymin+20.0f, unit*4, 20,            &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1377         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1378
1379         bt= uiDefBut(block, BUT_COLORBAND, 0, "",               xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, "");
1380         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1381
1382         uiBlockEndAlign(block);
1383 }
1384
1385 static void colorband_buttons_layout(uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb)
1386 {
1387         if(small)
1388                 colorband_buttons_small(block, coba, butr, cb);
1389         else
1390                 colorband_buttons_large(block, coba, 0, 0, cb);
1391 }
1392
1393 void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, char *propname, int expand)
1394 {
1395         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1396         PointerRNA cptr;
1397         RNAUpdateCb *cb;
1398         uiBlock *block;
1399         rctf rect;
1400
1401         if(!prop || RNA_property_type(prop) != PROP_POINTER)
1402                 return;
1403
1404         cptr= RNA_property_pointer_get(ptr, prop);
1405         if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp))
1406                 return;
1407
1408         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1409         cb->ptr= *ptr;
1410         cb->prop= prop;
1411
1412         rect.xmin= 0; rect.xmax= 200;
1413         rect.ymin= 0; rect.ymax= 190;
1414
1415         block= uiLayoutFreeBlock(layout);
1416         colorband_buttons_layout(block, cptr.data, &rect, !expand, cb);
1417
1418         MEM_freeN(cb);
1419 }
1420
1421 /********************* CurveMapping Template ************************/
1422
1423 #include "DNA_color_types.h"
1424 #include "BKE_colortools.h"
1425
1426 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *unused)
1427 {
1428         CurveMapping *cumap = cumap_v;
1429         float d;
1430
1431         /* we allow 20 times zoom */
1432         if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1433                 d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
1434                 cumap->curr.xmin+= d;
1435                 cumap->curr.xmax-= d;
1436                 d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
1437                 cumap->curr.ymin+= d;
1438                 cumap->curr.ymax-= d;
1439         }
1440
1441         ED_region_tag_redraw(CTX_wm_region(C));
1442 }
1443
1444 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *unused)
1445 {
1446         CurveMapping *cumap = cumap_v;
1447         float d, d1;
1448
1449         /* we allow 20 times zoom, but dont view outside clip */
1450         if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1451                 d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
1452
1453                 if(cumap->flag & CUMA_DO_CLIP) 
1454                         if(cumap->curr.xmin-d < cumap->clipr.xmin)
1455                                 d1= cumap->curr.xmin - cumap->clipr.xmin;
1456                 cumap->curr.xmin-= d1;
1457
1458                 d1= d;
1459                 if(cumap->flag & CUMA_DO_CLIP) 
1460                         if(cumap->curr.xmax+d > cumap->clipr.xmax)
1461                                 d1= -cumap->curr.xmax + cumap->clipr.xmax;
1462                 cumap->curr.xmax+= d1;
1463
1464                 d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
1465
1466                 if(cumap->flag & CUMA_DO_CLIP) 
1467                         if(cumap->curr.ymin-d < cumap->clipr.ymin)
1468                                 d1= cumap->curr.ymin - cumap->clipr.ymin;
1469                 cumap->curr.ymin-= d1;
1470
1471                 d1= d;
1472                 if(cumap->flag & CUMA_DO_CLIP) 
1473                         if(cumap->curr.ymax+d > cumap->clipr.ymax)
1474                                 d1= -cumap->curr.ymax + cumap->clipr.ymax;
1475                 cumap->curr.ymax+= d1;
1476         }
1477
1478         ED_region_tag_redraw(CTX_wm_region(C));
1479 }
1480
1481 static void curvemap_buttons_setclip(bContext *C, void *cumap_v, void *unused)
1482 {
1483         CurveMapping *cumap = cumap_v;
1484
1485         curvemapping_changed(cumap, 0);
1486 }       
1487
1488 static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
1489 {
1490         CurveMapping *cumap = cumap_v;
1491
1492         curvemap_remove(cumap->cm+cumap->cur, SELECT);
1493         curvemapping_changed(cumap, 0);
1494
1495         rna_update_cb(C, cb_v, NULL);
1496 }
1497
1498 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
1499 static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v)
1500 {
1501         CurveMapping *cumap = cumap_v;
1502         uiBlock *block;
1503         uiBut *bt;
1504
1505         block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS);
1506
1507         /* use this for a fake extra empy space around the buttons */
1508         uiDefBut(block, LABEL, 0, "",                   -4, 16, 128, 106, NULL, 0, 0, 0, 0, "");
1509
1510         bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",    
1511                         0,100,120,18, &cumap->flag, 0.0, 0.0, 10, 0, "");
1512         uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
1513
1514         uiBlockBeginAlign(block);
1515         uiDefButF(block, NUM, 0, "Min X ",       0,74,120,18, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, "");
1516         uiDefButF(block, NUM, 0, "Min Y ",       0,56,120,18, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, "");
1517         uiDefButF(block, NUM, 0, "Max X ",       0,38,120,18, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, "");
1518         uiDefButF(block, NUM, 0, "Max Y ",       0,20,120,18, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, "");
1519
1520         uiBlockSetDirection(block, UI_RIGHT);
1521
1522         uiEndBlock(C, block);
1523         return block;
1524 }
1525
1526 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
1527 {
1528         CurveMapping *cumap = cumap_v;
1529         CurveMap *cuma= cumap->cm+cumap->cur;
1530
1531         switch(event) {
1532                 case 0:
1533                         curvemap_reset(cuma, &cumap->clipr);
1534                         curvemapping_changed(cumap, 0);
1535                         break;
1536                 case 1:
1537                         cumap->curr= cumap->clipr;
1538                         break;
1539                 case 2: /* set vector */
1540                         curvemap_sethandle(cuma, 1);
1541                         curvemapping_changed(cumap, 0);
1542                         break;
1543                 case 3: /* set auto */
1544                         curvemap_sethandle(cuma, 0);
1545                         curvemapping_changed(cumap, 0);
1546                         break;
1547                 case 4: /* extend horiz */
1548                         cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
1549                         curvemapping_changed(cumap, 0);
1550                         break;
1551                 case 5: /* extend extrapolate */
1552                         cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
1553                         curvemapping_changed(cumap, 0);
1554                         break;
1555         }
1556         ED_region_tag_redraw(CTX_wm_region(C));
1557 }
1558
1559 static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1560 {
1561         uiBlock *block;
1562         short yco= 0, menuwidth=120;
1563
1564         block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1565         uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1566
1567         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View",                             0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
1568         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle",                  0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
1569         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
1570         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal",              0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
1571         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated",    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
1572         uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve",                    0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
1573
1574         uiBlockSetDirection(block, UI_RIGHT);
1575         uiTextBoundsBlock(block, 50);
1576
1577         uiEndBlock(C, block);
1578         return block;
1579 }
1580
1581 static void curvemap_buttons_redraw(bContext *C, void *arg1, void *arg2)
1582 {
1583         ED_region_tag_redraw(CTX_wm_region(C));
1584 }
1585
1586 static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
1587 {
1588         CurveMapping *cumap = cumap_v;
1589         int a;
1590         
1591         for(a=0; a<CM_TOT; a++)
1592                 curvemap_reset(cumap->cm+a, &cumap->clipr);
1593         
1594         cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
1595         cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
1596         curvemapping_set_black_white(cumap, NULL, NULL);
1597         
1598         curvemapping_changed(cumap, 0);
1599
1600         rna_update_cb(C, cb_v, NULL);
1601 }
1602
1603 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
1604 static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, RNAUpdateCb *cb)
1605 {
1606         CurveMapping *cumap= ptr->data;
1607         uiLayout *row, *sub, *split;
1608         uiBlock *block;
1609         uiBut *bt;
1610         float dx= UI_UNIT_X;
1611         int icon, size;
1612
1613         block= uiLayoutGetBlock(layout);
1614
1615         /* curve chooser */
1616         row= uiLayoutRow(layout, 0);
1617
1618         if(labeltype=='v') {
1619                 /* vector */
1620                 sub= uiLayoutRow(row, 1);
1621                 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1622
1623                 if(cumap->cm[0].curve) {
1624                         bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1625                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1626                 }
1627                 if(cumap->cm[1].curve) {
1628                         bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1629                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1630                 }
1631                 if(cumap->cm[2].curve) {
1632                         bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1633                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1634                 }
1635         }
1636         else if(labeltype=='c') {
1637                 /* color */
1638                 sub= uiLayoutRow(row, 1);
1639                 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1640
1641                 if(cumap->cm[3].curve) {
1642                         bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
1643                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1644                 }
1645                 if(cumap->cm[0].curve) {
1646                         bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1647                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1648                 }
1649                 if(cumap->cm[1].curve) {
1650                         bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1651                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1652                 }
1653                 if(cumap->cm[2].curve) {
1654                         bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1655                         uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1656                 }
1657         }
1658         else
1659                 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
1660
1661         /* operation buttons */
1662         sub= uiLayoutRow(row, 1);
1663
1664         uiBlockSetEmboss(block, UI_EMBOSSN);
1665
1666         bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
1667         uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
1668
1669         bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
1670         uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
1671
1672         bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, 18, "Tools");
1673         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1674
1675         if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
1676         bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, 18, "Clipping Options");
1677         uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1678
1679         bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
1680         uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
1681
1682         uiBlockSetEmboss(block, UI_EMBOSS);
1683
1684         uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
1685
1686         /* curve itself */
1687         size= uiLayoutGetWidth(layout);
1688         row= uiLayoutRow(layout, 0);
1689         uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, 0, 0, "");
1690
1691         /* black/white levels */
1692         if(levels) {
1693                 split= uiLayoutSplit(layout, 0);
1694                 uiItemR(uiLayoutColumn(split, 0), NULL, 0, ptr, "black_level", UI_ITEM_R_EXPAND);
1695                 uiItemR(uiLayoutColumn(split, 0), NULL, 0, ptr, "white_level", UI_ITEM_R_EXPAND);
1696
1697                 uiLayoutRow(layout, 0);
1698                 bt=uiDefBut(block, BUT, 0, "Reset",     0, 0, UI_UNIT_X*10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves");
1699                 uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
1700         }
1701
1702         uiBlockSetNFunc(block, NULL, NULL, NULL);
1703 }
1704
1705 void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, char *propname, int type, int levels)
1706 {
1707         RNAUpdateCb *cb;
1708         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1709         PointerRNA cptr;
1710
1711         if(!prop || RNA_property_type(prop) != PROP_POINTER)
1712                 return;
1713
1714         cptr= RNA_property_pointer_get(ptr, prop);
1715         if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping))
1716                 return;
1717
1718         cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1719         cb->ptr= *ptr;
1720         cb->prop= prop;
1721
1722         curvemap_buttons_layout(layout, &cptr, type, levels, cb);
1723
1724         MEM_freeN(cb);
1725 }
1726
1727 /********************* TriColor (ThemeWireColorSet) Template ************************/
1728
1729 void uiTemplateTriColorSet(uiLayout *layout, PointerRNA *ptr, char *propname)
1730 {
1731         PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1732         uiLayout *row;
1733         PointerRNA csPtr;
1734
1735         if (!prop) {
1736                 printf("uiTemplateTriColorSet: property not found: %s\n", propname);
1737                 return;
1738         }
1739         
1740         /* we lay out the data in a row as 3 color swatches */
1741         row= uiLayoutRow(layout, 1);
1742         
1743         /* nselected, selected, active color swatches */
1744         csPtr= RNA_property_pointer_get(ptr, prop);
1745         
1746         uiItemR(row, "", 0, &csPtr, "normal", 0);
1747         uiItemR(row, "", 0, &csPtr, "selected", 0);
1748         uiItemR(row, "", 0, &csPtr, "active", 0);
1749 }
1750
1751 /********************* Layer Buttons Template ************************/
1752
1753 // TODO:
1754 //      - option for showing extra info like whether layer has contents?
1755 //      - for now, grouping of layers is determined by dividing up the length of 
1756 //        the array of layer bitflags
1757
1758 void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname)
1759 {
1760         uiLayout *uRow, *uSplit, *uCol;
1761         PropertyRNA *prop;
1762         int groups, cols, layers;
1763         int group, col, layer, row;
1764         
1765         if (!ptr->data)
1766                 return;
1767         
1768         prop= RNA_struct_find_property(ptr, propname);
1769         if (!prop) {
1770                 printf("uiTemplateLayer: layers property not found: %s\n", propname);
1771                 return;
1772         }
1773         
1774         /* the number of layers determines the way we group them 
1775          *      - we want 2 rows only (for now)
1776          *      - the number of columns (cols) is the total number of buttons per row
1777          *        the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
1778          *      - for now, only split into groups if if group will have at least 5 items
1779          */
1780         layers= RNA_property_array_length(ptr, prop);
1781         cols= (layers / 2) + (layers % 2);
1782         groups= ((cols / 2) < 5) ? (1) : (cols / 2);
1783         
1784         /* layers are laid out going across rows, with the columns being divided into groups */
1785         if (groups > 1)
1786                 uSplit= uiLayoutSplit(layout, (1.0f/(float)groups));
1787         else    
1788                 uSplit= layout;
1789         
1790         for (group= 0; group < groups; group++) {
1791                 uCol= uiLayoutColumn(uSplit, 1);
1792                 
1793                 for (row= 0; row < 2; row++) {
1794                         uRow= uiLayoutRow(uCol, 1);
1795                         layer= groups*cols*row + cols*group;
1796                         
1797                         /* add layers as toggle buts */
1798                         for (col= 0; (col < cols) && (layer < layers); col++, layer++) {
1799                                 int icon=0; // XXX - add some way of setting this...
1800                                 uiItemFullR(uRow, "", icon, ptr, prop, layer, 0, UI_ITEM_R_TOGGLE);
1801                         }
1802                 }
1803         }
1804 }
1805
1806
1807 /************************* List Template **************************/
1808
1809 #if 0
1810 static void list_item_add(ListBase *lb, ListBase *itemlb, uiLayout *layout, PointerRNA *data)
1811 {
1812         CollectionPointerLink *link;
1813         uiListItem *item;
1814
1815         /* add to list to store in box */
1816         item= MEM_callocN(sizeof(uiListItem), "uiListItem");
1817         item->layout= layout;
1818         item->data= *data;
1819         BLI_addtail(itemlb, item);
1820
1821         /* add to list to return from function */
1822         link= MEM_callocN(sizeof(CollectionPointerLink), "uiTemplateList return");
1823         RNA_pointer_create(NULL, &RNA_UIListItem, item, &link->ptr);
1824         BLI_addtail(lb, link);
1825 }
1826 #endif
1827
1828 ListBase uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *activeptr, char *activepropname, int rows, int listtype)
1829 {
1830         //Scene *scene= CTX_data_scene(C);
1831         PropertyRNA *prop= NULL, *activeprop;
1832         PropertyType type, activetype;
1833         StructRNA *ptype;
1834         uiLayout *box, *row, *col, *subrow;
1835         uiBlock *block;
1836         uiBut *but;
1837         Panel *pa;
1838         ListBase lb, *itemlb;
1839         char *name, str[32];
1840         int icon=0, i= 0, activei= 0, len= 0, items, found, min, max;
1841
1842         lb.first= lb.last= NULL;
1843         
1844         /* validate arguments */
1845         block= uiLayoutGetBlock(layout);
1846         pa= block->panel;
1847
1848         if(!pa) {
1849                 printf("uiTemplateList: only works inside a panel.\n");
1850                 return lb;
1851         }
1852
1853         if(!activeptr->data)
1854                 return lb;
1855         
1856         if(ptr->data) {
1857                 prop= RNA_struct_find_property(ptr, propname);
1858                 if(!prop) {
1859                         printf("uiTemplateList: property not found: %s\n", propname);
1860                         return lb;
1861                 }
1862         }
1863
1864         activeprop= RNA_struct_find_property(activeptr, activepropname);
1865         if(!activeprop) {
1866                 printf("uiTemplateList: property not found: %s\n", activepropname);
1867                 return lb;
1868         }
1869
1870         if(prop) {
1871                 type= RNA_property_type(prop);
1872                 if(type != PROP_COLLECTION) {
1873                         printf("uiTemplateList: expected collection property.\n");
1874                         return lb;
1875                 }
1876         }
1877
1878         activetype= RNA_property_type(activeprop);
1879         if(activetype != PROP_INT) {
1880                 printf("uiTemplateList: expected integer property.\n");
1881                 return lb;
1882         }
1883
1884         /* get icon */
1885         if(ptr->data && prop) {
1886                 ptype= RNA_property_pointer_type(ptr, prop);
1887                 icon= RNA_struct_ui_icon(ptype);
1888         }
1889
1890         /* get active data */
1891         activei= RNA_property_int_get(activeptr, activeprop);
1892
1893         if(listtype == 'i') {
1894                 box= uiLayoutListBox(layout);
1895                 col= uiLayoutColumn(box, 1);
1896                 row= uiLayoutRow(col, 0);
1897
1898                 itemlb= uiLayoutBoxGetList(box);
1899
1900                 if(ptr->data && prop) {
1901                         /* create list items */
1902                         RNA_PROP_BEGIN(ptr, itemptr, prop) {
1903                                 /* create button */
1904                                 if(i == 9)
1905                                         row= uiLayoutRow(col, 0);
1906
1907                                 if(RNA_struct_is_a(itemptr.type, &RNA_TextureSlot)) {
1908 #if 0
1909                                         MTex *mtex= itemptr.data;
1910
1911                                         if(mtex && mtex->tex)
1912                                                 icon= ui_id_icon_get(scene, &mtex->tex->id);
1913 #endif
1914                                 }
1915
1916                                 uiDefIconButR(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
1917
1918                                 //list_item_add(&lb, itemlb, uiLayoutRow(row, 1), &itemptr);
1919
1920                                 i++;
1921                         }
1922                         RNA_PROP_END;
1923                 }
1924         }
1925         else if(listtype == 'c') {
1926                 /* compact layout */
1927                 found= 0;
1928
1929                 row= uiLayoutRow(layout, 1);
1930
1931                 if(ptr->data && prop) {
1932                         /* create list items */
1933                         RNA_PROP_BEGIN(ptr, itemptr, prop) {
1934                                 found= (activei == i);
1935
1936                                 if(found) {
1937                                         /* create button */
1938                                         name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
1939                                         uiItemL(row, (name)? name: "", icon);
1940
1941                                         if(name)
1942                                                 MEM_freeN(name);
1943
1944                                         /* add to list to return */
1945                                         //list_item_add(&lb, itemlb, uiLayoutRow(row, 1), &itemptr);
1946                                 }
1947
1948                                 i++;
1949                         }
1950                         RNA_PROP_END;
1951                 }
1952
1953                 /* if not found, add in dummy button */
1954                 if(i == 0)
1955                         uiItemL(row, "", 0);
1956
1957                 /* next/prev button */
1958                 sprintf(str, "%d :", i);
1959                 but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activepropname, 0, 0, 0, 0, 0, "");
1960                 if(i == 0)
1961                         uiButSetFlag(but, UI_BUT_DISABLED);
1962         }
1963         else {
1964                 /* default rows */
1965                 if(rows == 0)
1966                         rows= 5;
1967
1968                 /* layout */
1969                 box= uiLayoutListBox(layout);
1970                 row= uiLayoutRow(box, 0);
1971                 col = uiLayoutColumn(row, 1);
1972
1973                 /* init numbers */
1974                 RNA_property_int_range(activeptr, activeprop, &min, &max);
1975
1976                 if(prop)
1977                         len= RNA_property_collection_length(ptr, prop);
1978                 items= CLAMPIS(len, rows, 5);
1979
1980                 pa->list_scroll= MIN2(pa->list_scroll, len-items);
1981                 pa->list_scroll= MAX2(pa->list_scroll, 0);
1982
1983                 itemlb= uiLayoutBoxGetList(box);
1984
1985                 if(ptr->data && prop) {
1986                         /* create list items */
1987                         RNA_PROP_BEGIN(ptr, itemptr, prop) {
1988                                 if(i >= pa->list_scroll && i<pa->list_scroll+items) {
1989                                         name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
1990
1991                                         subrow= uiLayoutRow(col, 0);
1992
1993                                         /* create button */
1994                                         if(!icon || icon == ICON_DOT)
1995                                                 but= uiDefButR(block, LISTROW, 0, (name)? name: "", 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
1996                                         else
1997                                                 but= uiDefIconTextButR(block, LISTROW, 0, icon, (name)? name: "", 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
1998                                         uiButSetFlag(but, UI_ICON_LEFT|UI_TEXT_LEFT);
1999
2000                                         /* XXX hardcoded */
2001                                         if(itemptr.type == &RNA_MeshTextureFaceLayer || itemptr.type == &RNA_MeshColorLayer) {
2002                                                 uiBlockSetEmboss(block, UI_EMBOSSN);
2003                                                 uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, &itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
2004                                                 uiBlockSetEmboss(block, UI_EMBOSS);
2005                                         }
2006
2007                                         if(name)
2008                                                 MEM_freeN(name);
2009
2010                                         /* add to list to return */
2011                                         //list_item_add(&lb, itemlb, subrow, &itemptr);
2012                                 }
2013
2014                                 i++;
2015                         }
2016                         RNA_PROP_END;
2017                 }
2018
2019                 /* add dummy buttons to fill space */
2020                 while(i < pa->list_scroll+items) {
2021                         if(i >= pa->list_scroll)
2022                                 uiItemL(col, "", 0);
2023                         i++;
2024                 }
2025
2026                 /* add scrollbar */
2027                 if(len > items) {
2028                         col= uiLayoutColumn(row, 0);
2029                         uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
2030                 }
2031         }
2032
2033         /* return items in list */
2034         return lb;
2035 }
2036
2037 /************************* Operator Search Template **************************/
2038
2039 static void operator_call_cb(struct bContext *C, void *arg1, void *arg2)
2040 {
2041         wmOperatorType *ot= arg2;
2042         
2043         if(ot)
2044                 WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
2045 }
2046
2047 static void operator_search_cb(const struct bContext *C, void *arg, char *str, uiSearchItems *items)
2048 {
2049         wmOperatorType *ot = WM_operatortype_first();
2050         
2051         for(; ot; ot= ot->next) {
2052                 
2053                 if(BLI_strcasestr(ot->name, str)) {
2054                         if(ot->poll==NULL || ot->poll((bContext *)C)) {
2055                                 char name[256];
2056                                 int len= strlen(ot->name);
2057                                 
2058                                 /* display name for menu, can hold hotkey */
2059                                 BLI_strncpy(name, ot->name, 256);
2060                                 
2061                                 /* check for hotkey */
2062                                 if(len < 256-6) {
2063                                         if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
2064                                                 name[len]= '|';
2065                                 }
2066                                 
2067                                 if(0==uiSearchItemAdd(items, name, ot, 0))
2068                                         break;
2069                         }
2070                 }
2071         }
2072 }
2073
2074 void uiTemplateOperatorSearch(uiLayout *layout)
2075 {
2076         uiBlock *block;
2077         uiBut *but;
2078         static char search[256]= "";
2079                 
2080         block= uiLayoutGetBlock(layout);
2081         uiBlockSetCurLayout(block, layout);
2082
2083         but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, "");
2084         uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
2085 }
2086
2087 /************************* Running Jobs Template **************************/
2088
2089 #define B_STOPRENDER    1
2090 #define B_STOPCAST              2
2091 #define B_STOPANIM              3
2092
2093 static void do_running_jobs(bContext *C, void *arg, int event)
2094 {
2095         switch(event) {
2096                 case B_STOPRENDER:
2097                         G.afbreek= 1;
2098                         break;
2099                 case B_STOPCAST:
2100                         WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C));
2101                         break;
2102                 case B_STOPANIM:
2103                         WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
2104                         break;
2105         }
2106 }
2107
2108 void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
2109 {
2110         bScreen *screen= CTX_wm_screen(C);
2111         Scene *scene= CTX_data_scene(C);
2112         wmWindowManager *wm= CTX_wm_manager(C);
2113         uiBlock *block;
2114
2115         block= uiLayoutGetBlock(layout);
2116         uiBlockSetCurLayout(block, layout);
2117
2118         uiBlockSetHandleFunc(block, do_running_jobs, NULL);
2119
2120         if(WM_jobs_test(wm, scene))
2121                 uiDefIconTextBut(block, BUT, B_STOPRENDER, ICON_REC, "Render", 0,0,75,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop rendering");
2122         if(WM_jobs_test(wm, screen))
2123                 uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_REC, "Capture", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast");
2124         if(screen->animtimer)
2125                 uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_REC, "Anim Player", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop animation playback");
2126 }
2127
2128