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