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_key_types.h"
37 #include "DNA_scene_types.h"
38 #include "DNA_userdef_types.h"
40 #include "BLI_string.h"
41 #include "BLI_utildefines.h"
43 #include "BKE_animsys.h"
44 #include "BKE_colortools.h"
45 #include "BKE_context.h"
46 #include "BKE_global.h"
47 #include "BKE_library.h"
49 #include "BKE_object.h"
50 #include "BKE_material.h"
51 #include "BKE_texture.h"
52 #include "BKE_report.h"
53 #include "BKE_displist.h"
55 #include "ED_screen.h"
56 #include "ED_render.h"
58 #include "RNA_access.h"
63 #include "UI_interface.h"
64 #include "interface_intern.h"
68 void UI_template_fix_linking(void)
72 /********************** Header Template *************************/
74 void uiTemplateHeader(uiLayout *layout, bContext *C, int menus)
78 block= uiLayoutAbsoluteBlock(layout);
79 if(menus) ED_area_header_standardbuttons(C, block, 0);
80 else ED_area_header_switchbutton(C, block, 0);
83 /********************** Search Callbacks *************************/
85 typedef struct TemplateID {
90 int prv_rows, prv_cols;
93 /* Search browse menu, assign */
94 static void id_search_call_cb(bContext *C, void *arg_template, void *item)
96 TemplateID *template= (TemplateID*)arg_template;
102 RNA_id_pointer_create(item, &idptr);
103 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
104 RNA_property_update(C, &template->ptr, template->prop);
108 /* ID Search browse menu, do the search */
109 static void id_search_cb(const bContext *C, void *arg_template, const char *str, uiSearchItems *items)
111 TemplateID *template= (TemplateID*)arg_template;
112 ListBase *lb= template->idlb;
113 ID *id, *id_from= template->ptr.id.data;
115 int flag= RNA_property_flag(template->prop);
118 for(id= lb->first; id; id= id->next) {
119 if(!((flag & PROP_ID_SELF_CHECK) && id == id_from)) {
122 if(RNA_property_type(template->prop)==PROP_POINTER) {
124 RNA_id_pointer_create(id, &ptr);
125 if(RNA_property_pointer_poll(&template->ptr, template->prop, &ptr)==0)
129 /* hide dot-datablocks, but only if filter does not force it visible */
130 if(U.uiflag & USER_HIDE_DOT)
131 if ((id->name[2]=='.') && (str[0] != '.'))
134 if(BLI_strcasestr(id->name+2, str)) {
136 name_uiprefix_id(name_ui, id);
138 iconid= ui_id_icon_get((bContext*)C, id, 1);
140 if(!uiSearchItemAdd(items, name_ui, id, iconid))
147 /* ID Search browse menu, open */
148 static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
150 static char search[256];
151 static TemplateID template;
153 wmWindow *win= CTX_wm_window(C);
157 /* clear initial search string, then all items show */
159 /* arg_litem is malloced, can be freed by parent button */
160 template= *((TemplateID*)arg_litem);
162 /* get active id for showing first item */
163 idptr= RNA_property_pointer_get(&template.ptr, template.prop);
165 block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
166 uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
168 /* preview thumbnails */
169 if (template.prv_rows > 0 && template.prv_cols > 0) {
170 int w = 96 * template.prv_cols;
171 int h = 96 * template.prv_rows + 20;
173 /* fake button, it holds space for search items */
174 uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL);
176 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, w, 19, template.prv_rows, template.prv_cols, "");
177 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
181 /* fake button, it holds space for search items */
182 uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
184 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, 0, 0, "");
185 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
189 uiBoundsBlock(block, 6);
190 uiBlockSetDirection(block, UI_DOWN);
191 uiEndBlock(C, block);
193 /* give search-field focus */
194 uiButSetFocusOnEnter(win, but);
195 /* this type of search menu requires undo */
196 but->flag |= UI_BUT_UNDO;
201 /************************ ID Template ***************************/
202 /* This is for browsing and editing the ID-blocks used */
204 /* for new/open operators */
205 void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
207 TemplateID *template;
208 ARegion *ar= CTX_wm_region(C);
212 memset(ptr, 0, sizeof(*ptr));
218 for(block=ar->uiblocks.first; block; block=block->next) {
219 for(but=block->buttons.first; but; but= but->next) {
220 /* find the button before the active one */
221 if((but->flag & (UI_BUT_LAST_ACTIVE|UI_ACTIVE))) {
223 template= but->func_argN;
225 *prop= template->prop;
234 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
236 TemplateID *template= (TemplateID*)arg_litem;
237 PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
238 ID *id= idptr.data, *newid;
239 int event= GET_INT_FROM_POINTER(arg_event);
244 RNA_warning("warning, id event %d shouldnt come here\n", event);
248 /* these call uiIDContextPropertySet */
251 memset(&idptr, 0, sizeof(idptr));
252 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
253 RNA_property_update(C, &template->ptr, template->prop);
255 if(id && CTX_wm_window(C)->eventstate->shift) /* useful hidden functionality, */
259 case UI_ID_FAKE_USER:
261 if(id->flag & LIB_FAKEUSER) id_us_plus(id);
268 if(id_make_local(id, 0)) {
269 /* reassign to get get proper updates/notifiers */
270 idptr= RNA_property_pointer_get(&template->ptr, template->prop);
271 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
272 RNA_property_update(C, &template->ptr, template->prop);
279 if(id_copy(id, &newid, 0) && newid) {
280 /* copy animation actions too */
281 BKE_copy_animdata_id_action(id);
282 /* us is 1 by convention, but RNA_property_pointer_set
283 will also incremement it, so set it to zero */
287 RNA_id_pointer_create(newid, &idptr);
288 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
289 RNA_property_update(C, &template->ptr, template->prop);
294 case UI_ID_AUTO_NAME:
300 static const char *template_id_browse_tip(StructRNA *type)
303 switch(RNA_type_to_ID_code(type)) {
304 case ID_SCE: return "Browse Scene to be linked";
305 case ID_OB: return "Browse Object to be linked";
306 case ID_ME: return "Browse Mesh Data to be linked";
307 case ID_CU: return "Browse Curve Data to be linked";
308 case ID_MB: return "Browse MetaBall Data to be linked";
309 case ID_MA: return "Browse Material to be linked";
310 case ID_TE: return "Browse Texture to be linked";
311 case ID_IM: return "Browse Image to be linked";
312 case ID_LA: return "Browse Lattice Data to be linked";
313 case ID_CA: return "Browse Camera Data to be linked";
314 case ID_WO: return "Browse World Settings to be linked";
315 case ID_SCR: return "Choose Screen lay-out";
316 case ID_TXT: return "Browse Text to be linked";
317 case ID_SO: return "Browse Sound to be linked";
318 case ID_AR: return "Browse Armature data to be linked";
319 case ID_AC: return "Browse Action to be linked";
320 case ID_NT: return "Browse Node Tree to be linked";
321 case ID_BR: return "Browse Brush to be linked";
322 case ID_PA: return "Browse Particle System to be linked";
323 case ID_GD: return "Browse Grease Pencil Data to be linked";
326 return "Browse ID data to be linked";
329 static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag, const char *newop, const char *openop, const char *unlinkop)
334 // ListBase *lb; // UNUSED
336 int editable= RNA_property_editable(&template->ptr, template->prop);
338 idptr= RNA_property_pointer_get(&template->ptr, template->prop);
340 idfrom= template->ptr.id.data;
341 // lb= template->idlb;
343 block= uiLayoutGetBlock(layout);
344 uiBlockBeginAlign(block);
349 if(flag & UI_ID_PREVIEWS) {
351 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, template_id_browse_tip(type));
353 but->icon= RNA_struct_ui_icon(type);
354 if (id) but->icon = ui_id_icon_get(C, id, 1);
355 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_PREVIEW);
357 if((idfrom && idfrom->lib) || !editable)
358 uiButSetFlag(but, UI_BUT_DISABLED);
360 uiLayoutRow(layout, 1);
362 else if(flag & UI_ID_BROWSE) {
363 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y, template_id_browse_tip(type));
365 but->icon= RNA_struct_ui_icon(type);
366 /* default dragging of icon for id browse buttons */
367 uiButSetDragID(but, id);
368 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_LEFT);
371 if((idfrom && idfrom->lib) || !editable)
372 uiButSetFlag(but, UI_BUT_DISABLED);
375 /* text button with name */
377 char name[UI_MAX_NAME_STR];
378 const short user_alert= (id->us <= 0);
380 //text_idbutton(id, name);
382 but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
383 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
384 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
387 if(id->flag & LIB_INDIRECT) {
388 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0,
389 "Indirect library datablock, cannot change.");
390 uiButSetFlag(but, UI_BUT_DISABLED);
393 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0,
394 "Direct linked library datablock, click to make local.");
395 if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib))
396 uiButSetFlag(but, UI_BUT_DISABLED);
399 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
405 sprintf(str, "%d", id->us);
408 but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
410 but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X+10,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
412 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
413 if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib) || !editable)
414 uiButSetFlag(but, UI_BUT_DISABLED);
417 if(user_alert) uiButSetFlag(but, UI_BUT_REDALERT);
419 if(id->lib == NULL && !(ELEM5(GS(id->name), ID_GR, ID_SCE, ID_SCR, ID_TXT, ID_OB))) {
420 uiDefButR(block, TOG, 0, "F", 0, 0, UI_UNIT_X, UI_UNIT_Y, &idptr, "use_fake_user", -1, 0, 0, -1, -1, NULL);
424 if(flag & UI_ID_ADD_NEW) {
425 int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
428 but= uiDefIconTextButO(block, BUT, newop, WM_OP_INVOKE_DEFAULT, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
429 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
432 but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
433 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
436 if((idfrom && idfrom->lib) || !editable)
437 uiButSetFlag(but, UI_BUT_DISABLED);
440 if(flag & UI_ID_OPEN) {
441 int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
444 but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
445 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
448 but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
449 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
452 if((idfrom && idfrom->lib) || !editable)
453 uiButSetFlag(but, UI_BUT_DISABLED);
457 if(id && (flag & UI_ID_DELETE) && (RNA_property_flag(template->prop) & PROP_NEVER_UNLINK)==0) {
459 but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
460 /* so we can access the template from operators, font unlinking needs this */
461 uiButSetNFunc(but, NULL, MEM_dupallocN(template), NULL);
464 but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, "Unlink datablock. Shift + Click to set users to zero, data will then not be saved");
465 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
467 if(RNA_property_flag(template->prop) & PROP_NEVER_NULL)
468 uiButSetFlag(but, UI_BUT_DISABLED);
471 if((idfrom && idfrom->lib) || !editable)
472 uiButSetFlag(but, UI_BUT_DISABLED);
475 uiBlockEndAlign(block);
478 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)
480 TemplateID *template;
484 prop= RNA_struct_find_property(ptr, propname);
486 if(!prop || RNA_property_type(prop) != PROP_POINTER) {
487 RNA_warning("uiTemplateID: pointer property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
491 template= MEM_callocN(sizeof(TemplateID), "TemplateID");
493 template->prop= prop;
494 template->prv_rows = prv_rows;
495 template->prv_cols = prv_cols;
498 flag |= UI_ID_ADD_NEW;
502 type= RNA_property_pointer_type(ptr, prop);
503 template->idlb= which_libbase(CTX_data_main(C), RNA_type_to_ID_code(type));
505 /* create UI elements for this template
506 * - template_ID makes a copy of the template data and assigns it to the relevant buttons
509 uiLayoutRow(layout, 1);
510 template_ID(C, layout, template, type, flag, newop, openop, unlinkop);
516 void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
518 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE, 0, 0);
521 void uiTemplateIDBrowse(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop)
523 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME, 0, 0);
526 void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop, int rows, int cols)
528 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE|UI_ID_PREVIEWS, rows, cols);
531 /************************ ID Chooser Template ***************************/
533 /* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use
535 * - propname: property identifier for property that ID-pointer gets stored to
536 * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used
538 void uiTemplateAnyID(uiLayout *layout, PointerRNA *ptr, const char *propname, const char *proptypename, const char *text)
540 PropertyRNA *propID, *propType;
543 /* get properties... */
544 propID= RNA_struct_find_property(ptr, propname);
545 propType= RNA_struct_find_property(ptr, proptypename);
547 if (!propID || RNA_property_type(propID) != PROP_POINTER) {
548 RNA_warning("uiTemplateAnyID: pointer property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
551 if (!propType || RNA_property_type(propType) != PROP_ENUM) {
552 RNA_warning("uiTemplateAnyID: pointer-type property not found: %s.%s\n", RNA_struct_identifier(ptr->type), proptypename);
556 /* Start drawing UI Elements using standard defines */
557 row= uiLayoutRow(layout, 1);
559 /* Label - either use the provided text, or will become "ID-Block:" */
561 uiItemL(row, text, ICON_NONE);
563 uiItemL(row, "ID-Block:", ICON_NONE);
565 /* ID-Type Selector - just have a menu of icons */
566 // FIXME: the icon-only setting doesn't work when we supply a blank name
567 uiItemFullR(row, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
569 /* ID-Block Selector - just use pointer widget... */
570 uiItemFullR(row, ptr, propID, 0, 0, 0, "", ICON_NONE);
573 /********************* RNA Path Builder Template ********************/
577 /* This is creating/editing RNA-Paths
579 * - ptr: struct which holds the path property
580 * - propname: property identifier for property that path gets stored to
581 * - root_ptr: struct that path gets built from
583 void uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const char *propname, PointerRNA *UNUSED(root_ptr), const char *text)
585 PropertyRNA *propPath;
588 /* check that properties are valid */
589 propPath= RNA_struct_find_property(ptr, propname);
590 if (!propPath || RNA_property_type(propPath) != PROP_STRING) {
591 RNA_warning("uiTemplatePathBuilder: path property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
595 /* Start drawing UI Elements using standard defines */
596 row= uiLayoutRow(layout, 1);
598 /* Path (existing string) Widget */
599 uiItemR(row, ptr, propname, 0, text, ICON_RNA);
601 // TODO: attach something to this to make allow searching of nested properties to 'build' the path
604 /************************ Modifier Template *************************/
606 #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
610 #include "DNA_object_force.h"
612 #include "BKE_depsgraph.h"
613 #include "BKE_modifier.h"
614 #include "BKE_particle.h"
618 #include "BLI_math.h"
619 #include "BLI_listbase.h"
621 #include "ED_object.h"
623 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
625 Scene *scene = CTX_data_scene(C);
627 ModifierData *md= md_v;
628 int i, cageIndex = modifiers_getCageIndex(scene, ob, NULL, 0);
630 /* undo button operation */
631 md->mode ^= eModifierMode_OnCage;
633 for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) {
636 md->mode ^= eModifierMode_OnCage;
641 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
642 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
645 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
648 ModifierData *md = md_v;
649 ModifierData *nmd = modifier_new(md->type);
651 modifier_copyData(md, nmd);
652 nmd->mode &= ~eModifierMode_Virtual;
654 BLI_addhead(&ob->modifiers, nmd);
656 modifier_unique_name(&ob->modifiers, nmd);
658 ob->partype = PAROBJECT;
660 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
661 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
663 ED_undo_push(C, "Modifier convert to real");
666 static int modifier_can_delete(ModifierData *md)
668 // fluid particle modifier can't be deleted here
669 if(md->type == eModifierType_ParticleSystem)
670 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
676 // Check wheter Modifier is a simulation or not, this is used for switching to the physics/particles context tab
677 static int modifier_is_simulation(ModifierData *md)
680 if(ELEM6(md->type, eModifierType_Cloth, eModifierType_Collision, eModifierType_Fluidsim, eModifierType_Smoke, eModifierType_Softbody, eModifierType_Surface)) {
684 else if (md->type == eModifierType_ParticleSystem) {
692 static uiLayout *draw_modifier(uiLayout *layout, Scene *scene, Object *ob, ModifierData *md, int index, int cageIndex, int lastCageIndex)
694 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
698 uiLayout *box, *column, *row;
699 uiLayout *result= NULL;
700 int isVirtual = (md->mode & eModifierMode_Virtual);
703 /* create RNA pointer */
704 RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
706 column= uiLayoutColumn(layout, 1);
707 uiLayoutSetContextPointer(column, "modifier", &ptr);
709 /* rounded header ------------------------------------------------------------------- */
710 box= uiLayoutBox(column);
713 row= uiLayoutRow(box, 0);
714 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
715 block= uiLayoutGetBlock(row);
716 /* VIRTUAL MODIFIER */
717 // XXX this is not used now, since these cannot be accessed via RNA
718 sprintf(str, "%s parent deform", md->name);
719 uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name");
721 but = uiDefBut(block, BUT, 0, "Make Real", 0, 0, 80, 16, NULL, 0.0, 0.0, 0.0, 0.0, "Convert virtual modifier to a real modifier");
722 uiButSetFunc(but, modifiers_convertToReal, ob, md);
726 row = uiLayoutRow(box, 0);
727 block = uiLayoutGetBlock(row);
729 uiBlockSetEmboss(block, UI_EMBOSSN);
730 /* Open/Close ................................. */
731 uiItemR(row, &ptr, "show_expanded", 0, "", ICON_NONE);
733 /* modifier-type icon */
734 uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
735 uiBlockSetEmboss(block, UI_EMBOSS);
738 uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
740 /* mode enabling buttons */
741 uiBlockBeginAlign(block);
742 /* Softbody not allowed in this situation, enforce! */
743 if ( ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect))
744 && (md->type!=eModifierType_Surface) )
746 uiItemR(row, &ptr, "show_render", 0, "", ICON_NONE);
747 uiItemR(row, &ptr, "show_viewport", 0, "", ICON_NONE);
749 if (mti->flags & eModifierTypeFlag_SupportsEditmode)
750 uiItemR(row, &ptr, "show_in_editmode", 0, "", ICON_NONE);
752 if ((ob->type==OB_MESH) && modifier_couldBeCage(scene, md) && (index <= lastCageIndex))
754 /* -- convert to rna ? */
755 but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, UI_UNIT_X-2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode");
756 if (index < cageIndex)
757 uiButSetFlag(but, UI_BUT_DISABLED);
758 uiButSetFunc(but, modifiers_setOnCage, ob, md);
761 /* tesselation point for curve-typed objects */
762 if (ELEM3(ob->type, OB_CURVE, OB_SURF, OB_FONT)) {
763 /* some modifiers could work with pre-tesselated curves only */
764 if (ELEM3(md->type, eModifierType_Hook, eModifierType_Softbody, eModifierType_MeshDeform)) {
765 /* add disabled pre-tesselated button, so users could have
766 message for this modifiers */
767 but = uiDefIconButBitI(block, TOG, eModifierMode_ApplyOnSpline, 0, ICON_SURFACE_DATA, 0, 0, UI_UNIT_X-2, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, "This modifier could be applied on splines' points only");
768 uiButSetFlag(but, UI_BUT_DISABLED);
769 } else if (mti->type != eModifierTypeType_Constructive) {
770 /* constructive modifiers tesselates curve before applying */
771 uiItemR(row, &ptr, "use_apply_on_spline", 0, "", ICON_NONE);
775 uiBlockEndAlign(block);
777 /* Up/Down + Delete ........................... */
778 uiBlockBeginAlign(block);
779 uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up");
780 uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down");
781 uiBlockEndAlign(block);
783 uiBlockSetEmboss(block, UI_EMBOSSN);
784 // When Modifier is a simulation, show button to switch to context rather than the delete button.
785 if (modifier_can_delete(md) && !modifier_is_simulation(md))
786 uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
787 if (modifier_is_simulation(md) == 1)
788 uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PHYSICS");
789 else if (modifier_is_simulation(md) == 2)
790 uiItemStringO(row, "", ICON_BUTS, "WM_OT_properties_context_change", "context", "PARTICLES");
791 uiBlockSetEmboss(block, UI_EMBOSS);
795 /* modifier settings (under the header) --------------------------------------------------- */
796 if (!isVirtual && (md->mode & eModifierMode_Expanded)) {
797 /* apply/convert/copy */
798 box= uiLayoutBox(column);
799 row= uiLayoutRow(box, 0);
801 if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) {
802 /* only here obdata, the rest of modifiers is ob level */
803 uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
805 if (md->type==eModifierType_ParticleSystem) {
806 ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
808 if (!(ob->mode & OB_MODE_PARTICLE_EDIT) && psys->pathcache) {
809 if(ELEM(psys->part->ren_as, PART_DRAW_GR, PART_DRAW_OB))
810 uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_duplicates_make_real");
811 else if(psys->part->ren_as == PART_DRAW_PATH)
812 uiItemO(row, "Convert", ICON_NONE, "OBJECT_OT_modifier_convert");
816 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
817 uiItemEnumO(row, "OBJECT_OT_modifier_apply", "Apply", 0, "apply_as", MODIFIER_APPLY_DATA);
819 if (modifier_sameTopology(md))
820 uiItemEnumO(row, "OBJECT_OT_modifier_apply", "Apply as Shape", 0, "apply_as", MODIFIER_APPLY_SHAPE);
823 uiBlockClearButLock(block);
824 uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
826 if (!ELEM5(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth, eModifierType_Smoke))
827 uiItemO(row, "Copy", ICON_NONE, "OBJECT_OT_modifier_copy");
830 /* result is the layout block inside the box, that we return so that modifier settings can be drawn */
831 result= uiLayoutColumn(box, 0);
832 block= uiLayoutAbsoluteBlock(box);
837 box = uiLayoutBox(column);
838 row = uiLayoutRow(box, 0);
839 uiItemL(row, md->error, ICON_ERROR);
845 uiLayout *uiTemplateModifier(uiLayout *layout, bContext *C, PointerRNA *ptr)
847 Scene *scene = CTX_data_scene(C);
849 ModifierData *md, *vmd;
850 int i, lastCageIndex, cageIndex;
852 /* verify we have valid data */
853 if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
854 RNA_warning("uiTemplateModifier: Expected modifier on object.\n");
861 if(!ob || !(GS(ob->id.name) == ID_OB)) {
862 RNA_warning("uiTemplateModifier: Expected modifier on object.\n");
866 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
868 /* find modifier and draw it */
869 cageIndex = modifiers_getCageIndex(scene, ob, &lastCageIndex, 0);
871 // XXX virtual modifiers are not accesible for python
872 vmd = modifiers_getVirtualModifierList(ob);
874 for(i=0; vmd; i++, vmd=vmd->next) {
876 return draw_modifier(layout, scene, ob, md, i, cageIndex, lastCageIndex);
877 else if(vmd->mode & eModifierMode_Virtual)
884 /************************ Constraint Template *************************/
886 #include "DNA_constraint_types.h"
888 #include "BKE_action.h"
889 #include "BKE_constraint.h"
893 #define REDRAWBUTSOBJECT 3
894 #define REDRAWACTION 4
895 #define B_CONSTRAINT_TEST 5
896 #define B_CONSTRAINT_CHANGETARGET 6
900 static void do_constraint_panels(bContext *C, void *ob_pt, int event)
902 Main *bmain= CTX_data_main(C);
903 Scene *scene= CTX_data_scene(C);
904 Object *ob= (Object *)ob_pt;
907 case B_CONSTRAINT_TEST:
908 break; // no handling
909 case B_CONSTRAINT_CHANGETARGET:
910 if (ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels
911 DAG_scene_sort(bmain, scene);
917 // note: RNA updates now call this, commenting else it gets called twice.
918 // if there are problems because of this, then rna needs changed update functions.
920 // object_test_constraints(ob);
921 // if(ob->pose) update_pose_constraint_flags(ob->pose);
923 if(ob->type==OB_ARMATURE) DAG_id_tag_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB);
924 else DAG_id_tag_update(&ob->id, OB_RECALC_OB);
926 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
929 static void constraint_active_func(bContext *UNUSED(C), void *ob_v, void *con_v)
931 ED_object_constraint_set_active(ob_v, con_v);
934 /* draw panel showing settings for a constraint */
935 static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
937 bPoseChannel *pchan= get_active_posechannel(ob);
938 bConstraintTypeInfo *cti;
940 uiLayout *result= NULL, *col, *box, *row;
943 short proxy_protected, xco=0, yco=0;
944 // int rb_col; // UNUSED
946 /* get constraint typeinfo */
947 cti= constraint_get_typeinfo(con);
949 /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
950 if (con->type == CONSTRAINT_TYPE_NULL)
951 strcpy(typestr, "Null");
953 strcpy(typestr, "Unknown");
956 strcpy(typestr, cti->name);
958 /* determine whether constraint is proxy protected or not */
959 if (proxylocked_constraints_owner(ob, pchan))
960 proxy_protected= (con->flag & CONSTRAINT_PROXY_LOCAL)==0;
964 /* unless button has own callback, it adds this callback to button */
965 block= uiLayoutGetBlock(layout);
966 uiBlockSetHandleFunc(block, do_constraint_panels, ob);
967 uiBlockSetFunc(block, constraint_active_func, ob, con);
969 RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
971 col= uiLayoutColumn(layout, 1);
972 uiLayoutSetContextPointer(col, "constraint", &ptr);
974 box= uiLayoutBox(col);
975 row = uiLayoutRow(box, 0);
976 block= uiLayoutGetBlock(box);
978 /* Draw constraint header */
981 uiBlockSetEmboss(block, UI_EMBOSSN);
982 uiItemR(row, &ptr, "show_expanded", UI_ITEM_R_ICON_ONLY, "", ICON_NONE);
983 uiBlockSetEmboss(block, UI_EMBOSS);
986 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
988 if (con->flag & CONSTRAINT_DISABLE)
989 uiLayoutSetRedAlert(row, 1);
991 if(proxy_protected == 0) {
992 uiItemR(row, &ptr, "name", 0, "", ICON_NONE);
995 uiItemL(row, con->name, ICON_NONE);
997 uiLayoutSetRedAlert(row, 0);
999 /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
1000 if (proxy_protected) {
1001 uiBlockSetEmboss(block, UI_EMBOSSN);
1003 /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */
1004 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco+244, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
1005 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco+262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
1007 uiBlockSetEmboss(block, UI_EMBOSS);
1010 short prev_proxylock, show_upbut, show_downbut;
1013 * Proxy-constraints are not allowed to occur after local (non-proxy) constraints
1014 * as that poses problems when restoring them, so disable the "up" button where
1015 * it may cause this situation.
1017 * Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose.
1019 if (proxylocked_constraints_owner(ob, pchan)) {
1021 prev_proxylock= (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
1029 show_upbut= ((prev_proxylock == 0) && (con->prev));
1030 show_downbut= (con->next) ? 1 : 0;
1033 uiBlockSetEmboss(block, UI_EMBOSSN);
1034 uiItemR(row, &ptr, "mute", 0, "", (con->flag & CONSTRAINT_OFF) ? ICON_MUTE_IPO_ON : ICON_MUTE_IPO_OFF);
1035 uiBlockSetEmboss(block, UI_EMBOSS);
1037 uiLayoutSetOperatorContext(row, WM_OP_INVOKE_DEFAULT);
1040 if (show_upbut || show_downbut) {
1041 uiBlockBeginAlign(block);
1043 uiItemO(row, "", ICON_TRIA_UP, "CONSTRAINT_OT_move_up");
1046 uiItemO(row, "", ICON_TRIA_DOWN, "CONSTRAINT_OT_move_down");
1047 uiBlockEndAlign(block);
1050 /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
1051 uiBlockSetEmboss(block, UI_EMBOSSN);
1052 uiItemO(row, "", ICON_X, "CONSTRAINT_OT_delete");
1053 uiBlockSetEmboss(block, UI_EMBOSS);
1056 /* Set but-locks for protected settings (magic numbers are used here!) */
1057 if (proxy_protected)
1058 uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint");
1060 /* Draw constraint data */
1061 if ((con->flag & CONSTRAINT_EXPAND) == 0) {
1065 box= uiLayoutBox(col);
1066 block= uiLayoutAbsoluteBlock(box);
1070 /* clear any locks set up for proxies/lib-linking */
1071 uiBlockClearButLock(block);
1076 uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
1081 /* verify we have valid data */
1082 if(!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
1083 RNA_warning("uiTemplateConstraint: Expected constraint on object.\n");
1090 if(!ob || !(GS(ob->id.name) == ID_OB)) {
1091 RNA_warning("uiTemplateConstraint: Expected constraint on object.\n");
1095 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
1097 /* hrms, the temporal constraint should not draw! */
1098 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
1099 bKinematicConstraint *data= con->data;
1100 if(data->flag & CONSTRAINT_IK_TEMP)
1104 return draw_constraint(layout, ob, con);
1108 /************************* Preview Template ***************************/
1110 #include "DNA_lamp_types.h"
1111 #include "DNA_material_types.h"
1112 #include "DNA_world_types.h"
1116 static void do_preview_buttons(bContext *C, void *arg, int event)
1120 WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, arg);
1125 void uiTemplatePreview(uiLayout *layout, ID *id, int show_buttons, ID *parent, MTex *slot)
1127 uiLayout *row, *col;
1130 Tex *tex = (Tex*)id;
1132 short *pr_texture= NULL;
1133 PointerRNA material_ptr;
1134 PointerRNA texture_ptr;
1136 if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
1137 RNA_warning("uiTemplatePreview: Expected ID of type material, texture, lamp or world.\n");
1141 /* decide what to render */
1145 if(id && (GS(id->name) == ID_TE)) {
1146 if(parent && (GS(parent->name) == ID_MA))
1147 pr_texture= &((Material*)parent)->pr_texture;
1148 else if(parent && (GS(parent->name) == ID_WO))
1149 pr_texture= &((World*)parent)->pr_texture;
1150 else if(parent && (GS(parent->name) == ID_LA))
1151 pr_texture= &((Lamp*)parent)->pr_texture;
1154 if(*pr_texture == TEX_PR_OTHER)
1156 else if(*pr_texture == TEX_PR_BOTH)
1162 block= uiLayoutGetBlock(layout);
1163 row= uiLayoutRow(layout, 0);
1164 col= uiLayoutColumn(row, 0);
1165 uiLayoutSetKeepAspect(col, 1);
1168 uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, pid, 0.0, 0.0, 0, 0, "");
1169 uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot);
1170 uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
1173 if (pid && show_buttons) {
1174 if(GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
1175 if(GS(pid->name) == ID_MA) ma= (Material*)pid;
1176 else ma= (Material*)pparent;
1178 /* Create RNA Pointer */
1179 RNA_pointer_create(id, &RNA_Material, ma, &material_ptr);
1181 col = uiLayoutColumn(row, 1);
1182 uiLayoutSetScaleX(col, 1.5);
1183 uiItemR(col, &material_ptr, "preview_render_type", UI_ITEM_R_EXPAND, "", ICON_NONE);
1187 /* Create RNA Pointer */
1188 RNA_pointer_create(id, &RNA_Texture, tex, &texture_ptr);
1190 uiLayoutRow(layout, 1);
1191 uiDefButS(block, ROW, B_MATPRV, "Texture", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
1192 if(GS(parent->name) == ID_MA)
1193 uiDefButS(block, ROW, B_MATPRV, "Material", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1194 else if(GS(parent->name) == ID_LA)
1195 uiDefButS(block, ROW, B_MATPRV, "Lamp", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1196 else if(GS(parent->name) == ID_WO)
1197 uiDefButS(block, ROW, B_MATPRV, "World", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1198 uiDefButS(block, ROW, B_MATPRV, "Both", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
1200 /* Alpha buton for texture preview */
1201 if(*pr_texture!=TEX_PR_OTHER) {
1202 row = uiLayoutRow(layout, 0);
1203 uiItemR(row, &texture_ptr, "use_preview_alpha", 0, NULL, ICON_NONE);
1209 /********************** ColorRamp Template **************************/
1212 typedef struct RNAUpdateCb {
1217 static void rna_update_cb(bContext *C, void *arg_cb, void *UNUSED(arg))
1219 RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
1221 /* we call update here on the pointer property, this way the
1222 owner of the curve mapping can still define it's own update
1223 and notifier, even if the CurveMapping struct is shared. */
1224 RNA_property_update(C, &cb->ptr, cb->prop);
1229 static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
1231 ColorBand *coba= coba_v;
1235 if(coba->cur > 0) pos= (coba->data[coba->cur-1].pos + coba->data[coba->cur].pos) * 0.5f;
1236 else pos= (coba->data[coba->cur+1].pos + coba->data[coba->cur].pos) * 0.5f;
1239 if(colorband_element_add(coba, pos)) {
1240 rna_update_cb(C, cb_v, NULL);
1241 ED_undo_push(C, "Add colorband");
1245 static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v)
1247 ColorBand *coba= coba_v;
1249 if(colorband_element_remove(coba, coba->cur)) {
1250 ED_undo_push(C, "Delete colorband");
1251 rna_update_cb(C, cb_v, NULL);
1255 static void colorband_flip_cb(bContext *C, void *cb_v, void *coba_v)
1257 CBData data_tmp[MAXCOLORBAND];
1259 ColorBand *coba= coba_v;
1262 for(a=0; a<coba->tot; a++) {
1263 data_tmp[a]= coba->data[coba->tot - (a + 1)];
1265 for(a=0; a<coba->tot; a++) {
1266 data_tmp[a].pos = 1.0f - data_tmp[a].pos;
1267 coba->data[a]= data_tmp[a];
1270 /* may as well flip the cur*/
1271 coba->cur= coba->tot - (coba->cur + 1);
1273 ED_undo_push(C, "Flip colorband");
1275 rna_update_cb(C, cb_v, NULL);
1279 /* offset aligns from bottom, standard width 300, height 115 */
1280 static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb)
1284 const int line1_y= yoffs + 65 + UI_UNIT_Y + 2; /* 2 for some space between the buttons */
1285 const int line2_y= yoffs + 65;
1287 if(coba==NULL) return;
1289 bt= uiDefBut(block, BUT, 0, "Add", 0+xoffs,line1_y,40,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband");
1290 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1292 bt= uiDefBut(block, BUT, 0, "Delete", 45+xoffs,line1_y,45,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Delete the active position");
1293 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1296 /* XXX, todo for later - convert to operator - campbell */
1297 bt= uiDefBut(block, BUT, 0, "F", 95+xoffs,line1_y,20,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Flip colorband");
1298 uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
1300 uiDefButS(block, NUM, 0, "", 120+xoffs,line1_y,80, UI_UNIT_Y, &coba->cur, 0.0, (float)(MAX2(0, coba->tot-1)), 0, 0, "Choose active color stop");
1302 bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1303 210+xoffs, line1_y, 90, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1304 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1305 uiBlockEndAlign(block);
1307 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xoffs,line2_y,300,UI_UNIT_Y, coba, 0, 0, 0, 0, "");
1308 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1313 CBData *cbd= coba->data + coba->cur;
1315 /* better to use rna so we can animate them */
1317 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1318 row= uiLayoutRow(layout, 0);
1319 uiItemR(row, &ptr, "position", 0, "Pos", ICON_NONE);
1320 uiItemR(row, &ptr, "color", 0, "", ICON_NONE);
1325 static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
1328 float unit= (butr->xmax-butr->xmin)/14.0f;
1329 float xs= butr->xmin;
1331 uiBlockBeginAlign(block);
1332 bt= uiDefBut(block, BUT, 0, "Add", xs,butr->ymin+UI_UNIT_Y,2.0f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband");
1333 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1334 bt= uiDefBut(block, BUT, 0, "Delete", xs+2.0f*unit,butr->ymin+UI_UNIT_Y,1.5f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Delete the active position");
1335 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1336 bt= uiDefBut(block, BUT, 0, "F", xs+3.5f*unit,butr->ymin+UI_UNIT_Y,0.5f*unit,UI_UNIT_Y, NULL, 0, 0, 0, 0, "Flip the color ramp");
1337 uiButSetNFunc(bt, colorband_flip_cb, MEM_dupallocN(cb), coba);
1338 uiBlockEndAlign(block);
1341 CBData *cbd= coba->data + coba->cur;
1343 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1344 uiItemR(layout, &ptr, "color", 0, "", ICON_NONE);
1347 bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1348 xs+10.0f*unit, butr->ymin+UI_UNIT_Y, unit*4, UI_UNIT_Y, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1349 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1351 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xs,butr->ymin,butr->xmax-butr->xmin,UI_UNIT_Y, coba, 0, 0, 0, 0, "");
1352 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1354 uiBlockEndAlign(block);
1357 static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb)
1360 colorband_buttons_small(layout, block, coba, butr, cb);
1362 colorband_buttons_large(layout, block, coba, 0, 0, cb);
1365 void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, const char *propname, int expand)
1367 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1373 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1376 cptr= RNA_property_pointer_get(ptr, prop);
1377 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp))
1380 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1384 rect.xmin= 0; rect.xmax= 200;
1385 rect.ymin= 0; rect.ymax= 190;
1387 block= uiLayoutAbsoluteBlock(layout);
1388 colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1393 /********************* Histogram Template ************************/
1395 void uiTemplateHistogram(uiLayout *layout, PointerRNA *ptr, const char *propname)
1397 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1405 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1408 cptr= RNA_property_pointer_get(ptr, prop);
1409 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Histogram))
1412 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1416 rect.xmin= 0; rect.xmax= 200;
1417 rect.ymin= 0; rect.ymax= 190;
1419 block= uiLayoutAbsoluteBlock(layout);
1420 //colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1422 hist = (Histogram *)cptr.data;
1424 hist->height= (hist->height<=UI_UNIT_Y)?UI_UNIT_Y:hist->height;
1426 bt= uiDefBut(block, HISTOGRAM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, hist->height, hist, 0, 0, 0, 0, "");
1427 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1432 /********************* Waveform Template ************************/
1434 void uiTemplateWaveform(uiLayout *layout, PointerRNA *ptr, const char *propname)
1436 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1444 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1447 cptr= RNA_property_pointer_get(ptr, prop);
1448 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
1450 scopes = (Scopes *)cptr.data;
1452 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1456 rect.xmin= 0; rect.xmax= 200;
1457 rect.ymin= 0; rect.ymax= 190;
1459 block= uiLayoutAbsoluteBlock(layout);
1461 scopes->wavefrm_height= (scopes->wavefrm_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->wavefrm_height;
1463 bt= uiDefBut(block, WAVEFORM, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->wavefrm_height, scopes, 0, 0, 0, 0, "");
1469 /********************* Vectorscope Template ************************/
1471 void uiTemplateVectorscope(uiLayout *layout, PointerRNA *ptr, const char *propname)
1473 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1481 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1484 cptr= RNA_property_pointer_get(ptr, prop);
1485 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_Scopes))
1487 scopes = (Scopes *)cptr.data;
1489 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1493 rect.xmin= 0; rect.xmax= 200;
1494 rect.ymin= 0; rect.ymax= 190;
1496 block= uiLayoutAbsoluteBlock(layout);
1498 scopes->vecscope_height= (scopes->vecscope_height<=UI_UNIT_Y)?UI_UNIT_Y:scopes->vecscope_height;
1500 bt= uiDefBut(block, VECTORSCOPE, 0, "", rect.xmin, rect.ymin, rect.xmax-rect.xmin, scopes->vecscope_height, scopes, 0, 0, 0, 0, "");
1501 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1506 /********************* CurveMapping Template ************************/
1509 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *UNUSED(arg))
1511 CurveMapping *cumap = cumap_v;
1514 /* we allow 20 times zoom */
1515 if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1516 d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
1517 cumap->curr.xmin+= d;
1518 cumap->curr.xmax-= d;
1519 d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
1520 cumap->curr.ymin+= d;
1521 cumap->curr.ymax-= d;
1524 ED_region_tag_redraw(CTX_wm_region(C));
1527 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *UNUSED(unused))
1529 CurveMapping *cumap = cumap_v;
1532 /* we allow 20 times zoom, but dont view outside clip */
1533 if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1534 d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
1536 if(cumap->flag & CUMA_DO_CLIP)
1537 if(cumap->curr.xmin-d < cumap->clipr.xmin)
1538 d1= cumap->curr.xmin - cumap->clipr.xmin;
1539 cumap->curr.xmin-= d1;
1542 if(cumap->flag & CUMA_DO_CLIP)
1543 if(cumap->curr.xmax+d > cumap->clipr.xmax)
1544 d1= -cumap->curr.xmax + cumap->clipr.xmax;
1545 cumap->curr.xmax+= d1;
1547 d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
1549 if(cumap->flag & CUMA_DO_CLIP)
1550 if(cumap->curr.ymin-d < cumap->clipr.ymin)
1551 d1= cumap->curr.ymin - cumap->clipr.ymin;
1552 cumap->curr.ymin-= d1;
1555 if(cumap->flag & CUMA_DO_CLIP)
1556 if(cumap->curr.ymax+d > cumap->clipr.ymax)
1557 d1= -cumap->curr.ymax + cumap->clipr.ymax;
1558 cumap->curr.ymax+= d1;
1561 ED_region_tag_redraw(CTX_wm_region(C));
1564 static void curvemap_buttons_setclip(bContext *UNUSED(C), void *cumap_v, void *UNUSED(arg))
1566 CurveMapping *cumap = cumap_v;
1568 curvemapping_changed(cumap, 0);
1571 static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
1573 CurveMapping *cumap = cumap_v;
1575 curvemap_remove(cumap->cm+cumap->cur, SELECT);
1576 curvemapping_changed(cumap, 0);
1578 rna_update_cb(C, cb_v, NULL);
1581 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
1582 static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v)
1584 CurveMapping *cumap = cumap_v;
1587 float width= 8*UI_UNIT_X;
1589 block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS);
1591 /* use this for a fake extra empy space around the buttons */
1592 uiDefBut(block, LABEL, 0, "", -4, 16, width+8, 6*UI_UNIT_Y, NULL, 0, 0, 0, 0, "");
1594 bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",
1595 0,5*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->flag, 0.0, 0.0, 10, 0, "");
1596 uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
1598 uiBlockBeginAlign(block);
1599 uiDefButF(block, NUM, 0, "Min X ", 0,4*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, "");
1600 uiDefButF(block, NUM, 0, "Min Y ", 0,3*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, "");
1601 uiDefButF(block, NUM, 0, "Max X ", 0,2*UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, "");
1602 uiDefButF(block, NUM, 0, "Max Y ", 0,UI_UNIT_Y,width,UI_UNIT_Y, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, "");
1604 uiBlockSetDirection(block, UI_RIGHT);
1606 uiEndBlock(C, block);
1610 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
1612 CurveMapping *cumap = cumap_v;
1613 CurveMap *cuma= cumap->cm+cumap->cur;
1617 curvemap_reset(cuma, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
1618 curvemapping_changed(cumap, 0);
1621 cumap->curr= cumap->clipr;
1623 case 2: /* set vector */
1624 curvemap_sethandle(cuma, 1);
1625 curvemapping_changed(cumap, 0);
1627 case 3: /* set auto */
1628 curvemap_sethandle(cuma, 0);
1629 curvemapping_changed(cumap, 0);
1631 case 4: /* extend horiz */
1632 cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
1633 curvemapping_changed(cumap, 0);
1635 case 5: /* extend extrapolate */
1636 cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
1637 curvemapping_changed(cumap, 0);
1640 ED_region_tag_redraw(CTX_wm_region(C));
1643 static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1646 short yco= 0, menuwidth=10*UI_UNIT_X;
1648 block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1649 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1651 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, "");
1652 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, "");
1653 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, "");
1654 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 4, "");
1655 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 5, "");
1656 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1658 uiBlockSetDirection(block, UI_RIGHT);
1659 uiTextBoundsBlock(block, 50);
1661 uiEndBlock(C, block);
1665 static uiBlock *curvemap_brush_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1668 short yco= 0, menuwidth=10*UI_UNIT_X;
1670 block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1671 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1673 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 1, "");
1674 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 2, "");
1675 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 3, "");
1676 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=UI_UNIT_Y, menuwidth, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
1678 uiBlockSetDirection(block, UI_RIGHT);
1679 uiTextBoundsBlock(block, 50);
1681 uiEndBlock(C, block);
1685 static void curvemap_buttons_redraw(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
1687 ED_region_tag_redraw(CTX_wm_region(C));
1690 static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
1692 CurveMapping *cumap = cumap_v;
1695 cumap->preset = CURVE_PRESET_LINE;
1696 for(a=0; a<CM_TOT; a++)
1697 curvemap_reset(cumap->cm+a, &cumap->clipr, cumap->preset, CURVEMAP_SLOPE_POSITIVE);
1699 cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
1700 cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
1701 curvemapping_set_black_white(cumap, NULL, NULL);
1703 curvemapping_changed(cumap, 0);
1705 rna_update_cb(C, cb_v, NULL);
1708 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
1709 static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb)
1711 CurveMapping *cumap= ptr->data;
1712 uiLayout *row, *sub, *split;
1715 float dx= UI_UNIT_X;
1719 block= uiLayoutGetBlock(layout);
1722 row= uiLayoutRow(layout, 0);
1724 if(labeltype=='v') {
1726 sub= uiLayoutRow(row, 1);
1727 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1729 if(cumap->cm[0].curve) {
1730 bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1731 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1733 if(cumap->cm[1].curve) {
1734 bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1735 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1737 if(cumap->cm[2].curve) {
1738 bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1739 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1742 else if(labeltype=='c') {
1744 sub= uiLayoutRow(row, 1);
1745 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1747 if(cumap->cm[3].curve) {
1748 bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, dx, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
1749 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1751 if(cumap->cm[0].curve) {
1752 bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1753 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1755 if(cumap->cm[1].curve) {
1756 bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1757 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1759 if(cumap->cm[2].curve) {
1760 bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1761 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1764 else if (labeltype == 'h') {
1766 sub= uiLayoutRow(row, 1);
1767 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1769 if(cumap->cm[0].curve) {
1770 bt= uiDefButI(block, ROW, 0, "H", 0, 0, dx, dx, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1771 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1773 if(cumap->cm[1].curve) {
1774 bt= uiDefButI(block, ROW, 0, "S", 0, 0, dx, dx, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1775 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1777 if(cumap->cm[2].curve) {
1778 bt= uiDefButI(block, ROW, 0, "V", 0, 0, dx, dx, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1779 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1783 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
1788 /* operation buttons */
1789 sub= uiLayoutRow(row, 1);
1791 uiBlockSetEmboss(block, UI_EMBOSSN);
1793 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
1794 uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
1796 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
1797 uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
1800 bt= uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, "Tools");
1802 bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, dx, "Tools");
1804 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1806 if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
1807 bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, dx, "Clipping Options");
1808 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1810 bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, dx, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
1811 uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
1813 uiBlockSetEmboss(block, UI_EMBOSS);
1815 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
1818 size= uiLayoutGetWidth(layout);
1819 row= uiLayoutRow(layout, 0);
1820 uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, bg, 0, "");
1822 /* black/white levels */
1824 split= uiLayoutSplit(layout, 0, 0);
1825 uiItemR(uiLayoutColumn(split, 0), ptr, "black_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1826 uiItemR(uiLayoutColumn(split, 0), ptr, "white_level", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1828 uiLayoutRow(layout, 0);
1829 bt=uiDefBut(block, BUT, 0, "Reset", 0, 0, UI_UNIT_X*10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Reset Black/White point and curves");
1830 uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
1833 uiBlockSetNFunc(block, NULL, NULL, NULL);
1836 void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propname, int type, int levels, int brush)
1839 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1843 RNA_warning("uiTemplateCurveMapping: curve property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
1847 if(RNA_property_type(prop) != PROP_POINTER) {
1848 RNA_warning("uiTemplateCurveMapping: curve is not a pointer: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
1852 cptr= RNA_property_pointer_get(ptr, prop);
1853 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping))
1856 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1860 curvemap_buttons_layout(layout, &cptr, type, levels, brush, cb);
1865 /********************* ColorWheel Template ************************/
1867 #define WHEEL_SIZE 100
1869 void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic)
1871 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1872 uiBlock *block= uiLayoutGetBlock(layout);
1873 uiLayout *col, *row;
1875 float softmin, softmax, step, precision;
1878 RNA_warning("uiTemplateColorWheel: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
1882 RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision);
1884 col = uiLayoutColumn(layout, 0);
1885 row= uiLayoutRow(col, 1);
1887 but= uiDefButR(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, propname, -1, 0.0, 0.0, 0, 0, "");
1890 but->flag |= UI_BUT_COLOR_LOCK;
1893 if(lock_luminosity) {
1894 float color[4]; /* incase of alpha */
1895 but->flag |= UI_BUT_VEC_SIZE_LOCK;
1896 RNA_property_float_get_array(ptr, prop, color);
1897 but->a2= len_v3(color);
1901 but->flag |= UI_BUT_COLOR_CUBIC;
1906 uiDefButR(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, propname, -1, softmin, softmax, UI_GRAD_V_ALT, 0, "");
1909 /********************* Layer Buttons Template ************************/
1911 static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
1914 int cur = GET_INT_FROM_POINTER(arg2);
1915 wmWindow *win= CTX_wm_window(C);
1916 int i, tot, shift= win->eventstate->shift;
1919 tot= RNA_property_array_length(&but->rnapoin, but->rnaprop);
1921 /* Normally clicking only selects one layer */
1922 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, 1);
1923 for(i = 0; i < tot; ++i) {
1925 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, 0);
1929 /* view3d layer change should update depsgraph (invisible object changed maybe) */
1930 /* see view3d_header.c */
1934 // - for now, grouping of layers is determined by dividing up the length of
1935 // the array of layer bitflags
1937 void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, const char *propname,
1938 PointerRNA *used_ptr, const char *used_propname, int active_layer)
1940 uiLayout *uRow, *uCol;
1941 PropertyRNA *prop, *used_prop= NULL;
1942 int groups, cols, layers;
1943 int group, col, layer, row;
1944 int cols_per_group = 5;
1946 prop= RNA_struct_find_property(ptr, propname);
1948 RNA_warning("uiTemplateLayer: layers property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
1952 /* the number of layers determines the way we group them
1953 * - we want 2 rows only (for now)
1954 * - the number of columns (cols) is the total number of buttons per row
1955 * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
1956 * - for now, only split into groups if group will have at least 5 items
1958 layers= RNA_property_array_length(ptr, prop);
1959 cols= (layers / 2) + (layers % 2);
1960 groups= ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
1962 if(used_ptr && used_propname) {
1963 used_prop= RNA_struct_find_property(used_ptr, used_propname);
1965 RNA_warning("uiTemplateLayer: used layers property not found: %s.%s\n", RNA_struct_identifier(ptr->type), used_propname);
1969 if(RNA_property_array_length(used_ptr, used_prop) < layers)
1973 /* layers are laid out going across rows, with the columns being divided into groups */
1975 for (group= 0; group < groups; group++) {
1976 uCol= uiLayoutColumn(layout, 1);
1978 for (row= 0; row < 2; row++) {
1982 uRow= uiLayoutRow(uCol, 1);
1983 block= uiLayoutGetBlock(uRow);
1984 layer= groups*cols_per_group*row + cols_per_group*group;
1986 /* add layers as toggle buts */
1987 for (col= 0; (col < cols_per_group) && (layer < layers); col++, layer++) {
1989 int butlay = 1 << layer;
1991 if(active_layer & butlay)
1992 icon = ICON_LAYER_ACTIVE;
1993 else if(used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer))
1994 icon = ICON_LAYER_USED;
1996 but= uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, UI_UNIT_X/2, UI_UNIT_Y/2);
1997 uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer));
2005 /************************* List Template **************************/
2007 static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big)
2015 /* try ID, material or texture slot */
2016 if(RNA_struct_is_ID(itemptr->type)) {
2017 id= itemptr->id.data;
2019 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
2020 id= RNA_pointer_get(itemptr, "material").data;
2022 else if(RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
2023 id= RNA_pointer_get(itemptr, "texture").data;
2026 /* get icon from ID */
2028 icon= ui_id_icon_get(C, id, big);
2037 static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, const char *activepropname)
2039 uiBlock *block= uiLayoutGetBlock(layout);
2041 uiLayout *split, *overlap, *sub, *row;
2046 overlap= uiLayoutOverlap(layout);
2048 /* list item behind label & other buttons */
2049 sub= uiLayoutRow(overlap, 0);
2051 but= uiDefButR(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
2052 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2054 sub= uiLayoutRow(overlap, 0);
2056 /* retrieve icon and name */
2057 icon= list_item_icon_get(C, itemptr, rnaicon, 0);
2058 if(icon == ICON_NONE || icon == ICON_DOT)
2061 namebuf= RNA_struct_name_get_alloc(itemptr, NULL, 0);
2062 name= (namebuf)? namebuf: "";
2064 /* hardcoded types */
2065 if(itemptr->type == &RNA_MeshTextureFaceLayer || itemptr->type == &RNA_MeshColorLayer) {
2066 uiItemL(sub, name, icon);
2067 uiBlockSetEmboss(block, UI_EMBOSSN);
2068 uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
2069 uiBlockSetEmboss(block, UI_EMBOSS);
2071 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
2072 uiItemL(sub, name, icon);
2073 uiBlockSetEmboss(block, UI_EMBOSS);
2074 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
2076 else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
2077 uiItemL(sub, name, icon);
2078 uiBlockSetEmboss(block, UI_EMBOSS);
2079 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
2081 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
2082 /* provision to draw active node name */
2083 Material *ma, *manode;
2084 Object *ob= (Object*)ptr->id.data;
2085 int index= (Material**)itemptr->data - ob->mat;
2087 /* default item with material base name */
2088 uiItemL(sub, name, icon);
2090 ma= give_current_material(ob, index+1);
2092 manode= give_node_material(ma);
2094 char str[MAX_ID_NAME + 12];
2095 sprintf(str, "Node %s", manode->id.name+2);
2096 uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1));
2098 else if(ma->use_nodes) {
2099 uiItemL(sub, "Node <none>", ICON_NONE);
2103 else if(itemptr->type == &RNA_ShapeKey) {
2104 Object *ob= (Object*)activeptr->data;
2105 Key *key= (Key*)itemptr->data;
2107 split= uiLayoutSplit(sub, 0.75f, 0);
2109 uiItemL(split, name, icon);
2111 uiBlockSetEmboss(block, UI_EMBOSSN);
2112 row= uiLayoutRow(split, 1);
2113 if(i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE);
2114 else uiItemR(row, itemptr, "value", 0, "", ICON_NONE);
2116 if(ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH))
2117 uiLayoutSetActive(row, 0);
2118 //uiItemR(row, itemptr, "mute", 0, "", ICON_MUTE_IPO_OFF);
2119 uiBlockSetEmboss(block, UI_EMBOSS);
2121 /* Jason was here: I need the RNA struct for vertex groups */
2122 else if(RNA_struct_is_a(itemptr->type, &RNA_VertexGroup)) {
2123 uiItemL(sub, name, icon);
2124 uiBlockSetEmboss(block, UI_EMBOSS);
2125 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "flag", 0, 0, 0, 0, 0, NULL);
2128 uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
2135 void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr, const char *activepropname, int rows, int maxrows, int listtype)
2137 //Scene *scene= CTX_data_scene(C);
2138 PropertyRNA *prop= NULL, *activeprop;
2139 PropertyType type, activetype;
2141 uiLayout *box, *row, *col;
2145 char *name, str[32];
2146 int rnaicon=0, icon=0, i= 0, activei= 0, len= 0, items, found, min, max;
2148 /* validate arguments */
2149 block= uiLayoutGetBlock(layout);
2153 RNA_warning("uiTemplateList: only works inside a panel.\n");
2157 if(!activeptr->data)
2161 prop= RNA_struct_find_property(ptr, propname);
2163 RNA_warning("uiTemplateList: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), propname);
2168 activeprop= RNA_struct_find_property(activeptr, activepropname);
2170 RNA_warning("uiTemplateList: property not found: %s.%s\n", RNA_struct_identifier(ptr->type), activepropname);
2175 type= RNA_property_type(prop);
2176 if(type != PROP_COLLECTION) {
2177 RNA_warning("uiTemplateList: Expected collection property.\n");
2182 activetype= RNA_property_type(activeprop);
2183 if(activetype != PROP_INT) {
2184 RNA_warning("uiTemplateList: Expected integer property.\n");
2189 if(ptr->data && prop) {
2190 ptype= RNA_property_pointer_type(ptr, prop);
2191 rnaicon= RNA_struct_ui_icon(ptype);
2194 /* get active data */
2195 activei= RNA_property_int_get(activeptr, activeprop);
2197 if(listtype == 'i') {
2198 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2199 col= uiLayoutColumn(box, 1);
2200 row= uiLayoutRow(col, 0);
2202 if(ptr->data && prop) {
2203 /* create list items */
2204 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2207 row= uiLayoutRow(col, 0);
2209 icon= list_item_icon_get(C, &itemptr, rnaicon, 1);
2210 but= uiDefIconButR(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
2211 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2219 else if(listtype == 'c') {
2220 /* compact layout */
2222 row= uiLayoutRow(layout, 1);
2224 if(ptr->data && prop) {
2225 /* create list items */
2226 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2227 found= (activei == i);
2231 name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
2232 icon= list_item_icon_get(C, &itemptr, rnaicon, 0);
2233 uiItemL(row, (name)? name: "", icon);
2244 /* if not found, add in dummy button */
2246 uiItemL(row, "", ICON_NONE);
2248 /* next/prev button */
2249 sprintf(str, "%d :", i);
2250 but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activepropname, 0, 0, 0, 0, 0, "");
2252 uiButSetFlag(but, UI_BUT_DISABLED);
2260 if(pa->list_grip_size != 0)
2261 rows= pa->list_grip_size;
2264 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2265 row= uiLayoutRow(box, 0);
2266 col = uiLayoutColumn(row, 1);
2269 RNA_property_int_range(activeptr, activeprop, &min, &max);
2272 len= RNA_property_collection_length(ptr, prop);
2273 items= CLAMPIS(len, rows, MAX2(rows, maxrows));
2275 /* if list length changes and active is out of view, scroll to it */
2276 if(pa->list_last_len != len)
2277 if((activei < pa->list_scroll || activei >= pa->list_scroll+items))
2278 pa->list_scroll= activei;
2280 pa->list_scroll= MIN2(pa->list_scroll, len-items);
2281 pa->list_scroll= MAX2(pa->list_scroll, 0);
2282 pa->list_size= items;
2283 pa->list_last_len= len;
2285 if(ptr->data && prop) {
2286 /* create list items */
2287 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2288 if(i >= pa->list_scroll && i<pa->list_scroll+items)
2289 list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activepropname);
2296 /* add dummy buttons to fill space */
2297 while(i < pa->list_scroll+items) {
2298 if(i >= pa->list_scroll)
2299 uiItemL(col, "", ICON_NONE);
2305 col= uiLayoutColumn(row, 0);
2306 uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
2311 /************************* Operator Search Template **************************/
2313 static void operator_call_cb(bContext *C, void *UNUSED(arg1), void *arg2)
2315 wmOperatorType *ot= arg2;
2318 WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
2321 static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items)
2323 wmOperatorType *ot = WM_operatortype_first();
2325 for(; ot; ot= ot->next) {
2327 if(BLI_strcasestr(ot->name, str)) {
2328 if(WM_operator_poll((bContext*)C, ot)) {
2330 int len= strlen(ot->name);
2332 /* display name for menu, can hold hotkey */
2333 BLI_strncpy(name, ot->name, 256);
2335 /* check for hotkey */
2337 if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
2341 if(0==uiSearchItemAdd(items, name, ot, 0))
2348 void uiTemplateOperatorSearch(uiLayout *layout)
2352 static char search[256]= "";
2354 block= uiLayoutGetBlock(layout);
2355 uiBlockSetCurLayout(block, layout);
2357 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, 0, 0, "");
2358 uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
2361 /************************* Running Jobs Template **************************/
2363 #define B_STOPRENDER 1
2364 #define B_STOPCAST 2
2365 #define B_STOPANIM 3
2366 #define B_STOPCOMPO 4
2368 static void do_running_jobs(bContext *C, void *UNUSED(arg), int event)
2375 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C), NULL);
2378 WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
2381 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_area(C), NULL);
2386 void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
2388 bScreen *screen= CTX_wm_screen(C);
2389 wmWindowManager *wm= CTX_wm_manager(C);
2390 ScrArea *sa= CTX_wm_area(C);
2395 block= uiLayoutGetBlock(layout);
2396 uiBlockSetCurLayout(block, layout);
2398 uiBlockSetHandleFunc(block, do_running_jobs, NULL);
2400 if(sa->spacetype==SPACE_NODE) {
2401 if(WM_jobs_test(wm, sa))
2403 handle_event= B_STOPCOMPO;
2407 /* another scene can be rendering too, for example via compositor */
2408 for(scene= CTX_data_main(C)->scene.first; scene; scene= scene->id.next)
2409 if(WM_jobs_test(wm, scene))
2412 handle_event= B_STOPRENDER;
2418 ui_abs= uiLayoutAbsolute(layout, 0);
2419 (void)ui_abs; // UNUSED
2421 uiDefIconBut(block, BUT, handle_event, ICON_PANEL_CLOSE,
2422 0, UI_UNIT_Y*0.1, UI_UNIT_X*0.8, UI_UNIT_Y*0.8, NULL, 0.0f, 0.0f, 0, 0, "Stop this job");
2423 uiDefBut(block, PROGRESSBAR, 0, WM_jobs_name(wm, owner),
2424 UI_UNIT_X, 0, 100, UI_UNIT_Y, NULL, 0.0f, 0.0f, WM_jobs_progress(wm, owner), 0, "Progress");
2426 uiLayoutRow(layout, 0);
2428 if(WM_jobs_test(wm, screen))
2429 uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, "Capture", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast");
2430 if(screen->animtimer)
2431 uiDefIconTextBut(block, BUT, B_STOPANIM, ICON_CANCEL, "Anim Player", 0,0,100,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop animation playback");
2434 /************************* Reports for Last Operator Template **************************/
2436 void uiTemplateReportsBanner(uiLayout *layout, bContext *C)
2438 ReportList *reports = CTX_wm_reports(C);
2439 Report *report= BKE_reports_last_displayable(reports);
2440 ReportTimerInfo *rti;
2445 uiStyle *style= U.uistyles.first;
2449 /* if the report display has timed out, don't show */
2450 if (!reports->reporttimer) return;
2452 rti= (ReportTimerInfo *)reports->reporttimer->customdata;
2454 if (!rti || rti->widthfac==0.0f || !report) return;
2456 ui_abs= uiLayoutAbsolute(layout, 0);
2457 block= uiLayoutGetBlock(ui_abs);
2459 width = BLF_width(style->widget.uifont_id, report->message);
2460 width = MIN2(rti->widthfac*width, width);
2461 width = MAX2(width, 10);
2463 /* make a box around the report to make it stand out */
2464 uiBlockBeginAlign(block);
2465 but= uiDefBut(block, ROUNDBOX, 0, "", 0, 0, UI_UNIT_X+10, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2466 /* set the report's bg color in but->col - ROUNDBOX feature */
2467 but->col[0]= FTOCHAR(rti->col[0]);
2468 but->col[1]= FTOCHAR(rti->col[1]);
2469 but->col[2]= FTOCHAR(rti->col[2]);
2472 but= uiDefBut(block, ROUNDBOX, 0, "", UI_UNIT_X+10, 0, UI_UNIT_X+width, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2473 but->col[0]= but->col[1]= but->col[2]= FTOCHAR(rti->greyscale);
2476 uiBlockEndAlign(block);
2479 /* icon and report message on top */
2480 if(report->type & RPT_ERROR_ALL)
2482 else if(report->type & RPT_WARNING_ALL)
2484 else if(report->type & RPT_INFO_ALL)
2487 /* XXX: temporary operator to dump all reports to a text block, but only if more than 1 report
2488 * to be shown instead of icon when appropriate...
2490 uiBlockSetEmboss(block, UI_EMBOSSN);
2492 if (reports->list.first != reports->list.last)
2493 uiDefIconButO(block, BUT, "UI_OT_reports_to_textblock", WM_OP_INVOKE_REGION_WIN, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, "Click to see rest of reports in textblock: 'Recent Reports'");
2495 uiDefIconBut(block, LABEL, 0, icon, 2, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "");
2497 uiBlockSetEmboss(block, UI_EMBOSS);
2499 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, "");