4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * Contributor(s): Blender Foundation 2009.
22 * ***** END GPL LICENSE BLOCK *****
25 /** \file blender/editors/interface/interface_templates.c
26 * \ingroup edinterface
34 #include "MEM_guardedalloc.h"
36 #include "DNA_anim_types.h"
37 #include "DNA_key_types.h"
38 #include "DNA_scene_types.h"
39 #include "DNA_userdef_types.h"
41 #include "BLI_string.h"
42 #include "BLI_utildefines.h"
43 #include "BLI_ghash.h"
45 #include "BKE_animsys.h"
46 #include "BKE_colortools.h"
47 #include "BKE_context.h"
48 #include "BKE_global.h"
49 #include "BKE_library.h"
51 #include "BKE_object.h"
52 #include "BKE_material.h"
53 #include "BKE_texture.h"
54 #include "BKE_report.h"
55 #include "BKE_displist.h"
57 #include "ED_screen.h"
58 #include "ED_object.h"
59 #include "ED_render.h"
61 #include "RNA_access.h"
62 #include "RNA_enum_types.h"
67 #include "UI_interface.h"
68 #include "interface_intern.h"
72 void UI_template_fix_linking(void)
76 /********************** Header Template *************************/
78 void uiTemplateHeader(uiLayout *layout, bContext *C, int menus)
82 block= uiLayoutAbsoluteBlock(layout);
83 if(menus) ED_area_header_standardbuttons(C, block, 0);
84 else ED_area_header_switchbutton(C, block, 0);
87 /********************** Search Callbacks *************************/
89 typedef struct TemplateID {
94 int prv_rows, prv_cols;
97 /* Search browse menu, assign */
98 static void id_search_call_cb(bContext *C, void *arg_template, void *item)
100 TemplateID *template= (TemplateID*)arg_template;
106 RNA_id_pointer_create(item, &idptr);
107 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
108 RNA_property_update(C, &template->ptr, template->prop);
112 /* ID Search browse menu, do the search */
113 static void id_search_cb(const bContext *C, void *arg_template, const char *str, uiSearchItems *items)
115 TemplateID *template= (TemplateID*)arg_template;
116 ListBase *lb= template->idlb;
117 ID *id, *id_from= template->ptr.id.data;
119 int flag= RNA_property_flag(template->prop);
122 for(id= lb->first; id; id= id->next) {
123 if(!((flag & PROP_ID_SELF_CHECK) && id == id_from)) {
126 if(RNA_property_type(template->prop)==PROP_POINTER) {
128 RNA_id_pointer_create(id, &ptr);
129 if(RNA_property_pointer_poll(&template->ptr, template->prop, &ptr)==0)
133 /* hide dot-datablocks, but only if filter does not force it visible */
134 if(U.uiflag & USER_HIDE_DOT)
135 if ((id->name[2]=='.') && (str[0] != '.'))
138 if(BLI_strcasestr(id->name+2, str)) {
140 name_uiprefix_id(name_ui, id);
142 iconid= ui_id_icon_get((bContext*)C, id, 1);
144 if(!uiSearchItemAdd(items, name_ui, id, iconid))
151 /* ID Search browse menu, open */
152 static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
154 static char search[256];
155 static TemplateID template;
157 wmWindow *win= CTX_wm_window(C);
161 /* clear initial search string, then all items show */
163 /* arg_litem is malloced, can be freed by parent button */
164 template= *((TemplateID*)arg_litem);
166 /* get active id for showing first item */
167 idptr= RNA_property_pointer_get(&template.ptr, template.prop);
169 block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
170 uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
172 /* preview thumbnails */
173 if (template.prv_rows > 0 && template.prv_cols > 0) {
174 int w = 96 * template.prv_cols;
175 int h = 96 * template.prv_rows + 20;
177 /* fake button, it holds space for search items */
178 uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL);
180 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, w, 19, template.prv_rows, template.prv_cols, "");
181 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
185 /* fake button, it holds space for search items */
186 uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
188 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, 0, 0, "");
189 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
193 uiBoundsBlock(block, 6);
194 uiBlockSetDirection(block, UI_DOWN);
195 uiEndBlock(C, block);
197 /* give search-field focus */
198 uiButSetFocusOnEnter(win, but);
199 /* this type of search menu requires undo */
200 but->flag |= UI_BUT_UNDO;
205 /************************ ID Template ***************************/
206 /* This is for browsing and editing the ID-blocks used */
208 /* for new/open operators */
209 void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
211 TemplateID *template;
212 ARegion *ar= CTX_wm_region(C);
216 memset(ptr, 0, sizeof(*ptr));
222 for(block=ar->uiblocks.first; block; block=block->next) {
223 for(but=block->buttons.first; but; but= but->next) {
224 /* find the button before the active one */
225 if((but->flag & (UI_BUT_LAST_ACTIVE|UI_ACTIVE))) {
227 template= but->func_argN;
229 *prop= template->prop;
238 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
240 TemplateID *template= (TemplateID*)arg_litem;
241 PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
243 int event= GET_INT_FROM_POINTER(arg_event);
248 RNA_warning("warning, id event %d shouldnt come here\n", event);
252 /* these call uiIDContextPropertySet */
255 memset(&idptr, 0, sizeof(idptr));
256 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
257 RNA_property_update(C, &template->ptr, template->prop);
259 if(id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */
263 case UI_ID_FAKE_USER:
265 if(id->flag & LIB_FAKEUSER) id_us_plus(id);
272 if(id_make_local(id, 0)) {
273 /* reassign to get get proper updates/notifiers */
274 idptr= RNA_property_pointer_get(&template->ptr, template->prop);
275 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
276 RNA_property_update(C, &template->ptr, template->prop);
282 const int do_scene_obj= (GS(id->name) == ID_OB) &&
283 (template->ptr.type == &RNA_SceneObjects);
287 Scene *scene= CTX_data_scene(C);
288 ED_object_single_user(scene, (struct Object *)id);
289 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
293 id_single_user(C, id, &template->ptr, template->prop);
299 case UI_ID_AUTO_NAME:
305 static const char *template_id_browse_tip(StructRNA *type)
308 switch(RNA_type_to_ID_code(type)) {
309 case ID_SCE: return "Browse Scene to be linked";
310 case ID_OB: return "Browse Object to be linked";
311 case ID_ME: return "Browse Mesh Data to be linked";
312 case ID_CU: return "Browse Curve Data to be linked";
313 case ID_MB: return "Browse MetaBall Data to be linked";
314 case ID_MA: return "Browse Material to be linked";
315 case ID_TE: return "Browse Texture to be linked";
316 case ID_IM: return "Browse Image to be linked";
317 case ID_LT: return "Browse Lattice Data to be linked";
318 case ID_LA: return "Browse Lamp Data to be linked";
319 case ID_CA: return "Browse Camera Data to be linked";
320 case ID_WO: return "Browse World Settings to be linked";
321 case ID_SCR: return "Choose Screen lay-out";
322 case ID_TXT: return "Browse Text to be linked";
323 case ID_SPK: return "Browse Speaker Data to be linked";
324 case ID_SO: return "Browse Sound to be linked";
325 case ID_AR: return "Browse Armature data to be linked";
326 case ID_AC: return "Browse Action to be linked";
327 case ID_NT: return "Browse Node Tree to be linked";
328 case ID_BR: return "Browse Brush to be linked";
329 case ID_PA: return "Browse Particle System to be linked";
330 case ID_GD: return "Browse Grease Pencil Data to be linked";
333 return "Browse ID data to be linked";
336 static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag, const char *newop, const char *openop, const char *unlinkop)
341 // ListBase *lb; // UNUSED
343 int editable= RNA_property_editable(&template->ptr, template->prop);
345 idptr= RNA_property_pointer_get(&template->ptr, template->prop);
347 idfrom= template->ptr.id.data;
348 // lb= template->idlb;
350 block= uiLayoutGetBlock(layout);
351 uiBlockBeginAlign(block);
356 if(flag & UI_ID_PREVIEWS) {
358 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, template_id_browse_tip(type));
360 but->icon= RNA_struct_ui_icon(type);
361 if (id) but->icon = ui_id_icon_get(C, id, 1);
362 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_PREVIEW);
364 if((idfrom && idfrom->lib) || !editable)
365 uiButSetFlag(but, UI_BUT_DISABLED);
367 uiLayoutRow(layout, 1);
369 else if(flag & UI_ID_BROWSE) {
370 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y, template_id_browse_tip(type));
372 but->icon= RNA_struct_ui_icon(type);
373 /* default dragging of icon for id browse buttons */
374 uiButSetDragID(but, id);
375 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_LEFT);
378 if((idfrom && idfrom->lib) || !editable)
379 uiButSetFlag(but, UI_BUT_DISABLED);
382 /* text button with name */
384 char name[UI_MAX_NAME_STR];
385 const short user_alert= (id->us <= 0);
387 //text_idbutton(id, name);
389 but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
390 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
391 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
394 if(id->flag & LIB_INDIRECT) {
395 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0,
396 "Indirect library datablock, cannot change.");
397 uiButSetFlag(but, UI_BUT_DISABLED);
400 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0,
401 "Direct linked library datablock, click to make local.");
402 if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib))
403 uiButSetFlag(but, UI_BUT_DISABLED);
406 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
412 sprintf(str, "%d", id->us);
414 but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X + ((id->us < 10) ? 0:10), UI_UNIT_Y, NULL, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
416 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
417 if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib) || !editable)
418 uiButSetFlag(but, UI_BUT_DISABLED);
421 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
423 if(id->lib == NULL && !(ELEM5(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
424 uiDefButR(block, TOG, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
428 if(flag & UI_ID_ADD_NEW) {
429 int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
432 but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
433 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
436 but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
437 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
440 if((idfrom && idfrom->lib) || !editable)
441 uiButSetFlag(but, UI_BUT_DISABLED);
444 if(flag & UI_ID_OPEN) {
445 int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
448 but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
449 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
452 but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
453 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
456 if((idfrom && idfrom->lib) || !editable)
457 uiButSetFlag(but, UI_BUT_DISABLED);
461 if(id && (flag & UI_ID_DELETE) && (RNA_property_flag(template->prop) & PROP_NEVER_UNLINK)==0) {
463 but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
464 /* so we can access the template from operators, font unlinking needs this */
465 uiButSetNFunc(but, NULL, MEM_dupallocN(template), NULL);
468 but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Unlink datablock. Shift + Click to set users to zero, data will then not be saved");
469 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
471 if(RNA_property_flag(template->prop) & PROP_NEVER_NULL)
472 uiButSetFlag(but, UI_BUT_DISABLED);
475 if((idfrom && idfrom->lib) || !editable)
476 uiButSetFlag(but, UI_BUT_DISABLED);
479 uiBlockEndAlign(block);
482 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)
484 TemplateID *template;
488 prop= RNA_struct_find_property(ptr, propname);
490 if(!prop || RNA_property_type(prop) != PROP_POINTER) {
491 RNA_warning("uiTemplateID: pointer property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
495 template= MEM_callocN(sizeof(TemplateID), "TemplateID");
497 template->prop= prop;
498 template->prv_rows = prv_rows;
499 template->prv_cols = prv_cols;
502 flag |= UI_ID_ADD_NEW;
506 type= RNA_property_pointer_type(ptr, prop);
507 template->idlb= which_libbase(CTX_data_main(C), RNA_type_to_ID_code(type));
509 /* create UI elements for this template
510 * - template_ID makes a copy of the template data and assigns it to the relevant buttons
513 uiLayoutRow(layout, 1);
514 template_ID(C, layout, template, type, flag, newop, openop, unlinkop);
520 void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
522 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE, 0, 0);
525 void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
527 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME, 0, 0);
530 void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols)
532 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE|UI_ID_PREVIEWS, rows, cols);
535 /************************ ID Chooser Template ***************************/
537 /* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use
539 * - propname: property identifier for property that ID-pointer gets stored to
540 * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used
542 void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *text)
544 PropertyRNA *propID, *propType;
547 /* get properties... */
548 propID= RNA_struct_find_property(ptr, propname);
549 propType= RNA_struct_find_property(ptr, proptypename);
551 if (!propID || RNA_property_type(propID) != PROP_POINTER) {
552 RNA_warning("uiTemplateAnyID: pointer property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
555 if (!propType || RNA_property_type(propType) != PROP_ENUM) {
556 RNA_warning("uiTemplateAnyID: pointer-type property not found: %s.%s\n", RNA_struct_identifier(ptr->type), proptypename);
560 /* Start drawing UI Elements using standard defines */
561 row= uiLayoutRow(layout, 1);
563 /* Label - either use the provided text, or will become "ID-Block:" */
565 uiItemL(row, text, ICON_NONE);
567 uiItemL(row, "ID-Block:", ICON_NONE);
569 /* ID-Type Selector - just have a menu of icons */
570 // FIXME: the icon-only setting doesn't work when we supply a blank name
571 uiItemFullR(row, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
573 /* ID-Block Selector - just use pointer widget... */
574 uiItemFullR(row, ptr, propID, 0, 0, 0, "", ICON_NONE);
577 /********************* RNA Path Builder Template ********************/
581 /* This is creating/editing RNA-Paths
583 * - ptr: struct which holds the path property
584 * - propname: property identifier for property that path gets stored to
585 * - root_ptr: struct that path gets built from
587 void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), const char *text)
589 PropertyRNA *propPath;
592 /* check that properties are valid */
593 propPath= RNA_struct_find_property(ptr, propname);
594 if (!propPath || RNA_property_type(propPath) != PROP_STRING) {
595 RNA_warning("uiTemplatePathBuilder: path property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
599 /* Start drawing UI Elements using standard defines */
600 row= uiLayoutRow(layout, 1);
602 /* Path (existing string) Widget */
603 uiItemR(row, ptr, propname, 0, text, ICON_RNA);
605 // TODO: attach something to this to make allow searching of nested properties to 'build' the path
608 /************************ Modifier Template *************************/
610 #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
614 #include "DNA_object_force.h"
616 #include "BKE_depsgraph.h"
617 #include "BKE_modifier.h"
618 #include "BKE_particle.h"
622 #include "BLI_math.h"
623 #include "BLI_listbase.h"
625 #include "ED_object.h"
627 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
629 Scene *scene = CTX_data_scene(C);
631 ModifierData *md= md_v;
632 int i, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 0);
634 /* undo button operation */
635 md->mode ^= eModifierMode_OnCage;
637 for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) {
640 md->mode ^= eModifierMode_OnCage;
645 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
646 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
649 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
652 ModifierData *md = md_v;
653 ModifierData *nmd = modifier_new(md->type);
655 modifier_copyData(md, nmd);
656 nmd->mode &= ~eModifierMode_Virtual;
658 BLI_addhead(&ob->modifiers, nmd);
660 modifier_unique_name(&ob->modifiers, nmd);
662 ob->partype = PAROBJECT;
664 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
665 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
667 ED_undo_push(C, "Modifier convert to real");
670 static int modifier_can_delete(ModifierData *md)
672 // fluid particle modifier can't be deleted here
673 if(md->type == eModifierType_ParticleSystem)
674 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
680 // Check wheter Modifier is a simulation or not, this is used for switching to the physics/particles context tab
681 static int modifier_is_simulation(ModifierData *md)
684 if(ELEM6(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke, eModifierType_Softbody, eModifierType_Surface)) {
688 else if (md->type == eModifierType_ParticleSystem) {
696 static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, ModifierData *md, int index, int cageIndex, int lastCageIndex)
698 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
702 uiLayout *box, *column, *row;
703 uiLayout *result= NULL;
704 int isVirtual = (md->mode & eModifierMode_Virtual);
707 /* create RNA pointer */
708 RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
710 column= uiLayoutColumn(layout, 1);
711 uiLayoutSetContextPointer(column, "modifier", &ptr);
713 /* rounded header ------------------------------------------------------------------- */
714 box= uiLayoutBox(column);
717 row= uiLayoutRow(box, 0);
718 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
719 block= uiLayoutGetBlock(row);
720 /* VIRTUAL MODIFIER */
721 // XXX this is not used now, since these cannot be accessed via RNA
722 sprintf(str, "%s parent deform", md->name);
723 uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name");
725 but = uiDefBut(block, BUT, 0, "Make Real", 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Convert virtual modifier to a real modifier");
726 uiButSetFunc(but, modifiers_convertToReal, ob, md);
730 row = uiLayoutRow(box, 0);
731 block = uiLayoutGetBlock(row);
733 uiBlockSetEmboss(block, UI_EMBOSSN);
734 /* Open/Close ................................. */
735 uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
737 /* modifier-type icon */
738 uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
739 uiBlockSetEmboss(block, UI_EMBOSS);
742 uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
744 /* mode enabling buttons */
745 uiBlockBeginAlign(block);
746 /* Softbody not allowed in this situation, enforce! */
747 if ( ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect))
748 && (md->type!=eModifierType_Surface) )
750 uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
751 uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
753 if (mti->flags & eModifierTypeFlag_SupportsEditmode)
754 uiItemR(row, &ptr, "show_in_editmode", 0, "", ICON_NONE);
756 if ((ob->type==OB_MESH) && modifier_couldBeCage(scene, md) && (index <= lastCageIndex))
758 /* -- convert to rna ? */
759 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, "Apply modifier to editing cage during Editmode");
760 if (index < cageIndex)
761 uiButSetFlag(but, UI_BUT_DISABLED);
762 uiButSetFunc(but, modifiers_setOnCage, ob, md);
765 /* tesselation point for curve-typed objects */
766 if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
767 /* some modifiers could work with pre-tesselated curves only */
768 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
769 /* add disabled pre-tesselated button, so users could have
770 message for this modifiers */
771 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, "This modifier could be applied on splines' points only");
772 uiButSetFlag(but, UI_BUT_DISABLED);
773 } else if (mti->type != eModifierTypeType_Constructive) {
774 /* constructive modifiers tesselates curve before applying */
775 uiItemR(row, &ptr, "use_apply_on_spline", 0, "", ICON_NONE);
779 uiBlockEndAlign(block);
781 /* Up/Down + Delete ........................... */
782 uiBlockBeginAlign(block);
783 uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up");
784 uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down");
785 uiBlockEndAlign(block);
787 uiBlockSetEmboss(block, UI_EMBOSSN);
788 // When Modifier is a simulation, show button to switch to context rather than the delete button.
789 if (modifier_can_delete(md) && !modifier_is_simulation(md))
790 uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
791 if (modifier_is_simulation(md) == 1)
792 uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PHYSICS");
793 else if (modifier_is_simulation(md) == 2)
794 uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PARTICLES");
795 uiBlockSetEmboss(block, UI_EMBOSS);
799 /* modifier settings (under the header) --------------------------------------------------- */
800 if (!isVirtual && (md->mode & eModifierMode_Expanded)) {
801 /* apply/convert/copy */
802 box= uiLayoutBox(column);
803 row= uiLayoutRow(box, 0);
805 if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) {
806 /* only here obdata, the rest of modifiers is ob level */
807 uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
809 if (md->type==eModifierType_ParticleSystem) {
810 ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
812 if (!(ob->mode & OB_MODE_PARTICLE_EDIT) && psys->pathcache) {
813 if(ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB))
814 uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_duplicates_make_real");
815 else if(psys->part->ren_as == PART_DRAW_PATH)
816 uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_modifier_convert");
820 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
821 uiItemEnumO(row, "OBJECT_OT_modifier_apply", "Apply", 0, "apply_as", MODIFIER_APPLY_DATA);
823 if (modifier_sameTopology(md))
824 uiItemEnumO(row, "OBJECT_OT_modifier_apply", "Apply as Shape", 0, "apply_as", MODIFIER_APPLY_SHAPE);
827 uiBlockClearButLock(block);
828 uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
830 if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke))
831 uiItemO(row, "Copy", ICON_NONE, "OBJECT_OT_modifier_copy");
834 /* result is the layout block inside the box, that we return so that modifier settings can be drawn */
835 result= uiLayoutColumn(box, 0);
836 block= uiLayoutAbsoluteBlock(box);
841 box = uiLayoutBox(column);
842 row = uiLayoutRow(box, 0);
843 uiItemL(row, md->error, ICON_ERROR);
849 uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
851 Scene *scene = CTX_data_scene(C);
853 ModifierData *md, *vmd;
854 int i, lastCageIndex, cageIndex;
856 /* verify we have valid data */
857 if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
858 RNA_warning("uiTemplateModifier: Expected modifier on object.\n");
865 if(!ob || !(GS(ob->id.name) == ID_OB)) {
866 RNA_warning("uiTemplateModifier: Expected modifier on object.\n");
870 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
872 /* find modifier and draw it */
873 cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
875 // XXX virtual modifiers are not accesible for python
876 vmd = modifiers_getVirtualModifierList(ob);
878 for(i=0; vmd; i++, vmd=vmd->next) {
880 return draw_modifier(layout, scene, ob, md, i, cageIndex, lastCageIndex);
881 else if(vmd->mode & eModifierMode_Virtual)
888 /************************ Constraint Template *************************/
890 #include "DNA_constraint_types.h"
892 #include "BKE_action.h"
893 #include "BKE_constraint.h"
897 #define REDRAWBUTSOBJECT 3
898 #define REDRAWACTION 4
899 #define B_CONSTRAINT_TEST 5
900 #define B_CONSTRAINT_CHANGETARGET 6
904 static void do_constraint_panels(bContext *C, void *ob_pt, int event)
906 Main *bmain= CTX_data_main(C);
907 Scene *scene= CTX_data_scene(C);
908 Object *ob= (Object *)ob_pt;
911 case B_CONSTRAINT_TEST:
912 break; // no handling
913 case B_CONSTRAINT_CHANGETARGET:
914 if (ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels
915 DAG_scene_sort(bmain, scene);
921 // note: RNA updates now call this, commenting else it gets called twice.
922 // if there are problems because of this, then rna needs changed update functions.
924 // object_test_constraints(ob);
925 // if(ob->pose) update_pose_constraint_flags(ob->pose);
927 if(ob->type==OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB);
928 else DAG_id_tag_update(&ob->id, OB_RECALC_OB);
930 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
933 static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
935 ED_object_constraint_set_active(ob_v, con_v);
938 /* draw panel showing settings for a constraint */
939 static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
941 bPoseChannel *pchan= get_active_posechannel(ob);
942 bConstraintTypeInfo *cti;
944 uiLayout *result= NULL, *col, *box, *row;
947 short proxy_protected, xco=0, yco=0;
948 // int rb_col; // UNUSED
950 /* get constraint typeinfo */
951 cti= constraint_get_typeinfo(con);
953 /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
954 if (con->type == CONSTRAINT_TYPE_NULL)
955 strcpy(typestr, "Null");
957 strcpy(typestr, "Unknown");
960 strcpy(typestr, cti->name);
962 /* determine whether constraint is proxy protected or not */
963 if (proxylocked_constraints_owner(ob, pchan))
964 proxy_protected= (con->flag & CONSTRAINT_PROXY_LOCAL)==0;
968 /* unless button has own callback, it adds this callback to button */
969 block= uiLayoutGetBlock(layout);
970 uiBlockSetHandleFunc(block, do_constraint_panels, ob);
971 uiBlockSetFunc(block, constraint_active_func, ob, con);
973 RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
975 col= uiLayoutColumn(layout, 1);
976 uiLayoutSetContextPointer(col, "constraint", &ptr);
978 box= uiLayoutBox(col);
979 row = uiLayoutRow(box, 0);
980 block= uiLayoutGetBlock(box);
982 /* Draw constraint header */
985 uiBlockSetEmboss(block, UI_EMBOSSN);
986 uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
987 uiBlockSetEmboss(block, UI_EMBOSS);
990 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
992 if (con->flag & CONSTRAINT_DISABLE)
993 uiLayoutSetRedAlert(row, 1);
995 if(proxy_protected == 0) {
996 uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
999 uiItemL(row, con->name, ICON_NONE);
1001 uiLayoutSetRedAlert(row, 0);
1003 /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
1004 if (proxy_protected) {
1005 uiBlockSetEmboss(block, UI_EMBOSSN);
1007 /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */
1008 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco+244, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
1009 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco+262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
1011 uiBlockSetEmboss(block, UI_EMBOSS);
1014 short prev_proxylock, show_upbut, show_downbut;
1017 * Proxy-constraints are not allowed to occur after local (non-proxy) constraints
1018 * as that poses problems when restoring them, so disable the "up" button where
1019 * it may cause this situation.
1021 * Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose.
1023 if (proxylocked_constraints_owner(ob, pchan)) {
1025 prev_proxylock= (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
1033 show_upbut= ((prev_proxylock == 0) && (con->prev));
1034 show_downbut= (con->next) ? 1 : 0;
1037 uiBlockSetEmboss(block, UI_EMBOSSN);
1038 uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF);
1039 uiBlockSetEmboss(block, UI_EMBOSS);
1041 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
1044 if (show_upbut || show_downbut) {
1045 uiBlockBeginAlign(block);
1047 uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up");
1050 uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down");
1051 uiBlockEndAlign(block);
1054 /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
1055 uiBlockSetEmboss(block, UI_EMBOSSN);
1056 uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete");
1057 uiBlockSetEmboss(block, UI_EMBOSS);
1060 /* Set but-locks for protected settings (magic numbers are used here!) */
1061 if (proxy_protected)
1062 uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint");
1064 /* Draw constraint data */
1065 if ((con->flag & CONSTRAINT_EXPAND) == 0) {
1069 box= uiLayoutBox(col);
1070 block= uiLayoutAbsoluteBlock(box);
1074 /* clear any locks set up for proxies/lib-linking */
1075 uiBlockClearButLock(block);
1080 uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
1085 /* verify we have valid data */
1086 if(!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
1087 RNA_warning("uiTemplateConstraint: Expected constraint on object.\n");
1094 if(!ob || !(GS(ob->id.name) == ID_OB)) {
1095 RNA_warning("uiTemplateConstraint: Expected constraint on object.\n");
1099 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
1101 /* hrms, the temporal constraint should not draw! */
1102 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
1103 bKinematicConstraint *data= con->data;
1104 if(data->flag & CONSTRAINT_IK_TEMP)
1108 return draw_constraint(layout, ob, con);
1112 /************************* Preview Template ***************************/
1114 #include "DNA_lamp_types.h"
1115 #include "DNA_material_types.h"
1116 #include "DNA_world_types.h"
1120 static void do_preview_buttons(bContext *C, void *arg, int event)
1124 WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, arg);
1129 void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, MTex *slot)
1131 uiLayout *row, *col;
1134 Tex *tex = (Tex*)id;
1136 short *pr_texture= NULL;
1137 PointerRNA material_ptr;
1138 PointerRNA texture_ptr;
1140 if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
1141 RNA_warning("uiTemplatePreview: Expected ID of type material, texture, lamp or world.\n");
1145 /* decide what to render */
1149 if(id && (GS(id->name) == ID_TE)) {
1150 if(parent && (GS(parent->name) == ID_MA))
1151 pr_texture= &((Material*)parent)->pr_texture;
1152 else if(parent && (GS(parent->name) == ID_WO))
1153 pr_texture= &((World*)parent)->pr_texture;
1154 else if(parent && (GS(parent->name) == ID_LA))
1155 pr_texture= &((Lamp*)parent)->pr_texture;
1158 if(*pr_texture == TEX_PR_OTHER)
1160 else if(*pr_texture == TEX_PR_BOTH)
1166 block= uiLayoutGetBlock(layout);
1167 row= uiLayoutRow(layout, 0);
1168 col= uiLayoutColumn(row, 0);
1169 uiLayoutSetKeepAspect(col, 1);
1172 uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, pid, 0.0, 0.0, 0, 0, "");
1173 uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot);
1174 uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
1177 if (pid && show_buttons) {
1178 if(GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
1179 if(GS(pid->name) == ID_MA) ma= (Material*)pid;
1180 else ma= (Material*)pparent;
1182 /* Create RNA Pointer */
1183 RNA_pointer_create(id, &RNA_Material, ma, &material_ptr);
1185 col = uiLayoutColumn(row, 1);
1186 uiLayoutSetScaleX(col, 1.5);
1187 uiItemR(col, &material_ptr, "preview_render_type", UI_ITEM_R_EXPAND, "", ICON_NONE);
1191 /* Create RNA Pointer */
1192 RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr);
1194 uiLayoutRow(layout, 1);
1195 uiDefButS(block, ROW, B_MATPRV, "Texture", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
1196 if(GS(parent->name) == ID_MA)
1197 uiDefButS(block, ROW, B_MATPRV, "Material", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1198 else if(GS(parent->name) == ID_LA)
1199 uiDefButS(block, ROW, B_MATPRV, "Lamp", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1200 else if(GS(parent->name) == ID_WO)
1201 uiDefButS(block, ROW, B_MATPRV, "World", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1202 uiDefButS(block, ROW, B_MATPRV, "Both", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
1204 /* Alpha buton for texture preview */
1205 if(*pr_texture!=TEX_PR_OTHER) {
1206 row = uiLayoutRow(layout, 0);
1207 uiItemR(row, &texture_ptr, "use_preview_alpha", 0, NULL, ICON_NONE);
1213 /********************** ColorRamp Template **************************/
1216 typedef struct RNAUpdateCb {
1221 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
1223 RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
1225 /* we call update here on the pointer property, this way the
1226 owner of the curve mapping can still define it's own update
1227 and notifier, even if the CurveMapping struct is shared. */
1228 RNA_property_update(C, &cb->ptr, cb->prop);
1233 static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
1235 ColorBand *coba= coba_v;
1239 if(coba->cur > 0) pos= (coba->data[coba->cur-1].pos + coba->data[coba->cur].pos) * 0.5f;
1240 else pos= (coba->data[coba->cur+1].pos + coba->data[coba->cur].pos) * 0.5f;
1243 if(colorband_element_add(coba, pos)) {
1244 rna_update_cb(C, cb_v, NULL);
1245 ED_undo_push(C, "Add colorband");
1249 static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v)
1251 ColorBand *coba= coba_v;
1253 if(colorband_element_remove(coba, coba->cur)) {
1254 ED_undo_push(C, "Delete colorband");
1255 rna_update_cb(C, cb_v, NULL);
1259 static void colorband_flip_cb(bContext *C, void *cb_v, void *coba_v)
1261 CBData data_tmp[MAXCOLORBAND];
1263 ColorBand *coba= coba_v;
1266 for(a=0; a<coba->tot; a++) {
1267 data_tmp[a]= coba->data[coba->tot - (a + 1)];
1269 for(a=0; a<coba->tot; a++) {
1270 data_tmp[a].pos = 1.0f - data_tmp[a].pos;
1271 coba->data[a]= data_tmp[a];
1274 /* may as well flip the cur*/
1275 coba->cur= coba->tot - (coba->cur + 1);
1277 ED_undo_push(C, "Flip colorband");
1279 rna_update_cb(C, cb_v, NULL);
1283 /* offset aligns from bottom, standard width 300, height 115 */
1284 static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb)
1288 const int line1_y= yoffs + 65 + UI_UNIT_Y + 2; /* 2 for some space between the buttons */
1289 const int line2_y= yoffs + 65;
1291 if(coba==NULL) return;
1293 bt= uiDefBut(block, BUT, 0, "Add", 0+xoffs,line1_y,40,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband");
1294 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1296 bt= uiDefBut(block, BUT, 0, "Delete", 45+xoffs,line1_y,45,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Delete the active position");
1297 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1300 /* XXX, todo for later - convert to operator - campbell */
1301 bt= uiDefBut(block, BUT, 0, "F", 95+xoffs,line1_y,20,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Flip colorband");
1302 uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
1304 uiDefButS(block, NUM, 0, "", 120+xoffs,line1_y,80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot-1)), 0, 0, "Choose active color stop");
1306 bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1307 210+xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1308 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1309 uiBlockEndAlign(block);
1311 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xoffs,line2_y,300,UI_UNIT_Y, coba, 0, 0, 0, 0, "");
1312 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1317 CBData *cbd= coba->data + coba->cur;
1319 /* better to use rna so we can animate them */
1321 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1322 row= uiLayoutRow(layout, 0);
1323 uiItemR(row, &ptr, "position", 0, "Pos", ICON_NONE);
1324 uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
1329 static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
1332 float unit= (butr->xmax-butr->xmin)/14.0f;
1333 float xs= butr->xmin;
1335 uiBlockBeginAlign(block);
1336 bt= uiDefBut(block, BUT, 0, "Add", xs,butr->ymin+UI_UNIT_Y,2.0f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband");
1337 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1338 bt= uiDefBut(block, BUT, 0, "Delete", xs+2.0f*unit,butr->ymin+UI_UNIT_Y,1.5f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Delete the active position");
1339 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1340 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, "Flip the color ramp");
1341 uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
1342 uiBlockEndAlign(block);
1345 CBData *cbd= coba->data + coba->cur;
1347 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1348 uiItemR(layout, &ptr, "color", 0, "", ICON_NONE);
1351 bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1352 xs+10.0f*unit, butr->ymin+UI_UNIT_Y, unit*4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1353 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1355 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xs,butr->ymin,butr->xmax-butr->xmin,UI_UNIT_Y, coba, 0, 0, 0, 0, "");
1356 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1358 uiBlockEndAlign(block);
1361 static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb)
1364 colorband_buttons_small(layout, block, coba, butr, cb);
1366 colorband_buttons_large(layout, block, coba, 0, 0, cb);
1369 void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname, int expand)
1371 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1377 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1380 cptr= RNA_property_pointer_get(ptr, prop);
1381 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp))
1384 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1388 rect.xmin= 0; rect.xmax= 200;
1389 rect.ymin= 0; rect.ymax= 190;
1391 block= uiLayoutAbsoluteBlock(layout);
1392 colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1397 /********************* Histogram Template ************************/
1399 void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname)
1401 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1409 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1412 cptr= RNA_property_pointer_get(ptr, prop);
1413 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram))
1416 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1420 rect.xmin= 0; rect.xmax= 200;
1421 rect.ymin= 0; rect.ymax= 190;
1423 block= uiLayoutAbsoluteBlock(layout);
1424 //colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1426 hist = (Histogram *)cptr.data;
1428 hist->height= (hist->height<=UI_UNIT_Y)?UI_UNIT_Y:hist->height;
1430 bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, hist->height, hist, 0, 0, 0, 0, "");
1431 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1436 /********************* Waveform Template ************************/
1438 void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname)
1440 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1448 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1451 cptr= RNA_property_pointer_get(ptr, prop);
1452 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
1454 scopes = (Scopes *)cptr.data;
1456 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1460 rect.xmin= 0; rect.xmax= 200;
1461 rect.ymin= 0; rect.ymax= 190;
1463 block= uiLayoutAbsoluteBlock(layout);
1465 scopes->wavefrm_height= (scopes->wavefrm_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->wavefrm_height;
1467 bt= uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
1473 /********************* Vectorscope Template ************************/
1475 void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propname)
1477 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1485 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1488 cptr= RNA_property_pointer_get(ptr, prop);
1489 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
1491 scopes = (Scopes *)cptr.data;
1493 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1497 rect.xmin= 0; rect.xmax= 200;
1498 rect.ymin= 0; rect.ymax= 190;
1500 block= uiLayoutAbsoluteBlock(layout);
1502 scopes->vecscope_height= (scopes->vecscope_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->vecscope_height;
1504 bt= uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
1505 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1510 /********************* CurveMapping Template ************************/
1513 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *UNUSED(arg))
1515 CurveMapping *cumap = cumap_v;
1518 /* we allow 20 times zoom */
1519 if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1520 d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
1521 cumap->curr.xmin+= d;
1522 cumap->curr.xmax-= d;
1523 d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
1524 cumap->curr.ymin+= d;
1525 cumap->curr.ymax-= d;
1528 ED_region_tag_redraw(CTX_wm_region(C));
1531 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(unused))
1533 CurveMapping *cumap = cumap_v;
1536 /* we allow 20 times zoom, but dont view outside clip */
1537 if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1538 d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
1540 if(cumap->flag & CUMA_DO_CLIP)
1541 if(cumap->curr.xmin-d < cumap->clipr.xmin)
1542 d1= cumap->curr.xmin - cumap->clipr.xmin;
1543 cumap->curr.xmin-= d1;
1546 if(cumap->flag & CUMA_DO_CLIP)
1547 if(cumap->curr.xmax+d > cumap->clipr.xmax)
1548 d1= -cumap->curr.xmax + cumap->clipr.xmax;
1549 cumap->curr.xmax+= d1;
1551 d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
1553 if(cumap->flag & CUMA_DO_CLIP)
1554 if(cumap->curr.ymin-d < cumap->clipr.ymin)
1555 d1= cumap->curr.ymin - cumap->clipr.ymin;
1556 cumap->curr.ymin-= d1;
1559 if(cumap->flag & CUMA_DO_CLIP)
1560 if(cumap->curr.ymax+d > cumap->clipr.ymax)
1561 d1= -cumap->curr.ymax + cumap->clipr.ymax;
1562 cumap->curr.ymax+= d1;
1565 ED_region_tag_redraw(CTX_wm_region(C));
1568 static void curvemap_buttons_setclip(bContext *UNUSED(C), void *cumap_v, void *UNUSED(arg))
1570 CurveMapping *cumap = cumap_v;
1572 curvemapping_changed(cumap, 0);
1575 static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
1577 CurveMapping *cumap = cumap_v;
1579 curvemap_remove(cumap->cm+cumap->cur, SELECT);
1580 curvemapping_changed(cumap, 0);
1582 rna_update_cb(C, cb_v, NULL);
1585 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
1586 static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v)
1588 CurveMapping *cumap = cumap_v;
1591 float width= 8*UI_UNIT_X;
1593 block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS);
1595 /* use this for a fake extra empy space around the buttons */
1596 uiDefBut(block, LABEL, 0, "", -4, 16, width+8, 6*UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
1598 bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",
1599 0,5*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->flag, 0.0, 0.0, 10, 0, "");
1600 uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
1602 uiBlockBeginAlign(block);
1603 uiDefButF(block, NUM, 0, "Min X ", 0,4*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, "");
1604 uiDefButF(block, NUM, 0, "Min Y ", 0,3*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, "");
1605 uiDefButF(block, NUM, 0, "Max X ", 0,2*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, "");
1606 uiDefButF(block, NUM, 0, "Max Y ", 0,UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, "");
1608 uiBlockSetDirection(block, UI_RIGHT);
1610 uiEndBlock(C, block);
1614 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
1616 CurveMapping *cumap = cumap_v;
1617 CurveMap *cuma= cumap->cm+cumap->cur;
1621 curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
1622 curvemapping_changed(cumap, 0);
1625 cumap->curr= cumap->clipr;
1627 case 2: /* set vector */
1628 curvemap_sethandle(cuma, 1);
1629 curvemapping_changed(cumap, 0);
1631 case 3: /* set auto */
1632 curvemap_sethandle(cuma, 0);
1633 curvemapping_changed(cumap, 0);
1635 case 4: /* extend horiz */
1636 cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
1637 curvemapping_changed(cumap, 0);
1639 case 5: /* extend extrapolate */
1640 cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
1641 curvemapping_changed(cumap, 0);
1644 ED_region_tag_redraw(CTX_wm_region(C));
1647 static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1650 short yco= 0, menuwidth=10*UI_UNIT_X;
1652 block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1653 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1655 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, "");
1656 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, "");
1657 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, "");
1658 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 4, "");
1659 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 5, "");
1660 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1662 uiBlockSetDirection(block, UI_RIGHT);
1663 uiTextBoundsBlock(block, 50);
1665 uiEndBlock(C, block);
1669 static uiBlock *curvemap_brush_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1672 short yco= 0, menuwidth=10*UI_UNIT_X;
1674 block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1675 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1677 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, "");
1678 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, "");
1679 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, "");
1680 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1682 uiBlockSetDirection(block, UI_RIGHT);
1683 uiTextBoundsBlock(block, 50);
1685 uiEndBlock(C, block);
1689 static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
1691 ED_region_tag_redraw(CTX_wm_region(C));
1694 static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
1696 CurveMapping *cumap = cumap_v;
1699 cumap->preset = CURVE_PRESET_LINE;
1700 for(a=0; a<CM_TOT; a++)
1701 curvemap_reset(cumap->cm+a, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
1703 cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
1704 cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
1705 curvemapping_set_black_white(cumap, NULL, NULL);
1707 curvemapping_changed(cumap, 0);
1709 rna_update_cb(C, cb_v, NULL);
1712 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
1713 static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb)
1715 CurveMapping *cumap= ptr->data;
1716 uiLayout *row, *sub, *split;
1719 float dx= UI_UNIT_X;
1723 block= uiLayoutGetBlock(layout);
1726 row= uiLayoutRow(layout, 0);
1728 if(labeltype=='v') {
1730 sub= uiLayoutRow(row, 1);
1731 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1733 if(cumap->cm[0].curve) {
1734 bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1735 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1737 if(cumap->cm[1].curve) {
1738 bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1739 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1741 if(cumap->cm[2].curve) {
1742 bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1743 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1746 else if(labeltype=='c') {
1748 sub= uiLayoutRow(row, 1);
1749 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1751 if(cumap->cm[3].curve) {
1752 bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, dx, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
1753 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1755 if(cumap->cm[0].curve) {
1756 bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1757 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1759 if(cumap->cm[1].curve) {
1760 bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1761 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1763 if(cumap->cm[2].curve) {
1764 bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1765 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1768 else if (labeltype == 'h') {
1770 sub= uiLayoutRow(row, 1);
1771 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1773 if(cumap->cm[0].curve) {
1774 bt= uiDefButI(block, ROW, 0, "H", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1775 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1777 if(cumap->cm[1].curve) {
1778 bt= uiDefButI(block, ROW, 0, "S", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1779 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1781 if(cumap->cm[2].curve) {
1782 bt= uiDefButI(block, ROW, 0, "V", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1783 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1787 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
1792 /* operation buttons */
1793 sub= uiLayoutRow(row, 1);
1795 uiBlockSetEmboss(block, UI_EMBOSSN);
1797 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
1798 uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
1800 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
1801 uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
1804 bt= uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, "Tools");
1806 bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, "Tools");
1808 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1810 if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
1811 bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, "Clipping Options");
1812 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1814 bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
1815 uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
1817 uiBlockSetEmboss(block, UI_EMBOSS);
1819 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
1822 size= uiLayoutGetWidth(layout);
1823 row= uiLayoutRow(layout, 0);
1824 uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, bg, 0, "");
1826 /* black/white levels */
1828 split= uiLayoutSplit(layout, 0, 0);
1829 uiItemR(uiLayoutColumn(split, 0), ptr, "black_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1830 uiItemR(uiLayoutColumn(split, 0), ptr, "white_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1832 uiLayoutRow(layout, 0);
1833 bt=uiDefBut(block, BUT, 0, "Reset", 0, 0, UI_UNIT_X*10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves");
1834 uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
1837 uiBlockSetNFunc(block, NULL, NULL, NULL);
1840 void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, int levels, int brush)
1843 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1847 RNA_warning("uiTemplateCurveMapping: curve property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
1851 if(RNA_property_type(prop) != PROP_POINTER) {
1852 RNA_warning("uiTemplateCurveMapping: curve is not a pointer: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
1856 cptr= RNA_property_pointer_get(ptr, prop);
1857 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping))
1860 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1864 curvemap_buttons_layout(layout, &cptr, type, levels, brush, cb);
1869 /********************* ColorWheel Template ************************/
1871 #define WHEEL_SIZE 100
1873 void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic)
1875 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1876 uiBlock *block= uiLayoutGetBlock(layout);
1877 uiLayout *col, *row;
1879 float softmin, softmax, step, precision;
1882 RNA_warning("uiTemplateColorWheel: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
1886 RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
1888 col = uiLayoutColumn(layout, 0);
1889 row= uiLayoutRow(col, 1);
1891 but= uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, "");
1894 but->flag |= UI_BUT_COLOR_LOCK;
1897 if(lock_luminosity) {
1898 float color[4]; /* incase of alpha */
1899 but->flag |= UI_BUT_VEC_SIZE_LOCK;
1900 RNA_property_float_get_array(ptr, prop, color);
1901 but->a2= len_v3(color);
1905 but->flag |= UI_BUT_COLOR_CUBIC;
1910 uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
1913 /********************* Layer Buttons Template ************************/
1915 static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
1918 int cur = GET_INT_FROM_POINTER(arg2);
1919 wmWindow *win= CTX_wm_window(C);
1920 int i, tot, shift= win->eventstate->shift;
1923 tot= RNA_property_array_length(&but->rnapoin, but->rnaprop);
1925 /* Normally clicking only selects one layer */
1926 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, 1);
1927 for(i = 0; i < tot; ++i) {
1929 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, 0);
1933 /* view3d layer change should update depsgraph (invisible object changed maybe) */
1934 /* see view3d_header.c */
1938 // - for now, grouping of layers is determined by dividing up the length of
1939 // the array of layer bitflags
1941 void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname,
1942 PointerRNA *used_ptr, const char *used_propname, int active_layer)
1944 uiLayout *uRow, *uCol;
1945 PropertyRNA *prop, *used_prop= NULL;
1946 int groups, cols, layers;
1947 int group, col, layer, row;
1948 int cols_per_group = 5;
1950 prop= RNA_struct_find_property(ptr, propname);
1952 RNA_warning("uiTemplateLayer: layers property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
1956 /* the number of layers determines the way we group them
1957 * - we want 2 rows only (for now)
1958 * - the number of columns (cols) is the total number of buttons per row
1959 * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
1960 * - for now, only split into groups if group will have at least 5 items
1962 layers= RNA_property_array_length(ptr, prop);
1963 cols= (layers / 2) + (layers % 2);
1964 groups= ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
1966 if(used_ptr && used_propname) {
1967 used_prop= RNA_struct_find_property(used_ptr, used_propname);
1969 RNA_warning("uiTemplateLayer: used layers property not found: %s.%s\n", RNA_struct_identifier(ptr->type), used_propname);
1973 if(RNA_property_array_length(used_ptr, used_prop) < layers)
1977 /* layers are laid out going across rows, with the columns being divided into groups */
1979 for (group= 0; group < groups; group++) {
1980 uCol= uiLayoutColumn(layout, 1);
1982 for (row= 0; row < 2; row++) {
1986 uRow= uiLayoutRow(uCol, 1);
1987 block= uiLayoutGetBlock(uRow);
1988 layer= groups*cols_per_group*row + cols_per_group*group;
1990 /* add layers as toggle buts */
1991 for (col= 0; (col < cols_per_group) && (layer < layers); col++, layer++) {
1993 int butlay = 1 << layer;
1995 if(active_layer & butlay)
1996 icon = ICON_LAYER_ACTIVE;
1997 else if(used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer))
1998 icon = ICON_LAYER_USED;
2000 but= uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, UI_UNIT_X/2, UI_UNIT_Y/2);
2001 uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer));
2009 /************************* List Template **************************/
2011 static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big)
2019 /* try ID, material or texture slot */
2020 if(RNA_struct_is_ID(itemptr->type)) {
2021 id= itemptr->id.data;
2023 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
2024 id= RNA_pointer_get(itemptr, "material").data;
2026 else if(RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
2027 id= RNA_pointer_get(itemptr, "texture").data;
2030 /* get icon from ID */
2032 icon= ui_id_icon_get(C, id, big);
2041 static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop)
2043 uiBlock *block= uiLayoutGetBlock(layout);
2045 uiLayout *split, *overlap, *sub, *row;
2050 overlap= uiLayoutOverlap(layout);
2052 /* list item behind label & other buttons */
2053 sub= uiLayoutRow(overlap, 0);
2055 but= uiDefButR_prop(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, "");
2056 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2058 sub= uiLayoutRow(overlap, 0);
2060 /* retrieve icon and name */
2061 icon= list_item_icon_get(C, itemptr, rnaicon, 0);
2062 if(icon == ICON_NONE || icon == ICON_DOT)
2065 namebuf= RNA_struct_name_get_alloc(itemptr, NULL, 0);
2066 name= (namebuf)? namebuf: "";
2068 /* hardcoded types */
2069 if(itemptr->type == &RNA_MeshTextureFaceLayer || itemptr->type == &RNA_MeshColorLayer) {
2070 uiItemL(sub, name, icon);
2071 uiBlockSetEmboss(block, UI_EMBOSSN);
2072 uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
2073 uiBlockSetEmboss(block, UI_EMBOSS);
2075 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
2076 uiItemL(sub, name, icon);
2077 uiBlockSetEmboss(block, UI_EMBOSS);
2078 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
2080 else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
2081 uiItemL(sub, name, icon);
2082 uiBlockSetEmboss(block, UI_EMBOSS);
2083 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
2085 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
2086 /* provision to draw active node name */
2087 Material *ma, *manode;
2088 Object *ob= (Object*)ptr->id.data;
2089 int index= (Material**)itemptr->data - ob->mat;
2091 /* default item with material base name */
2092 uiItemL(sub, name, icon);
2094 ma= give_current_material(ob, index+1);
2096 manode= give_node_material(ma);
2098 char str[MAX_ID_NAME + 12];
2099 sprintf(str, "Node %s", manode->id.name+2);
2100 uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1));
2102 else if(ma->use_nodes) {
2103 uiItemL(sub, "Node <none>", ICON_NONE);
2107 else if(itemptr->type == &RNA_ShapeKey) {
2108 Object *ob= (Object*)activeptr->data;
2109 Key *key= (Key*)itemptr->id.data;
2111 split= uiLayoutSplit(sub, 0.75f, 0);
2113 uiItemL(split, name, icon);
2115 uiBlockSetEmboss(block, UI_EMBOSSN);
2116 row= uiLayoutRow(split, 1);
2117 if(i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE);
2118 else uiItemR(row, itemptr, "value", 0, "", ICON_NONE);
2120 if(ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH))
2121 uiLayoutSetActive(row, 0);
2122 //uiItemR(row, itemptr, "mute", 0, "", ICON_MUTE_IPO_OFF);
2123 uiBlockSetEmboss(block, UI_EMBOSS);
2125 else if(itemptr->type == &RNA_KeyingSetPath) {
2126 KS_Path *ksp = (KS_Path*)itemptr->data;
2128 /* icon needs to be the type of ID which is currently active */
2129 RNA_enum_icon_from_value(id_type_items, ksp->idtype, &icon);
2131 /* nothing else special to do... */
2132 uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
2135 uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
2142 void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, const char *activepropname, int rows, int maxrows, int listtype)
2144 //Scene *scene= CTX_data_scene(C);
2145 PropertyRNA *prop= NULL, *activeprop;
2146 PropertyType type, activetype;
2148 uiLayout *box, *row, *col;
2152 char *name, str[32];
2153 int rnaicon=0, icon=0, i= 0, activei= 0, len= 0, items, found, min, max;
2155 /* validate arguments */
2156 block= uiLayoutGetBlock(layout);
2160 RNA_warning("uiTemplateList: only works inside a panel.\n");
2164 if(!activeptr->data)
2168 prop= RNA_struct_find_property(ptr, propname);
2170 RNA_warning("uiTemplateList: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
2175 activeprop= RNA_struct_find_property(activeptr, activepropname);
2177 RNA_warning("uiTemplateList: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), activepropname);
2182 type= RNA_property_type(prop);
2183 if(type != PROP_COLLECTION) {
2184 RNA_warning("uiTemplateList: Expected collection property.\n");
2189 activetype= RNA_property_type(activeprop);
2190 if(activetype != PROP_INT) {
2191 RNA_warning("uiTemplateList: Expected integer property.\n");
2196 if(ptr->data && prop) {
2197 ptype= RNA_property_pointer_type(ptr, prop);
2198 rnaicon= RNA_struct_ui_icon(ptype);
2201 /* get active data */
2202 activei= RNA_property_int_get(activeptr, activeprop);
2204 if(listtype == 'i') {
2205 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2206 col= uiLayoutColumn(box, 1);
2207 row= uiLayoutRow(col, 0);
2209 if(ptr->data && prop) {
2210 /* create list items */
2211 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2214 row= uiLayoutRow(col, 0);
2216 icon= list_item_icon_get(C, &itemptr, rnaicon, 1);
2217 but= uiDefIconButR_prop(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, "");
2218 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2226 else if(listtype == 'c') {
2227 /* compact layout */
2229 row= uiLayoutRow(layout, 1);
2231 if(ptr->data && prop) {
2232 /* create list items */
2233 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2234 found= (activei == i);
2238 name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
2239 icon= list_item_icon_get(C, &itemptr, rnaicon, 0);
2240 uiItemL(row, (name)? name: "", icon);
2251 /* if not found, add in dummy button */
2253 uiItemL(row, "", ICON_NONE);
2255 /* next/prev button */
2256 sprintf(str, "%d :", i);
2257 but= uiDefIconTextButR_prop(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activeprop, 0, 0, 0, 0, 0, "");
2259 uiButSetFlag(but, UI_BUT_DISABLED);
2267 if(pa->list_grip_size != 0)
2268 rows= pa->list_grip_size;
2271 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2272 row= uiLayoutRow(box, 0);
2273 col = uiLayoutColumn(row, 1);
2276 RNA_property_int_range(activeptr, activeprop, &min, &max);
2279 len= RNA_property_collection_length(ptr, prop);
2280 items= CLAMPIS(len, rows, MAX2(rows, maxrows));
2282 /* if list length changes and active is out of view, scroll to it */
2283 if(pa->list_last_len != len)
2284 if((activei < pa->list_scroll || activei >= pa->list_scroll+items))
2285 pa->list_scroll= activei;
2287 pa->list_scroll= MIN2(pa->list_scroll, len-items);
2288 pa->list_scroll= MAX2(pa->list_scroll, 0);
2289 pa->list_size= items;
2290 pa->list_last_len= len;
2292 if(ptr->data && prop) {
2293 /* create list items */
2294 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2295 if(i >= pa->list_scroll && i<pa->list_scroll+items)
2296 list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activeprop);
2303 /* add dummy buttons to fill space */
2304 while(i < pa->list_scroll+items) {
2305 if(i >= pa->list_scroll)
2306 uiItemL(col, "", ICON_NONE);
2312 col= uiLayoutColumn(row, 0);
2313 uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
2318 /************************* Operator Search Template **************************/
2320 static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
2322 wmOperatorType *ot= arg2;
2325 WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
2328 static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
2330 GHashIterator *iter= WM_operatortype_iter();
2332 for( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
2333 wmOperatorType *ot= BLI_ghashIterator_getValue(iter);
2335 if(BLI_strcasestr(ot->name, str)) {
2336 if(WM_operator_poll((bContext*)C, ot)) {
2338 int len= strlen(ot->name);
2340 /* display name for menu, can hold hotkey */
2341 BLI_strncpy(name, ot->name, 256);
2343 /* check for hotkey */
2345 if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
2349 if(0==uiSearchItemAdd(items, name, ot, 0))
2354 BLI_ghashIterator_free(iter);
2357 void uiTemplateOperatorSearch(uiLayout *layout)
2361 static char search[256]= "";
2363 block= uiLayoutGetBlock(layout);
2364 uiBlockSetCurLayout(block, layout);
2366 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, 0, 0, "");
2367 uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
2370 /************************* Running Jobs Template **************************/
2372 #define B_STOPRENDER 1
2373 #define B_STOPCAST 2
2374 #define B_STOPANIM 3
2375 #define B_STOPCOMPO 4
2378 static void do_running_jobs(bContext *C, void *UNUSED(arg), int event)
2385 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL);
2388 WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
2391 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
2394 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
2399 void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
2401 bScreen *screen= CTX_wm_screen(C);
2402 wmWindowManager *wm= CTX_wm_manager(C);
2403 ScrArea *sa= CTX_wm_area(C);
2408 block= uiLayoutGetBlock(layout);
2409 uiBlockSetCurLayout(block, layout);
2411 uiBlockSetHandleFunc(block, do_running_jobs, NULL);
2413 if(sa->spacetype==SPACE_NODE) {
2414 if(WM_jobs_test(wm, sa))
2416 handle_event= B_STOPCOMPO;
2417 } else if (sa->spacetype==SPACE_SEQ) {
2418 if(WM_jobs_test(wm, sa))
2420 handle_event = B_STOPSEQ;
2423 /* another scene can be rendering too, for example via compositor */
2424 for(scene= CTX_data_main(C)->scene.first; scene; scene= scene->id.next)
2425 if(WM_jobs_test(wm, scene))
2428 handle_event= B_STOPRENDER;
2434 ui_abs= uiLayoutAbsolute(layout, 0);
2435 (void)ui_abs; // UNUSED
2437 uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE,
2438 0, UI_UNIT_Y*0.1, UI_UNIT_X*0.8, UI_UNIT_Y*0.8, NULL, 0.0f, 0.0f, 0, 0, "Stop this job");
2439 uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner),
2440 UI_UNIT_X, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, "Progress");
2442 uiLayoutRow(layout, 0);
2444 if(WM_jobs_test(wm, screen))
2445 uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, "Capture", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast");
2446 if(screen->animtimer)
2447 uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, "Anim Player", 0,0,100,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop animation playback");
2450 /************************* Reports for Last Operator Template **************************/
2452 void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
2454 ReportList *reports = CTX_wm_reports(C);
2455 Report *report= BKE_reports_last_displayable(reports);
2456 ReportTimerInfo *rti;
2461 uiStyle *style= U.uistyles.first;
2465 /* if the report display has timed out, don't show */
2466 if (!reports->reporttimer) return;
2468 rti= (ReportTimerInfo *)reports->reporttimer->customdata;
2470 if (!rti || rti->widthfac==0.0f || !report) return;
2472 ui_abs= uiLayoutAbsolute(layout, 0);
2473 block= uiLayoutGetBlock(ui_abs);
2475 width = BLF_width(style->widget.uifont_id, report->message);
2476 width = MIN2(rti->widthfac*width, width);
2477 width = MAX2(width, 10);
2479 /* make a box around the report to make it stand out */
2480 uiBlockBeginAlign(block);
2481 but= uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X+10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2482 /* set the report's bg color in but->col - ROUNDBOX feature */
2483 but->col[0]= FTOCHAR(rti->col[0]);
2484 but->col[1]= FTOCHAR(rti->col[1]);
2485 but->col[2]= FTOCHAR(rti->col[2]);
2488 but= uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2489 but->col[0]= but->col[1]= but->col[2]= FTOCHAR(rti->greyscale);
2492 uiBlockEndAlign(block);
2495 /* icon and report message on top */
2496 if(report->type & RPT_ERROR_ALL)
2498 else if(report->type & RPT_WARNING_ALL)
2500 else if(report->type & RPT_INFO_ALL)
2503 /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report
2504 * to be shown instead of icon when appropriate...
2506 uiBlockSetEmboss(block, UI_EMBOSSN);
2508 if (reports->list.first != reports->list.last)
2509 uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, "Click to see rest of reports in textblock: 'Recent Reports'");
2511 uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2513 uiBlockSetEmboss(block, UI_EMBOSS);
2515 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, "");