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_utildefines.h"
42 #include "BLI_string.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"
71 #include "BLF_translation.h"
73 void UI_template_fix_linking(void)
77 /********************** Header Template *************************/
79 void uiTemplateHeader(uiLayout *layout, bContext *C, int menus)
83 block= uiLayoutAbsoluteBlock(layout);
84 if(menus) ED_area_header_standardbuttons(C, block, 0);
85 else ED_area_header_switchbutton(C, block, 0);
88 /********************** Search Callbacks *************************/
90 typedef struct TemplateID {
95 int prv_rows, prv_cols;
98 /* Search browse menu, assign */
99 static void id_search_call_cb(bContext *C, void *arg_template, void *item)
101 TemplateID *template= (TemplateID*)arg_template;
107 RNA_id_pointer_create(item, &idptr);
108 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
109 RNA_property_update(C, &template->ptr, template->prop);
113 /* ID Search browse menu, do the search */
114 static void id_search_cb(const bContext *C, void *arg_template, const char *str, uiSearchItems *items)
116 TemplateID *template= (TemplateID*)arg_template;
117 ListBase *lb= template->idlb;
118 ID *id, *id_from= template->ptr.id.data;
120 int flag= RNA_property_flag(template->prop);
123 for(id= lb->first; id; id= id->next) {
124 if(!((flag & PROP_ID_SELF_CHECK) && id == id_from)) {
127 if(RNA_property_type(template->prop)==PROP_POINTER) {
129 RNA_id_pointer_create(id, &ptr);
130 if(RNA_property_pointer_poll(&template->ptr, template->prop, &ptr)==0)
134 /* hide dot-datablocks, but only if filter does not force it visible */
135 if(U.uiflag & USER_HIDE_DOT)
136 if ((id->name[2]=='.') && (str[0] != '.'))
139 if(BLI_strcasestr(id->name+2, str)) {
141 name_uiprefix_id(name_ui, id);
143 iconid= ui_id_icon_get((bContext*)C, id, 1);
145 if(!uiSearchItemAdd(items, name_ui, id, iconid))
152 /* ID Search browse menu, open */
153 static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
155 static char search[256];
156 static TemplateID template;
158 wmWindow *win= CTX_wm_window(C);
162 /* clear initial search string, then all items show */
164 /* arg_litem is malloced, can be freed by parent button */
165 template= *((TemplateID*)arg_litem);
167 /* get active id for showing first item */
168 idptr= RNA_property_pointer_get(&template.ptr, template.prop);
170 block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
171 uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
173 /* preview thumbnails */
174 if (template.prv_rows > 0 && template.prv_cols > 0) {
175 int w = 96 * template.prv_cols;
176 int h = 96 * template.prv_rows + 20;
178 /* fake button, it holds space for search items */
179 uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL);
181 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, w, 19, template.prv_rows, template.prv_cols, "");
182 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
186 /* fake button, it holds space for search items */
187 uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
189 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, 0, 0, "");
190 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
194 uiBoundsBlock(block, 6);
195 uiBlockSetDirection(block, UI_DOWN);
196 uiEndBlock(C, block);
198 /* give search-field focus */
199 uiButSetFocusOnEnter(win, but);
200 /* this type of search menu requires undo */
201 but->flag |= UI_BUT_UNDO;
206 /************************ ID Template ***************************/
207 /* This is for browsing and editing the ID-blocks used */
209 /* for new/open operators */
210 void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
212 TemplateID *template;
213 ARegion *ar= CTX_wm_region(C);
217 memset(ptr, 0, sizeof(*ptr));
223 for(block=ar->uiblocks.first; block; block=block->next) {
224 for(but=block->buttons.first; but; but= but->next) {
225 /* find the button before the active one */
226 if((but->flag & (UI_BUT_LAST_ACTIVE|UI_ACTIVE))) {
228 template= but->func_argN;
230 *prop= template->prop;
239 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
241 TemplateID *template= (TemplateID*)arg_litem;
242 PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
244 int event= GET_INT_FROM_POINTER(arg_event);
249 RNA_warning("warning, id event %d shouldnt come here", event);
253 /* these call uiIDContextPropertySet */
256 memset(&idptr, 0, sizeof(idptr));
257 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
258 RNA_property_update(C, &template->ptr, template->prop);
260 if(id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */
264 case UI_ID_FAKE_USER:
266 if(id->flag & LIB_FAKEUSER) id_us_plus(id);
273 if(id_make_local(id, 0)) {
274 /* reassign to get get proper updates/notifiers */
275 idptr= RNA_property_pointer_get(&template->ptr, template->prop);
276 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
277 RNA_property_update(C, &template->ptr, template->prop);
283 const int do_scene_obj= (GS(id->name) == ID_OB) &&
284 (template->ptr.type == &RNA_SceneObjects);
288 Scene *scene= CTX_data_scene(C);
289 ED_object_single_user(scene, (struct Object *)id);
290 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
294 id_single_user(C, id, &template->ptr, template->prop);
300 case UI_ID_AUTO_NAME:
306 static const char *template_id_browse_tip(StructRNA *type)
309 switch(RNA_type_to_ID_code(type)) {
310 case ID_SCE: return N_("Browse Scene to be linked");
311 case ID_OB: return N_("Browse Object to be linked");
312 case ID_ME: return N_("Browse Mesh Data to be linked");
313 case ID_CU: return N_("Browse Curve Data to be linked");
314 case ID_MB: return N_("Browse MetaBall Data to be linked");
315 case ID_MA: return N_("Browse Material to be linked");
316 case ID_TE: return N_("Browse Texture to be linked");
317 case ID_IM: return N_("Browse Image to be linked");
318 case ID_LT: return N_("Browse Lattice Data to be linked");
319 case ID_LA: return N_("Browse Lamp Data to be linked");
320 case ID_CA: return N_("Browse Camera Data to be linked");
321 case ID_WO: return N_("Browse World Settings to be linked");
322 case ID_SCR: return N_("Choose Screen lay-out");
323 case ID_TXT: return N_("Browse Text to be linked");
324 case ID_SPK: return N_("Browse Speaker Data to be linked");
325 case ID_SO: return N_("Browse Sound to be linked");
326 case ID_AR: return N_("Browse Armature data to be linked");
327 case ID_AC: return N_("Browse Action to be linked");
328 case ID_NT: return N_("Browse Node Tree to be linked");
329 case ID_BR: return N_("Browse Brush to be linked");
330 case ID_PA: return N_("Browse Particle System to be linked");
331 case ID_GD: return N_("Browse Grease Pencil Data to be linked");
334 return N_("Browse ID data to be linked");
337 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)
342 // ListBase *lb; // UNUSED
344 int editable= RNA_property_editable(&template->ptr, template->prop);
346 idptr= RNA_property_pointer_get(&template->ptr, template->prop);
348 idfrom= template->ptr.id.data;
349 // lb= template->idlb;
351 block= uiLayoutGetBlock(layout);
352 uiBlockBeginAlign(block);
357 if(flag & UI_ID_PREVIEWS) {
359 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6,
360 TIP_(template_id_browse_tip(type)));
362 but->icon= RNA_struct_ui_icon(type);
363 if (id) but->icon = ui_id_icon_get(C, id, 1);
364 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_PREVIEW);
366 if((idfrom && idfrom->lib) || !editable)
367 uiButSetFlag(but, UI_BUT_DISABLED);
369 uiLayoutRow(layout, 1);
371 else if(flag & UI_ID_BROWSE) {
372 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y,
373 TIP_(template_id_browse_tip(type)));
375 but->icon= RNA_struct_ui_icon(type);
376 /* default dragging of icon for id browse buttons */
377 uiButSetDragID(but, id);
378 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_LEFT);
381 if((idfrom && idfrom->lib) || !editable)
382 uiButSetFlag(but, UI_BUT_DISABLED);
385 /* text button with name */
387 char name[UI_MAX_NAME_STR];
388 const short user_alert= (id->us <= 0);
390 //text_idbutton(id, name);
392 but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
393 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
394 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
397 if(id->flag & LIB_INDIRECT) {
398 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0,
399 TIP_("Indirect library datablock, cannot change"));
400 uiButSetFlag(but, UI_BUT_DISABLED);
403 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0,
404 TIP_("Direct linked library datablock, click to make local"));
405 if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib))
406 uiButSetFlag(but, UI_BUT_DISABLED);
409 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
415 BLI_snprintf(str, sizeof(str), "%d", id->us);
417 but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X + ((id->us < 10) ? 0:10), UI_UNIT_Y, NULL, 0, 0, 0, 0,
418 TIP_("Display number of users of this data (click to make a single-user copy)"));
420 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
421 if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib) || !editable)
422 uiButSetFlag(but, UI_BUT_DISABLED);
425 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
427 if(id->lib == NULL && !(ELEM5(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
428 uiDefButR(block, TOG, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
432 if(flag & UI_ID_ADD_NEW) {
433 int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
436 but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, (id)? "": IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL);
437 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
440 but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
441 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
444 if((idfrom && idfrom->lib) || !editable)
445 uiButSetFlag(but, UI_BUT_DISABLED);
448 if(flag & UI_ID_OPEN) {
449 int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
452 but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id)? "": IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL);
453 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
456 but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
457 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
460 if((idfrom && idfrom->lib) || !editable)
461 uiButSetFlag(but, UI_BUT_DISABLED);
465 if(id && (flag & UI_ID_DELETE) && (RNA_property_flag(template->prop) & PROP_NEVER_UNLINK)==0) {
467 but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
468 /* so we can access the template from operators, font unlinking needs this */
469 uiButSetNFunc(but, NULL, MEM_dupallocN(template), NULL);
472 but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
473 TIP_("Unlink datablock. Shift + Click to set users to zero, data will then not be saved"));
474 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
476 if(RNA_property_flag(template->prop) & PROP_NEVER_NULL)
477 uiButSetFlag(but, UI_BUT_DISABLED);
480 if((idfrom && idfrom->lib) || !editable)
481 uiButSetFlag(but, UI_BUT_DISABLED);
485 uiTemplateTextureShow(layout, C, &template->ptr, template->prop);
487 uiBlockEndAlign(block);
490 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)
492 TemplateID *template;
497 prop= RNA_struct_find_property(ptr, propname);
499 if(!prop || RNA_property_type(prop) != PROP_POINTER) {
500 RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
504 template= MEM_callocN(sizeof(TemplateID), "TemplateID");
506 template->prop= prop;
507 template->prv_rows = prv_rows;
508 template->prv_cols = prv_cols;
511 flag |= UI_ID_ADD_NEW;
515 type= RNA_property_pointer_type(ptr, prop);
516 idcode= RNA_type_to_ID_code(type);
517 template->idlb= which_libbase(CTX_data_main(C), idcode);
519 /* create UI elements for this template
520 * - template_ID makes a copy of the template data and assigns it to the relevant buttons
523 uiLayoutRow(layout, 1);
524 template_ID(C, layout, template, type, idcode, flag, newop, openop, unlinkop);
530 void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
532 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE, 0, 0);
535 void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
537 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME, 0, 0);
540 void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols)
542 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE|UI_ID_PREVIEWS, rows, cols);
545 /************************ ID Chooser Template ***************************/
547 /* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use
549 * - propname: property identifier for property that ID-pointer gets stored to
550 * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used
552 void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *text)
554 PropertyRNA *propID, *propType;
557 /* get properties... */
558 propID= RNA_struct_find_property(ptr, propname);
559 propType= RNA_struct_find_property(ptr, proptypename);
561 if (!propID || RNA_property_type(propID) != PROP_POINTER) {
562 RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
565 if (!propType || RNA_property_type(propType) != PROP_ENUM) {
566 RNA_warning("pointer-type property not found: %s.%s", RNA_struct_identifier(ptr->type), proptypename);
570 /* Start drawing UI Elements using standard defines */
571 row= uiLayoutRow(layout, 1);
573 /* Label - either use the provided text, or will become "ID-Block:" */
575 uiItemL(row, text, ICON_NONE);
577 uiItemL(row, "ID-Block:", ICON_NONE);
579 /* ID-Type Selector - just have a menu of icons */
580 // FIXME: the icon-only setting doesn't work when we supply a blank name
581 uiItemFullR(row, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
583 /* ID-Block Selector - just use pointer widget... */
584 uiItemFullR(row, ptr, propID, 0, 0, 0, "", ICON_NONE);
587 /********************* RNA Path Builder Template ********************/
591 /* This is creating/editing RNA-Paths
593 * - ptr: struct which holds the path property
594 * - propname: property identifier for property that path gets stored to
595 * - root_ptr: struct that path gets built from
597 void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), const char *text)
599 PropertyRNA *propPath;
602 /* check that properties are valid */
603 propPath= RNA_struct_find_property(ptr, propname);
604 if (!propPath || RNA_property_type(propPath) != PROP_STRING) {
605 RNA_warning("path property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
609 /* Start drawing UI Elements using standard defines */
610 row= uiLayoutRow(layout, 1);
612 /* Path (existing string) Widget */
613 uiItemR(row, ptr, propname, 0, text, ICON_RNA);
615 // TODO: attach something to this to make allow searching of nested properties to 'build' the path
618 /************************ Modifier Template *************************/
620 #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
624 #include "DNA_object_force.h"
626 #include "BKE_depsgraph.h"
627 #include "BKE_modifier.h"
628 #include "BKE_particle.h"
632 #include "BLI_math.h"
633 #include "BLI_listbase.h"
635 #include "ED_object.h"
637 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
639 Scene *scene = CTX_data_scene(C);
641 ModifierData *md= md_v;
642 int i, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 0);
644 /* undo button operation */
645 md->mode ^= eModifierMode_OnCage;
647 for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) {
650 md->mode ^= eModifierMode_OnCage;
655 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
656 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
659 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
662 ModifierData *md = md_v;
663 ModifierData *nmd = modifier_new(md->type);
665 modifier_copyData(md, nmd);
666 nmd->mode &= ~eModifierMode_Virtual;
668 BLI_addhead(&ob->modifiers, nmd);
670 modifier_unique_name(&ob->modifiers, nmd);
672 ob->partype = PAROBJECT;
674 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
675 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
677 ED_undo_push(C, "Modifier convert to real");
680 static int modifier_can_delete(ModifierData *md)
682 // fluid particle modifier can't be deleted here
683 if(md->type == eModifierType_ParticleSystem)
684 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
690 // Check wheter Modifier is a simulation or not, this is used for switching to the physics/particles context tab
691 static int modifier_is_simulation(ModifierData *md)
694 if(ELEM6(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke, eModifierType_Softbody, eModifierType_Surface)) {
698 else if (md->type == eModifierType_ParticleSystem) {
706 static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, ModifierData *md, int index, int cageIndex, int lastCageIndex)
708 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
712 uiLayout *box, *column, *row;
713 uiLayout *result= NULL;
714 int isVirtual = (md->mode & eModifierMode_Virtual);
717 /* create RNA pointer */
718 RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
720 column= uiLayoutColumn(layout, 1);
721 uiLayoutSetContextPointer(column, "modifier", &ptr);
723 /* rounded header ------------------------------------------------------------------- */
724 box= uiLayoutBox(column);
727 row= uiLayoutRow(box, 0);
728 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
729 block= uiLayoutGetBlock(row);
730 /* VIRTUAL MODIFIER */
731 // XXX this is not used now, since these cannot be accessed via RNA
732 BLI_snprintf(str, sizeof(str), "%s parent deform", md->name);
733 uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name");
735 but = uiDefBut(block, BUT, 0, IFACE_("Make Real"), 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0,
736 TIP_("Convert virtual modifier to a real modifier"));
737 uiButSetFunc(but, modifiers_convertToReal, ob, md);
741 row = uiLayoutRow(box, 0);
742 block = uiLayoutGetBlock(row);
744 uiBlockSetEmboss(block, UI_EMBOSSN);
745 /* Open/Close ................................. */
746 uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
748 /* modifier-type icon */
749 uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
750 uiBlockSetEmboss(block, UI_EMBOSS);
753 uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
755 /* mode enabling buttons */
756 uiBlockBeginAlign(block);
757 /* Softbody not allowed in this situation, enforce! */
758 if ( ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect))
759 && (md->type!=eModifierType_Surface) )
761 uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
762 uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
764 if (mti->flags & eModifierTypeFlag_SupportsEditmode)
765 uiItemR(row, &ptr, "show_in_editmode", 0, "", ICON_NONE);
768 if (ob->type==OB_MESH) {
769 if (modifier_couldBeCage(scene, md) && (index <= lastCageIndex))
771 /* -- convert to rna ? */
772 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,
773 TIP_("Apply modifier to editing cage during Editmode"));
774 if (index < cageIndex)
775 uiButSetFlag(but, UI_BUT_DISABLED);
776 uiButSetFunc(but, modifiers_setOnCage, ob, md);
779 uiBlockEndAlign(block);
781 /* place holder button */
782 uiBlockSetEmboss(block, UI_EMBOSSN);
783 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);
784 uiButSetFlag(but, UI_BUT_DISABLED);
785 uiBlockSetEmboss(block, UI_EMBOSS);
787 } /* tesselation point for curve-typed objects */
788 else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
789 /* some modifiers could work with pre-tesselated curves only */
790 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
791 /* add disabled pre-tesselated button, so users could have
792 message for this modifiers */
793 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,
794 TIP_("This modifier could be applied on splines' points only"));
795 uiButSetFlag(but, UI_BUT_DISABLED);
796 } else if (mti->type != eModifierTypeType_Constructive) {
797 /* constructive modifiers tesselates curve before applying */
798 uiItemR(row, &ptr, "use_apply_on_spline", 0, "", ICON_NONE);
802 uiBlockEndAlign(block);
804 /* Up/Down + Delete ........................... */
805 uiBlockBeginAlign(block);
806 uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up");
807 uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down");
808 uiBlockEndAlign(block);
810 uiBlockSetEmboss(block, UI_EMBOSSN);
811 // When Modifier is a simulation, show button to switch to context rather than the delete button.
812 if (modifier_can_delete(md) && !modifier_is_simulation(md))
813 uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
814 if (modifier_is_simulation(md) == 1)
815 uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PHYSICS");
816 else if (modifier_is_simulation(md) == 2)
817 uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PARTICLES");
818 uiBlockSetEmboss(block, UI_EMBOSS);
822 /* modifier settings (under the header) --------------------------------------------------- */
823 if (!isVirtual && (md->mode & eModifierMode_Expanded)) {
824 /* apply/convert/copy */
825 box= uiLayoutBox(column);
826 row= uiLayoutRow(box, 0);
828 if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) {
829 /* only here obdata, the rest of modifiers is ob level */
830 uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
832 if (md->type==eModifierType_ParticleSystem) {
833 ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
835 if (!(ob->mode & OB_MODE_PARTICLE_EDIT) && psys->pathcache) {
836 if(ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB))
837 uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_duplicates_make_real");
838 else if(psys->part->ren_as == PART_DRAW_PATH)
839 uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_modifier_convert");
843 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
844 uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply"), 0, "apply_as", MODIFIER_APPLY_DATA);
846 if (modifier_sameTopology(md))
847 uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape"), 0, "apply_as", MODIFIER_APPLY_SHAPE);
850 uiBlockClearButLock(block);
851 uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
853 if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke))
854 uiItemO(row, TIP_("Copy"), ICON_NONE, "OBJECT_OT_modifier_copy");
857 /* result is the layout block inside the box, that we return so that modifier settings can be drawn */
858 result= uiLayoutColumn(box, 0);
859 block= uiLayoutAbsoluteBlock(box);
864 box = uiLayoutBox(column);
865 row = uiLayoutRow(box, 0);
866 uiItemL(row, md->error, ICON_ERROR);
872 uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
874 Scene *scene = CTX_data_scene(C);
876 ModifierData *md, *vmd;
877 int i, lastCageIndex, cageIndex;
879 /* verify we have valid data */
880 if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
881 RNA_warning("Expected modifier on object");
888 if(!ob || !(GS(ob->id.name) == ID_OB)) {
889 RNA_warning("Expected modifier on object");
893 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
895 /* find modifier and draw it */
896 cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
898 // XXX virtual modifiers are not accesible for python
899 vmd = modifiers_getVirtualModifierList(ob);
901 for(i=0; vmd; i++, vmd=vmd->next) {
903 return draw_modifier(layout, scene, ob, md, i, cageIndex, lastCageIndex);
904 else if(vmd->mode & eModifierMode_Virtual)
911 /************************ Constraint Template *************************/
913 #include "DNA_constraint_types.h"
915 #include "BKE_action.h"
916 #include "BKE_constraint.h"
920 #define REDRAWBUTSOBJECT 3
921 #define REDRAWACTION 4
922 #define B_CONSTRAINT_TEST 5
923 #define B_CONSTRAINT_CHANGETARGET 6
927 static void do_constraint_panels(bContext *C, void *ob_pt, int event)
929 Main *bmain= CTX_data_main(C);
930 Scene *scene= CTX_data_scene(C);
931 Object *ob= (Object *)ob_pt;
934 case B_CONSTRAINT_TEST:
935 break; // no handling
936 case B_CONSTRAINT_CHANGETARGET:
937 if (ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels
938 DAG_scene_sort(bmain, scene);
944 // note: RNA updates now call this, commenting else it gets called twice.
945 // if there are problems because of this, then rna needs changed update functions.
947 // object_test_constraints(ob);
948 // if(ob->pose) update_pose_constraint_flags(ob->pose);
950 if(ob->type==OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB);
951 else DAG_id_tag_update(&ob->id, OB_RECALC_OB);
953 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
956 static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
958 ED_object_constraint_set_active(ob_v, con_v);
961 /* draw panel showing settings for a constraint */
962 static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
964 bPoseChannel *pchan= get_active_posechannel(ob);
965 bConstraintTypeInfo *cti;
967 uiLayout *result= NULL, *col, *box, *row;
970 short proxy_protected, xco=0, yco=0;
971 // int rb_col; // UNUSED
973 /* get constraint typeinfo */
974 cti= constraint_get_typeinfo(con);
976 /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
977 BLI_strncpy(typestr, (con->type == CONSTRAINT_TYPE_NULL) ? "Null" : "Unknown", sizeof(typestr));
980 BLI_strncpy(typestr, cti->name, sizeof(typestr));
982 /* determine whether constraint is proxy protected or not */
983 if (proxylocked_constraints_owner(ob, pchan))
984 proxy_protected= (con->flag & CONSTRAINT_PROXY_LOCAL)==0;
988 /* unless button has own callback, it adds this callback to button */
989 block= uiLayoutGetBlock(layout);
990 uiBlockSetHandleFunc(block, do_constraint_panels, ob);
991 uiBlockSetFunc(block, constraint_active_func, ob, con);
993 RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
995 col= uiLayoutColumn(layout, 1);
996 uiLayoutSetContextPointer(col, "constraint", &ptr);
998 box= uiLayoutBox(col);
999 row = uiLayoutRow(box, 0);
1000 block= uiLayoutGetBlock(box);
1002 /* Draw constraint header */
1005 uiBlockSetEmboss(block, UI_EMBOSSN);
1006 uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
1007 uiBlockSetEmboss(block, UI_EMBOSS);
1010 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
1012 if (con->flag & CONSTRAINT_DISABLE)
1013 uiLayoutSetRedAlert(row, 1);
1015 if(proxy_protected == 0) {
1016 uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
1019 uiItemL(row, con->name, ICON_NONE);
1021 uiLayoutSetRedAlert(row, 0);
1023 /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
1024 if (proxy_protected) {
1025 uiBlockSetEmboss(block, UI_EMBOSSN);
1027 /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */
1028 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"));
1029 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"));
1031 uiBlockSetEmboss(block, UI_EMBOSS);
1034 short prev_proxylock, show_upbut, show_downbut;
1037 * Proxy-constraints are not allowed to occur after local (non-proxy) constraints
1038 * as that poses problems when restoring them, so disable the "up" button where
1039 * it may cause this situation.
1041 * Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose.
1043 if (proxylocked_constraints_owner(ob, pchan)) {
1045 prev_proxylock= (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
1053 show_upbut= ((prev_proxylock == 0) && (con->prev));
1054 show_downbut= (con->next) ? 1 : 0;
1057 uiBlockSetEmboss(block, UI_EMBOSSN);
1058 uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF);
1059 uiBlockSetEmboss(block, UI_EMBOSS);
1061 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
1064 if (show_upbut || show_downbut) {
1065 uiBlockBeginAlign(block);
1067 uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up");
1070 uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down");
1071 uiBlockEndAlign(block);
1074 /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
1075 uiBlockSetEmboss(block, UI_EMBOSSN);
1076 uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete");
1077 uiBlockSetEmboss(block, UI_EMBOSS);
1080 /* Set but-locks for protected settings (magic numbers are used here!) */
1081 if (proxy_protected)
1082 uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint");
1084 /* Draw constraint data */
1085 if ((con->flag & CONSTRAINT_EXPAND) == 0) {
1089 box= uiLayoutBox(col);
1090 block= uiLayoutAbsoluteBlock(box);
1094 /* clear any locks set up for proxies/lib-linking */
1095 uiBlockClearButLock(block);
1100 uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
1105 /* verify we have valid data */
1106 if(!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
1107 RNA_warning("Expected constraint on object");
1114 if(!ob || !(GS(ob->id.name) == ID_OB)) {
1115 RNA_warning("Expected constraint on object");
1119 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
1121 /* hrms, the temporal constraint should not draw! */
1122 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
1123 bKinematicConstraint *data= con->data;
1124 if(data->flag & CONSTRAINT_IK_TEMP)
1128 return draw_constraint(layout, ob, con);
1132 /************************* Preview Template ***************************/
1134 #include "DNA_lamp_types.h"
1135 #include "DNA_material_types.h"
1136 #include "DNA_world_types.h"
1140 static void do_preview_buttons(bContext *C, void *arg, int event)
1144 WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, arg);
1149 void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, MTex *slot)
1151 uiLayout *row, *col;
1154 Tex *tex = (Tex*)id;
1156 short *pr_texture= NULL;
1157 PointerRNA material_ptr;
1158 PointerRNA texture_ptr;
1160 if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
1161 RNA_warning("Expected ID of type material, texture, lamp or world");
1165 /* decide what to render */
1169 if(id && (GS(id->name) == ID_TE)) {
1170 if(parent && (GS(parent->name) == ID_MA))
1171 pr_texture= &((Material*)parent)->pr_texture;
1172 else if(parent && (GS(parent->name) == ID_WO))
1173 pr_texture= &((World*)parent)->pr_texture;
1174 else if(parent && (GS(parent->name) == ID_LA))
1175 pr_texture= &((Lamp*)parent)->pr_texture;
1178 if(*pr_texture == TEX_PR_OTHER)
1180 else if(*pr_texture == TEX_PR_BOTH)
1186 block= uiLayoutGetBlock(layout);
1187 row= uiLayoutRow(layout, 0);
1188 col= uiLayoutColumn(row, 0);
1189 uiLayoutSetKeepAspect(col, 1);
1192 uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, pid, 0.0, 0.0, 0, 0, "");
1193 uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot);
1194 uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
1197 if (pid && show_buttons) {
1198 if(GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
1199 if(GS(pid->name) == ID_MA) ma= (Material*)pid;
1200 else ma= (Material*)pparent;
1202 /* Create RNA Pointer */
1203 RNA_pointer_create(id, &RNA_Material, ma, &material_ptr);
1205 col = uiLayoutColumn(row, 1);
1206 uiLayoutSetScaleX(col, 1.5);
1207 uiItemR(col, &material_ptr, "preview_render_type", UI_ITEM_R_EXPAND, "", ICON_NONE);
1211 /* Create RNA Pointer */
1212 RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr);
1214 uiLayoutRow(layout, 1);
1215 uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
1216 if(GS(parent->name) == ID_MA)
1217 uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1218 else if(GS(parent->name) == ID_LA)
1219 uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1220 else if(GS(parent->name) == ID_WO)
1221 uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1222 uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
1224 /* Alpha buton for texture preview */
1225 if(*pr_texture!=TEX_PR_OTHER) {
1226 row = uiLayoutRow(layout, 0);
1227 uiItemR(row, &texture_ptr, "use_preview_alpha", 0, NULL, ICON_NONE);
1233 /********************** ColorRamp Template **************************/
1236 typedef struct RNAUpdateCb {
1241 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
1243 RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
1245 /* we call update here on the pointer property, this way the
1246 owner of the curve mapping can still define it's own update
1247 and notifier, even if the CurveMapping struct is shared. */
1248 RNA_property_update(C, &cb->ptr, cb->prop);
1253 static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
1255 ColorBand *coba= coba_v;
1259 if(coba->cur > 0) pos= (coba->data[coba->cur-1].pos + coba->data[coba->cur].pos) * 0.5f;
1260 else pos= (coba->data[coba->cur+1].pos + coba->data[coba->cur].pos) * 0.5f;
1263 if(colorband_element_add(coba, pos)) {
1264 rna_update_cb(C, cb_v, NULL);
1265 ED_undo_push(C, "Add colorband");
1269 static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v)
1271 ColorBand *coba= coba_v;
1273 if(colorband_element_remove(coba, coba->cur)) {
1274 ED_undo_push(C, "Delete colorband");
1275 rna_update_cb(C, cb_v, NULL);
1279 static void colorband_flip_cb(bContext *C, void *cb_v, void *coba_v)
1281 CBData data_tmp[MAXCOLORBAND];
1283 ColorBand *coba= coba_v;
1286 for(a=0; a<coba->tot; a++) {
1287 data_tmp[a]= coba->data[coba->tot - (a + 1)];
1289 for(a=0; a<coba->tot; a++) {
1290 data_tmp[a].pos = 1.0f - data_tmp[a].pos;
1291 coba->data[a]= data_tmp[a];
1294 /* may as well flip the cur*/
1295 coba->cur= coba->tot - (coba->cur + 1);
1297 ED_undo_push(C, "Flip colorband");
1299 rna_update_cb(C, cb_v, NULL);
1303 /* offset aligns from bottom, standard width 300, height 115 */
1304 static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb)
1308 const int line1_y= yoffs + 65 + UI_UNIT_Y + 2; /* 2 for some space between the buttons */
1309 const int line2_y= yoffs + 65;
1311 if(coba==NULL) return;
1313 bt= uiDefBut(block, BUT, 0, IFACE_("Add"), 0+xoffs,line1_y,40,UI_UNIT_Y, NULL, 0, 0, 0, 0,
1314 TIP_("Add a new color stop to the colorband"));
1315 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1317 bt= uiDefBut(block, BUT, 0, IFACE_("Delete"), 45+xoffs,line1_y,45,UI_UNIT_Y, NULL, 0, 0, 0, 0,
1318 TIP_("Delete the active position"));
1319 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1322 /* XXX, todo for later - convert to operator - campbell */
1323 bt= uiDefBut(block, BUT, 0, "F", 95+xoffs,line1_y,20,UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip colorband"));
1324 uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
1326 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"));
1328 bt= uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"),
1329 210+xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops"));
1330 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1331 uiBlockEndAlign(block);
1333 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xoffs,line2_y,300,UI_UNIT_Y, coba, 0, 0, 0, 0, "");
1334 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1339 CBData *cbd= coba->data + coba->cur;
1341 /* better to use rna so we can animate them */
1343 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1344 row= uiLayoutRow(layout, 0);
1345 uiItemR(row, &ptr, "position", 0, "Pos", ICON_NONE);
1346 uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
1351 static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
1354 float unit= (butr->xmax-butr->xmin)/14.0f;
1355 float xs= butr->xmin;
1357 uiBlockBeginAlign(block);
1358 bt= uiDefBut(block, BUT, 0, IFACE_("Add"), xs,butr->ymin+UI_UNIT_Y,2.0f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0,
1359 TIP_("Add a new color stop to the colorband"));
1360 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1361 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,
1362 TIP_("Delete the active position"));
1363 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1364 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"));
1365 uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
1366 uiBlockEndAlign(block);
1369 CBData *cbd= coba->data + coba->cur;
1371 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1372 uiItemR(layout, &ptr, "color", 0, "", ICON_NONE);
1375 bt= uiDefButS(block, MENU, 0, TIP_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"),
1376 xs+10.0f*unit, butr->ymin+UI_UNIT_Y, unit*4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0,
1377 TIP_("Set interpolation between color stops"));
1378 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1380 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xs,butr->ymin,butr->xmax-butr->xmin,UI_UNIT_Y, coba, 0, 0, 0, 0, "");
1381 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1383 uiBlockEndAlign(block);
1386 static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb)
1389 colorband_buttons_small(layout, block, coba, butr, cb);
1391 colorband_buttons_large(layout, block, coba, 0, 0, cb);
1394 void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname, int expand)
1396 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1402 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1405 cptr= RNA_property_pointer_get(ptr, prop);
1406 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp))
1409 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1413 rect.xmin= 0; rect.xmax= 200;
1414 rect.ymin= 0; rect.ymax= 190;
1416 block= uiLayoutAbsoluteBlock(layout);
1417 colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1422 /********************* Histogram Template ************************/
1424 void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname)
1426 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1434 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1437 cptr= RNA_property_pointer_get(ptr, prop);
1438 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram))
1441 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1445 rect.xmin= 0; rect.xmax= 200;
1446 rect.ymin= 0; rect.ymax= 190;
1448 block= uiLayoutAbsoluteBlock(layout);
1449 //colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1451 hist = (Histogram *)cptr.data;
1453 hist->height= (hist->height<=UI_UNIT_Y)?UI_UNIT_Y:hist->height;
1455 bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, hist->height, hist, 0, 0, 0, 0, "");
1456 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1461 /********************* Waveform Template ************************/
1463 void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname)
1465 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1473 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1476 cptr= RNA_property_pointer_get(ptr, prop);
1477 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
1479 scopes = (Scopes *)cptr.data;
1481 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1485 rect.xmin= 0; rect.xmax= 200;
1486 rect.ymin= 0; rect.ymax= 190;
1488 block= uiLayoutAbsoluteBlock(layout);
1490 scopes->wavefrm_height= (scopes->wavefrm_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->wavefrm_height;
1492 bt= uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
1498 /********************* Vectorscope Template ************************/
1500 void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propname)
1502 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1510 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1513 cptr= RNA_property_pointer_get(ptr, prop);
1514 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
1516 scopes = (Scopes *)cptr.data;
1518 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1522 rect.xmin= 0; rect.xmax= 200;
1523 rect.ymin= 0; rect.ymax= 190;
1525 block= uiLayoutAbsoluteBlock(layout);
1527 scopes->vecscope_height= (scopes->vecscope_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->vecscope_height;
1529 bt= uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
1530 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1535 /********************* CurveMapping Template ************************/
1538 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *UNUSED(arg))
1540 CurveMapping *cumap = cumap_v;
1543 /* we allow 20 times zoom */
1544 if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1545 d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
1546 cumap->curr.xmin+= d;
1547 cumap->curr.xmax-= d;
1548 d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
1549 cumap->curr.ymin+= d;
1550 cumap->curr.ymax-= d;
1553 ED_region_tag_redraw(CTX_wm_region(C));
1556 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(unused))
1558 CurveMapping *cumap = cumap_v;
1561 /* we allow 20 times zoom, but dont view outside clip */
1562 if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1563 d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
1565 if(cumap->flag & CUMA_DO_CLIP)
1566 if(cumap->curr.xmin-d < cumap->clipr.xmin)
1567 d1= cumap->curr.xmin - cumap->clipr.xmin;
1568 cumap->curr.xmin-= d1;
1571 if(cumap->flag & CUMA_DO_CLIP)
1572 if(cumap->curr.xmax+d > cumap->clipr.xmax)
1573 d1= -cumap->curr.xmax + cumap->clipr.xmax;
1574 cumap->curr.xmax+= d1;
1576 d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
1578 if(cumap->flag & CUMA_DO_CLIP)
1579 if(cumap->curr.ymin-d < cumap->clipr.ymin)
1580 d1= cumap->curr.ymin - cumap->clipr.ymin;
1581 cumap->curr.ymin-= d1;
1584 if(cumap->flag & CUMA_DO_CLIP)
1585 if(cumap->curr.ymax+d > cumap->clipr.ymax)
1586 d1= -cumap->curr.ymax + cumap->clipr.ymax;
1587 cumap->curr.ymax+= d1;
1590 ED_region_tag_redraw(CTX_wm_region(C));
1593 static void curvemap_buttons_setclip(bContext *UNUSED(C), void *cumap_v, void *UNUSED(arg))
1595 CurveMapping *cumap = cumap_v;
1597 curvemapping_changed(cumap, 0);
1600 static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
1602 CurveMapping *cumap = cumap_v;
1604 curvemap_remove(cumap->cm+cumap->cur, SELECT);
1605 curvemapping_changed(cumap, 0);
1607 rna_update_cb(C, cb_v, NULL);
1610 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
1611 static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v)
1613 CurveMapping *cumap = cumap_v;
1616 float width= 8*UI_UNIT_X;
1618 block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS);
1620 /* use this for a fake extra empy space around the buttons */
1621 uiDefBut(block, LABEL, 0, "", -4, 16, width+8, 6*UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
1623 bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",
1624 0,5*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->flag, 0.0, 0.0, 10, 0, "");
1625 uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
1627 uiBlockBeginAlign(block);
1628 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, "");
1629 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, "");
1630 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, "");
1631 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, "");
1633 uiBlockSetDirection(block, UI_RIGHT);
1635 uiEndBlock(C, block);
1639 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
1641 CurveMapping *cumap = cumap_v;
1642 CurveMap *cuma= cumap->cm+cumap->cur;
1646 curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
1647 curvemapping_changed(cumap, 0);
1650 cumap->curr= cumap->clipr;
1652 case 2: /* set vector */
1653 curvemap_sethandle(cuma, 1);
1654 curvemapping_changed(cumap, 0);
1656 case 3: /* set auto */
1657 curvemap_sethandle(cuma, 0);
1658 curvemapping_changed(cumap, 0);
1660 case 4: /* extend horiz */
1661 cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
1662 curvemapping_changed(cumap, 0);
1664 case 5: /* extend extrapolate */
1665 cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
1666 curvemapping_changed(cumap, 0);
1669 ED_region_tag_redraw(CTX_wm_region(C));
1672 static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1675 short yco= 0, menuwidth=10*UI_UNIT_X;
1677 block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1678 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1680 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, "");
1681 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, "");
1682 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, "");
1683 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, "");
1684 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, "");
1685 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, "");
1687 uiBlockSetDirection(block, UI_RIGHT);
1688 uiTextBoundsBlock(block, 50);
1690 uiEndBlock(C, block);
1694 static uiBlock *curvemap_brush_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1697 short yco= 0, menuwidth=10*UI_UNIT_X;
1699 block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1700 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1702 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, "");
1703 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, "");
1704 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, "");
1705 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, "");
1707 uiBlockSetDirection(block, UI_RIGHT);
1708 uiTextBoundsBlock(block, 50);
1710 uiEndBlock(C, block);
1714 static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
1716 ED_region_tag_redraw(CTX_wm_region(C));
1719 static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
1721 CurveMapping *cumap = cumap_v;
1724 cumap->preset = CURVE_PRESET_LINE;
1725 for(a=0; a<CM_TOT; a++)
1726 curvemap_reset(cumap->cm+a, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
1728 cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
1729 cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
1730 curvemapping_set_black_white(cumap, NULL, NULL);
1732 curvemapping_changed(cumap, 0);
1734 rna_update_cb(C, cb_v, NULL);
1737 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
1738 static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb)
1740 CurveMapping *cumap= ptr->data;
1741 uiLayout *row, *sub, *split;
1744 float dx= UI_UNIT_X;
1748 block= uiLayoutGetBlock(layout);
1751 row= uiLayoutRow(layout, 0);
1753 if(labeltype=='v') {
1755 sub= uiLayoutRow(row, 1);
1756 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1758 if(cumap->cm[0].curve) {
1759 bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1760 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1762 if(cumap->cm[1].curve) {
1763 bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1764 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1766 if(cumap->cm[2].curve) {
1767 bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1768 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1771 else if(labeltype=='c') {
1773 sub= uiLayoutRow(row, 1);
1774 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1776 if(cumap->cm[3].curve) {
1777 bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, dx, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
1778 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1780 if(cumap->cm[0].curve) {
1781 bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1782 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1784 if(cumap->cm[1].curve) {
1785 bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1786 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1788 if(cumap->cm[2].curve) {
1789 bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1790 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1793 else if (labeltype == 'h') {
1795 sub= uiLayoutRow(row, 1);
1796 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1798 if(cumap->cm[0].curve) {
1799 bt= uiDefButI(block, ROW, 0, "H", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1800 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1802 if(cumap->cm[1].curve) {
1803 bt= uiDefButI(block, ROW, 0, "S", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1804 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1806 if(cumap->cm[2].curve) {
1807 bt= uiDefButI(block, ROW, 0, "V", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1808 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1812 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
1817 /* operation buttons */
1818 sub= uiLayoutRow(row, 1);
1820 uiBlockSetEmboss(block, UI_EMBOSSN);
1822 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom in"));
1823 uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
1825 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom out"));
1826 uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
1829 bt= uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, TIP_("Tools"));
1831 bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, TIP_("Tools"));
1833 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1835 if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
1836 bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, TIP_("Clipping Options"));
1837 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1839 bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete points"));
1840 uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
1842 uiBlockSetEmboss(block, UI_EMBOSS);
1844 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
1847 size= uiLayoutGetWidth(layout);
1848 row= uiLayoutRow(layout, 0);
1849 uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, bg, 0, "");
1851 /* black/white levels */
1853 split= uiLayoutSplit(layout, 0, 0);
1854 uiItemR(uiLayoutColumn(split, 0), ptr, "black_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1855 uiItemR(uiLayoutColumn(split, 0), ptr, "white_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1857 uiLayoutRow(layout, 0);
1858 bt=uiDefBut(block, BUT, 0, IFACE_("Reset"), 0, 0, UI_UNIT_X*10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
1859 TIP_("Reset Black/White point and curves"));
1860 uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
1863 uiBlockSetNFunc(block, NULL, NULL, NULL);
1866 void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, int levels, int brush)
1869 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1873 RNA_warning("curve property not found: %s.%s",
1874 RNA_struct_identifier(ptr->type), propname);
1878 if(RNA_property_type(prop) != PROP_POINTER) {
1879 RNA_warning("curve is not a pointer: %s.%s",
1880 RNA_struct_identifier(ptr->type), propname);
1884 cptr= RNA_property_pointer_get(ptr, prop);
1885 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping))
1888 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1892 curvemap_buttons_layout(layout, &cptr, type, levels, brush, cb);
1897 /********************* ColorWheel Template ************************/
1899 #define WHEEL_SIZE 100
1901 void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic)
1903 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1904 uiBlock *block= uiLayoutGetBlock(layout);
1905 uiLayout *col, *row;
1907 float softmin, softmax, step, precision;
1910 RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
1914 RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
1916 col = uiLayoutColumn(layout, 0);
1917 row= uiLayoutRow(col, 1);
1919 but= uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, "");
1922 but->flag |= UI_BUT_COLOR_LOCK;
1925 if(lock_luminosity) {
1926 float color[4]; /* incase of alpha */
1927 but->flag |= UI_BUT_VEC_SIZE_LOCK;
1928 RNA_property_float_get_array(ptr, prop, color);
1929 but->a2= len_v3(color);
1933 but->flag |= UI_BUT_COLOR_CUBIC;
1938 uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
1941 /********************* Layer Buttons Template ************************/
1943 static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
1946 int cur = GET_INT_FROM_POINTER(arg2);
1947 wmWindow *win= CTX_wm_window(C);
1948 int i, tot, shift= win->eventstate->shift;
1951 tot= RNA_property_array_length(&but->rnapoin, but->rnaprop);
1953 /* Normally clicking only selects one layer */
1954 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, 1);
1955 for(i = 0; i < tot; ++i) {
1957 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, 0);
1961 /* view3d layer change should update depsgraph (invisible object changed maybe) */
1962 /* see view3d_header.c */
1966 // - for now, grouping of layers is determined by dividing up the length of
1967 // the array of layer bitflags
1969 void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname,
1970 PointerRNA *used_ptr, const char *used_propname, int active_layer)
1972 uiLayout *uRow, *uCol;
1973 PropertyRNA *prop, *used_prop= NULL;
1974 int groups, cols, layers;
1975 int group, col, layer, row;
1976 int cols_per_group = 5;
1978 prop= RNA_struct_find_property(ptr, propname);
1980 RNA_warning("layers property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
1984 /* the number of layers determines the way we group them
1985 * - we want 2 rows only (for now)
1986 * - the number of columns (cols) is the total number of buttons per row
1987 * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
1988 * - for now, only split into groups if group will have at least 5 items
1990 layers= RNA_property_array_length(ptr, prop);
1991 cols= (layers / 2) + (layers % 2);
1992 groups= ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
1994 if(used_ptr && used_propname) {
1995 used_prop= RNA_struct_find_property(used_ptr, used_propname);
1997 RNA_warning("used layers property not found: %s.%s", RNA_struct_identifier(ptr->type), used_propname);
2001 if(RNA_property_array_length(used_ptr, used_prop) < layers)
2005 /* layers are laid out going across rows, with the columns being divided into groups */
2007 for (group= 0; group < groups; group++) {
2008 uCol= uiLayoutColumn(layout, 1);
2010 for (row= 0; row < 2; row++) {
2014 uRow= uiLayoutRow(uCol, 1);
2015 block= uiLayoutGetBlock(uRow);
2016 layer= groups*cols_per_group*row + cols_per_group*group;
2018 /* add layers as toggle buts */
2019 for (col= 0; (col < cols_per_group) && (layer < layers); col++, layer++) {
2021 int butlay = 1 << layer;
2023 if(active_layer & butlay)
2024 icon = ICON_LAYER_ACTIVE;
2025 else if(used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer))
2026 icon = ICON_LAYER_USED;
2028 but= uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, UI_UNIT_X/2, UI_UNIT_Y/2);
2029 uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer));
2037 /************************* List Template **************************/
2039 static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big)
2047 /* try ID, material or texture slot */
2048 if(RNA_struct_is_ID(itemptr->type)) {
2049 id= itemptr->id.data;
2051 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
2052 id= RNA_pointer_get(itemptr, "material").data;
2054 else if(RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
2055 id= RNA_pointer_get(itemptr, "texture").data;
2058 /* get icon from ID */
2060 icon= ui_id_icon_get(C, id, big);
2069 static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop)
2071 uiBlock *block= uiLayoutGetBlock(layout);
2073 uiLayout *split, *overlap, *sub, *row;
2078 overlap= uiLayoutOverlap(layout);
2080 /* list item behind label & other buttons */
2081 sub= uiLayoutRow(overlap, 0);
2083 but= uiDefButR_prop(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, "");
2084 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2086 sub= uiLayoutRow(overlap, 0);
2088 /* retrieve icon and name */
2089 icon= list_item_icon_get(C, itemptr, rnaicon, 0);
2090 if(icon == ICON_NONE || icon == ICON_DOT)
2093 namebuf= RNA_struct_name_get_alloc(itemptr, NULL, 0, NULL);
2094 name= (namebuf)? namebuf: "";
2096 /* hardcoded types */
2097 if(itemptr->type == &RNA_MeshTextureFaceLayer || itemptr->type == &RNA_MeshColorLayer) {
2098 uiItemL(sub, name, icon);
2099 uiBlockSetEmboss(block, UI_EMBOSSN);
2100 uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
2101 uiBlockSetEmboss(block, UI_EMBOSS);
2103 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
2104 uiItemL(sub, name, icon);
2105 uiBlockSetEmboss(block, UI_EMBOSS);
2106 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
2108 else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
2109 uiItemL(sub, name, icon);
2110 uiBlockSetEmboss(block, UI_EMBOSS);
2111 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
2113 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
2114 /* provision to draw active node name */
2115 Material *ma, *manode;
2116 Object *ob= (Object*)ptr->id.data;
2117 int index= (Material**)itemptr->data - ob->mat;
2119 /* default item with material base name */
2120 uiItemL(sub, name, icon);
2122 ma= give_current_material(ob, index+1);
2124 manode= give_node_material(ma);
2126 char str[MAX_ID_NAME + 12];
2127 BLI_snprintf(str, sizeof(str), "Node %s", manode->id.name+2);
2128 uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1));
2130 else if(ma->use_nodes) {
2131 uiItemL(sub, "Node <none>", ICON_NONE);
2135 else if(itemptr->type == &RNA_ShapeKey) {
2136 Object *ob= (Object*)activeptr->data;
2137 Key *key= (Key*)itemptr->id.data;
2139 split= uiLayoutSplit(sub, 0.75f, 0);
2141 uiItemL(split, name, icon);
2143 uiBlockSetEmboss(block, UI_EMBOSSN);
2144 row= uiLayoutRow(split, 1);
2145 if(i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE);
2146 else uiItemR(row, itemptr, "value", 0, "", ICON_NONE);
2148 if(ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH))
2149 uiLayoutSetActive(row, 0);
2150 //uiItemR(row, itemptr, "mute", 0, "", ICON_MUTE_IPO_OFF);
2151 uiBlockSetEmboss(block, UI_EMBOSS);
2153 else if(itemptr->type == &RNA_VertexGroup) {
2154 bDeformGroup *dg= (bDeformGroup *)itemptr->data;
2155 uiItemL(sub, name, icon);
2156 /* RNA does not allow nice lock icons, use lower level buttons */
2158 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "lock_weight", 0, 0, 0, 0, 0, NULL);
2160 uiBlockSetEmboss(block, UI_EMBOSSN);
2161 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");
2162 uiBlockSetEmboss(block, UI_EMBOSS);
2165 else if(itemptr->type == &RNA_KeyingSetPath) {
2166 KS_Path *ksp = (KS_Path*)itemptr->data;
2168 /* icon needs to be the type of ID which is currently active */
2169 RNA_enum_icon_from_value(id_type_items, ksp->idtype, &icon);
2171 /* nothing else special to do... */
2172 uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
2175 uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
2182 void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, const char *activepropname, int rows, int maxrows, int listtype)
2184 //Scene *scene= CTX_data_scene(C);
2185 PropertyRNA *prop= NULL, *activeprop;
2186 PropertyType type, activetype;
2188 uiLayout *box, *row, *col;
2192 char *name, str[32];
2193 int rnaicon=0, icon=0, i= 0, activei= 0, len= 0, items, found, min, max;
2195 /* validate arguments */
2196 block= uiLayoutGetBlock(layout);
2200 RNA_warning("Only works inside a panel");
2204 if(!activeptr->data)
2208 prop= RNA_struct_find_property(ptr, propname);
2210 RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
2215 activeprop= RNA_struct_find_property(activeptr, activepropname);
2217 RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), activepropname);
2222 type= RNA_property_type(prop);
2223 if(type != PROP_COLLECTION) {
2224 RNA_warning("uiExpected collection property");
2229 activetype= RNA_property_type(activeprop);
2230 if(activetype != PROP_INT) {
2231 RNA_warning("Expected integer property");
2236 if(ptr->data && prop) {
2237 ptype= RNA_property_pointer_type(ptr, prop);
2238 rnaicon= RNA_struct_ui_icon(ptype);
2241 /* get active data */
2242 activei= RNA_property_int_get(activeptr, activeprop);
2244 if(listtype == 'i') {
2245 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2246 col= uiLayoutColumn(box, 1);
2247 row= uiLayoutRow(col, 0);
2249 if(ptr->data && prop) {
2250 /* create list items */
2251 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2254 row= uiLayoutRow(col, 0);
2256 icon= list_item_icon_get(C, &itemptr, rnaicon, 1);
2257 but= uiDefIconButR_prop(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, "");
2258 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2266 else if(listtype == 'c') {
2267 /* compact layout */
2269 row= uiLayoutRow(layout, 1);
2271 if(ptr->data && prop) {
2272 /* create list items */
2273 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2274 found= (activei == i);
2278 name= RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
2279 icon= list_item_icon_get(C, &itemptr, rnaicon, 0);
2280 uiItemL(row, (name)? name: "", icon);
2291 /* if not found, add in dummy button */
2293 uiItemL(row, "", ICON_NONE);
2295 /* next/prev button */
2296 BLI_snprintf(str, sizeof(str), "%d :", i);
2297 but= uiDefIconTextButR_prop(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activeprop, 0, 0, 0, 0, 0, "");
2299 uiButSetFlag(but, UI_BUT_DISABLED);
2307 if(pa->list_grip_size != 0)
2308 rows= pa->list_grip_size;
2311 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2312 row= uiLayoutRow(box, 0);
2313 col = uiLayoutColumn(row, 1);
2316 RNA_property_int_range(activeptr, activeprop, &min, &max);
2319 len= RNA_property_collection_length(ptr, prop);
2320 items= CLAMPIS(len, rows, MAX2(rows, maxrows));
2322 /* if list length changes and active is out of view, scroll to it */
2323 if(pa->list_last_len != len)
2324 if((activei < pa->list_scroll || activei >= pa->list_scroll+items))
2325 pa->list_scroll= activei;
2327 pa->list_scroll= MIN2(pa->list_scroll, len-items);
2328 pa->list_scroll= MAX2(pa->list_scroll, 0);
2329 pa->list_size= items;
2330 pa->list_last_len= len;
2332 if(ptr->data && prop) {
2333 /* create list items */
2334 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2335 if(i >= pa->list_scroll && i<pa->list_scroll+items)
2336 list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activeprop);
2343 /* add dummy buttons to fill space */
2344 while(i < pa->list_scroll+items) {
2345 if(i >= pa->list_scroll)
2346 uiItemL(col, "", ICON_NONE);
2352 col= uiLayoutColumn(row, 0);
2353 uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
2358 /************************* Operator Search Template **************************/
2360 static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
2362 wmOperatorType *ot= arg2;
2365 WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
2368 static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
2370 GHashIterator *iter= WM_operatortype_iter();
2372 for( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
2373 wmOperatorType *ot= BLI_ghashIterator_getValue(iter);
2375 if(BLI_strcasestr(ot->name, str)) {
2376 if(WM_operator_poll((bContext*)C, ot)) {
2378 int len= strlen(ot->name);
2380 /* display name for menu, can hold hotkey */
2381 BLI_strncpy(name, ot->name, 256);
2383 /* check for hotkey */
2385 if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
2389 if(0==uiSearchItemAdd(items, name, ot, 0))
2394 BLI_ghashIterator_free(iter);
2397 void uiTemplateOperatorSearch(uiLayout *layout)
2401 static char search[256]= "";
2403 block= uiLayoutGetBlock(layout);
2404 uiBlockSetCurLayout(block, layout);
2406 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, 0, 0, "");
2407 uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
2410 /************************* Running Jobs Template **************************/
2412 #define B_STOPRENDER 1
2413 #define B_STOPCAST 2
2414 #define B_STOPANIM 3
2415 #define B_STOPCOMPO 4
2418 static void do_running_jobs(bContext *C, void *UNUSED(arg), int event)
2425 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL);
2428 WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
2431 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
2434 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
2439 void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
2441 bScreen *screen= CTX_wm_screen(C);
2442 wmWindowManager *wm= CTX_wm_manager(C);
2443 ScrArea *sa= CTX_wm_area(C);
2448 block= uiLayoutGetBlock(layout);
2449 uiBlockSetCurLayout(block, layout);
2451 uiBlockSetHandleFunc(block, do_running_jobs, NULL);
2453 if(sa->spacetype==SPACE_NODE) {
2454 if(WM_jobs_test(wm, sa))
2456 handle_event= B_STOPCOMPO;
2457 } else if (sa->spacetype==SPACE_SEQ) {
2458 if(WM_jobs_test(wm, sa))
2460 handle_event = B_STOPSEQ;
2463 /* another scene can be rendering too, for example via compositor */
2464 for(scene= CTX_data_main(C)->scene.first; scene; scene= scene->id.next)
2465 if(WM_jobs_test(wm, scene))
2468 handle_event= B_STOPRENDER;
2474 ui_abs= uiLayoutAbsolute(layout, 0);
2475 (void)ui_abs; // UNUSED
2477 uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE,
2478 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"));
2479 uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner),
2480 UI_UNIT_X, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, TIP_("Progress"));
2482 uiLayoutRow(layout, 0);
2484 if(WM_jobs_test(wm, screen))
2485 uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
2486 TIP_("Stop screencast"));
2487 if(screen->animtimer)
2488 uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, TIP_("Anim Player"), 0,0,100,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
2489 TIP_("Stop animation playback"));
2492 /************************* Reports for Last Operator Template **************************/
2494 void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
2496 ReportList *reports = CTX_wm_reports(C);
2497 Report *report= BKE_reports_last_displayable(reports);
2498 ReportTimerInfo *rti;
2503 uiStyle *style= UI_GetStyle();
2507 /* if the report display has timed out, don't show */
2508 if (!reports->reporttimer) return;
2510 rti= (ReportTimerInfo *)reports->reporttimer->customdata;
2512 if (!rti || rti->widthfac==0.0f || !report) return;
2514 ui_abs= uiLayoutAbsolute(layout, 0);
2515 block= uiLayoutGetBlock(ui_abs);
2517 width = BLF_width(style->widget.uifont_id, report->message);
2518 width = MIN2(rti->widthfac*width, width);
2519 width = MAX2(width, 10);
2521 /* make a box around the report to make it stand out */
2522 uiBlockBeginAlign(block);
2523 but= uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X+10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2524 /* set the report's bg color in but->col - ROUNDBOX feature */
2525 but->col[0]= FTOCHAR(rti->col[0]);
2526 but->col[1]= FTOCHAR(rti->col[1]);
2527 but->col[2]= FTOCHAR(rti->col[2]);
2530 but= uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2531 but->col[0]= but->col[1]= but->col[2]= FTOCHAR(rti->greyscale);
2534 uiBlockEndAlign(block);
2537 /* icon and report message on top */
2538 if(report->type & RPT_ERROR_ALL)
2540 else if(report->type & RPT_WARNING_ALL)
2542 else if(report->type & RPT_INFO_ALL)
2545 /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report
2546 * to be shown instead of icon when appropriate...
2548 uiBlockSetEmboss(block, UI_EMBOSSN);
2550 if (reports->list.first != reports->list.last)
2551 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'"));
2553 uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2555 uiBlockSetEmboss(block, UI_EMBOSS);
2557 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, "");
2559 /* XXX linking hack */
2560 uiTemplateNodeView(NULL, NULL, NULL, NULL, NULL);
2563 /********************************* Keymap *************************************/
2565 static void keymap_item_modified(bContext *UNUSED(C), void *kmi_p, void *UNUSED(unused))
2567 wmKeyMapItem *kmi= (wmKeyMapItem*)kmi_p;
2568 WM_keyconfig_update_tag(NULL, kmi);
2571 static void template_keymap_item_properties(uiLayout *layout, const char *title, PointerRNA *ptr)
2578 uiItemL(layout, title, ICON_NONE);
2580 flow= uiLayoutColumnFlow(layout, 2, 0);
2582 RNA_STRUCT_BEGIN(ptr, prop) {
2583 int flag= RNA_property_flag(prop);
2585 if(flag & PROP_HIDDEN)
2588 /* recurse for nested properties */
2589 if(RNA_property_type(prop) == PROP_POINTER) {
2590 PointerRNA propptr= RNA_property_pointer_get(ptr, prop);
2591 const char *name= RNA_property_ui_name(prop);
2593 if(propptr.data && RNA_struct_is_a(propptr.type, &RNA_OperatorProperties)) {
2594 template_keymap_item_properties(layout, name, &propptr);
2600 uiItemR(flow, ptr, RNA_property_identifier(prop), 0, NULL, ICON_NONE);
2605 void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
2607 PointerRNA propptr= RNA_pointer_get(ptr, "properties");
2610 uiBut *but= uiLayoutGetBlock(layout)->buttons.last;
2612 template_keymap_item_properties(layout, NULL, &propptr);
2614 /* attach callbacks to compensate for missing properties update,
2615 we don't know which keymap (item) is being modified there */
2616 for(; but; but=but->next)
2617 uiButSetFunc(but, keymap_item_modified, ptr->data, NULL);