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