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