Blender V2.61 - r43446

interface_templates.c

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributor(s): Blender Foundation 2009.
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00028 #include <stdlib.h>
00029 #include <stddef.h>
00030 #include <string.h>
00031 
00032 #include "MEM_guardedalloc.h"
00033 
00034 #include "DNA_anim_types.h"
00035 #include "DNA_dynamicpaint_types.h"
00036 #include "DNA_key_types.h"
00037 #include "DNA_scene_types.h"
00038 #include "DNA_userdef_types.h"
00039 
00040 #include "BLI_utildefines.h"
00041 #include "BLI_string.h"
00042 #include "BLI_ghash.h"
00043 
00044 #include "BLF_translation.h"
00045 
00046 #include "BKE_animsys.h"
00047 #include "BKE_colortools.h"
00048 #include "BKE_context.h"
00049 #include "BKE_dynamicpaint.h"
00050 #include "BKE_global.h"
00051 #include "BKE_library.h"
00052 #include "BKE_main.h"
00053 #include "BKE_object.h"
00054 #include "BKE_material.h"
00055 #include "BKE_texture.h"
00056 #include "BKE_report.h"
00057 #include "BKE_displist.h"
00058 #include "BKE_scene.h"
00059 
00060 #include "ED_screen.h"
00061 #include "ED_object.h"
00062 #include "ED_render.h"
00063 
00064 #include "RNA_access.h"
00065 #include "RNA_enum_types.h"
00066 
00067 #include "WM_api.h"
00068 #include "WM_types.h"
00069 
00070 #include "UI_interface.h"
00071 #include "interface_intern.h"
00072 
00073 #include "BLF_api.h"
00074 #include "BLF_translation.h"
00075 
00076 void UI_template_fix_linking(void)
00077 {
00078 }
00079 
00080 /********************** Header Template *************************/
00081 
00082 void uiTemplateHeader(uiLayout *layout, bContext *C, int menus)
00083 {
00084     uiBlock *block;
00085 
00086     block= uiLayoutAbsoluteBlock(layout);
00087     if(menus) ED_area_header_standardbuttons(C, block, 0);
00088     else ED_area_header_switchbutton(C, block, 0);
00089 }
00090 
00091 /********************** Search Callbacks *************************/
00092 
00093 typedef struct TemplateID {
00094     PointerRNA ptr;
00095     PropertyRNA *prop;
00096 
00097     ListBase *idlb;
00098     int prv_rows, prv_cols;
00099 } TemplateID;
00100 
00101 /* Search browse menu, assign  */
00102 static void id_search_call_cb(bContext *C, void *arg_template, void *item)
00103 {
00104     TemplateID *template= (TemplateID*)arg_template;
00105 
00106     /* ID */
00107     if(item) {
00108         PointerRNA idptr;
00109 
00110         RNA_id_pointer_create(item, &idptr);
00111         RNA_property_pointer_set(&template->ptr, template->prop, idptr);
00112         RNA_property_update(C, &template->ptr, template->prop);
00113     }
00114 }
00115 
00116 /* ID Search browse menu, do the search */
00117 static void id_search_cb(const bContext *C, void *arg_template, const char *str, uiSearchItems *items)
00118 {
00119     TemplateID *template= (TemplateID*)arg_template;
00120     ListBase *lb= template->idlb;
00121     ID *id, *id_from= template->ptr.id.data;
00122     int iconid;
00123     int flag= RNA_property_flag(template->prop);
00124 
00125     /* ID listbase */
00126     for(id= lb->first; id; id= id->next) {
00127         if(!((flag & PROP_ID_SELF_CHECK) && id == id_from)) {
00128 
00129             /* use filter */
00130             if(RNA_property_type(template->prop)==PROP_POINTER) {
00131                 PointerRNA ptr;
00132                 RNA_id_pointer_create(id, &ptr);
00133                 if(RNA_property_pointer_poll(&template->ptr, template->prop, &ptr)==0)
00134                     continue;
00135             }
00136 
00137             /* hide dot-datablocks, but only if filter does not force it visible */
00138             if(U.uiflag & USER_HIDE_DOT)
00139                 if ((id->name[2]=='.') && (str[0] != '.'))
00140                     continue;
00141 
00142             if(BLI_strcasestr(id->name+2, str)) {
00143                 char name_ui[MAX_ID_NAME];
00144                 name_uiprefix_id(name_ui, id);
00145 
00146                 iconid= ui_id_icon_get((bContext*)C, id, 1);
00147 
00148                 if(!uiSearchItemAdd(items, name_ui, id, iconid))
00149                     break;
00150             }
00151         }
00152     }
00153 }
00154 
00155 /* ID Search browse menu, open */
00156 static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
00157 {
00158     static char search[256];
00159     static TemplateID template;
00160     PointerRNA idptr;
00161     wmWindow *win= CTX_wm_window(C);
00162     uiBlock *block;
00163     uiBut *but;
00164     
00165     /* clear initial search string, then all items show */
00166     search[0]= 0;
00167     /* arg_litem is malloced, can be freed by parent button */
00168     template= *((TemplateID*)arg_litem);
00169     
00170     /* get active id for showing first item */
00171     idptr= RNA_property_pointer_get(&template.ptr, template.prop);
00172 
00173     block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
00174     uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
00175     
00176     /* preview thumbnails */
00177     if (template.prv_rows > 0 && template.prv_cols > 0) {
00178         int w = 96 * template.prv_cols;
00179         int h = 96 * template.prv_rows + 20;
00180         
00181         /* fake button, it holds space for search items */
00182         uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL);
00183         
00184         but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, 19, template.prv_rows, template.prv_cols, "");
00185         uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
00186     }
00187     /* list view */
00188     else {
00189         /* fake button, it holds space for search items */
00190         uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
00191         
00192         but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, "");
00193         uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
00194     }
00195         
00196     
00197     uiBoundsBlock(block, 6);
00198     uiBlockSetDirection(block, UI_DOWN);    
00199     uiEndBlock(C, block);
00200     
00201     /* give search-field focus */
00202     uiButSetFocusOnEnter(win, but);
00203     /* this type of search menu requires undo */
00204     but->flag |= UI_BUT_UNDO;
00205     
00206     return block;
00207 }
00208 
00209 /************************ ID Template ***************************/
00210 /* This is for browsing and editing the ID-blocks used */
00211 
00212 /* for new/open operators */
00213 void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
00214 {
00215     TemplateID *template;
00216     ARegion *ar= CTX_wm_region(C);
00217     uiBlock *block;
00218     uiBut *but;
00219 
00220     memset(ptr, 0, sizeof(*ptr));
00221     *prop= NULL;
00222 
00223     if(!ar)
00224         return;
00225 
00226     for(block=ar->uiblocks.first; block; block=block->next) {
00227         for(but=block->buttons.first; but; but= but->next) {
00228             /* find the button before the active one */
00229             if((but->flag & (UI_BUT_LAST_ACTIVE|UI_ACTIVE))) {
00230                 if(but->func_argN) {
00231                     template= but->func_argN;
00232                     *ptr= template->ptr;
00233                     *prop= template->prop;
00234                     return;
00235                 }
00236             }
00237         }
00238     }
00239 }
00240 
00241 
00242 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
00243 {
00244     TemplateID *template= (TemplateID*)arg_litem;
00245     PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
00246     ID *id= idptr.data;
00247     int event= GET_INT_FROM_POINTER(arg_event);
00248     
00249     switch(event) {
00250         case UI_ID_BROWSE:
00251         case UI_ID_PIN:
00252             RNA_warning("warning, id event %d shouldnt come here", event);
00253             break;
00254         case UI_ID_OPEN:
00255         case UI_ID_ADD_NEW:
00256             /* these call uiIDContextPropertySet */
00257             break;
00258         case UI_ID_DELETE:
00259             memset(&idptr, 0, sizeof(idptr));
00260             RNA_property_pointer_set(&template->ptr, template->prop, idptr);
00261             RNA_property_update(C, &template->ptr, template->prop);
00262 
00263             if(id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */
00264                 id->us= 0;
00265 
00266             break;
00267         case UI_ID_FAKE_USER:
00268             if(id) {
00269                 if(id->flag & LIB_FAKEUSER) id_us_plus(id);
00270                 else id_us_min(id);
00271             }
00272             else return;
00273             break;
00274         case UI_ID_LOCAL:
00275             if(id) {
00276                 if(id_make_local(id, 0)) {
00277                     /* reassign to get get proper updates/notifiers */
00278                     idptr= RNA_property_pointer_get(&template->ptr, template->prop);
00279                     RNA_property_pointer_set(&template->ptr, template->prop, idptr);
00280                     RNA_property_update(C, &template->ptr, template->prop);
00281                 }
00282             }
00283             break;
00284         case UI_ID_ALONE:
00285             if(id) {
00286                 const int do_scene_obj= (GS(id->name) == ID_OB) &&
00287                                         (template->ptr.type == &RNA_SceneObjects);
00288 
00289                 /* make copy */
00290                 if(do_scene_obj) {
00291                     Scene *scene= CTX_data_scene(C);
00292                     ED_object_single_user(scene, (struct Object *)id);
00293                     WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
00294                 }
00295                 else {
00296                     if(id) {
00297                         id_single_user(C, id, &template->ptr, template->prop);
00298                     }
00299                 }
00300             }
00301             break;
00302 #if 0
00303         case UI_ID_AUTO_NAME:
00304             break;
00305 #endif
00306     }
00307 }
00308 
00309 static const char *template_id_browse_tip(StructRNA *type)
00310 {
00311     if(type) {
00312         switch(RNA_type_to_ID_code(type)) {
00313             case ID_SCE: return N_("Browse Scene to be linked");
00314             case ID_OB: return N_("Browse Object to be linked");
00315             case ID_ME: return N_("Browse Mesh Data to be linked");
00316             case ID_CU: return N_("Browse Curve Data to be linked");
00317             case ID_MB: return N_("Browse MetaBall Data to be linked");
00318             case ID_MA: return N_("Browse Material to be linked");
00319             case ID_TE: return N_("Browse Texture to be linked");
00320             case ID_IM: return N_("Browse Image to be linked");
00321             case ID_LT: return N_("Browse Lattice Data to be linked");
00322             case ID_LA: return N_("Browse Lamp Data to be linked");
00323             case ID_CA: return N_("Browse Camera Data to be linked");
00324             case ID_WO: return N_("Browse World Settings to be linked");
00325             case ID_SCR: return N_("Choose Screen lay-out");
00326             case ID_TXT: return N_("Browse Text to be linked");
00327             case ID_SPK: return N_("Browse Speaker Data to be linked");
00328             case ID_SO: return N_("Browse Sound to be linked");
00329             case ID_AR: return N_("Browse Armature data to be linked");
00330             case ID_AC: return N_("Browse Action to be linked");
00331             case ID_NT: return N_("Browse Node Tree to be linked");
00332             case ID_BR: return N_("Browse Brush to be linked");
00333             case ID_PA: return N_("Browse Particle System to be linked");
00334             case ID_GD: return N_("Browse Grease Pencil Data to be linked");
00335         }
00336     }
00337     return N_("Browse ID data to be linked");
00338 }
00339 
00340 static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, short idcode, int flag, const char *newop, const char *openop, const char *unlinkop)
00341 {
00342     uiBut *but;
00343     uiBlock *block;
00344     PointerRNA idptr;
00345     // ListBase *lb; // UNUSED
00346     ID *id, *idfrom;
00347     int editable= RNA_property_editable(&template->ptr, template->prop);
00348 
00349     idptr= RNA_property_pointer_get(&template->ptr, template->prop);
00350     id= idptr.data;
00351     idfrom= template->ptr.id.data;
00352     // lb= template->idlb;
00353 
00354     block= uiLayoutGetBlock(layout);
00355     uiBlockBeginAlign(block);
00356 
00357     if(idptr.type)
00358         type= idptr.type;
00359 
00360     if(flag & UI_ID_PREVIEWS) {
00361 
00362         but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6,
00363                 TIP_(template_id_browse_tip(type)));
00364         if(type) {
00365             but->icon= RNA_struct_ui_icon(type);
00366             if (id) but->icon = ui_id_icon_get(C, id, 1);
00367             uiButSetFlag(but, UI_HAS_ICON|UI_ICON_PREVIEW);
00368         }
00369         if((idfrom && idfrom->lib) || !editable)
00370             uiButSetFlag(but, UI_BUT_DISABLED);
00371         
00372         uiLayoutRow(layout, 1);
00373     }
00374     else if(flag & UI_ID_BROWSE) {
00375         but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y,
00376                 TIP_(template_id_browse_tip(type)));
00377         if(type) {
00378             but->icon= RNA_struct_ui_icon(type);
00379             /* default dragging of icon for id browse buttons */
00380             uiButSetDragID(but, id);
00381             uiButSetFlag(but, UI_HAS_ICON|UI_ICON_LEFT);
00382         }
00383 
00384         if((idfrom && idfrom->lib) || !editable)
00385             uiButSetFlag(but, UI_BUT_DISABLED);
00386     }
00387 
00388     /* text button with name */
00389     if(id) {
00390         char name[UI_MAX_NAME_STR];
00391         const short user_alert= (id->us <= 0);
00392 
00393         //text_idbutton(id, name);
00394         name[0]= '\0';
00395         but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
00396         uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
00397         if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
00398 
00399         if(id->lib) {
00400             if(id->flag & LIB_INDIRECT) {
00401                 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0,
00402                     TIP_("Indirect library datablock, cannot change"));
00403                 uiButSetFlag(but, UI_BUT_DISABLED);
00404             }
00405             else {
00406                 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0,
00407                     TIP_("Direct linked library datablock, click to make local"));
00408                 if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib))
00409                     uiButSetFlag(but, UI_BUT_DISABLED);
00410             }
00411 
00412             uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
00413         }
00414 
00415         if(id->us > 1) {
00416             char numstr[32];
00417 
00418             BLI_snprintf(numstr, sizeof(numstr), "%d", id->us);
00419 
00420             but= uiDefBut(block, BUT, 0, numstr, 0,0,UI_UNIT_X + ((id->us < 10) ? 0:10), UI_UNIT_Y, NULL, 0, 0, 0, 0,
00421                           TIP_("Display number of users of this data (click to make a single-user copy)"));
00422 
00423             uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
00424             if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib) || !editable)
00425                 uiButSetFlag(but, UI_BUT_DISABLED);
00426         }
00427     
00428         if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
00429         
00430         if(id->lib == NULL && !(ELEM5(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
00431             uiDefButR(block, TOG, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
00432         }
00433     }
00434     
00435     if(flag & UI_ID_ADD_NEW) {
00436         int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
00437         
00438         if(newop) {
00439             but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, (id)? "": IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL);
00440             uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
00441         }
00442         else {
00443             but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
00444             uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
00445         }
00446 
00447         if((idfrom && idfrom->lib) || !editable)
00448             uiButSetFlag(but, UI_BUT_DISABLED);
00449     }
00450 
00451     if(flag & UI_ID_OPEN) {
00452         int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
00453         
00454         if(openop) {
00455             but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id)? "": IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL);
00456             uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
00457         }
00458         else {
00459             but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
00460             uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
00461         }
00462 
00463         if((idfrom && idfrom->lib) || !editable)
00464             uiButSetFlag(but, UI_BUT_DISABLED);
00465     }
00466     
00467     /* delete button */
00468     if(id && (flag & UI_ID_DELETE) && (RNA_property_flag(template->prop) & PROP_NEVER_UNLINK)==0) {
00469         if(unlinkop) {
00470             but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
00471             /* so we can access the template from operators, font unlinking needs this */
00472             uiButSetNFunc(but, NULL, MEM_dupallocN(template), NULL);
00473         }
00474         else {
00475             but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
00476                     TIP_("Unlink datablock. Shift + Click to set users to zero, data will then not be saved"));
00477             uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
00478 
00479             if(RNA_property_flag(template->prop) & PROP_NEVER_NULL)
00480                 uiButSetFlag(but, UI_BUT_DISABLED);
00481         }
00482 
00483         if((idfrom && idfrom->lib) || !editable)
00484             uiButSetFlag(but, UI_BUT_DISABLED);
00485     }
00486 
00487     if(idcode == ID_TE)
00488         uiTemplateTextureShow(layout, C, &template->ptr, template->prop);
00489     
00490     uiBlockEndAlign(block);
00491 }
00492 
00493 static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int flag, int prv_rows, int prv_cols)
00494 {
00495     TemplateID *template;
00496     PropertyRNA *prop;
00497     StructRNA *type;
00498     short idcode;
00499 
00500     prop= RNA_struct_find_property(ptr, propname);
00501 
00502     if(!prop || RNA_property_type(prop) != PROP_POINTER) {
00503         RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
00504         return;
00505     }
00506 
00507     template= MEM_callocN(sizeof(TemplateID), "TemplateID");
00508     template->ptr= *ptr;
00509     template->prop= prop;
00510     template->prv_rows = prv_rows;
00511     template->prv_cols = prv_cols;
00512 
00513     if(newop)
00514         flag |= UI_ID_ADD_NEW;
00515     if(openop)
00516         flag |= UI_ID_OPEN;
00517 
00518     type= RNA_property_pointer_type(ptr, prop);
00519     idcode= RNA_type_to_ID_code(type);
00520     template->idlb= which_libbase(CTX_data_main(C), idcode);
00521     
00522     /* create UI elements for this template
00523      *  - template_ID makes a copy of the template data and assigns it to the relevant buttons
00524      */
00525     if(template->idlb) {
00526         uiLayoutRow(layout, 1);
00527         template_ID(C, layout, template, type, idcode, flag, newop, openop, unlinkop);
00528     }
00529 
00530     MEM_freeN(template);
00531 }
00532 
00533 void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
00534 {
00535     ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE, 0, 0);
00536 }
00537 
00538 void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
00539 {
00540     ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME, 0, 0);
00541 }
00542 
00543 void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols)
00544 {
00545     ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE|UI_ID_PREVIEWS, rows, cols);
00546 }
00547 
00548 /************************ ID Chooser Template ***************************/
00549 
00550 /* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use 
00551  *
00552  * - propname: property identifier for property that ID-pointer gets stored to
00553  * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used
00554  */
00555 void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *text)
00556 {
00557     PropertyRNA *propID, *propType;
00558     uiLayout *row;
00559     
00560     /* get properties... */
00561     propID= RNA_struct_find_property(ptr, propname);
00562     propType= RNA_struct_find_property(ptr, proptypename);
00563 
00564     if (!propID || RNA_property_type(propID) != PROP_POINTER) {
00565         RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
00566         return;
00567     }
00568     if (!propType || RNA_property_type(propType) != PROP_ENUM) { 
00569         RNA_warning("pointer-type property not found: %s.%s", RNA_struct_identifier(ptr->type), proptypename);
00570         return;
00571     }
00572     
00573     /* Start drawing UI Elements using standard defines */
00574     row= uiLayoutRow(layout, 1);
00575     
00576     /* Label - either use the provided text, or will become "ID-Block:" */
00577     if (text)
00578         uiItemL(row, text, ICON_NONE);
00579     else
00580         uiItemL(row, "ID-Block:", ICON_NONE);
00581     
00582     /* ID-Type Selector - just have a menu of icons */
00583     // FIXME: the icon-only setting doesn't work when we supply a blank name
00584     uiItemFullR(row, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
00585     
00586     /* ID-Block Selector - just use pointer widget... */
00587     uiItemFullR(row, ptr, propID, 0, 0, 0, "", ICON_NONE);
00588 }
00589 
00590 /********************* RNA Path Builder Template ********************/
00591 
00592 /* ---------- */
00593 
00594 /* This is creating/editing RNA-Paths 
00595  *
00596  * - ptr: struct which holds the path property
00597  * - propname: property identifier for property that path gets stored to
00598  * - root_ptr: struct that path gets built from
00599  */
00600 void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), const char *text)
00601 {
00602     PropertyRNA *propPath;
00603     uiLayout *row;
00604     
00605     /* check that properties are valid */
00606     propPath= RNA_struct_find_property(ptr, propname);
00607     if (!propPath || RNA_property_type(propPath) != PROP_STRING) {
00608         RNA_warning("path property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
00609         return;
00610     }
00611     
00612     /* Start drawing UI Elements using standard defines */
00613     row= uiLayoutRow(layout, 1);
00614     
00615     /* Path (existing string) Widget */
00616     uiItemR(row, ptr, propname, 0, text, ICON_RNA);
00617     
00618     // TODO: attach something to this to make allow searching of nested properties to 'build' the path
00619 }
00620 
00621 /************************ Modifier Template *************************/
00622 
00623 #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
00624 
00625 #include <string.h>
00626 
00627 #include "DNA_object_force.h"
00628 
00629 #include "BKE_depsgraph.h"
00630 #include "BKE_modifier.h"
00631 #include "BKE_particle.h"
00632 
00633 #include "ED_util.h"
00634 
00635 #include "BLI_math.h"
00636 #include "BLI_listbase.h"
00637 
00638 #include "ED_object.h"
00639 
00640 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
00641 {
00642     Scene *scene = CTX_data_scene(C);
00643     Object *ob = ob_v;
00644     ModifierData *md= md_v;
00645     int i, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 0);
00646 
00647     /* undo button operation */
00648     md->mode ^= eModifierMode_OnCage;
00649 
00650     for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) {
00651         if(md == md_v) {
00652             if(i >= cageIndex)
00653                 md->mode ^= eModifierMode_OnCage;
00654             break;
00655         }
00656     }
00657 
00658     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00659     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00660 }
00661 
00662 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
00663 {
00664     Object *ob = ob_v;
00665     ModifierData *md = md_v;
00666     ModifierData *nmd = modifier_new(md->type);
00667 
00668     modifier_copyData(md, nmd);
00669     nmd->mode &= ~eModifierMode_Virtual;
00670 
00671     BLI_addhead(&ob->modifiers, nmd);
00672     
00673     modifier_unique_name(&ob->modifiers, nmd);
00674 
00675     ob->partype = PAROBJECT;
00676 
00677     WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
00678     DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
00679 
00680     ED_undo_push(C, "Modifier convert to real");
00681 }
00682 
00683 static int modifier_can_delete(ModifierData *md)
00684 {
00685     /* fluid particle modifier can't be deleted here */
00686     if(md->type == eModifierType_ParticleSystem)
00687         if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
00688             return 0;
00689 
00690     return 1;
00691 }
00692 
00693 /* Check wheter Modifier is a simulation or not, this is used for switching to the physics/particles context tab */
00694 static int modifier_is_simulation(ModifierData *md)
00695 {
00696     /* Physic Tab */
00697     if (ELEM7(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke,
00698                         eModifierType_Softbody, eModifierType_Surface, eModifierType_DynamicPaint))
00699     {
00700         return 1;
00701     }
00702     /* Particle Tab */
00703     else if (md->type == eModifierType_ParticleSystem) {
00704         return 2;
00705     }
00706     else {
00707         return 0;
00708     }
00709 }
00710 
00711 static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
00712                                ModifierData *md, int index, int cageIndex, int lastCageIndex)
00713 {
00714     ModifierTypeInfo *mti = modifierType_getInfo(md->type);
00715     PointerRNA ptr;
00716     uiBut *but;
00717     uiBlock *block;
00718     uiLayout *box, *column, *row;
00719     uiLayout *result= NULL;
00720     int isVirtual = (md->mode & eModifierMode_Virtual);
00721     char str[128];
00722 
00723     /* create RNA pointer */
00724     RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
00725 
00726     column= uiLayoutColumn(layout, 1);
00727     uiLayoutSetContextPointer(column, "modifier", &ptr);
00728 
00729     /* rounded header ------------------------------------------------------------------- */
00730     box= uiLayoutBox(column);
00731     
00732     if (isVirtual) {
00733         row= uiLayoutRow(box, 0);
00734         uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
00735         block= uiLayoutGetBlock(row);
00736         /* VIRTUAL MODIFIER */
00737         // XXX this is not used now, since these cannot be accessed via RNA
00738         BLI_snprintf(str, sizeof(str), "%s parent deform", md->name);
00739         uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name"); 
00740         
00741         but = uiDefBut(block, BUT, 0, IFACE_("Make Real"), 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0,
00742                     TIP_("Convert virtual modifier to a real modifier"));
00743         uiButSetFunc(but, modifiers_convertToReal, ob, md);
00744     }
00745     else {
00746         /* REAL MODIFIER */
00747         row = uiLayoutRow(box, 0);
00748         block = uiLayoutGetBlock(row);
00749         
00750         uiBlockSetEmboss(block, UI_EMBOSSN);
00751         /* Open/Close .................................  */
00752         uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
00753         
00754         /* modifier-type icon */
00755         uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
00756         uiBlockSetEmboss(block, UI_EMBOSS);
00757         
00758         /* modifier name */
00759         uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
00760         
00761         /* mode enabling buttons */
00762         uiBlockBeginAlign(block);
00763         /* Softbody not allowed in this situation, enforce! */
00764         if ( ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect)) 
00765             && (md->type!=eModifierType_Surface) ) 
00766         {
00767             uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
00768             uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
00769             
00770             if (mti->flags & eModifierTypeFlag_SupportsEditmode)
00771                 uiItemR(row, &ptr, "show_in_editmode", 0, "", ICON_NONE);
00772         }
00773 
00774         if (ob->type==OB_MESH) {
00775             if (modifier_couldBeCage(scene, md) && (index <= lastCageIndex))
00776             {
00777                 /* -- convert to rna ? */
00778                 but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, UI_UNIT_X-2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0,
00779                         TIP_("Apply modifier to editing cage during Editmode"));
00780                 if (index < cageIndex)
00781                     uiButSetFlag(but, UI_BUT_DISABLED);
00782                 uiButSetFunc(but, modifiers_setOnCage, ob, md);
00783             }
00784             else {
00785                 uiBlockEndAlign(block);
00786 
00787                 /* place holder button */
00788                 uiBlockSetEmboss(block, UI_EMBOSSN);
00789                 but= uiDefIconBut(block, BUT, 0, ICON_NONE, 0, 0, UI_UNIT_X-2, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, NULL);
00790                 uiButSetFlag(but, UI_BUT_DISABLED);
00791                 uiBlockSetEmboss(block, UI_EMBOSS);
00792             }
00793         } /* tesselation point for curve-typed objects */
00794         else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
00795             /* some modifiers could work with pre-tesselated curves only */
00796             if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
00797                 /* add disabled pre-tesselated button, so users could have
00798                    message for this modifiers */
00799                 but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, UI_UNIT_X-2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0,
00800                         TIP_("This modifier could be applied on splines' points only"));
00801                 uiButSetFlag(but, UI_BUT_DISABLED);
00802             } else if (mti->type != eModifierTypeType_Constructive) {
00803                 /* constructive modifiers tesselates curve before applying */
00804                 uiItemR(row, &ptr, "use_apply_on_spline", 0, "", ICON_NONE);
00805             }
00806         }
00807 
00808         uiBlockEndAlign(block);
00809         
00810         /* Up/Down + Delete ........................... */
00811         uiBlockBeginAlign(block);
00812         uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up");
00813         uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down");
00814         uiBlockEndAlign(block);
00815         
00816         uiBlockSetEmboss(block, UI_EMBOSSN);
00817         // When Modifier is a simulation, show button to switch to context rather than the delete button. 
00818         if (modifier_can_delete(md) && !modifier_is_simulation(md))
00819             uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
00820         if (modifier_is_simulation(md) == 1)
00821             uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PHYSICS");
00822         else if (modifier_is_simulation(md) == 2)
00823             uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PARTICLES");
00824         uiBlockSetEmboss(block, UI_EMBOSS);
00825     }
00826 
00827     
00828     /* modifier settings (under the header) --------------------------------------------------- */
00829     if (!isVirtual && (md->mode & eModifierMode_Expanded)) {
00830         /* apply/convert/copy */
00831         box= uiLayoutBox(column);
00832         row= uiLayoutRow(box, 0);
00833         
00834         if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) {
00835             /* only here obdata, the rest of modifiers is ob level */
00836             uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
00837             
00838             if (md->type==eModifierType_ParticleSystem) {
00839                 ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
00840                 
00841                 if (!(ob->mode & OB_MODE_PARTICLE_EDIT) && psys->pathcache) {
00842                     if(ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB))
00843                         uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_duplicates_make_real");
00844                     else if(psys->part->ren_as == PART_DRAW_PATH)
00845                         uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_modifier_convert");
00846                 }
00847             }
00848             else {
00849                 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
00850                 uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply"), 0, "apply_as", MODIFIER_APPLY_DATA);
00851                 
00852                 if (modifier_sameTopology(md) && !modifier_nonGeometrical(md))
00853                     uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape"), 0, "apply_as", MODIFIER_APPLY_SHAPE);
00854             }
00855             
00856             uiBlockClearButLock(block);
00857             uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
00858             
00859             if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke))
00860                 uiItemO(row, IFACE_("Copy"), ICON_NONE, "OBJECT_OT_modifier_copy");
00861         }
00862         
00863         /* result is the layout block inside the box, that we return so that modifier settings can be drawn */
00864         result= uiLayoutColumn(box, 0);
00865         block= uiLayoutAbsoluteBlock(box);
00866     }
00867     
00868     /* error messages */
00869     if(md->error) {
00870         box = uiLayoutBox(column);
00871         row = uiLayoutRow(box, 0);
00872         uiItemL(row, md->error, ICON_ERROR);
00873     }
00874     
00875     return result;
00876 }
00877 
00878 uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
00879 {
00880     Scene *scene = CTX_data_scene(C);
00881     Object *ob;
00882     ModifierData *md, *vmd;
00883     int i, lastCageIndex, cageIndex;
00884 
00885     /* verify we have valid data */
00886     if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
00887         RNA_warning("Expected modifier on object");
00888         return NULL;
00889     }
00890 
00891     ob= ptr->id.data;
00892     md= ptr->data;
00893 
00894     if(!ob || !(GS(ob->id.name) == ID_OB)) {
00895         RNA_warning("Expected modifier on object");
00896         return NULL;
00897     }
00898     
00899     uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
00900     
00901     /* find modifier and draw it */
00902     cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
00903 
00904     // XXX virtual modifiers are not accesible for python
00905     vmd = modifiers_getVirtualModifierList(ob);
00906 
00907     for(i=0; vmd; i++, vmd=vmd->next) {
00908         if(md == vmd)
00909             return draw_modifier(layout, scene, ob, md, i, cageIndex, lastCageIndex);
00910         else if(vmd->mode & eModifierMode_Virtual)
00911             i--;
00912     }
00913 
00914     return NULL;
00915 }
00916 
00917 /************************ Constraint Template *************************/
00918 
00919 #include "DNA_constraint_types.h"
00920 
00921 #include "BKE_action.h"
00922 #include "BKE_constraint.h"
00923 
00924 #define REDRAWIPO                   1
00925 #define REDRAWNLA                   2
00926 #define REDRAWBUTSOBJECT            3       
00927 #define REDRAWACTION                4
00928 #define B_CONSTRAINT_TEST           5
00929 #define B_CONSTRAINT_CHANGETARGET   6
00930 #define REMAKEIPO                   8
00931 #define B_DIFF                      9
00932 
00933 static void do_constraint_panels(bContext *C, void *ob_pt, int event)
00934 {
00935     Main *bmain= CTX_data_main(C);
00936     Scene *scene= CTX_data_scene(C);
00937     Object *ob= (Object *)ob_pt;
00938     
00939     switch(event) {
00940     case B_CONSTRAINT_TEST:
00941         break;  // no handling
00942     case B_CONSTRAINT_CHANGETARGET:
00943         if (ob->pose) ob->pose->flag |= POSE_RECALC;    // checks & sorts pose channels
00944         DAG_scene_sort(bmain, scene);
00945         break;
00946     default:
00947         break;
00948     }
00949 
00950     // note: RNA updates now call this, commenting else it gets called twice.
00951     // if there are problems because of this, then rna needs changed update functions.
00952     // 
00953     // object_test_constraints(ob);
00954     // if(ob->pose) update_pose_constraint_flags(ob->pose);
00955     
00956     if(ob->type==OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB);
00957     else DAG_id_tag_update(&ob->id, OB_RECALC_OB);
00958 
00959     WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
00960 }
00961 
00962 static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
00963 {
00964     ED_object_constraint_set_active(ob_v, con_v);
00965 }
00966 
00967 /* draw panel showing settings for a constraint */
00968 static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
00969 {
00970     bPoseChannel *pchan= get_active_posechannel(ob);
00971     bConstraintTypeInfo *cti;
00972     uiBlock *block;
00973     uiLayout *result= NULL, *col, *box, *row;
00974     PointerRNA ptr;
00975     char typestr[32];
00976     short proxy_protected, xco=0, yco=0;
00977     // int rb_col; // UNUSED
00978 
00979     /* get constraint typeinfo */
00980     cti= constraint_get_typeinfo(con);
00981     if (cti == NULL) {
00982         /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
00983         BLI_strncpy(typestr, (con->type == CONSTRAINT_TYPE_NULL) ? "Null" : "Unknown", sizeof(typestr));
00984     }
00985     else
00986         BLI_strncpy(typestr, cti->name, sizeof(typestr));
00987         
00988     /* determine whether constraint is proxy protected or not */
00989     if (proxylocked_constraints_owner(ob, pchan))
00990         proxy_protected= (con->flag & CONSTRAINT_PROXY_LOCAL)==0;
00991     else
00992         proxy_protected= 0;
00993 
00994     /* unless button has own callback, it adds this callback to button */
00995     block= uiLayoutGetBlock(layout);
00996     uiBlockSetHandleFunc(block, do_constraint_panels, ob);
00997     uiBlockSetFunc(block, constraint_active_func, ob, con);
00998 
00999     RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
01000 
01001     col= uiLayoutColumn(layout, 1);
01002     uiLayoutSetContextPointer(col, "constraint", &ptr);
01003 
01004     box= uiLayoutBox(col);
01005     row = uiLayoutRow(box, 0);
01006     block= uiLayoutGetBlock(box);
01007 
01008     /* Draw constraint header */
01009 
01010     /* open/close */
01011     uiBlockSetEmboss(block, UI_EMBOSSN);
01012     uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
01013     uiBlockSetEmboss(block, UI_EMBOSS);
01014     
01015     /* name */
01016     uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
01017 
01018     if (con->flag & CONSTRAINT_DISABLE)
01019         uiLayoutSetRedAlert(row, 1);
01020     
01021     if(proxy_protected == 0) {
01022         uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
01023     }
01024     else
01025         uiItemL(row, con->name, ICON_NONE);
01026     
01027     uiLayoutSetRedAlert(row, 0);
01028     
01029     /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
01030     if (proxy_protected) {
01031         uiBlockSetEmboss(block, UI_EMBOSSN);
01032         
01033         /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */
01034         uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco+244, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected"));
01035         uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco+262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Proxy Protected"));
01036         
01037         uiBlockSetEmboss(block, UI_EMBOSS);
01038     }
01039     else {
01040         short prev_proxylock, show_upbut, show_downbut;
01041         
01042         /* Up/Down buttons: 
01043          *  Proxy-constraints are not allowed to occur after local (non-proxy) constraints
01044          *  as that poses problems when restoring them, so disable the "up" button where
01045          *  it may cause this situation. 
01046          *
01047          *  Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose. 
01048          */
01049         if (proxylocked_constraints_owner(ob, pchan)) {
01050             if (con->prev) {
01051                 prev_proxylock= (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
01052             }
01053             else
01054                 prev_proxylock= 0;
01055         }
01056         else
01057             prev_proxylock= 0;
01058             
01059         show_upbut= ((prev_proxylock == 0) && (con->prev));
01060         show_downbut= (con->next) ? 1 : 0;
01061         
01062         /* enabled */
01063         uiBlockSetEmboss(block, UI_EMBOSSN);
01064         uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF);
01065         uiBlockSetEmboss(block, UI_EMBOSS);
01066         
01067         uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
01068         
01069         /* up/down */
01070         if (show_upbut || show_downbut) {
01071             uiBlockBeginAlign(block);
01072             if (show_upbut)
01073                 uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up");
01074                 
01075             if (show_downbut)
01076                 uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down");
01077             uiBlockEndAlign(block);
01078         }
01079         
01080         /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
01081         uiBlockSetEmboss(block, UI_EMBOSSN);
01082         uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete");
01083         uiBlockSetEmboss(block, UI_EMBOSS);
01084     }
01085 
01086     /* Set but-locks for protected settings (magic numbers are used here!) */
01087     if (proxy_protected)
01088         uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint");
01089 
01090     /* Draw constraint data */
01091     if ((con->flag & CONSTRAINT_EXPAND) == 0) {
01092         (yco) -= 21;
01093     }
01094     else {
01095         box= uiLayoutBox(col);
01096         block= uiLayoutAbsoluteBlock(box);
01097         result= box;
01098     }
01099 
01100     /* clear any locks set up for proxies/lib-linking */
01101     uiBlockClearButLock(block);
01102 
01103     return result;
01104 }
01105 
01106 uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
01107 {
01108     Object *ob;
01109     bConstraint *con;
01110 
01111     /* verify we have valid data */
01112     if(!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
01113         RNA_warning("Expected constraint on object");
01114         return NULL;
01115     }
01116 
01117     ob= ptr->id.data;
01118     con= ptr->data;
01119 
01120     if(!ob || !(GS(ob->id.name) == ID_OB)) {
01121         RNA_warning("Expected constraint on object");
01122         return NULL;
01123     }
01124     
01125     uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
01126 
01127     /* hrms, the temporal constraint should not draw! */
01128     if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
01129         bKinematicConstraint *data= con->data;
01130         if(data->flag & CONSTRAINT_IK_TEMP)
01131             return NULL;
01132     }
01133 
01134     return draw_constraint(layout, ob, con);
01135 }
01136 
01137 
01138 /************************* Preview Template ***************************/
01139 
01140 #include "DNA_lamp_types.h"
01141 #include "DNA_material_types.h"
01142 #include "DNA_world_types.h"
01143 
01144 #define B_MATPRV 1
01145 
01146 static void do_preview_buttons(bContext *C, void *arg, int event)
01147 {
01148     switch(event) {
01149         case B_MATPRV:
01150             WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, arg);
01151             break;
01152     }
01153 }
01154 
01155 void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, MTex *slot)
01156 {
01157     uiLayout *row, *col;
01158     uiBlock *block;
01159     Material *ma= NULL;
01160     Tex *tex = (Tex*)id;
01161     ID *pid, *pparent;
01162     short *pr_texture= NULL;
01163     PointerRNA material_ptr;
01164     PointerRNA texture_ptr;
01165 
01166     if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
01167         RNA_warning("Expected ID of type material, texture, lamp or world");
01168         return;
01169     }
01170 
01171     /* decide what to render */
01172     pid= id;
01173     pparent= NULL;
01174 
01175     if(id && (GS(id->name) == ID_TE)) {
01176         if(parent && (GS(parent->name) == ID_MA))
01177             pr_texture= &((Material*)parent)->pr_texture;
01178         else if(parent && (GS(parent->name) == ID_WO))
01179             pr_texture= &((World*)parent)->pr_texture;
01180         else if(parent && (GS(parent->name) == ID_LA))
01181             pr_texture= &((Lamp*)parent)->pr_texture;
01182 
01183         if(pr_texture) {
01184             if(*pr_texture == TEX_PR_OTHER)
01185                 pid= parent;
01186             else if(*pr_texture == TEX_PR_BOTH)
01187                 pparent= parent;
01188         }
01189     }
01190 
01191     /* layout */
01192     block= uiLayoutGetBlock(layout);
01193     row= uiLayoutRow(layout, 0);
01194     col= uiLayoutColumn(row, 0);
01195     uiLayoutSetKeepAspect(col, 1);
01196     
01197     /* add preview */
01198     uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, pid, 0.0, 0.0, 0, 0, "");
01199     uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot);
01200     uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
01201     
01202     /* add buttons */
01203     if (pid && show_buttons) {
01204         if(GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
01205             if(GS(pid->name) == ID_MA) ma= (Material*)pid;
01206             else ma= (Material*)pparent;
01207             
01208             /* Create RNA Pointer */
01209             RNA_pointer_create(id, &RNA_Material, ma, &material_ptr);
01210 
01211             col = uiLayoutColumn(row, 1);
01212             uiLayoutSetScaleX(col, 1.5);
01213             uiItemR(col, &material_ptr, "preview_render_type", UI_ITEM_R_EXPAND, "", ICON_NONE);
01214         }
01215 
01216         if(pr_texture) {
01217             /* Create RNA Pointer */
01218             RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr);
01219             
01220             uiLayoutRow(layout, 1);
01221             uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"),  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
01222             if(GS(parent->name) == ID_MA)
01223                 uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"),  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
01224             else if(GS(parent->name) == ID_LA)
01225                 uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"),  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
01226             else if(GS(parent->name) == ID_WO)
01227                 uiDefButS(block, ROW, B_MATPRV, IFACE_("World"),  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
01228             uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"),  0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
01229             
01230             /* Alpha button for texture preview */
01231             if(*pr_texture!=TEX_PR_OTHER) {
01232                 row = uiLayoutRow(layout, 0);
01233                 uiItemR(row, &texture_ptr, "use_preview_alpha", 0, NULL, ICON_NONE);
01234             }
01235         }
01236     }
01237 }
01238 
01239 /********************** ColorRamp Template **************************/
01240 
01241 
01242 typedef struct RNAUpdateCb {
01243     PointerRNA ptr;
01244     PropertyRNA *prop;
01245 } RNAUpdateCb;
01246 
01247 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
01248 {
01249     RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
01250 
01251     /* we call update here on the pointer property, this way the
01252        owner of the curve mapping can still define it's own update
01253        and notifier, even if the CurveMapping struct is shared. */
01254     RNA_property_update(C, &cb->ptr, cb->prop);
01255 }
01256 
01257 #define B_BANDCOL 1
01258 
01259 static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
01260 {
01261     ColorBand *coba= coba_v;
01262     float pos= 0.5f;
01263 
01264     if(coba->tot > 1) {
01265         if(coba->cur > 0)   pos= (coba->data[coba->cur-1].pos + coba->data[coba->cur].pos) * 0.5f;
01266         else                pos= (coba->data[coba->cur+1].pos + coba->data[coba->cur].pos) * 0.5f;
01267     }
01268 
01269     if(colorband_element_add(coba, pos)) {
01270         rna_update_cb(C, cb_v, NULL);
01271         ED_undo_push(C, "Add colorband");   
01272     }
01273 }
01274 
01275 static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v)
01276 {
01277     ColorBand *coba= coba_v;
01278 
01279     if(colorband_element_remove(coba, coba->cur)) {
01280         ED_undo_push(C, "Delete colorband");
01281         rna_update_cb(C, cb_v, NULL);
01282     }
01283 }
01284 
01285 static void colorband_flip_cb(bContext *C, void *cb_v, void *coba_v)
01286 {
01287     CBData data_tmp[MAXCOLORBAND];
01288 
01289     ColorBand *coba= coba_v;
01290     int a;
01291 
01292     for(a=0; a<coba->tot; a++) {
01293         data_tmp[a]= coba->data[coba->tot - (a + 1)];
01294     }
01295     for(a=0; a<coba->tot; a++) {
01296         data_tmp[a].pos = 1.0f - data_tmp[a].pos;
01297         coba->data[a]= data_tmp[a];
01298     }
01299 
01300     /* may as well flip the cur*/
01301     coba->cur= coba->tot - (coba->cur + 1);
01302 
01303     ED_undo_push(C, "Flip colorband");
01304 
01305     rna_update_cb(C, cb_v, NULL);
01306 }
01307 
01308 
01309 /* offset aligns from bottom, standard width 300, height 115 */
01310 static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb)
01311 {
01312     uiBut *bt;
01313     uiLayout *row;
01314     const int line1_y= yoffs + 65 + UI_UNIT_Y + 2; /* 2 for some space between the buttons */
01315     const int line2_y= yoffs + 65;
01316 
01317     if(coba==NULL) return;
01318 
01319     bt= uiDefBut(block, BUT, 0, IFACE_("Add"), 0+xoffs,line1_y,40,UI_UNIT_Y, NULL, 0, 0, 0, 0,
01320             TIP_("Add a new color stop to the colorband"));
01321     uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
01322 
01323     bt= uiDefBut(block, BUT, 0, IFACE_("Delete"), 45+xoffs,line1_y,45,UI_UNIT_Y, NULL, 0, 0, 0, 0,
01324             TIP_("Delete the active position"));
01325     uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
01326 
01327 
01328     /* XXX, todo for later - convert to operator - campbell */
01329     bt= uiDefBut(block, BUT, 0, "F",        95+xoffs,line1_y,20,UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip colorband"));
01330     uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
01331 
01332     uiDefButS(block, NUM, 0,        "",             120+xoffs,line1_y,80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot-1)), 0, 0, TIP_("Choose active color stop"));
01333 
01334     bt= uiDefButS(block, MENU, 0,       IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"),
01335             210+xoffs, line1_y, 90, UI_UNIT_Y,      &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops"));
01336     uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
01337     uiBlockEndAlign(block);
01338 
01339     bt= uiDefBut(block, BUT_COLORBAND, 0, "",   xoffs,line2_y,300,UI_UNIT_Y, coba, 0, 0, 0, 0, "");
01340     uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
01341 
01342 
01343 
01344     if(coba->tot) {
01345         CBData *cbd= coba->data + coba->cur;
01346 
01347         /* better to use rna so we can animate them */
01348         PointerRNA ptr;
01349         RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
01350         row= uiLayoutRow(layout, 0);
01351         uiItemR(row, &ptr, "position", 0, "Pos", ICON_NONE);
01352         uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
01353     }
01354 
01355 }
01356 
01357 static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
01358 {
01359     uiBut *bt;
01360     float unit= (butr->xmax-butr->xmin)/14.0f;
01361     float xs= butr->xmin;
01362 
01363     uiBlockBeginAlign(block);
01364     bt= uiDefBut(block, BUT, 0, IFACE_("Add"), xs,butr->ymin+UI_UNIT_Y,2.0f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0,
01365             TIP_("Add a new color stop to the colorband"));
01366     uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
01367     bt= uiDefBut(block, BUT, 0, IFACE_("Delete"), xs+2.0f*unit,butr->ymin+UI_UNIT_Y,1.5f*unit,UI_UNIT_Y,    NULL, 0, 0, 0, 0,
01368                  TIP_("Delete the active position"));
01369     uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
01370     bt= uiDefBut(block, BUT, 0, "F",        xs+3.5f*unit,butr->ymin+UI_UNIT_Y,0.5f*unit,UI_UNIT_Y,  NULL, 0, 0, 0, 0, TIP_("Flip the color ramp"));
01371     uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
01372     uiBlockEndAlign(block);
01373 
01374     if(coba->tot) {
01375         CBData *cbd= coba->data + coba->cur;
01376         PointerRNA ptr;
01377         RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
01378         uiItemR(layout, &ptr, "color", 0, "", ICON_NONE);
01379     }
01380 
01381     bt= uiDefButS(block, MENU, 0, TIP_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"),
01382             xs+10.0f*unit, butr->ymin+UI_UNIT_Y, unit*4, UI_UNIT_Y,     &coba->ipotype, 0.0, 0.0, 0, 0,
01383             TIP_("Set interpolation between color stops"));
01384     uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
01385 
01386     bt= uiDefBut(block, BUT_COLORBAND, 0, "",       xs,butr->ymin,butr->xmax-butr->xmin,UI_UNIT_Y, coba, 0, 0, 0, 0, "");
01387     uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
01388 
01389     uiBlockEndAlign(block);
01390 }
01391 
01392 static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb)
01393 {
01394     if(small)
01395         colorband_buttons_small(layout, block, coba, butr, cb);
01396     else
01397         colorband_buttons_large(layout, block, coba, 0, 0, cb);
01398 }
01399 
01400 void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname, int expand)
01401 {
01402     PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
01403     PointerRNA cptr;
01404     RNAUpdateCb *cb;
01405     uiBlock *block;
01406     rctf rect;
01407 
01408     if(!prop || RNA_property_type(prop) != PROP_POINTER)
01409         return;
01410 
01411     cptr= RNA_property_pointer_get(ptr, prop);
01412     if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp))
01413         return;
01414 
01415     cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
01416     cb->ptr= *ptr;
01417     cb->prop= prop;
01418 
01419     rect.xmin= 0; rect.xmax= 200;
01420     rect.ymin= 0; rect.ymax= 190;
01421 
01422     block= uiLayoutAbsoluteBlock(layout);
01423     colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
01424 
01425     MEM_freeN(cb);
01426 }
01427 
01428 /********************* Histogram Template ************************/
01429 
01430 void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname)
01431 {
01432     PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
01433     PointerRNA cptr;
01434     RNAUpdateCb *cb;
01435     uiBlock *block;
01436     uiBut *bt;
01437     Histogram *hist;
01438     rctf rect;
01439     
01440     if(!prop || RNA_property_type(prop) != PROP_POINTER)
01441         return;
01442     
01443     cptr= RNA_property_pointer_get(ptr, prop);
01444     if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram))
01445         return;
01446     
01447     cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
01448     cb->ptr= *ptr;
01449     cb->prop= prop;
01450     
01451     rect.xmin= 0; rect.xmax= 200;
01452     rect.ymin= 0; rect.ymax= 190;
01453     
01454     block= uiLayoutAbsoluteBlock(layout);
01455     //colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
01456 
01457     hist = (Histogram *)cptr.data;
01458 
01459     hist->height= (hist->height<=UI_UNIT_Y)?UI_UNIT_Y:hist->height;
01460 
01461     bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, hist->height, hist, 0, 0, 0, 0, "");
01462     uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
01463 
01464     MEM_freeN(cb);
01465 }
01466 
01467 /********************* Waveform Template ************************/
01468 
01469 void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname)
01470 {
01471     PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
01472     PointerRNA cptr;
01473     RNAUpdateCb *cb;
01474     uiBlock *block;
01475     uiBut *bt;
01476     Scopes *scopes;
01477     rctf rect;
01478     
01479     if(!prop || RNA_property_type(prop) != PROP_POINTER)
01480         return;
01481     
01482     cptr= RNA_property_pointer_get(ptr, prop);
01483     if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
01484         return;
01485     scopes = (Scopes *)cptr.data;
01486     
01487     cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
01488     cb->ptr= *ptr;
01489     cb->prop= prop;
01490     
01491     rect.xmin= 0; rect.xmax= 200;
01492     rect.ymin= 0; rect.ymax= 190;
01493     
01494     block= uiLayoutAbsoluteBlock(layout);
01495     
01496     scopes->wavefrm_height= (scopes->wavefrm_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->wavefrm_height;
01497 
01498     bt= uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
01499     (void)bt; // UNUSED
01500     
01501     MEM_freeN(cb);
01502 }
01503 
01504 /********************* Vectorscope Template ************************/
01505 
01506 void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propname)
01507 {
01508     PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
01509     PointerRNA cptr;
01510     RNAUpdateCb *cb;
01511     uiBlock *block;
01512     uiBut *bt;
01513     Scopes *scopes;
01514     rctf rect;
01515     
01516     if(!prop || RNA_property_type(prop) != PROP_POINTER)
01517         return;
01518     
01519     cptr= RNA_property_pointer_get(ptr, prop);
01520     if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
01521         return;
01522     scopes = (Scopes *)cptr.data;
01523 
01524     cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
01525     cb->ptr= *ptr;
01526     cb->prop= prop;
01527     
01528     rect.xmin= 0; rect.xmax= 200;
01529     rect.ymin= 0; rect.ymax= 190;
01530     
01531     block= uiLayoutAbsoluteBlock(layout);
01532 
01533     scopes->vecscope_height= (scopes->vecscope_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->vecscope_height;
01534     
01535     bt= uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
01536     uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
01537     
01538     MEM_freeN(cb);
01539 }
01540 
01541 /********************* CurveMapping Template ************************/
01542 
01543 
01544 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *UNUSED(arg))
01545 {
01546     CurveMapping *cumap = cumap_v;
01547     float d;
01548 
01549     /* we allow 20 times zoom */
01550     if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
01551         d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
01552         cumap->curr.xmin+= d;
01553         cumap->curr.xmax-= d;
01554         d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
01555         cumap->curr.ymin+= d;
01556         cumap->curr.ymax-= d;
01557     }
01558 
01559     ED_region_tag_redraw(CTX_wm_region(C));
01560 }
01561 
01562 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(unused))
01563 {
01564     CurveMapping *cumap = cumap_v;
01565     float d, d1;
01566 
01567     /* we allow 20 times zoom, but dont view outside clip */
01568     if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
01569         d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
01570 
01571         if(cumap->flag & CUMA_DO_CLIP) 
01572             if(cumap->curr.xmin-d < cumap->clipr.xmin)
01573                 d1= cumap->curr.xmin - cumap->clipr.xmin;
01574         cumap->curr.xmin-= d1;
01575 
01576         d1= d;
01577         if(cumap->flag & CUMA_DO_CLIP) 
01578             if(cumap->curr.xmax+d > cumap->clipr.xmax)
01579                 d1= -cumap->curr.xmax + cumap->clipr.xmax;
01580         cumap->curr.xmax+= d1;
01581 
01582         d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
01583 
01584         if(cumap->flag & CUMA_DO_CLIP) 
01585             if(cumap->curr.ymin-d < cumap->clipr.ymin)
01586                 d1= cumap->curr.ymin - cumap->clipr.ymin;
01587         cumap->curr.ymin-= d1;
01588 
01589         d1= d;
01590         if(cumap->flag & CUMA_DO_CLIP) 
01591             if(cumap->curr.ymax+d > cumap->clipr.ymax)
01592                 d1= -cumap->curr.ymax + cumap->clipr.ymax;
01593         cumap->curr.ymax+= d1;
01594     }
01595 
01596     ED_region_tag_redraw(CTX_wm_region(C));
01597 }
01598 
01599 static void curvemap_buttons_setclip(bContext *UNUSED(C), void *cumap_v, void *UNUSED(arg))
01600 {
01601     CurveMapping *cumap = cumap_v;
01602 
01603     curvemapping_changed(cumap, 0);
01604 }   
01605 
01606 static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
01607 {
01608     CurveMapping *cumap = cumap_v;
01609 
01610     curvemap_remove(cumap->cm+cumap->cur, SELECT);
01611     curvemapping_changed(cumap, 0);
01612 
01613     rna_update_cb(C, cb_v, NULL);
01614 }
01615 
01616 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
01617 static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v)
01618 {
01619     CurveMapping *cumap = cumap_v;
01620     uiBlock *block;
01621     uiBut *bt;
01622     float width= 8*UI_UNIT_X;
01623 
01624     block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
01625 
01626     /* use this for a fake extra empy space around the buttons */
01627     uiDefBut(block, LABEL, 0, "",           -4, 16, width+8, 6*UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
01628 
01629     bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",    
01630             0,5*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->flag, 0.0, 0.0, 10, 0, "");
01631     uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
01632 
01633     uiBlockBeginAlign(block);
01634     uiDefButF(block, NUM, 0, IFACE_("Min X "),   0,4*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, "");
01635     uiDefButF(block, NUM, 0, IFACE_("Min Y "),   0,3*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, "");
01636     uiDefButF(block, NUM, 0, IFACE_("Max X "),   0,2*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, "");
01637     uiDefButF(block, NUM, 0, IFACE_("Max Y "),   0,UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, "");
01638 
01639     uiBlockSetDirection(block, UI_RIGHT);
01640 
01641     uiEndBlock(C, block);
01642     return block;
01643 }
01644 
01645 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
01646 {
01647     CurveMapping *cumap = cumap_v;
01648     CurveMap *cuma= cumap->cm+cumap->cur;
01649 
01650     switch(event) {
01651         case 0: /* reset */
01652             curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
01653             curvemapping_changed(cumap, 0);
01654             break;
01655         case 1:
01656             cumap->curr= cumap->clipr;
01657             break;
01658         case 2: /* set vector */
01659             curvemap_sethandle(cuma, 1);
01660             curvemapping_changed(cumap, 0);
01661             break;
01662         case 3: /* set auto */
01663             curvemap_sethandle(cuma, 0);
01664             curvemapping_changed(cumap, 0);
01665             break;
01666         case 4: /* extend horiz */
01667             cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
01668             curvemapping_changed(cumap, 0);
01669             break;
01670         case 5: /* extend extrapolate */
01671             cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
01672             curvemapping_changed(cumap, 0);
01673             break;
01674     }
01675     ED_region_tag_redraw(CTX_wm_region(C));
01676 }
01677 
01678 static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
01679 {
01680     uiBlock *block;
01681     short yco= 0, menuwidth=10*UI_UNIT_X;
01682 
01683     block= uiBeginBlock(C, ar, __func__, UI_EMBOSS);
01684     uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
01685 
01686     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"),         0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, "");
01687     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"),      0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, "");
01688     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"),            0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, "");
01689     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Horizontal"),  0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 4, "");
01690     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Extend Extrapolated"),    0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 5, "");
01691     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"),            0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
01692 
01693     uiBlockSetDirection(block, UI_RIGHT);
01694     uiTextBoundsBlock(block, 50);
01695 
01696     uiEndBlock(C, block);
01697     return block;
01698 }
01699 
01700 static uiBlock *curvemap_brush_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
01701 {
01702     uiBlock *block;
01703     short yco= 0, menuwidth=10*UI_UNIT_X;
01704 
01705     block= uiBeginBlock(C, ar, __func__, UI_EMBOSS);
01706     uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
01707 
01708     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset View"),     0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, "");
01709     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Vector Handle"),  0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, "");
01710     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Auto Handle"),        0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, "");
01711     uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, IFACE_("Reset Curve"),        0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
01712 
01713     uiBlockSetDirection(block, UI_RIGHT);
01714     uiTextBoundsBlock(block, 50);
01715 
01716     uiEndBlock(C, block);
01717     return block;
01718 }
01719 
01720 static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
01721 {
01722     ED_region_tag_redraw(CTX_wm_region(C));
01723 }
01724 
01725 static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
01726 {
01727     CurveMapping *cumap = cumap_v;
01728     int a;
01729     
01730     cumap->preset = CURVE_PRESET_LINE;
01731     for(a=0; a<CM_TOT; a++)
01732         curvemap_reset(cumap->cm+a, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
01733     
01734     cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
01735     cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
01736     curvemapping_set_black_white(cumap, NULL, NULL);
01737     
01738     curvemapping_changed(cumap, 0);
01739 
01740     rna_update_cb(C, cb_v, NULL);
01741 }
01742 
01743 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
01744 static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb)
01745 {
01746     CurveMapping *cumap= ptr->data;
01747     uiLayout *row, *sub, *split;
01748     uiBlock *block;
01749     uiBut *bt;
01750     float dx= UI_UNIT_X;
01751     int icon, size;
01752     int bg=-1;
01753 
01754     block= uiLayoutGetBlock(layout);
01755 
01756     /* curve chooser */
01757     row= uiLayoutRow(layout, 0);
01758 
01759     if(labeltype=='v') {
01760         /* vector */
01761         sub= uiLayoutRow(row, 1);
01762         uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
01763 
01764         if(cumap->cm[0].curve) {
01765             bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
01766             uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
01767         }
01768         if(cumap->cm[1].curve) {
01769             bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
01770             uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
01771         }
01772         if(cumap->cm[2].curve) {
01773             bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
01774             uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
01775         }
01776     }
01777     else if(labeltype=='c') {
01778         /* color */
01779         sub= uiLayoutRow(row, 1);
01780         uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
01781 
01782         if(cumap->cm[3].curve) {
01783             bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, dx, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
01784             uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
01785         }
01786         if(cumap->cm[0].curve) {
01787             bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
01788             uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
01789         }
01790         if(cumap->cm[1].curve) {
01791             bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
01792             uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
01793         }
01794         if(cumap->cm[2].curve) {
01795             bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
01796             uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
01797         }
01798     }
01799     else if (labeltype == 'h') {
01800         /* HSV */
01801         sub= uiLayoutRow(row, 1);
01802         uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
01803         
01804         if(cumap->cm[0].curve) {
01805             bt= uiDefButI(block, ROW, 0, "H", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
01806             uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
01807         }
01808         if(cumap->cm[1].curve) {
01809             bt= uiDefButI(block, ROW, 0, "S", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
01810             uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
01811         }
01812         if(cumap->cm[2].curve) {
01813             bt= uiDefButI(block, ROW, 0, "V", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
01814             uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
01815         }
01816     }
01817     else
01818         uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
01819     
01820     if (labeltype=='h')
01821         bg = UI_GRAD_H;
01822 
01823     /* operation buttons */
01824     sub= uiLayoutRow(row, 1);
01825 
01826     uiBlockSetEmboss(block, UI_EMBOSSN);
01827 
01828     bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom in"));
01829     uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
01830 
01831     bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom out"));
01832     uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
01833 
01834     if(brush)
01835         bt= uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, TIP_("Tools"));
01836     else
01837         bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, TIP_("Tools"));
01838 
01839     uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
01840 
01841     if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
01842     bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, TIP_("Clipping Options"));
01843     uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
01844 
01845     bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete points"));
01846     uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
01847 
01848     uiBlockSetEmboss(block, UI_EMBOSS);
01849 
01850     uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
01851 
01852     /* curve itself */
01853     size= uiLayoutGetWidth(layout);
01854     row= uiLayoutRow(layout, 0);
01855     uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, bg, 0, "");
01856 
01857     /* black/white levels */
01858     if(levels) {
01859         split= uiLayoutSplit(layout, 0, 0);
01860         uiItemR(uiLayoutColumn(split, 0), ptr, "black_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
01861         uiItemR(uiLayoutColumn(split, 0), ptr, "white_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
01862 
01863         uiLayoutRow(layout, 0);
01864         bt=uiDefBut(block, BUT, 0, IFACE_("Reset"), 0, 0, UI_UNIT_X*10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
01865                 TIP_("Reset Black/White point and curves"));
01866         uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
01867     }
01868 
01869     uiBlockSetNFunc(block, NULL, NULL, NULL);
01870 }
01871 
01872 void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, int levels, int brush)
01873 {
01874     RNAUpdateCb *cb;
01875     PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
01876     PointerRNA cptr;
01877 
01878     if(!prop) {
01879         RNA_warning("curve property not found: %s.%s",
01880                     RNA_struct_identifier(ptr->type), propname);
01881         return;
01882     }
01883 
01884     if(RNA_property_type(prop) != PROP_POINTER) {
01885         RNA_warning("curve is not a pointer: %s.%s",
01886                     RNA_struct_identifier(ptr->type), propname);
01887         return;
01888     }
01889 
01890     cptr= RNA_property_pointer_get(ptr, prop);
01891     if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping))
01892         return;
01893 
01894     cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
01895     cb->ptr= *ptr;
01896     cb->prop= prop;
01897 
01898     curvemap_buttons_layout(layout, &cptr, type, levels, brush, cb);
01899 
01900     MEM_freeN(cb);
01901 }
01902 
01903 /********************* ColorWheel Template ************************/
01904 
01905 #define WHEEL_SIZE  100
01906 
01907 void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic)
01908 {
01909     PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
01910     uiBlock *block= uiLayoutGetBlock(layout);
01911     uiLayout *col, *row;
01912     uiBut *but;
01913     float softmin, softmax, step, precision;
01914     
01915     if (!prop) {
01916         RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
01917         return;
01918     }
01919 
01920     RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
01921     
01922     col = uiLayoutColumn(layout, 0);
01923     row= uiLayoutRow(col, 1);
01924     
01925     but= uiDefButR_prop(block, HSVCIRCLE, 0, "",    0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, "");
01926 
01927     if(lock) {
01928         but->flag |= UI_BUT_COLOR_LOCK;
01929     }
01930 
01931     if(lock_luminosity) {
01932         float color[4]; /* incase of alpha */
01933         but->flag |= UI_BUT_VEC_SIZE_LOCK;
01934         RNA_property_float_get_array(ptr, prop, color);
01935         but->a2= len_v3(color);
01936     }
01937 
01938     if(cubic)
01939         but->flag |= UI_BUT_COLOR_CUBIC;
01940 
01941     uiItemS(row);
01942     
01943     if (value_slider)
01944         uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
01945 }
01946 
01947 /********************* Layer Buttons Template ************************/
01948 
01949 static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
01950 {
01951     uiBut *but = arg1;
01952     int cur = GET_INT_FROM_POINTER(arg2);
01953     wmWindow *win= CTX_wm_window(C);
01954     int i, tot, shift= win->eventstate->shift;
01955 
01956     if(!shift) {
01957         tot= RNA_property_array_length(&but->rnapoin, but->rnaprop);
01958         
01959         /* Normally clicking only selects one layer */
01960         RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, TRUE);
01961         for(i = 0; i < tot; ++i) {
01962             if(i != cur)
01963                 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, FALSE);
01964         }
01965     }
01966     
01967     /* view3d layer change should update depsgraph (invisible object changed maybe) */
01968     /* see view3d_header.c */
01969 }
01970 
01971 // TODO:
01972 //  - for now, grouping of layers is determined by dividing up the length of 
01973 //    the array of layer bitflags
01974 
01975 void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname,
01976               PointerRNA *used_ptr, const char *used_propname, int active_layer)
01977 {
01978     uiLayout *uRow, *uCol;
01979     PropertyRNA *prop, *used_prop= NULL;
01980     int groups, cols, layers;
01981     int group, col, layer, row;
01982     int cols_per_group = 5;
01983 
01984     prop= RNA_struct_find_property(ptr, propname);
01985     if (!prop) {
01986         RNA_warning("layers property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
01987         return;
01988     }
01989     
01990     /* the number of layers determines the way we group them 
01991      *  - we want 2 rows only (for now)
01992      *  - the number of columns (cols) is the total number of buttons per row
01993      *    the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
01994      *  - for now, only split into groups if group will have at least 5 items
01995      */
01996     layers= RNA_property_array_length(ptr, prop);
01997     cols= (layers / 2) + (layers % 2);
01998     groups= ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
01999 
02000     if(used_ptr && used_propname) {
02001         used_prop= RNA_struct_find_property(used_ptr, used_propname);
02002         if (!used_prop) {
02003             RNA_warning("used layers property not found: %s.%s", RNA_struct_identifier(ptr->type), used_propname);
02004             return;
02005         }
02006 
02007         if(RNA_property_array_length(used_ptr, used_prop) < layers)
02008             used_prop = NULL;
02009     }
02010     
02011     /* layers are laid out going across rows, with the columns being divided into groups */
02012     
02013     for (group= 0; group < groups; group++) {
02014         uCol= uiLayoutColumn(layout, 1);
02015         
02016         for (row= 0; row < 2; row++) {
02017             uiBlock *block;
02018             uiBut *but;
02019 
02020             uRow= uiLayoutRow(uCol, 1);
02021             block= uiLayoutGetBlock(uRow);
02022             layer= groups*cols_per_group*row + cols_per_group*group;
02023             
02024             /* add layers as toggle buts */
02025             for (col= 0; (col < cols_per_group) && (layer < layers); col++, layer++) {
02026                 int icon = 0;
02027                 int butlay = 1 << layer;
02028 
02029                 if(active_layer & butlay)
02030                     icon = ICON_LAYER_ACTIVE;
02031                 else if(used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer))
02032                     icon = ICON_LAYER_USED;
02033                 
02034                 but= uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, UI_UNIT_X/2, UI_UNIT_Y/2);
02035                 uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer));
02036                 but->type= TOG;
02037             }
02038         }
02039     }
02040 }
02041 
02042 
02043 /************************* List Template **************************/
02044 
02045 static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big)
02046 {
02047     ID *id= NULL;
02048     int icon;
02049 
02050     if(!itemptr->data)
02051         return rnaicon;
02052 
02053     /* try ID, material or texture slot */
02054     if(RNA_struct_is_ID(itemptr->type)) {
02055         id= itemptr->id.data;
02056     }
02057     else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
02058         id= RNA_pointer_get(itemptr, "material").data;
02059     }
02060     else if(RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
02061         id= RNA_pointer_get(itemptr, "texture").data;
02062     }
02063     else if(RNA_struct_is_a(itemptr->type, &RNA_DynamicPaintSurface)) {
02064         DynamicPaintSurface *surface= (DynamicPaintSurface*)itemptr->data;
02065 
02066         if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) return ICON_TEXTURE_SHADED;
02067         else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) return ICON_OUTLINER_DATA_MESH;
02068         else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return ICON_FILE_IMAGE;
02069     }
02070 
02071     /* get icon from ID */
02072     if(id) {
02073         icon= ui_id_icon_get(C, id, big);
02074 
02075         if(icon)
02076             return icon;
02077     }
02078 
02079     return rnaicon;
02080 }
02081 
02082 static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id)
02083 {
02084     uiBlock *block= uiLayoutGetBlock(layout);
02085     uiBut *but;
02086     uiLayout *split, *overlap, *sub, *row;
02087     char *namebuf;
02088     const char *name;
02089     int icon;
02090 
02091     overlap= uiLayoutOverlap(layout);
02092 
02093     /* list item behind label & other buttons */
02094     sub= uiLayoutRow(overlap, 0);
02095 
02096     but= uiDefButR_prop(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, "");
02097     uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
02098 
02099     sub= uiLayoutRow(overlap, 0);
02100 
02101     /* retrieve icon and name */
02102     icon= list_item_icon_get(C, itemptr, rnaicon, 0);
02103     if(icon == ICON_NONE || icon == ICON_DOT)
02104         icon= 0;
02105 
02106     namebuf= RNA_struct_name_get_alloc(itemptr, NULL, 0, NULL);
02107     name= (namebuf)? namebuf: "";
02108 
02109     /* hardcoded types */
02110     if(itemptr->type == &RNA_MeshTextureFaceLayer || itemptr->type == &RNA_MeshColorLayer) {
02111         uiItemL(sub, name, icon);
02112         uiBlockSetEmboss(block, UI_EMBOSSN);
02113         uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
02114         uiBlockSetEmboss(block, UI_EMBOSS);
02115     }
02116     else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
02117         uiItemL(sub, name, icon);
02118         uiBlockSetEmboss(block, UI_EMBOSS);
02119         uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0,  NULL);
02120     }
02121     else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
02122         uiItemL(sub, name, icon);
02123         uiBlockSetEmboss(block, UI_EMBOSS);
02124         uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0,  NULL);
02125     }
02126     else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
02127         /* provision to draw active node name */
02128         Material *ma, *manode;
02129         Scene *scene= CTX_data_scene(C);
02130         Object *ob= (Object*)ptr->id.data;
02131         int index= (Material**)itemptr->data - ob->mat;
02132         
02133         /* default item with material base name */
02134         uiItemL(sub, name, icon);
02135         
02136         ma= give_current_material(ob, index+1);
02137         if (ma && !scene_use_new_shading_nodes(scene)){
02138             manode= give_node_material(ma);
02139             if(manode) {
02140                 char str[MAX_ID_NAME + 12];
02141                 BLI_snprintf(str, sizeof(str), "Node %s", manode->id.name+2);
02142                 uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1));
02143             }
02144             else if(ma->use_nodes) {
02145                 uiItemL(sub, "Node <none>", ICON_NONE);
02146             }
02147         }
02148     }
02149     else if(itemptr->type == &RNA_ShapeKey) {
02150         Object *ob= (Object*)activeptr->data;
02151         Key *key= (Key*)itemptr->id.data;
02152 
02153         split= uiLayoutSplit(sub, 0.75f, 0);
02154 
02155         uiItemL(split, name, icon);
02156 
02157         uiBlockSetEmboss(block, UI_EMBOSSN);
02158         row= uiLayoutRow(split, 1);
02159         if(i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE);
02160         else uiItemR(row, itemptr, "value", 0, "", ICON_NONE);
02161 
02162         if(ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH))
02163             uiLayoutSetActive(row, 0);
02164         //uiItemR(row, itemptr, "mute", 0, "", ICON_MUTE_IPO_OFF);
02165         uiBlockSetEmboss(block, UI_EMBOSS);
02166     }
02167     else if(itemptr->type == &RNA_VertexGroup) {
02168         bDeformGroup *dg= (bDeformGroup *)itemptr->data;
02169         uiItemL(sub, name, icon);
02170         /* RNA does not allow nice lock icons, use lower level buttons */
02171 #if 0
02172         uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "lock_weight", 0, 0, 0, 0, 0,  NULL);
02173 #else
02174         uiBlockSetEmboss(block, UI_EMBOSSN);
02175         uiDefIconButBitC(block, TOG, DG_LOCK_WEIGHT, 0, (dg->flag & DG_LOCK_WEIGHT) ? ICON_LOCKED : ICON_UNLOCKED, 0, 0, UI_UNIT_X, UI_UNIT_Y, &dg->flag, 0, 0, 0, 0, "Maintain relative weights while painting");
02176         uiBlockSetEmboss(block, UI_EMBOSS);
02177 #endif
02178     }
02179     else if(itemptr->type == &RNA_KeyingSetPath) {
02180         KS_Path *ksp = (KS_Path*)itemptr->data;
02181         
02182         /* icon needs to be the type of ID which is currently active */
02183         RNA_enum_icon_from_value(id_type_items, ksp->idtype, &icon);
02184         
02185         /* nothing else special to do... */
02186         uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
02187     }
02188     else if(itemptr->type == &RNA_DynamicPaintSurface) {
02189         char name_final[96];
02190         const char *enum_name;
02191         PropertyRNA *prop = RNA_struct_find_property(itemptr, "surface_type");
02192         DynamicPaintSurface *surface= (DynamicPaintSurface*)itemptr->data;
02193 
02194         RNA_property_enum_name(C, itemptr, prop, RNA_property_enum_get(itemptr, prop), &enum_name);
02195 
02196         BLI_snprintf(name_final, sizeof(name_final), "%s (%s)",name,enum_name);
02197         uiItemL(sub, name_final, icon);
02198         if (dynamicPaint_surfaceHasColorPreview(surface)) {
02199             uiBlockSetEmboss(block, UI_EMBOSSN);
02200             uiDefIconButR(block, OPTION, 0, (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON,
02201                 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "show_preview", 0, 0, 0, 0, 0, NULL);
02202             uiBlockSetEmboss(block, UI_EMBOSS);
02203         }
02204         uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "is_active", i, 0, 0, 0, 0,  NULL);
02205     }
02206     else if(itemptr->type == &RNA_MovieTrackingObject) {
02207         MovieTrackingObject *tracking_object= (MovieTrackingObject*)itemptr->data;
02208 
02209         split= uiLayoutSplit(sub, 0.75f, 0);
02210         if(tracking_object->flag&TRACKING_OBJECT_CAMERA) {
02211             uiItemL(split, name, ICON_CAMERA_DATA);
02212         }
02213         else {
02214             uiItemL(split, name, ICON_OBJECT_DATA);
02215         }
02216     }
02217 
02218     /* There is a last chance to display custom controls (in addition to the name/label):
02219      * If the given item property group features a string property named as prop_list,
02220      * this tries to add controls for all properties of the item listed in that string property.
02221      * (colon-separated names).
02222      *
02223      * This is especially useful for python. E.g., if you list a collection of this property
02224      * group:
02225      *
02226      * class TestPropertyGroup(bpy.types.PropertyGroup):
02227      *     bool    = BoolProperty(default=False)
02228      *     integer = IntProperty()
02229      *     string  = StringProperty()
02230      * 
02231      *     # A string of all identifiers (colon-separated) which property’s controls should be
02232      *     # displayed in a template_list.
02233      *     template_list_controls = StringProperty(default="integer:bool:string", options={"HIDDEN"})
02234      *
02235      * … you’ll get a numfield for the integer prop, a check box for the bool prop, and a textfield
02236      * for the string prop, after the name of each item of the collection.
02237      */
02238     else if (prop_list_id) {
02239         row = uiLayoutRow(sub, 1);
02240         uiItemL(row, name, icon);
02241 
02242         /* XXX: Check, as sometimes we get an itemptr looking like
02243          *      {id = {data = 0x0}, type = 0x0, data = 0x0}
02244          *      which would obviously produce a sigsev… */
02245         if (itemptr->type) {
02246             /* If the special property is set for the item, and it is a collection… */
02247             PropertyRNA *prop_list= RNA_struct_find_property(itemptr, prop_list_id);
02248 
02249             if(prop_list && RNA_property_type(prop_list) == PROP_STRING) {
02250                 int prop_names_len;
02251                 char *prop_names = RNA_property_string_get_alloc(itemptr, prop_list, NULL, 0, &prop_names_len);
02252                 char *prop_names_end= prop_names + prop_names_len;
02253                 char *id= prop_names;
02254                 char *id_next;
02255                 while (id < prop_names_end) {
02256                     if ((id_next= strchr(id, ':'))) *id_next++= '\0';
02257                     else id_next= prop_names_end;
02258                     uiItemR(row, itemptr, id, 0, NULL, 0);
02259                     id= id_next;
02260                 }
02261                 MEM_freeN(prop_names);
02262             }
02263         }
02264     }
02265 
02266     else
02267         uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
02268 
02269     /* free name */
02270     if(namebuf)
02271         MEM_freeN(namebuf);
02272 }
02273 
02274 void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype)
02275 {
02276     //Scene *scene= CTX_data_scene(C);
02277     PropertyRNA *prop= NULL, *activeprop;
02278     PropertyType type, activetype;
02279     StructRNA *ptype;
02280     uiLayout *box, *row, *col;
02281     uiBlock *block;
02282     uiBut *but;
02283     Panel *pa;
02284     const char *name;
02285     char numstr[32];
02286     int rnaicon=0, icon=0, i= 0, activei= 0, len= 0, items, found, min, max;
02287 
02288     /* validate arguments */
02289     block= uiLayoutGetBlock(layout);
02290     pa= block->panel;
02291 
02292     if(!pa) {
02293         RNA_warning("Only works inside a panel");
02294         return;
02295     }
02296 
02297     if(!activeptr->data)
02298         return;
02299     
02300     if(ptr->data) {
02301         prop= RNA_struct_find_property(ptr, propname);
02302         if(!prop) {
02303             RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
02304             return;
02305         }
02306     }
02307 
02308     activeprop= RNA_struct_find_property(activeptr, activepropname);
02309     if(!activeprop) {
02310         RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), activepropname);
02311         return;
02312     }
02313 
02314     if(prop) {
02315         type= RNA_property_type(prop);
02316         if(type != PROP_COLLECTION) {
02317             RNA_warning("uiExpected collection property");
02318             return;
02319         }
02320     }
02321 
02322     activetype= RNA_property_type(activeprop);
02323     if(activetype != PROP_INT) {
02324         RNA_warning("Expected integer property");
02325         return;
02326     }
02327 
02328     /* get icon */
02329     if(ptr->data && prop) {
02330         ptype= RNA_property_pointer_type(ptr, prop);
02331         rnaicon= RNA_struct_ui_icon(ptype);
02332     }
02333 
02334     /* get active data */
02335     activei= RNA_property_int_get(activeptr, activeprop);
02336 
02337     if(listtype == 'i') {
02338         box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
02339         col= uiLayoutColumn(box, 1);
02340         row= uiLayoutRow(col, 0);
02341 
02342         if(ptr->data && prop) {
02343             /* create list items */
02344             RNA_PROP_BEGIN(ptr, itemptr, prop) {
02345                 /* create button */
02346                 if(!(i % 9))
02347                     row= uiLayoutRow(col, 0);
02348 
02349                 icon= list_item_icon_get(C, &itemptr, rnaicon, 1);
02350                 but= uiDefIconButR_prop(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, "");
02351                 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
02352                 
02353 
02354                 i++;
02355             }
02356             RNA_PROP_END;
02357         }
02358     }
02359     else if(listtype == 'c') {
02360         /* compact layout */
02361 
02362         row= uiLayoutRow(layout, 1);
02363 
02364         if(ptr->data && prop) {
02365             /* create list items */
02366             RNA_PROP_BEGIN(ptr, itemptr, prop) {
02367                 found= (activei == i);
02368 
02369                 if(found) {
02370                     /* create button */
02371                     name= RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
02372                     icon= list_item_icon_get(C, &itemptr, rnaicon, 0);
02373                     uiItemL(row, (name)? name: "", icon);
02374 
02375                     if(name)
02376                         MEM_freeN((void *)name);
02377                 }
02378 
02379                 i++;
02380             }
02381             RNA_PROP_END;
02382         }
02383 
02384         /* if not found, add in dummy button */
02385         if(i == 0)
02386             uiItemL(row, "", ICON_NONE);
02387 
02388         /* next/prev button */
02389         BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
02390         but= uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activeprop, 0, 0, 0, 0, 0, "");
02391         if(i == 0)
02392             uiButSetFlag(but, UI_BUT_DISABLED);
02393     }
02394     else {
02395         /* default rows */
02396         if(rows == 0)
02397             rows= 5;
02398         if (maxrows == 0)
02399             maxrows = 5;
02400         if(pa->list_grip_size != 0)
02401             rows= pa->list_grip_size;
02402 
02403         /* layout */
02404         box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
02405         row= uiLayoutRow(box, 0);
02406         col = uiLayoutColumn(row, 1);
02407 
02408         /* init numbers */
02409         RNA_property_int_range(activeptr, activeprop, &min, &max);
02410 
02411         if(prop)
02412             len= RNA_property_collection_length(ptr, prop);
02413         items= CLAMPIS(len, rows, MAX2(rows, maxrows));
02414 
02415         /* if list length changes and active is out of view, scroll to it */
02416         if(pa->list_last_len != len)
02417             if((activei < pa->list_scroll || activei >= pa->list_scroll+items))
02418                 pa->list_scroll= activei;
02419 
02420         pa->list_scroll= MIN2(pa->list_scroll, len-items);
02421         pa->list_scroll= MAX2(pa->list_scroll, 0);
02422         pa->list_size= items;
02423         pa->list_last_len= len;
02424 
02425         if(ptr->data && prop) {
02426             /* create list items */
02427             RNA_PROP_BEGIN(ptr, itemptr, prop) {
02428                 if(i >= pa->list_scroll && i<pa->list_scroll+items)
02429                     list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activeprop, prop_list);
02430 
02431                 i++;
02432             }
02433             RNA_PROP_END;
02434         }
02435 
02436         /* add dummy buttons to fill space */
02437         while(i < pa->list_scroll+items) {
02438             if(i >= pa->list_scroll)
02439                 uiItemL(col, "", ICON_NONE);
02440             i++;
02441         }
02442 
02443         /* add scrollbar */
02444         if(len > items) {
02445             col= uiLayoutColumn(row, 0);
02446             uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
02447         }
02448     }
02449 }
02450 
02451 /************************* Operator Search Template **************************/
02452 
02453 static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
02454 {
02455     wmOperatorType *ot= arg2;
02456     
02457     if(ot)
02458         WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
02459 }
02460 
02461 static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
02462 {
02463     GHashIterator *iter= WM_operatortype_iter();
02464 
02465     for( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
02466         wmOperatorType *ot= BLI_ghashIterator_getValue(iter);
02467 
02468         if(BLI_strcasestr(ot->name, str)) {
02469             if(WM_operator_poll((bContext*)C, ot)) {
02470                 char name[256];
02471                 int len= strlen(ot->name);
02472                 
02473                 /* display name for menu, can hold hotkey */
02474                 BLI_strncpy(name, ot->name, sizeof(name));
02475                 
02476                 /* check for hotkey */
02477                 if(len < sizeof(name)-6) {
02478                     if (WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, TRUE,
02479                                                      &name[len+1], sizeof(name)-len-1))
02480                     {
02481                         name[len]= '|';
02482                     }
02483                 }
02484                 
02485                 if(0==uiSearchItemAdd(items, name, ot, 0))
02486                     break;
02487             }
02488         }
02489     }
02490     BLI_ghashIterator_free(iter);
02491 }
02492 
02493 void uiTemplateOperatorSearch(uiLayout *layout)
02494 {
02495     uiBlock *block;
02496     uiBut *but;
02497     static char search[256]= "";
02498         
02499     block= uiLayoutGetBlock(layout);
02500     uiBlockSetCurLayout(block, layout);
02501 
02502     but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, 0, 0, "");
02503     uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
02504 }
02505 
02506 /************************* Running Jobs Template **************************/
02507 
02508 #define B_STOPRENDER    1
02509 #define B_STOPCAST      2
02510 #define B_STOPANIM      3
02511 #define B_STOPCOMPO     4
02512 #define B_STOPSEQ       5
02513 #define B_STOPCLIP      6
02514 
02515 static void do_running_jobs(bContext *C, void *UNUSED(arg), int event)
02516 {
02517     switch(event) {
02518         case B_STOPRENDER:
02519             G.afbreek= 1;
02520             break;
02521         case B_STOPCAST:
02522             WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL);
02523             break;
02524         case B_STOPANIM:
02525             WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
02526             break;
02527         case B_STOPCOMPO:
02528             WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
02529             break;
02530         case B_STOPSEQ:
02531             WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
02532             break;
02533         case B_STOPCLIP:
02534             WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
02535             break;
02536     }
02537 }
02538 
02539 void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
02540 {
02541     bScreen *screen= CTX_wm_screen(C);
02542     wmWindowManager *wm= CTX_wm_manager(C);
02543     ScrArea *sa= CTX_wm_area(C);
02544     uiBlock *block;
02545     void *owner= NULL;
02546     int handle_event;
02547     
02548     block= uiLayoutGetBlock(layout);
02549     uiBlockSetCurLayout(block, layout);
02550 
02551     uiBlockSetHandleFunc(block, do_running_jobs, NULL);
02552 
02553     if(sa->spacetype==SPACE_NODE) {
02554         if(WM_jobs_test(wm, sa))
02555            owner = sa;
02556         handle_event= B_STOPCOMPO;
02557     } else if (sa->spacetype==SPACE_SEQ) {
02558         if(WM_jobs_test(wm, sa))
02559             owner = sa;
02560         handle_event = B_STOPSEQ;
02561     } else if(sa->spacetype==SPACE_CLIP) {
02562         if(WM_jobs_test(wm, sa))
02563            owner = sa;
02564         handle_event= B_STOPCLIP;
02565     } else {
02566         Scene *scene;
02567         /* another scene can be rendering too, for example via compositor */
02568         for(scene= CTX_data_main(C)->scene.first; scene; scene= scene->id.next)
02569             if(WM_jobs_test(wm, scene))
02570                 break;
02571         owner = scene;
02572         handle_event= B_STOPRENDER;
02573     }
02574 
02575     if(owner) {
02576         uiLayout *ui_abs;
02577         
02578         ui_abs= uiLayoutAbsolute(layout, 0);
02579         (void)ui_abs; // UNUSED
02580         
02581         uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE, 
02582                 0, UI_UNIT_Y*0.1, UI_UNIT_X*0.8, UI_UNIT_Y*0.8, NULL, 0.0f, 0.0f, 0, 0, TIP_("Stop this job"));
02583         uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner), 
02584                 UI_UNIT_X, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, TIP_("Progress"));
02585         
02586         uiLayoutRow(layout, 0);
02587     }
02588     if(WM_jobs_test(wm, screen))
02589         uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
02590                 TIP_("Stop screencast"));
02591     if(screen->animtimer)
02592         uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, TIP_("Anim Player"), 0,0,100,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
02593                 TIP_("Stop animation playback"));
02594 }
02595 
02596 /************************* Reports for Last Operator Template **************************/
02597 
02598 void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
02599 {
02600     ReportList *reports = CTX_wm_reports(C);
02601     Report *report= BKE_reports_last_displayable(reports);
02602     ReportTimerInfo *rti;
02603     
02604     uiLayout *ui_abs;
02605     uiBlock *block;
02606     uiBut *but;
02607     uiStyle *style= UI_GetStyle();
02608     int width;
02609     int icon=0;
02610     
02611     /* if the report display has timed out, don't show */
02612     if (!reports->reporttimer) return;
02613     
02614     rti= (ReportTimerInfo *)reports->reporttimer->customdata;
02615     
02616     if (!rti || rti->widthfac==0.0f || !report) return;
02617     
02618     ui_abs= uiLayoutAbsolute(layout, 0);
02619     block= uiLayoutGetBlock(ui_abs);
02620     
02621     width = BLF_width(style->widget.uifont_id, report->message);
02622     width = MIN2(rti->widthfac*width, width);
02623     width = MAX2(width, 10);
02624     
02625     /* make a box around the report to make it stand out */
02626     uiBlockBeginAlign(block);
02627     but= uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X+10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
02628     /* set the report's bg color in but->col - ROUNDBOX feature */
02629     but->col[0]= FTOCHAR(rti->col[0]);
02630     but->col[1]= FTOCHAR(rti->col[1]);
02631     but->col[2]= FTOCHAR(rti->col[2]);
02632     but->col[3]= 255; 
02633 
02634     but= uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
02635     but->col[0]= but->col[1]= but->col[2]= FTOCHAR(rti->greyscale);
02636     but->col[3]= 255;
02637 
02638     uiBlockEndAlign(block);
02639     
02640     
02641     /* icon and report message on top */
02642     if(report->type & RPT_ERROR_ALL)
02643         icon = ICON_ERROR;
02644     else if(report->type & RPT_WARNING_ALL)
02645         icon = ICON_ERROR;
02646     else if(report->type & RPT_INFO_ALL)
02647         icon = ICON_INFO;
02648     
02649     /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report 
02650      * to be shown instead of icon when appropriate...
02651      */
02652     uiBlockSetEmboss(block, UI_EMBOSSN);
02653 
02654     if (reports->list.first != reports->list.last)
02655         uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, TIP_("Click to see rest of reports in textblock: 'Recent Reports'"));
02656     else
02657         uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
02658 
02659     uiBlockSetEmboss(block, UI_EMBOSS);
02660     
02661     uiDefBut(block, LABEL, 0, report->message, UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
02662 }
02663 
02664 /********************************* Keymap *************************************/
02665 
02666 static void keymap_item_modified(bContext *UNUSED(C), void *kmi_p, void *UNUSED(unused))
02667 {
02668     wmKeyMapItem *kmi= (wmKeyMapItem*)kmi_p;
02669     WM_keyconfig_update_tag(NULL, kmi);
02670 }
02671 
02672 static void template_keymap_item_properties(uiLayout *layout, const char *title, PointerRNA *ptr)
02673 {
02674     uiLayout *flow;
02675 
02676     uiItemS(layout);
02677 
02678     if(title)
02679         uiItemL(layout, title, ICON_NONE);
02680     
02681     flow= uiLayoutColumnFlow(layout, 2, 0);
02682 
02683     RNA_STRUCT_BEGIN(ptr, prop) {
02684         int flag= RNA_property_flag(prop);
02685 
02686         if(flag & PROP_HIDDEN)
02687             continue;
02688 
02689         /* recurse for nested properties */
02690         if(RNA_property_type(prop) == PROP_POINTER) {
02691             PointerRNA propptr= RNA_property_pointer_get(ptr, prop);
02692             const char *name= RNA_property_ui_name(prop);
02693 
02694             if(propptr.data && RNA_struct_is_a(propptr.type, &RNA_OperatorProperties)) {
02695                 template_keymap_item_properties(layout, name, &propptr);
02696                 continue;
02697             }
02698         }
02699 
02700         /* add property */
02701         uiItemR(flow, ptr, RNA_property_identifier(prop), 0, NULL, ICON_NONE);
02702     }
02703     RNA_STRUCT_END;
02704 }
02705 
02706 void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
02707 {
02708     PointerRNA propptr= RNA_pointer_get(ptr, "properties");
02709 
02710     if(propptr.data) {
02711         uiBut *but= uiLayoutGetBlock(layout)->buttons.last;
02712 
02713         template_keymap_item_properties(layout, NULL, &propptr);
02714 
02715         /* attach callbacks to compensate for missing properties update,
02716            we don't know which keymap (item) is being modified there */
02717         for(; but; but=but->next)
02718             uiButSetFunc(but, keymap_item_modified, ptr->data, NULL);
02719     }
02720 }
02721