2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Contributor(s): Blender Foundation 2009.
20 * ***** END GPL LICENSE BLOCK *****
23 /** \file blender/editors/interface/interface_templates.c
24 * \ingroup edinterface
32 #include "MEM_guardedalloc.h"
34 #include "DNA_anim_types.h"
35 #include "DNA_dynamicpaint_types.h"
36 #include "DNA_key_types.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_userdef_types.h"
40 #include "BLI_utildefines.h"
41 #include "BLI_string.h"
42 #include "BLI_ghash.h"
44 #include "BLF_translation.h"
46 #include "BKE_animsys.h"
47 #include "BKE_colortools.h"
48 #include "BKE_context.h"
49 #include "BKE_dynamicpaint.h"
50 #include "BKE_global.h"
51 #include "BKE_library.h"
53 #include "BKE_object.h"
54 #include "BKE_material.h"
55 #include "BKE_texture.h"
56 #include "BKE_report.h"
57 #include "BKE_displist.h"
58 #include "BKE_scene.h"
60 #include "ED_screen.h"
61 #include "ED_object.h"
62 #include "ED_render.h"
64 #include "RNA_access.h"
65 #include "RNA_enum_types.h"
70 #include "UI_interface.h"
71 #include "interface_intern.h"
74 #include "BLF_translation.h"
76 void UI_template_fix_linking(void)
80 /********************** Header Template *************************/
82 void uiTemplateHeader(uiLayout *layout, bContext *C, int menus)
86 block= uiLayoutAbsoluteBlock(layout);
87 if(menus) ED_area_header_standardbuttons(C, block, 0);
88 else ED_area_header_switchbutton(C, block, 0);
91 /********************** Search Callbacks *************************/
93 typedef struct TemplateID {
98 int prv_rows, prv_cols;
101 /* Search browse menu, assign */
102 static void id_search_call_cb(bContext *C, void *arg_template, void *item)
104 TemplateID *template= (TemplateID*)arg_template;
110 RNA_id_pointer_create(item, &idptr);
111 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
112 RNA_property_update(C, &template->ptr, template->prop);
116 /* ID Search browse menu, do the search */
117 static void id_search_cb(const bContext *C, void *arg_template, const char *str, uiSearchItems *items)
119 TemplateID *template= (TemplateID*)arg_template;
120 ListBase *lb= template->idlb;
121 ID *id, *id_from= template->ptr.id.data;
123 int flag= RNA_property_flag(template->prop);
126 for(id= lb->first; id; id= id->next) {
127 if(!((flag & PROP_ID_SELF_CHECK) && id == id_from)) {
130 if(RNA_property_type(template->prop)==PROP_POINTER) {
132 RNA_id_pointer_create(id, &ptr);
133 if(RNA_property_pointer_poll(&template->ptr, template->prop, &ptr)==0)
137 /* hide dot-datablocks, but only if filter does not force it visible */
138 if(U.uiflag & USER_HIDE_DOT)
139 if ((id->name[2]=='.') && (str[0] != '.'))
142 if(BLI_strcasestr(id->name+2, str)) {
143 char name_ui[MAX_ID_NAME];
144 name_uiprefix_id(name_ui, id);
146 iconid= ui_id_icon_get((bContext*)C, id, 1);
148 if(!uiSearchItemAdd(items, name_ui, id, iconid))
155 /* ID Search browse menu, open */
156 static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
158 static char search[256];
159 static TemplateID template;
161 wmWindow *win= CTX_wm_window(C);
165 /* clear initial search string, then all items show */
167 /* arg_litem is malloced, can be freed by parent button */
168 template= *((TemplateID*)arg_litem);
170 /* get active id for showing first item */
171 idptr= RNA_property_pointer_get(&template.ptr, template.prop);
173 block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
174 uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
176 /* preview thumbnails */
177 if (template.prv_rows > 0 && template.prv_cols > 0) {
178 int w = 96 * template.prv_cols;
179 int h = 96 * template.prv_rows + 20;
181 /* fake button, it holds space for search items */
182 uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL);
184 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, w, 19, template.prv_rows, template.prv_cols, "");
185 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
189 /* fake button, it holds space for search items */
190 uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
192 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 0, 150, 19, 0, 0, "");
193 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
197 uiBoundsBlock(block, 6);
198 uiBlockSetDirection(block, UI_DOWN);
199 uiEndBlock(C, block);
201 /* give search-field focus */
202 uiButSetFocusOnEnter(win, but);
203 /* this type of search menu requires undo */
204 but->flag |= UI_BUT_UNDO;
209 /************************ ID Template ***************************/
210 /* This is for browsing and editing the ID-blocks used */
212 /* for new/open operators */
213 void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
215 TemplateID *template;
216 ARegion *ar= CTX_wm_region(C);
220 memset(ptr, 0, sizeof(*ptr));
226 for(block=ar->uiblocks.first; block; block=block->next) {
227 for(but=block->buttons.first; but; but= but->next) {
228 /* find the button before the active one */
229 if((but->flag & (UI_BUT_LAST_ACTIVE|UI_ACTIVE))) {
231 template= but->func_argN;
233 *prop= template->prop;
242 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
244 TemplateID *template= (TemplateID*)arg_litem;
245 PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
247 int event= GET_INT_FROM_POINTER(arg_event);
252 RNA_warning("warning, id event %d shouldnt come here", event);
256 /* these call uiIDContextPropertySet */
259 memset(&idptr, 0, sizeof(idptr));
260 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
261 RNA_property_update(C, &template->ptr, template->prop);
263 if(id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */
267 case UI_ID_FAKE_USER:
269 if(id->flag & LIB_FAKEUSER) id_us_plus(id);
276 if(id_make_local(id, 0)) {
277 /* reassign to get get proper updates/notifiers */
278 idptr= RNA_property_pointer_get(&template->ptr, template->prop);
279 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
280 RNA_property_update(C, &template->ptr, template->prop);
286 const int do_scene_obj= (GS(id->name) == ID_OB) &&
287 (template->ptr.type == &RNA_SceneObjects);
291 Scene *scene= CTX_data_scene(C);
292 ED_object_single_user(scene, (struct Object *)id);
293 WM_event_add_notifier(C, NC_SCENE|ND_OB_ACTIVE, scene);
297 id_single_user(C, id, &template->ptr, template->prop);
303 case UI_ID_AUTO_NAME:
309 static const char *template_id_browse_tip(StructRNA *type)
312 switch(RNA_type_to_ID_code(type)) {
313 case ID_SCE: return N_("Browse Scene to be linked");
314 case ID_OB: return N_("Browse Object to be linked");
315 case ID_ME: return N_("Browse Mesh Data to be linked");
316 case ID_CU: return N_("Browse Curve Data to be linked");
317 case ID_MB: return N_("Browse MetaBall Data to be linked");
318 case ID_MA: return N_("Browse Material to be linked");
319 case ID_TE: return N_("Browse Texture to be linked");
320 case ID_IM: return N_("Browse Image to be linked");
321 case ID_LT: return N_("Browse Lattice Data to be linked");
322 case ID_LA: return N_("Browse Lamp Data to be linked");
323 case ID_CA: return N_("Browse Camera Data to be linked");
324 case ID_WO: return N_("Browse World Settings to be linked");
325 case ID_SCR: return N_("Choose Screen lay-out");
326 case ID_TXT: return N_("Browse Text to be linked");
327 case ID_SPK: return N_("Browse Speaker Data to be linked");
328 case ID_SO: return N_("Browse Sound to be linked");
329 case ID_AR: return N_("Browse Armature data to be linked");
330 case ID_AC: return N_("Browse Action to be linked");
331 case ID_NT: return N_("Browse Node Tree to be linked");
332 case ID_BR: return N_("Browse Brush to be linked");
333 case ID_PA: return N_("Browse Particle System to be linked");
334 case ID_GD: return N_("Browse Grease Pencil Data to be linked");
337 return N_("Browse ID data to be linked");
340 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)
345 // ListBase *lb; // UNUSED
347 int editable= RNA_property_editable(&template->ptr, template->prop);
349 idptr= RNA_property_pointer_get(&template->ptr, template->prop);
351 idfrom= template->ptr.id.data;
352 // lb= template->idlb;
354 block= uiLayoutGetBlock(layout);
355 uiBlockBeginAlign(block);
360 if(flag & UI_ID_PREVIEWS) {
362 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6,
363 TIP_(template_id_browse_tip(type)));
365 but->icon= RNA_struct_ui_icon(type);
366 if (id) but->icon = ui_id_icon_get(C, id, 1);
367 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_PREVIEW);
369 if((idfrom && idfrom->lib) || !editable)
370 uiButSetFlag(but, UI_BUT_DISABLED);
372 uiLayoutRow(layout, 1);
374 else if(flag & UI_ID_BROWSE) {
375 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y,
376 TIP_(template_id_browse_tip(type)));
378 but->icon= RNA_struct_ui_icon(type);
379 /* default dragging of icon for id browse buttons */
380 uiButSetDragID(but, id);
381 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_LEFT);
384 if((idfrom && idfrom->lib) || !editable)
385 uiButSetFlag(but, UI_BUT_DISABLED);
388 /* text button with name */
390 char name[UI_MAX_NAME_STR];
391 const short user_alert= (id->us <= 0);
393 //text_idbutton(id, name);
395 but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
396 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
397 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
400 if(id->flag & LIB_INDIRECT) {
401 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0,
402 TIP_("Indirect library datablock, cannot change"));
403 uiButSetFlag(but, UI_BUT_DISABLED);
406 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0,
407 TIP_("Direct linked library datablock, click to make local"));
408 if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib))
409 uiButSetFlag(but, UI_BUT_DISABLED);
412 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
418 BLI_snprintf(numstr, sizeof(numstr), "%d", id->us);
420 but= uiDefBut(block, BUT, 0, numstr, 0,0,UI_UNIT_X + ((id->us < 10) ? 0:10), UI_UNIT_Y, NULL, 0, 0, 0, 0,
421 TIP_("Display number of users of this data (click to make a single-user copy)"));
423 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
424 if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib) || !editable)
425 uiButSetFlag(but, UI_BUT_DISABLED);
428 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
430 if(id->lib == NULL && !(ELEM5(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
431 uiDefButR(block, TOG, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
435 if(flag & UI_ID_ADD_NEW) {
436 int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
439 but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, (id)? "": IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL);
440 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
443 but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": IFACE_("New"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
444 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
447 if((idfrom && idfrom->lib) || !editable)
448 uiButSetFlag(but, UI_BUT_DISABLED);
451 if(flag & UI_ID_OPEN) {
452 int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
455 but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id)? "": IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL);
456 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
459 but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": IFACE_("Open"), 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
460 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
463 if((idfrom && idfrom->lib) || !editable)
464 uiButSetFlag(but, UI_BUT_DISABLED);
468 if(id && (flag & UI_ID_DELETE) && (RNA_property_flag(template->prop) & PROP_NEVER_UNLINK)==0) {
470 but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
471 /* so we can access the template from operators, font unlinking needs this */
472 uiButSetNFunc(but, NULL, MEM_dupallocN(template), NULL);
475 but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0,
476 TIP_("Unlink datablock. Shift + Click to set users to zero, data will then not be saved"));
477 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
479 if(RNA_property_flag(template->prop) & PROP_NEVER_NULL)
480 uiButSetFlag(but, UI_BUT_DISABLED);
483 if((idfrom && idfrom->lib) || !editable)
484 uiButSetFlag(but, UI_BUT_DISABLED);
488 uiTemplateTextureShow(layout, C, &template->ptr, template->prop);
490 uiBlockEndAlign(block);
493 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)
495 TemplateID *template;
500 prop= RNA_struct_find_property(ptr, propname);
502 if(!prop || RNA_property_type(prop) != PROP_POINTER) {
503 RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
507 template= MEM_callocN(sizeof(TemplateID), "TemplateID");
509 template->prop= prop;
510 template->prv_rows = prv_rows;
511 template->prv_cols = prv_cols;
514 flag |= UI_ID_ADD_NEW;
518 type= RNA_property_pointer_type(ptr, prop);
519 idcode= RNA_type_to_ID_code(type);
520 template->idlb= which_libbase(CTX_data_main(C), idcode);
522 /* create UI elements for this template
523 * - template_ID makes a copy of the template data and assigns it to the relevant buttons
526 uiLayoutRow(layout, 1);
527 template_ID(C, layout, template, type, idcode, flag, newop, openop, unlinkop);
533 void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
535 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE, 0, 0);
538 void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
540 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME, 0, 0);
543 void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols)
545 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE|UI_ID_PREVIEWS, rows, cols);
548 /************************ ID Chooser Template ***************************/
550 /* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use
552 * - propname: property identifier for property that ID-pointer gets stored to
553 * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used
555 void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *text)
557 PropertyRNA *propID, *propType;
560 /* get properties... */
561 propID= RNA_struct_find_property(ptr, propname);
562 propType= RNA_struct_find_property(ptr, proptypename);
564 if (!propID || RNA_property_type(propID) != PROP_POINTER) {
565 RNA_warning("pointer property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
568 if (!propType || RNA_property_type(propType) != PROP_ENUM) {
569 RNA_warning("pointer-type property not found: %s.%s", RNA_struct_identifier(ptr->type), proptypename);
573 /* Start drawing UI Elements using standard defines */
574 row= uiLayoutRow(layout, 1);
576 /* Label - either use the provided text, or will become "ID-Block:" */
578 uiItemL(row, text, ICON_NONE);
580 uiItemL(row, "ID-Block:", ICON_NONE);
582 /* ID-Type Selector - just have a menu of icons */
583 // FIXME: the icon-only setting doesn't work when we supply a blank name
584 uiItemFullR(row, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
586 /* ID-Block Selector - just use pointer widget... */
587 uiItemFullR(row, ptr, propID, 0, 0, 0, "", ICON_NONE);
590 /********************* RNA Path Builder Template ********************/
594 /* This is creating/editing RNA-Paths
596 * - ptr: struct which holds the path property
597 * - propname: property identifier for property that path gets stored to
598 * - root_ptr: struct that path gets built from
600 void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), const char *text)
602 PropertyRNA *propPath;
605 /* check that properties are valid */
606 propPath= RNA_struct_find_property(ptr, propname);
607 if (!propPath || RNA_property_type(propPath) != PROP_STRING) {
608 RNA_warning("path property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
612 /* Start drawing UI Elements using standard defines */
613 row= uiLayoutRow(layout, 1);
615 /* Path (existing string) Widget */
616 uiItemR(row, ptr, propname, 0, text, ICON_RNA);
618 // TODO: attach something to this to make allow searching of nested properties to 'build' the path
621 /************************ Modifier Template *************************/
623 #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
627 #include "DNA_object_force.h"
629 #include "BKE_depsgraph.h"
630 #include "BKE_modifier.h"
631 #include "BKE_particle.h"
635 #include "BLI_math.h"
636 #include "BLI_listbase.h"
638 #include "ED_object.h"
640 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
642 Scene *scene = CTX_data_scene(C);
644 ModifierData *md= md_v;
645 int i, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 0);
647 /* undo button operation */
648 md->mode ^= eModifierMode_OnCage;
650 for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) {
653 md->mode ^= eModifierMode_OnCage;
658 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
659 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
662 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
665 ModifierData *md = md_v;
666 ModifierData *nmd = modifier_new(md->type);
668 modifier_copyData(md, nmd);
669 nmd->mode &= ~eModifierMode_Virtual;
671 BLI_addhead(&ob->modifiers, nmd);
673 modifier_unique_name(&ob->modifiers, nmd);
675 ob->partype = PAROBJECT;
677 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
678 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
680 ED_undo_push(C, "Modifier convert to real");
683 static int modifier_can_delete(ModifierData *md)
685 /* fluid particle modifier can't be deleted here */
686 if(md->type == eModifierType_ParticleSystem)
687 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
693 /* Check wheter Modifier is a simulation or not, this is used for switching to the physics/particles context tab */
694 static int modifier_is_simulation(ModifierData *md)
697 if (ELEM7(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke,
698 eModifierType_Softbody, eModifierType_Surface, eModifierType_DynamicPaint))
703 else if (md->type == eModifierType_ParticleSystem) {
711 static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob,
712 ModifierData *md, int index, int cageIndex, int lastCageIndex)
714 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
718 uiLayout *box, *column, *row;
719 uiLayout *result= NULL;
720 int isVirtual = (md->mode & eModifierMode_Virtual);
723 /* create RNA pointer */
724 RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
726 column= uiLayoutColumn(layout, 1);
727 uiLayoutSetContextPointer(column, "modifier", &ptr);
729 /* rounded header ------------------------------------------------------------------- */
730 box= uiLayoutBox(column);
733 row= uiLayoutRow(box, 0);
734 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
735 block= uiLayoutGetBlock(row);
736 /* VIRTUAL MODIFIER */
737 // XXX this is not used now, since these cannot be accessed via RNA
738 BLI_snprintf(str, sizeof(str), "%s parent deform", md->name);
739 uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name");
741 but = uiDefBut(block, BUT, 0, IFACE_("Make Real"), 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0,
742 TIP_("Convert virtual modifier to a real modifier"));
743 uiButSetFunc(but, modifiers_convertToReal, ob, md);
747 row = uiLayoutRow(box, 0);
748 block = uiLayoutGetBlock(row);
750 uiBlockSetEmboss(block, UI_EMBOSSN);
751 /* Open/Close ................................. */
752 uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
754 /* modifier-type icon */
755 uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
756 uiBlockSetEmboss(block, UI_EMBOSS);
759 uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
761 /* mode enabling buttons */
762 uiBlockBeginAlign(block);
763 /* Softbody not allowed in this situation, enforce! */
764 if ( ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect))
765 && (md->type!=eModifierType_Surface) )
767 uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
768 uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
770 if (mti->flags & eModifierTypeFlag_SupportsEditmode)
771 uiItemR(row, &ptr, "show_in_editmode", 0, "", ICON_NONE);
774 if (ob->type==OB_MESH) {
775 if (modifier_couldBeCage(scene, md) && (index <= lastCageIndex))
777 /* -- convert to rna ? */
778 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,
779 TIP_("Apply modifier to editing cage during Editmode"));
780 if (index < cageIndex)
781 uiButSetFlag(but, UI_BUT_DISABLED);
782 uiButSetFunc(but, modifiers_setOnCage, ob, md);
785 uiBlockEndAlign(block);
787 /* place holder button */
788 uiBlockSetEmboss(block, UI_EMBOSSN);
789 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);
790 uiButSetFlag(but, UI_BUT_DISABLED);
791 uiBlockSetEmboss(block, UI_EMBOSS);
793 } /* tesselation point for curve-typed objects */
794 else if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
795 /* some modifiers could work with pre-tesselated curves only */
796 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
797 /* add disabled pre-tesselated button, so users could have
798 message for this modifiers */
799 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,
800 TIP_("This modifier could be applied on splines' points only"));
801 uiButSetFlag(but, UI_BUT_DISABLED);
802 } else if (mti->type != eModifierTypeType_Constructive) {
803 /* constructive modifiers tesselates curve before applying */
804 uiItemR(row, &ptr, "use_apply_on_spline", 0, "", ICON_NONE);
808 uiBlockEndAlign(block);
810 /* Up/Down + Delete ........................... */
811 uiBlockBeginAlign(block);
812 uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up");
813 uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down");
814 uiBlockEndAlign(block);
816 uiBlockSetEmboss(block, UI_EMBOSSN);
817 // When Modifier is a simulation, show button to switch to context rather than the delete button.
818 if (modifier_can_delete(md) && !modifier_is_simulation(md))
819 uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
820 if (modifier_is_simulation(md) == 1)
821 uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PHYSICS");
822 else if (modifier_is_simulation(md) == 2)
823 uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PARTICLES");
824 uiBlockSetEmboss(block, UI_EMBOSS);
828 /* modifier settings (under the header) --------------------------------------------------- */
829 if (!isVirtual && (md->mode & eModifierMode_Expanded)) {
830 /* apply/convert/copy */
831 box= uiLayoutBox(column);
832 row= uiLayoutRow(box, 0);
834 if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) {
835 /* only here obdata, the rest of modifiers is ob level */
836 uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
838 if (md->type==eModifierType_ParticleSystem) {
839 ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
841 if (!(ob->mode & OB_MODE_PARTICLE_EDIT) && psys->pathcache) {
842 if(ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB))
843 uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_duplicates_make_real");
844 else if(psys->part->ren_as == PART_DRAW_PATH)
845 uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_modifier_convert");
849 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
850 uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply"), 0, "apply_as", MODIFIER_APPLY_DATA);
852 if (modifier_sameTopology(md) && !modifier_nonGeometrical(md))
853 uiItemEnumO(row, "OBJECT_OT_modifier_apply", IFACE_("Apply as Shape"), 0, "apply_as", MODIFIER_APPLY_SHAPE);
856 uiBlockClearButLock(block);
857 uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
859 if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke))
860 uiItemO(row, IFACE_("Copy"), ICON_NONE, "OBJECT_OT_modifier_copy");
863 /* result is the layout block inside the box, that we return so that modifier settings can be drawn */
864 result= uiLayoutColumn(box, 0);
865 block= uiLayoutAbsoluteBlock(box);
870 box = uiLayoutBox(column);
871 row = uiLayoutRow(box, 0);
872 uiItemL(row, md->error, ICON_ERROR);
878 uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
880 Scene *scene = CTX_data_scene(C);
882 ModifierData *md, *vmd;
883 int i, lastCageIndex, cageIndex;
885 /* verify we have valid data */
886 if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
887 RNA_warning("Expected modifier on object");
894 if(!ob || !(GS(ob->id.name) == ID_OB)) {
895 RNA_warning("Expected modifier on object");
899 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
901 /* find modifier and draw it */
902 cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
904 // XXX virtual modifiers are not accesible for python
905 vmd = modifiers_getVirtualModifierList(ob);
907 for(i=0; vmd; i++, vmd=vmd->next) {
909 return draw_modifier(layout, scene, ob, md, i, cageIndex, lastCageIndex);
910 else if(vmd->mode & eModifierMode_Virtual)
917 /************************ Constraint Template *************************/
919 #include "DNA_constraint_types.h"
921 #include "BKE_action.h"
922 #include "BKE_constraint.h"
926 #define REDRAWBUTSOBJECT 3
927 #define REDRAWACTION 4
928 #define B_CONSTRAINT_TEST 5
929 #define B_CONSTRAINT_CHANGETARGET 6
933 static void do_constraint_panels(bContext *C, void *ob_pt, int event)
935 Main *bmain= CTX_data_main(C);
936 Scene *scene= CTX_data_scene(C);
937 Object *ob= (Object *)ob_pt;
940 case B_CONSTRAINT_TEST:
941 break; // no handling
942 case B_CONSTRAINT_CHANGETARGET:
943 if (ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels
944 DAG_scene_sort(bmain, scene);
950 // note: RNA updates now call this, commenting else it gets called twice.
951 // if there are problems because of this, then rna needs changed update functions.
953 // object_test_constraints(ob);
954 // if(ob->pose) update_pose_constraint_flags(ob->pose);
956 if(ob->type==OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB);
957 else DAG_id_tag_update(&ob->id, OB_RECALC_OB);
959 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
962 static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
964 ED_object_constraint_set_active(ob_v, con_v);
967 /* draw panel showing settings for a constraint */
968 static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
970 bPoseChannel *pchan= get_active_posechannel(ob);
971 bConstraintTypeInfo *cti;
973 uiLayout *result= NULL, *col, *box, *row;
976 short proxy_protected, xco=0, yco=0;
977 // int rb_col; // UNUSED
979 /* get constraint typeinfo */
980 cti= constraint_get_typeinfo(con);
982 /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
983 BLI_strncpy(typestr, (con->type == CONSTRAINT_TYPE_NULL) ? "Null" : "Unknown", sizeof(typestr));
986 BLI_strncpy(typestr, cti->name, sizeof(typestr));
988 /* determine whether constraint is proxy protected or not */
989 if (proxylocked_constraints_owner(ob, pchan))
990 proxy_protected= (con->flag & CONSTRAINT_PROXY_LOCAL)==0;
994 /* unless button has own callback, it adds this callback to button */
995 block= uiLayoutGetBlock(layout);
996 uiBlockSetHandleFunc(block, do_constraint_panels, ob);
997 uiBlockSetFunc(block, constraint_active_func, ob, con);
999 RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
1001 col= uiLayoutColumn(layout, 1);
1002 uiLayoutSetContextPointer(col, "constraint", &ptr);
1004 box= uiLayoutBox(col);
1005 row = uiLayoutRow(box, 0);
1006 block= uiLayoutGetBlock(box);
1008 /* Draw constraint header */
1011 uiBlockSetEmboss(block, UI_EMBOSSN);
1012 uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
1013 uiBlockSetEmboss(block, UI_EMBOSS);
1016 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
1018 if (con->flag & CONSTRAINT_DISABLE)
1019 uiLayoutSetRedAlert(row, 1);
1021 if(proxy_protected == 0) {
1022 uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
1025 uiItemL(row, con->name, ICON_NONE);
1027 uiLayoutSetRedAlert(row, 0);
1029 /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
1030 if (proxy_protected) {
1031 uiBlockSetEmboss(block, UI_EMBOSSN);
1033 /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */
1034 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"));
1035 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"));
1037 uiBlockSetEmboss(block, UI_EMBOSS);
1040 short prev_proxylock, show_upbut, show_downbut;
1043 * Proxy-constraints are not allowed to occur after local (non-proxy) constraints
1044 * as that poses problems when restoring them, so disable the "up" button where
1045 * it may cause this situation.
1047 * Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose.
1049 if (proxylocked_constraints_owner(ob, pchan)) {
1051 prev_proxylock= (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
1059 show_upbut= ((prev_proxylock == 0) && (con->prev));
1060 show_downbut= (con->next) ? 1 : 0;
1063 uiBlockSetEmboss(block, UI_EMBOSSN);
1064 uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_RESTRICT_VIEW_ON : ICON_RESTRICT_VIEW_OFF);
1065 uiBlockSetEmboss(block, UI_EMBOSS);
1067 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
1070 if (show_upbut || show_downbut) {
1071 uiBlockBeginAlign(block);
1073 uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up");
1076 uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down");
1077 uiBlockEndAlign(block);
1080 /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
1081 uiBlockSetEmboss(block, UI_EMBOSSN);
1082 uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete");
1083 uiBlockSetEmboss(block, UI_EMBOSS);
1086 /* Set but-locks for protected settings (magic numbers are used here!) */
1087 if (proxy_protected)
1088 uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint");
1090 /* Draw constraint data */
1091 if ((con->flag & CONSTRAINT_EXPAND) == 0) {
1095 box= uiLayoutBox(col);
1096 block= uiLayoutAbsoluteBlock(box);
1100 /* clear any locks set up for proxies/lib-linking */
1101 uiBlockClearButLock(block);
1106 uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
1111 /* verify we have valid data */
1112 if(!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
1113 RNA_warning("Expected constraint on object");
1120 if(!ob || !(GS(ob->id.name) == ID_OB)) {
1121 RNA_warning("Expected constraint on object");
1125 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
1127 /* hrms, the temporal constraint should not draw! */
1128 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
1129 bKinematicConstraint *data= con->data;
1130 if(data->flag & CONSTRAINT_IK_TEMP)
1134 return draw_constraint(layout, ob, con);
1138 /************************* Preview Template ***************************/
1140 #include "DNA_lamp_types.h"
1141 #include "DNA_material_types.h"
1142 #include "DNA_world_types.h"
1146 static void do_preview_buttons(bContext *C, void *arg, int event)
1150 WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, arg);
1155 void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, MTex *slot)
1157 uiLayout *row, *col;
1160 Tex *tex = (Tex*)id;
1162 short *pr_texture= NULL;
1163 PointerRNA material_ptr;
1164 PointerRNA texture_ptr;
1166 if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
1167 RNA_warning("Expected ID of type material, texture, lamp or world");
1171 /* decide what to render */
1175 if(id && (GS(id->name) == ID_TE)) {
1176 if(parent && (GS(parent->name) == ID_MA))
1177 pr_texture= &((Material*)parent)->pr_texture;
1178 else if(parent && (GS(parent->name) == ID_WO))
1179 pr_texture= &((World*)parent)->pr_texture;
1180 else if(parent && (GS(parent->name) == ID_LA))
1181 pr_texture= &((Lamp*)parent)->pr_texture;
1184 if(*pr_texture == TEX_PR_OTHER)
1186 else if(*pr_texture == TEX_PR_BOTH)
1192 block= uiLayoutGetBlock(layout);
1193 row= uiLayoutRow(layout, 0);
1194 col= uiLayoutColumn(row, 0);
1195 uiLayoutSetKeepAspect(col, 1);
1198 uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, pid, 0.0, 0.0, 0, 0, "");
1199 uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot);
1200 uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
1203 if (pid && show_buttons) {
1204 if(GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
1205 if(GS(pid->name) == ID_MA) ma= (Material*)pid;
1206 else ma= (Material*)pparent;
1208 /* Create RNA Pointer */
1209 RNA_pointer_create(id, &RNA_Material, ma, &material_ptr);
1211 col = uiLayoutColumn(row, 1);
1212 uiLayoutSetScaleX(col, 1.5);
1213 uiItemR(col, &material_ptr, "preview_render_type", UI_ITEM_R_EXPAND, "", ICON_NONE);
1217 /* Create RNA Pointer */
1218 RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr);
1220 uiLayoutRow(layout, 1);
1221 uiDefButS(block, ROW, B_MATPRV, IFACE_("Texture"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
1222 if(GS(parent->name) == ID_MA)
1223 uiDefButS(block, ROW, B_MATPRV, IFACE_("Material"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1224 else if(GS(parent->name) == ID_LA)
1225 uiDefButS(block, ROW, B_MATPRV, IFACE_("Lamp"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1226 else if(GS(parent->name) == ID_WO)
1227 uiDefButS(block, ROW, B_MATPRV, IFACE_("World"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1228 uiDefButS(block, ROW, B_MATPRV, IFACE_("Both"), 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
1230 /* Alpha button for texture preview */
1231 if(*pr_texture!=TEX_PR_OTHER) {
1232 row = uiLayoutRow(layout, 0);
1233 uiItemR(row, &texture_ptr, "use_preview_alpha", 0, NULL, ICON_NONE);
1239 /********************** ColorRamp Template **************************/
1242 typedef struct RNAUpdateCb {
1247 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
1249 RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
1251 /* we call update here on the pointer property, this way the
1252 owner of the curve mapping can still define it's own update
1253 and notifier, even if the CurveMapping struct is shared. */
1254 RNA_property_update(C, &cb->ptr, cb->prop);
1259 static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
1261 ColorBand *coba= coba_v;
1265 if(coba->cur > 0) pos= (coba->data[coba->cur-1].pos + coba->data[coba->cur].pos) * 0.5f;
1266 else pos= (coba->data[coba->cur+1].pos + coba->data[coba->cur].pos) * 0.5f;
1269 if(colorband_element_add(coba, pos)) {
1270 rna_update_cb(C, cb_v, NULL);
1271 ED_undo_push(C, "Add colorband");
1275 static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v)
1277 ColorBand *coba= coba_v;
1279 if(colorband_element_remove(coba, coba->cur)) {
1280 ED_undo_push(C, "Delete colorband");
1281 rna_update_cb(C, cb_v, NULL);
1285 static void colorband_flip_cb(bContext *C, void *cb_v, void *coba_v)
1287 CBData data_tmp[MAXCOLORBAND];
1289 ColorBand *coba= coba_v;
1292 for(a=0; a<coba->tot; a++) {
1293 data_tmp[a]= coba->data[coba->tot - (a + 1)];
1295 for(a=0; a<coba->tot; a++) {
1296 data_tmp[a].pos = 1.0f - data_tmp[a].pos;
1297 coba->data[a]= data_tmp[a];
1300 /* may as well flip the cur*/
1301 coba->cur= coba->tot - (coba->cur + 1);
1303 ED_undo_push(C, "Flip colorband");
1305 rna_update_cb(C, cb_v, NULL);
1309 /* offset aligns from bottom, standard width 300, height 115 */
1310 static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb)
1314 const int line1_y= yoffs + 65 + UI_UNIT_Y + 2; /* 2 for some space between the buttons */
1315 const int line2_y= yoffs + 65;
1317 if(coba==NULL) return;
1319 bt= uiDefBut(block, BUT, 0, IFACE_("Add"), 0+xoffs,line1_y,40,UI_UNIT_Y, NULL, 0, 0, 0, 0,
1320 TIP_("Add a new color stop to the colorband"));
1321 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1323 bt= uiDefBut(block, BUT, 0, IFACE_("Delete"), 45+xoffs,line1_y,45,UI_UNIT_Y, NULL, 0, 0, 0, 0,
1324 TIP_("Delete the active position"));
1325 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1328 /* XXX, todo for later - convert to operator - campbell */
1329 bt= uiDefBut(block, BUT, 0, "F", 95+xoffs,line1_y,20,UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Flip colorband"));
1330 uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
1332 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"));
1334 bt= uiDefButS(block, MENU, 0, IFACE_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"),
1335 210+xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, TIP_("Set interpolation between color stops"));
1336 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1337 uiBlockEndAlign(block);
1339 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xoffs,line2_y,300,UI_UNIT_Y, coba, 0, 0, 0, 0, "");
1340 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1345 CBData *cbd= coba->data + coba->cur;
1347 /* better to use rna so we can animate them */
1349 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1350 row= uiLayoutRow(layout, 0);
1351 uiItemR(row, &ptr, "position", 0, "Pos", ICON_NONE);
1352 uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
1357 static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
1360 float unit= (butr->xmax-butr->xmin)/14.0f;
1361 float xs= butr->xmin;
1363 uiBlockBeginAlign(block);
1364 bt= uiDefBut(block, BUT, 0, IFACE_("Add"), xs,butr->ymin+UI_UNIT_Y,2.0f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0,
1365 TIP_("Add a new color stop to the colorband"));
1366 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1367 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,
1368 TIP_("Delete the active position"));
1369 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1370 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"));
1371 uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
1372 uiBlockEndAlign(block);
1375 CBData *cbd= coba->data + coba->cur;
1377 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1378 uiItemR(layout, &ptr, "color", 0, "", ICON_NONE);
1381 bt= uiDefButS(block, MENU, 0, TIP_("Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4"),
1382 xs+10.0f*unit, butr->ymin+UI_UNIT_Y, unit*4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0,
1383 TIP_("Set interpolation between color stops"));
1384 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1386 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xs,butr->ymin,butr->xmax-butr->xmin,UI_UNIT_Y, coba, 0, 0, 0, 0, "");
1387 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1389 uiBlockEndAlign(block);
1392 static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb)
1395 colorband_buttons_small(layout, block, coba, butr, cb);
1397 colorband_buttons_large(layout, block, coba, 0, 0, cb);
1400 void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname, int expand)
1402 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1408 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1411 cptr= RNA_property_pointer_get(ptr, prop);
1412 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp))
1415 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1419 rect.xmin= 0; rect.xmax= 200;
1420 rect.ymin= 0; rect.ymax= 190;
1422 block= uiLayoutAbsoluteBlock(layout);
1423 colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1428 /********************* Histogram Template ************************/
1430 void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname)
1432 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1440 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1443 cptr= RNA_property_pointer_get(ptr, prop);
1444 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram))
1447 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1451 rect.xmin= 0; rect.xmax= 200;
1452 rect.ymin= 0; rect.ymax= 190;
1454 block= uiLayoutAbsoluteBlock(layout);
1455 //colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1457 hist = (Histogram *)cptr.data;
1459 hist->height= (hist->height<=UI_UNIT_Y)?UI_UNIT_Y:hist->height;
1461 bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, hist->height, hist, 0, 0, 0, 0, "");
1462 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1467 /********************* Waveform Template ************************/
1469 void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname)
1471 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1479 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1482 cptr= RNA_property_pointer_get(ptr, prop);
1483 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
1485 scopes = (Scopes *)cptr.data;
1487 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1491 rect.xmin= 0; rect.xmax= 200;
1492 rect.ymin= 0; rect.ymax= 190;
1494 block= uiLayoutAbsoluteBlock(layout);
1496 scopes->wavefrm_height= (scopes->wavefrm_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->wavefrm_height;
1498 bt= uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
1504 /********************* Vectorscope Template ************************/
1506 void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propname)
1508 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1516 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1519 cptr= RNA_property_pointer_get(ptr, prop);
1520 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
1522 scopes = (Scopes *)cptr.data;
1524 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1528 rect.xmin= 0; rect.xmax= 200;
1529 rect.ymin= 0; rect.ymax= 190;
1531 block= uiLayoutAbsoluteBlock(layout);
1533 scopes->vecscope_height= (scopes->vecscope_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->vecscope_height;
1535 bt= uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
1536 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1541 /********************* CurveMapping Template ************************/
1544 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *UNUSED(arg))
1546 CurveMapping *cumap = cumap_v;
1549 /* we allow 20 times zoom */
1550 if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1551 d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
1552 cumap->curr.xmin+= d;
1553 cumap->curr.xmax-= d;
1554 d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
1555 cumap->curr.ymin+= d;
1556 cumap->curr.ymax-= d;
1559 ED_region_tag_redraw(CTX_wm_region(C));
1562 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(unused))
1564 CurveMapping *cumap = cumap_v;
1567 /* we allow 20 times zoom, but dont view outside clip */
1568 if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1569 d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
1571 if(cumap->flag & CUMA_DO_CLIP)
1572 if(cumap->curr.xmin-d < cumap->clipr.xmin)
1573 d1= cumap->curr.xmin - cumap->clipr.xmin;
1574 cumap->curr.xmin-= d1;
1577 if(cumap->flag & CUMA_DO_CLIP)
1578 if(cumap->curr.xmax+d > cumap->clipr.xmax)
1579 d1= -cumap->curr.xmax + cumap->clipr.xmax;
1580 cumap->curr.xmax+= d1;
1582 d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
1584 if(cumap->flag & CUMA_DO_CLIP)
1585 if(cumap->curr.ymin-d < cumap->clipr.ymin)
1586 d1= cumap->curr.ymin - cumap->clipr.ymin;
1587 cumap->curr.ymin-= d1;
1590 if(cumap->flag & CUMA_DO_CLIP)
1591 if(cumap->curr.ymax+d > cumap->clipr.ymax)
1592 d1= -cumap->curr.ymax + cumap->clipr.ymax;
1593 cumap->curr.ymax+= d1;
1596 ED_region_tag_redraw(CTX_wm_region(C));
1599 static void curvemap_buttons_setclip(bContext *UNUSED(C), void *cumap_v, void *UNUSED(arg))
1601 CurveMapping *cumap = cumap_v;
1603 curvemapping_changed(cumap, 0);
1606 static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
1608 CurveMapping *cumap = cumap_v;
1610 curvemap_remove(cumap->cm+cumap->cur, SELECT);
1611 curvemapping_changed(cumap, 0);
1613 rna_update_cb(C, cb_v, NULL);
1616 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
1617 static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v)
1619 CurveMapping *cumap = cumap_v;
1622 float width= 8*UI_UNIT_X;
1624 block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
1626 /* use this for a fake extra empy space around the buttons */
1627 uiDefBut(block, LABEL, 0, "", -4, 16, width+8, 6*UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
1629 bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",
1630 0,5*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->flag, 0.0, 0.0, 10, 0, "");
1631 uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
1633 uiBlockBeginAlign(block);
1634 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, "");
1635 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, "");
1636 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, "");
1637 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, "");
1639 uiBlockSetDirection(block, UI_RIGHT);
1641 uiEndBlock(C, block);
1645 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
1647 CurveMapping *cumap = cumap_v;
1648 CurveMap *cuma= cumap->cm+cumap->cur;
1652 curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
1653 curvemapping_changed(cumap, 0);
1656 cumap->curr= cumap->clipr;
1658 case 2: /* set vector */
1659 curvemap_sethandle(cuma, 1);
1660 curvemapping_changed(cumap, 0);
1662 case 3: /* set auto */
1663 curvemap_sethandle(cuma, 0);
1664 curvemapping_changed(cumap, 0);
1666 case 4: /* extend horiz */
1667 cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
1668 curvemapping_changed(cumap, 0);
1670 case 5: /* extend extrapolate */
1671 cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
1672 curvemapping_changed(cumap, 0);
1675 ED_region_tag_redraw(CTX_wm_region(C));
1678 static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1681 short yco= 0, menuwidth=10*UI_UNIT_X;
1683 block= uiBeginBlock(C, ar, __func__, UI_EMBOSS);
1684 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1686 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, "");
1687 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, "");
1688 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, "");
1689 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, "");
1690 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, "");
1691 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, "");
1693 uiBlockSetDirection(block, UI_RIGHT);
1694 uiTextBoundsBlock(block, 50);
1696 uiEndBlock(C, block);
1700 static uiBlock *curvemap_brush_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1703 short yco= 0, menuwidth=10*UI_UNIT_X;
1705 block= uiBeginBlock(C, ar, __func__, UI_EMBOSS);
1706 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1708 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, "");
1709 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, "");
1710 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, "");
1711 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, "");
1713 uiBlockSetDirection(block, UI_RIGHT);
1714 uiTextBoundsBlock(block, 50);
1716 uiEndBlock(C, block);
1720 static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
1722 ED_region_tag_redraw(CTX_wm_region(C));
1725 static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
1727 CurveMapping *cumap = cumap_v;
1730 cumap->preset = CURVE_PRESET_LINE;
1731 for(a=0; a<CM_TOT; a++)
1732 curvemap_reset(cumap->cm+a, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
1734 cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
1735 cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
1736 curvemapping_set_black_white(cumap, NULL, NULL);
1738 curvemapping_changed(cumap, 0);
1740 rna_update_cb(C, cb_v, NULL);
1743 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
1744 static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb)
1746 CurveMapping *cumap= ptr->data;
1747 uiLayout *row, *sub, *split;
1750 float dx= UI_UNIT_X;
1754 block= uiLayoutGetBlock(layout);
1757 row= uiLayoutRow(layout, 0);
1759 if(labeltype=='v') {
1761 sub= uiLayoutRow(row, 1);
1762 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1764 if(cumap->cm[0].curve) {
1765 bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1766 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1768 if(cumap->cm[1].curve) {
1769 bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1770 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1772 if(cumap->cm[2].curve) {
1773 bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1774 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1777 else if(labeltype=='c') {
1779 sub= uiLayoutRow(row, 1);
1780 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1782 if(cumap->cm[3].curve) {
1783 bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, dx, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
1784 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1786 if(cumap->cm[0].curve) {
1787 bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1788 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1790 if(cumap->cm[1].curve) {
1791 bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1792 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1794 if(cumap->cm[2].curve) {
1795 bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1796 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1799 else if (labeltype == 'h') {
1801 sub= uiLayoutRow(row, 1);
1802 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1804 if(cumap->cm[0].curve) {
1805 bt= uiDefButI(block, ROW, 0, "H", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1806 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1808 if(cumap->cm[1].curve) {
1809 bt= uiDefButI(block, ROW, 0, "S", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1810 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1812 if(cumap->cm[2].curve) {
1813 bt= uiDefButI(block, ROW, 0, "V", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1814 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1818 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
1823 /* operation buttons */
1824 sub= uiLayoutRow(row, 1);
1826 uiBlockSetEmboss(block, UI_EMBOSSN);
1828 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom in"));
1829 uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
1831 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Zoom out"));
1832 uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
1835 bt= uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, TIP_("Tools"));
1837 bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, TIP_("Tools"));
1839 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1841 if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
1842 bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, TIP_("Clipping Options"));
1843 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1845 bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, TIP_("Delete points"));
1846 uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
1848 uiBlockSetEmboss(block, UI_EMBOSS);
1850 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
1853 size= uiLayoutGetWidth(layout);
1854 row= uiLayoutRow(layout, 0);
1855 uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, bg, 0, "");
1857 /* black/white levels */
1859 split= uiLayoutSplit(layout, 0, 0);
1860 uiItemR(uiLayoutColumn(split, 0), ptr, "black_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1861 uiItemR(uiLayoutColumn(split, 0), ptr, "white_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1863 uiLayoutRow(layout, 0);
1864 bt=uiDefBut(block, BUT, 0, IFACE_("Reset"), 0, 0, UI_UNIT_X*10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
1865 TIP_("Reset Black/White point and curves"));
1866 uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
1869 uiBlockSetNFunc(block, NULL, NULL, NULL);
1872 void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, int levels, int brush)
1875 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1879 RNA_warning("curve property not found: %s.%s",
1880 RNA_struct_identifier(ptr->type), propname);
1884 if(RNA_property_type(prop) != PROP_POINTER) {
1885 RNA_warning("curve is not a pointer: %s.%s",
1886 RNA_struct_identifier(ptr->type), propname);
1890 cptr= RNA_property_pointer_get(ptr, prop);
1891 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping))
1894 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1898 curvemap_buttons_layout(layout, &cptr, type, levels, brush, cb);
1903 /********************* ColorWheel Template ************************/
1905 #define WHEEL_SIZE 100
1907 void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic)
1909 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1910 uiBlock *block= uiLayoutGetBlock(layout);
1911 uiLayout *col, *row;
1913 float softmin, softmax, step, precision;
1916 RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
1920 RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
1922 col = uiLayoutColumn(layout, 0);
1923 row= uiLayoutRow(col, 1);
1925 but= uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, "");
1928 but->flag |= UI_BUT_COLOR_LOCK;
1931 if(lock_luminosity) {
1932 float color[4]; /* incase of alpha */
1933 but->flag |= UI_BUT_VEC_SIZE_LOCK;
1934 RNA_property_float_get_array(ptr, prop, color);
1935 but->a2= len_v3(color);
1939 but->flag |= UI_BUT_COLOR_CUBIC;
1944 uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
1947 /********************* Layer Buttons Template ************************/
1949 static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
1952 int cur = GET_INT_FROM_POINTER(arg2);
1953 wmWindow *win= CTX_wm_window(C);
1954 int i, tot, shift= win->eventstate->shift;
1957 tot= RNA_property_array_length(&but->rnapoin, but->rnaprop);
1959 /* Normally clicking only selects one layer */
1960 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, 1);
1961 for(i = 0; i < tot; ++i) {
1963 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, 0);
1967 /* view3d layer change should update depsgraph (invisible object changed maybe) */
1968 /* see view3d_header.c */
1972 // - for now, grouping of layers is determined by dividing up the length of
1973 // the array of layer bitflags
1975 void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname,
1976 PointerRNA *used_ptr, const char *used_propname, int active_layer)
1978 uiLayout *uRow, *uCol;
1979 PropertyRNA *prop, *used_prop= NULL;
1980 int groups, cols, layers;
1981 int group, col, layer, row;
1982 int cols_per_group = 5;
1984 prop= RNA_struct_find_property(ptr, propname);
1986 RNA_warning("layers property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
1990 /* the number of layers determines the way we group them
1991 * - we want 2 rows only (for now)
1992 * - the number of columns (cols) is the total number of buttons per row
1993 * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
1994 * - for now, only split into groups if group will have at least 5 items
1996 layers= RNA_property_array_length(ptr, prop);
1997 cols= (layers / 2) + (layers % 2);
1998 groups= ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
2000 if(used_ptr && used_propname) {
2001 used_prop= RNA_struct_find_property(used_ptr, used_propname);
2003 RNA_warning("used layers property not found: %s.%s", RNA_struct_identifier(ptr->type), used_propname);
2007 if(RNA_property_array_length(used_ptr, used_prop) < layers)
2011 /* layers are laid out going across rows, with the columns being divided into groups */
2013 for (group= 0; group < groups; group++) {
2014 uCol= uiLayoutColumn(layout, 1);
2016 for (row= 0; row < 2; row++) {
2020 uRow= uiLayoutRow(uCol, 1);
2021 block= uiLayoutGetBlock(uRow);
2022 layer= groups*cols_per_group*row + cols_per_group*group;
2024 /* add layers as toggle buts */
2025 for (col= 0; (col < cols_per_group) && (layer < layers); col++, layer++) {
2027 int butlay = 1 << layer;
2029 if(active_layer & butlay)
2030 icon = ICON_LAYER_ACTIVE;
2031 else if(used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer))
2032 icon = ICON_LAYER_USED;
2034 but= uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, UI_UNIT_X/2, UI_UNIT_Y/2);
2035 uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer));
2043 /************************* List Template **************************/
2045 static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big)
2053 /* try ID, material or texture slot */
2054 if(RNA_struct_is_ID(itemptr->type)) {
2055 id= itemptr->id.data;
2057 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
2058 id= RNA_pointer_get(itemptr, "material").data;
2060 else if(RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
2061 id= RNA_pointer_get(itemptr, "texture").data;
2063 else if(RNA_struct_is_a(itemptr->type, &RNA_DynamicPaintSurface)) {
2064 DynamicPaintSurface *surface= (DynamicPaintSurface*)itemptr->data;
2066 if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) return ICON_TEXTURE_SHADED;
2067 else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) return ICON_OUTLINER_DATA_MESH;
2068 else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return ICON_FILE_IMAGE;
2071 /* get icon from ID */
2073 icon= ui_id_icon_get(C, id, big);
2082 static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id)
2084 uiBlock *block= uiLayoutGetBlock(layout);
2086 uiLayout *split, *overlap, *sub, *row;
2091 overlap= uiLayoutOverlap(layout);
2093 /* list item behind label & other buttons */
2094 sub= uiLayoutRow(overlap, 0);
2096 but= uiDefButR_prop(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, "");
2097 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2099 sub= uiLayoutRow(overlap, 0);
2101 /* retrieve icon and name */
2102 icon= list_item_icon_get(C, itemptr, rnaicon, 0);
2103 if(icon == ICON_NONE || icon == ICON_DOT)
2106 namebuf= RNA_struct_name_get_alloc(itemptr, NULL, 0, NULL);
2107 name= (namebuf)? namebuf: "";
2109 /* hardcoded types */
2110 if(itemptr->type == &RNA_MeshTextureFaceLayer || itemptr->type == &RNA_MeshColorLayer) {
2111 uiItemL(sub, name, icon);
2112 uiBlockSetEmboss(block, UI_EMBOSSN);
2113 uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
2114 uiBlockSetEmboss(block, UI_EMBOSS);
2116 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
2117 uiItemL(sub, name, icon);
2118 uiBlockSetEmboss(block, UI_EMBOSS);
2119 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
2121 else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
2122 uiItemL(sub, name, icon);
2123 uiBlockSetEmboss(block, UI_EMBOSS);
2124 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
2126 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
2127 /* provision to draw active node name */
2128 Material *ma, *manode;
2129 Scene *scene= CTX_data_scene(C);
2130 Object *ob= (Object*)ptr->id.data;
2131 int index= (Material**)itemptr->data - ob->mat;
2133 /* default item with material base name */
2134 uiItemL(sub, name, icon);
2136 ma= give_current_material(ob, index+1);
2137 if (ma && !scene_use_new_shading_nodes(scene)){
2138 manode= give_node_material(ma);
2140 char str[MAX_ID_NAME + 12];
2141 BLI_snprintf(str, sizeof(str), "Node %s", manode->id.name+2);
2142 uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1));
2144 else if(ma->use_nodes) {
2145 uiItemL(sub, "Node <none>", ICON_NONE);
2149 else if(itemptr->type == &RNA_ShapeKey) {
2150 Object *ob= (Object*)activeptr->data;
2151 Key *key= (Key*)itemptr->id.data;
2153 split= uiLayoutSplit(sub, 0.75f, 0);
2155 uiItemL(split, name, icon);
2157 uiBlockSetEmboss(block, UI_EMBOSSN);
2158 row= uiLayoutRow(split, 1);
2159 if(i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE);
2160 else uiItemR(row, itemptr, "value", 0, "", ICON_NONE);
2162 if(ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH))
2163 uiLayoutSetActive(row, 0);
2164 //uiItemR(row, itemptr, "mute", 0, "", ICON_MUTE_IPO_OFF);
2165 uiBlockSetEmboss(block, UI_EMBOSS);
2167 else if(itemptr->type == &RNA_VertexGroup) {
2168 bDeformGroup *dg= (bDeformGroup *)itemptr->data;
2169 uiItemL(sub, name, icon);
2170 /* RNA does not allow nice lock icons, use lower level buttons */
2172 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "lock_weight", 0, 0, 0, 0, 0, NULL);
2174 uiBlockSetEmboss(block, UI_EMBOSSN);
2175 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");
2176 uiBlockSetEmboss(block, UI_EMBOSS);
2179 else if(itemptr->type == &RNA_KeyingSetPath) {
2180 KS_Path *ksp = (KS_Path*)itemptr->data;
2182 /* icon needs to be the type of ID which is currently active */
2183 RNA_enum_icon_from_value(id_type_items, ksp->idtype, &icon);
2185 /* nothing else special to do... */
2186 uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
2188 else if(itemptr->type == &RNA_DynamicPaintSurface) {
2189 char name_final[96];
2190 const char *enum_name;
2191 PropertyRNA *prop = RNA_struct_find_property(itemptr, "surface_type");
2192 DynamicPaintSurface *surface= (DynamicPaintSurface*)itemptr->data;
2194 RNA_property_enum_name(C, itemptr, prop, RNA_property_enum_get(itemptr, prop), &enum_name);
2196 BLI_snprintf(name_final, sizeof(name_final), "%s (%s)",name,enum_name);
2197 uiItemL(sub, name_final, icon);
2198 if (dynamicPaint_surfaceHasColorPreview(surface)) {
2199 uiBlockSetEmboss(block, UI_EMBOSSN);
2200 uiDefIconButR(block, OPTION, 0, (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON,
2201 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "show_preview", 0, 0, 0, 0, 0, NULL);
2202 uiBlockSetEmboss(block, UI_EMBOSS);
2204 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "is_active", i, 0, 0, 0, 0, NULL);
2206 else if(itemptr->type == &RNA_MovieTrackingObject) {
2207 MovieTrackingObject *tracking_object= (MovieTrackingObject*)itemptr->data;
2209 split= uiLayoutSplit(sub, 0.75f, 0);
2210 if(tracking_object->flag&TRACKING_OBJECT_CAMERA) {
2211 uiItemL(split, name, ICON_CAMERA_DATA);
2214 uiItemL(split, name, ICON_OBJECT_DATA);
2218 /* There is a last chance to display custom controls (in addition to the name/label):
2219 * If the given item property group features a string property named as prop_list,
2220 * this tries to add controls for all properties of the item listed in that string property.
2221 * (colon-separated names).
2223 * This is especially useful for python. E.g., if you list a collection of this property
2226 * class TestPropertyGroup(bpy.types.PropertyGroup):
2227 * bool = BoolProperty(default=False)
2228 * integer = IntProperty()
2229 * string = StringProperty()
2231 * # A string of all identifiers (colon-separated) which property’s controls should be
2232 * # displayed in a template_list.
2233 * template_list_controls = StringProperty(default="integer:bool:string", options={"HIDDEN"})
2235 * … you’ll get a numfield for the integer prop, a check box for the bool prop, and a textfield
2236 * for the string prop, after the name of each item of the collection.
2238 else if (prop_list_id) {
2239 row = uiLayoutRow(sub, 1);
2240 uiItemL(row, name, icon);
2242 /* XXX: Check, as sometimes we get an itemptr looking like
2243 * {id = {data = 0x0}, type = 0x0, data = 0x0}
2244 * which would obviously produce a sigsev… */
2245 if (itemptr->type) {
2246 /* If the special property is set for the item, and it is a collection… */
2247 PropertyRNA *prop_list= RNA_struct_find_property(itemptr, prop_list_id);
2249 if(prop_list && RNA_property_type(prop_list) == PROP_STRING) {
2251 char *prop_names = RNA_property_string_get_alloc(itemptr, prop_list, NULL, 0, &prop_names_len);
2252 char *prop_names_end= prop_names + prop_names_len;
2253 char *id= prop_names;
2255 while (id < prop_names_end) {
2256 if ((id_next= strchr(id, ':'))) *id_next++= '\0';
2257 else id_next= prop_names_end;
2258 uiItemR(row, itemptr, id, 0, NULL, 0);
2261 MEM_freeN(prop_names);
2267 uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
2274 void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype)
2276 //Scene *scene= CTX_data_scene(C);
2277 PropertyRNA *prop= NULL, *activeprop;
2278 PropertyType type, activetype;
2280 uiLayout *box, *row, *col;
2286 int rnaicon=0, icon=0, i= 0, activei= 0, len= 0, items, found, min, max;
2288 /* validate arguments */
2289 block= uiLayoutGetBlock(layout);
2293 RNA_warning("Only works inside a panel");
2297 if(!activeptr->data)
2301 prop= RNA_struct_find_property(ptr, propname);
2303 RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
2308 activeprop= RNA_struct_find_property(activeptr, activepropname);
2310 RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), activepropname);
2315 type= RNA_property_type(prop);
2316 if(type != PROP_COLLECTION) {
2317 RNA_warning("uiExpected collection property");
2322 activetype= RNA_property_type(activeprop);
2323 if(activetype != PROP_INT) {
2324 RNA_warning("Expected integer property");
2329 if(ptr->data && prop) {
2330 ptype= RNA_property_pointer_type(ptr, prop);
2331 rnaicon= RNA_struct_ui_icon(ptype);
2334 /* get active data */
2335 activei= RNA_property_int_get(activeptr, activeprop);
2337 if(listtype == 'i') {
2338 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2339 col= uiLayoutColumn(box, 1);
2340 row= uiLayoutRow(col, 0);
2342 if(ptr->data && prop) {
2343 /* create list items */
2344 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2347 row= uiLayoutRow(col, 0);
2349 icon= list_item_icon_get(C, &itemptr, rnaicon, 1);
2350 but= uiDefIconButR_prop(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activeprop, 0, 0, i, 0, 0, "");
2351 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2359 else if(listtype == 'c') {
2360 /* compact layout */
2362 row= uiLayoutRow(layout, 1);
2364 if(ptr->data && prop) {
2365 /* create list items */
2366 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2367 found= (activei == i);
2371 name= RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
2372 icon= list_item_icon_get(C, &itemptr, rnaicon, 0);
2373 uiItemL(row, (name)? name: "", icon);
2376 MEM_freeN((void *)name);
2384 /* if not found, add in dummy button */
2386 uiItemL(row, "", ICON_NONE);
2388 /* next/prev button */
2389 BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
2390 but= uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activeprop, 0, 0, 0, 0, 0, "");
2392 uiButSetFlag(but, UI_BUT_DISABLED);
2400 if(pa->list_grip_size != 0)
2401 rows= pa->list_grip_size;
2404 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2405 row= uiLayoutRow(box, 0);
2406 col = uiLayoutColumn(row, 1);
2409 RNA_property_int_range(activeptr, activeprop, &min, &max);
2412 len= RNA_property_collection_length(ptr, prop);
2413 items= CLAMPIS(len, rows, MAX2(rows, maxrows));
2415 /* if list length changes and active is out of view, scroll to it */
2416 if(pa->list_last_len != len)
2417 if((activei < pa->list_scroll || activei >= pa->list_scroll+items))
2418 pa->list_scroll= activei;
2420 pa->list_scroll= MIN2(pa->list_scroll, len-items);
2421 pa->list_scroll= MAX2(pa->list_scroll, 0);
2422 pa->list_size= items;
2423 pa->list_last_len= len;
2425 if(ptr->data && prop) {
2426 /* create list items */
2427 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2428 if(i >= pa->list_scroll && i<pa->list_scroll+items)
2429 list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activeprop, prop_list);
2436 /* add dummy buttons to fill space */
2437 while(i < pa->list_scroll+items) {
2438 if(i >= pa->list_scroll)
2439 uiItemL(col, "", ICON_NONE);
2445 col= uiLayoutColumn(row, 0);
2446 uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
2451 /************************* Operator Search Template **************************/
2453 static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
2455 wmOperatorType *ot= arg2;
2458 WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
2461 static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
2463 GHashIterator *iter= WM_operatortype_iter();
2465 for( ; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
2466 wmOperatorType *ot= BLI_ghashIterator_getValue(iter);
2468 if(BLI_strcasestr(ot->name, str)) {
2469 if(WM_operator_poll((bContext*)C, ot)) {
2471 int len= strlen(ot->name);
2473 /* display name for menu, can hold hotkey */
2474 BLI_strncpy(name, ot->name, sizeof(name));
2476 /* check for hotkey */
2477 if(len < sizeof(name)-6) {
2478 if (WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, TRUE,
2479 &name[len+1], sizeof(name)-len-1))
2485 if(0==uiSearchItemAdd(items, name, ot, 0))
2490 BLI_ghashIterator_free(iter);
2493 void uiTemplateOperatorSearch(uiLayout *layout)
2497 static char search[256]= "";
2499 block= uiLayoutGetBlock(layout);
2500 uiBlockSetCurLayout(block, layout);
2502 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, 0, 0, "");
2503 uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
2506 /************************* Running Jobs Template **************************/
2508 #define B_STOPRENDER 1
2509 #define B_STOPCAST 2
2510 #define B_STOPANIM 3
2511 #define B_STOPCOMPO 4
2513 #define B_STOPCLIP 6
2515 static void do_running_jobs(bContext *C, void *UNUSED(arg), int event)
2522 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL);
2525 WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
2528 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
2531 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
2534 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
2539 void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
2541 bScreen *screen= CTX_wm_screen(C);
2542 wmWindowManager *wm= CTX_wm_manager(C);
2543 ScrArea *sa= CTX_wm_area(C);
2548 block= uiLayoutGetBlock(layout);
2549 uiBlockSetCurLayout(block, layout);
2551 uiBlockSetHandleFunc(block, do_running_jobs, NULL);
2553 if(sa->spacetype==SPACE_NODE) {
2554 if(WM_jobs_test(wm, sa))
2556 handle_event= B_STOPCOMPO;
2557 } else if (sa->spacetype==SPACE_SEQ) {
2558 if(WM_jobs_test(wm, sa))
2560 handle_event = B_STOPSEQ;
2561 } else if(sa->spacetype==SPACE_CLIP) {
2562 if(WM_jobs_test(wm, sa))
2564 handle_event= B_STOPCLIP;
2567 /* another scene can be rendering too, for example via compositor */
2568 for(scene= CTX_data_main(C)->scene.first; scene; scene= scene->id.next)
2569 if(WM_jobs_test(wm, scene))
2572 handle_event= B_STOPRENDER;
2578 ui_abs= uiLayoutAbsolute(layout, 0);
2579 (void)ui_abs; // UNUSED
2581 uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE,
2582 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"));
2583 uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner),
2584 UI_UNIT_X, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, TIP_("Progress"));
2586 uiLayoutRow(layout, 0);
2588 if(WM_jobs_test(wm, screen))
2589 uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, IFACE_("Capture"), 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
2590 TIP_("Stop screencast"));
2591 if(screen->animtimer)
2592 uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, TIP_("Anim Player"), 0,0,100,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0,
2593 TIP_("Stop animation playback"));
2596 /************************* Reports for Last Operator Template **************************/
2598 void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
2600 ReportList *reports = CTX_wm_reports(C);
2601 Report *report= BKE_reports_last_displayable(reports);
2602 ReportTimerInfo *rti;
2607 uiStyle *style= UI_GetStyle();
2611 /* if the report display has timed out, don't show */
2612 if (!reports->reporttimer) return;
2614 rti= (ReportTimerInfo *)reports->reporttimer->customdata;
2616 if (!rti || rti->widthfac==0.0f || !report) return;
2618 ui_abs= uiLayoutAbsolute(layout, 0);
2619 block= uiLayoutGetBlock(ui_abs);
2621 width = BLF_width(style->widget.uifont_id, report->message);
2622 width = MIN2(rti->widthfac*width, width);
2623 width = MAX2(width, 10);
2625 /* make a box around the report to make it stand out */
2626 uiBlockBeginAlign(block);
2627 but= uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X+10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2628 /* set the report's bg color in but->col - ROUNDBOX feature */
2629 but->col[0]= FTOCHAR(rti->col[0]);
2630 but->col[1]= FTOCHAR(rti->col[1]);
2631 but->col[2]= FTOCHAR(rti->col[2]);
2634 but= uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2635 but->col[0]= but->col[1]= but->col[2]= FTOCHAR(rti->greyscale);
2638 uiBlockEndAlign(block);
2641 /* icon and report message on top */
2642 if(report->type & RPT_ERROR_ALL)
2644 else if(report->type & RPT_WARNING_ALL)
2646 else if(report->type & RPT_INFO_ALL)
2649 /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report
2650 * to be shown instead of icon when appropriate...
2652 uiBlockSetEmboss(block, UI_EMBOSSN);
2654 if (reports->list.first != reports->list.last)
2655 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'"));
2657 uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2659 uiBlockSetEmboss(block, UI_EMBOSS);
2661 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, "");
2664 /********************************* Keymap *************************************/
2666 static void keymap_item_modified(bContext *UNUSED(C), void *kmi_p, void *UNUSED(unused))
2668 wmKeyMapItem *kmi= (wmKeyMapItem*)kmi_p;
2669 WM_keyconfig_update_tag(NULL, kmi);
2672 static void template_keymap_item_properties(uiLayout *layout, const char *title, PointerRNA *ptr)
2679 uiItemL(layout, title, ICON_NONE);
2681 flow= uiLayoutColumnFlow(layout, 2, 0);
2683 RNA_STRUCT_BEGIN(ptr, prop) {
2684 int flag= RNA_property_flag(prop);
2686 if(flag & PROP_HIDDEN)
2689 /* recurse for nested properties */
2690 if(RNA_property_type(prop) == PROP_POINTER) {
2691 PointerRNA propptr= RNA_property_pointer_get(ptr, prop);
2692 const char *name= RNA_property_ui_name(prop);
2694 if(propptr.data && RNA_struct_is_a(propptr.type, &RNA_OperatorProperties)) {
2695 template_keymap_item_properties(layout, name, &propptr);
2701 uiItemR(flow, ptr, RNA_property_identifier(prop), 0, NULL, ICON_NONE);
2706 void uiTemplateKeymapItemProperties(uiLayout *layout, PointerRNA *ptr)
2708 PointerRNA propptr= RNA_pointer_get(ptr, "properties");
2711 uiBut *but= uiLayoutGetBlock(layout)->buttons.last;
2713 template_keymap_item_properties(layout, NULL, &propptr);
2715 /* attach callbacks to compensate for missing properties update,
2716 we don't know which keymap (item) is being modified there */
2717 for(; but; but=but->next)
2718 uiButSetFunc(but, keymap_item_modified, ptr->data, NULL);