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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 * Contributor(s): Blender Foundation 2009.
22 * ***** END GPL LICENSE BLOCK *****
29 #include "MEM_guardedalloc.h"
31 #include "DNA_scene_types.h"
32 #include "DNA_screen_types.h"
34 #include "BLI_string.h"
36 #include "BKE_colortools.h"
37 #include "BKE_context.h"
38 #include "BKE_icons.h"
39 #include "BKE_global.h"
40 #include "BKE_library.h"
42 #include "BKE_utildefines.h"
44 #include "ED_screen.h"
45 #include "ED_render.h"
47 #include "RNA_access.h"
52 #include "UI_interface.h"
53 #include "UI_resources.h"
54 #include "interface_intern.h"
56 void ui_template_fix_linking()
60 /********************** Header Template *************************/
62 void uiTemplateHeader(uiLayout *layout, bContext *C, int menus)
66 block= uiLayoutAbsoluteBlock(layout);
67 if(menus) ED_area_header_standardbuttons(C, block, 0);
68 else ED_area_header_switchbutton(C, block, 0);
71 /********************** DopeSheet Filter Template *************************/
73 void uiTemplateDopeSheetFilter(uiLayout *layout, bContext *C, PointerRNA *ptr)
75 Main *mainptr= CTX_data_main(C);
76 ScrArea *sa= CTX_wm_area(C);
77 uiLayout *row= layout;
78 short nlaActive= ((sa) && (sa->spacetype==SPACE_NLA));
80 /* more 'generic' filtering options */
82 row= uiLayoutRow(layout, 1);
84 uiItemR(row, "", 0, ptr, "only_selected", 0);
87 uiItemR(row, "", 0, ptr, "include_missing_nla", 0);
92 /* datatype based - only available datatypes are shown */
93 row= uiLayoutRow(layout, 1);
95 uiItemR(row, "", 0, ptr, "display_scene", 0);
96 uiItemR(row, "", 0, ptr, "display_world", 0);
97 uiItemR(row, "", 0, ptr, "display_node", 0);
99 if (mainptr && mainptr->mesh.first)
100 uiItemR(row, "", 0, ptr, "display_mesh", 0);
101 if (mainptr && mainptr->key.first)
102 uiItemR(row, "", 0, ptr, "display_shapekeys", 0);
103 if (mainptr && mainptr->mat.first)
104 uiItemR(row, "", 0, ptr, "display_material", 0);
105 if (mainptr && mainptr->lamp.first)
106 uiItemR(row, "", 0, ptr, "display_lamp", 0);
107 if (mainptr && mainptr->camera.first)
108 uiItemR(row, "", 0, ptr, "display_camera", 0);
109 if (mainptr && mainptr->curve.first)
110 uiItemR(row, "", 0, ptr, "display_curve", 0);
111 if (mainptr && mainptr->mball.first)
112 uiItemR(row, "", 0, ptr, "display_metaball", 0);
113 if (mainptr && mainptr->armature.first)
114 uiItemR(row, "", 0, ptr, "display_armature", 0);
115 if (mainptr && mainptr->particle.first)
116 uiItemR(row, "", 0, ptr, "display_particle", 0);
119 /********************** Search Callbacks *************************/
121 typedef struct TemplateID {
126 int prv_rows, prv_cols;
129 /* Search browse menu, assign */
130 static void id_search_call_cb(bContext *C, void *arg_template, void *item)
132 TemplateID *template= (TemplateID*)arg_template;
138 RNA_id_pointer_create(item, &idptr);
139 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
140 RNA_property_update(C, &template->ptr, template->prop);
144 /* ID Search browse menu, do the search */
145 static void id_search_cb(const bContext *C, void *arg_template, char *str, uiSearchItems *items)
147 TemplateID *template= (TemplateID*)arg_template;
148 ListBase *lb= template->idlb;
153 for(id= lb->first; id; id= id->next) {
154 if(BLI_strcasestr(id->name+2, str)) {
155 iconid= ui_id_icon_get((bContext*)C, id, 0);
157 if(!uiSearchItemAdd(items, id->name+2, id, iconid))
163 /* ID Search browse menu, open */
164 static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
166 static char search[256];
167 static TemplateID template;
170 wmWindow *win= CTX_wm_window(C);
174 /* clear initial search string, then all items show */
176 /* arg_litem is malloced, can be freed by parent button */
177 template= *((TemplateID*)arg_litem);
179 /* get active id for showing first item */
180 idptr= RNA_property_pointer_get(&template.ptr, template.prop);
182 block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
183 uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
185 /* preview thumbnails */
186 if (template.prv_rows > 0 && template.prv_cols > 0) {
187 int w = 96 * template.prv_cols;
188 int h = 96 * template.prv_rows + 20;
190 /* fake button, it holds space for search items */
191 uiDefBut(block, LABEL, 0, "", 10, 15, w, h, NULL, 0, 0, 0, 0, NULL);
193 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, w, 19, template.prv_rows, template.prv_cols, "");
194 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
198 /* fake button, it holds space for search items */
199 uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
201 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, 0, 0, "");
202 uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb, idptr.data);
206 uiBoundsBlock(block, 6);
207 uiBlockSetDirection(block, UI_DOWN);
208 uiEndBlock(C, block);
210 event= *(win->eventstate); /* XXX huh huh? make api call */
211 event.type= EVT_BUT_OPEN;
213 event.customdata= but;
214 event.customdatafree= FALSE;
215 wm_event_add(win, &event);
220 /************************ ID Template ***************************/
221 /* This is for browsing and editing the ID-blocks used */
223 /* for new/open operators */
224 void uiIDContextProperty(bContext *C, PointerRNA *ptr, PropertyRNA **prop)
226 TemplateID *template;
227 ARegion *ar= CTX_wm_region(C);
231 memset(ptr, 0, sizeof(*ptr));
237 for(block=ar->uiblocks.first; block; block=block->next) {
238 for(but=block->buttons.first; but; but= but->next) {
239 /* find the button before the active one */
240 if((but->flag & (UI_BUT_LAST_ACTIVE|UI_ACTIVE))) {
242 template= but->func_argN;
244 *prop= template->prop;
253 static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
255 TemplateID *template= (TemplateID*)arg_litem;
256 PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
257 ID *id= idptr.data, *newid;
258 int event= GET_INT_FROM_POINTER(arg_event);
263 printf("warning, id event %d shouldnt come here\n", event);
267 /* these call uiIDContextPropertySet */
270 memset(&idptr, 0, sizeof(idptr));
271 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
272 RNA_property_update(C, &template->ptr, template->prop);
274 case UI_ID_FAKE_USER:
276 if(id->flag & LIB_FAKEUSER) id->us++;
283 if(id_make_local(id, 0)) {
284 /* reassign to get get proper updates/notifiers */
285 idptr= RNA_property_pointer_get(&template->ptr, template->prop);
286 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
287 RNA_property_update(C, &template->ptr, template->prop);
294 if(id_copy(id, &newid, 0) && newid) {
295 /* us is 1 by convention, but RNA_property_pointer_set
296 will also incremement it, so set it to zero */
300 RNA_id_pointer_create(newid, &idptr);
301 RNA_property_pointer_set(&template->ptr, template->prop, idptr);
302 RNA_property_update(C, &template->ptr, template->prop);
307 case UI_ID_AUTO_NAME:
313 static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, StructRNA *type, int flag, char *newop, char *openop, char *unlinkop)
321 idptr= RNA_property_pointer_get(&template->ptr, template->prop);
323 idfrom= template->ptr.id.data;
326 block= uiLayoutGetBlock(layout);
327 uiBlockBeginAlign(block);
332 if(flag & UI_ID_PREVIEWS) {
334 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, "Browse ID data");
336 but->icon= RNA_struct_ui_icon(type);
337 if (id) but->icon = ui_id_icon_get(C, id, 1);
338 uiButSetFlag(but, UI_HAS_ICON|UI_ICON_PREVIEW);
340 if((idfrom && idfrom->lib))
341 uiButSetFlag(but, UI_BUT_DISABLED);
344 uiLayoutRow(layout, 1);
347 if(flag & UI_ID_BROWSE) {
348 but= uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X*1.6, UI_UNIT_Y, "Browse ID data");
350 but->icon= RNA_struct_ui_icon(type);
351 but->flag|= UI_HAS_ICON;
352 but->flag|= UI_ICON_LEFT;
355 if((idfrom && idfrom->lib))
356 uiButSetFlag(but, UI_BUT_DISABLED);
359 /* text button with name */
363 //text_idbutton(id, name);
365 but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
366 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
369 if(id->flag & LIB_INDIRECT) {
370 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_INDIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0,
371 "Indirect library datablock, cannot change.");
372 uiButSetFlag(but, UI_BUT_DISABLED);
375 but= uiDefIconBut(block, BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0,
376 "Direct linked library datablock, click to make local.");
377 if(!id_make_local(id, 1 /* test */) || (idfrom && idfrom->lib))
378 uiButSetFlag(but, UI_BUT_DISABLED);
381 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_LOCAL));
387 sprintf(str, "%d", id->us);
390 but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X,UI_UNIT_Y, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
392 but= uiDefBut(block, BUT, 0, str, 0,0,UI_UNIT_X+10,UI_UNIT_Y, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
394 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ALONE));
395 if(!id_copy(id, NULL, 1 /* test only */) || (idfrom && idfrom->lib))
396 uiButSetFlag(but, UI_BUT_DISABLED);
400 if(flag & UI_ID_ADD_NEW) {
401 int w= id?UI_UNIT_X: (flag & UI_ID_OPEN)? UI_UNIT_X*3: UI_UNIT_X*6;
404 but= uiDefIconTextButO(block, BUT, newop, WM_OP_EXEC_DEFAULT, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL);
405 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
408 but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, (id)? "": "New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
409 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
412 if((idfrom && idfrom->lib))
413 uiButSetFlag(but, UI_BUT_DISABLED);
416 if(flag & UI_ID_OPEN) {
417 int w= id?UI_UNIT_X: (flag & UI_ID_ADD_NEW)? UI_UNIT_X*3: UI_UNIT_X*6;
420 but= uiDefIconTextButO(block, BUT, openop, WM_OP_INVOKE_DEFAULT, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL);
421 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
424 but= uiDefIconTextBut(block, BUT, 0, ICON_FILESEL, (id)? "": "Open", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
425 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_OPEN));
428 if((idfrom && idfrom->lib))
429 uiButSetFlag(but, UI_BUT_DISABLED);
433 if(id && (flag & UI_ID_DELETE)) {
435 but= uiDefIconButO(block, BUT, unlinkop, WM_OP_INVOKE_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
438 but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
439 uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
442 if((idfrom && idfrom->lib))
443 uiButSetFlag(but, UI_BUT_DISABLED);
446 uiBlockEndAlign(block);
449 static void ui_template_id(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, int previews, int prv_rows, int prv_cols)
451 TemplateID *template;
456 prop= RNA_struct_find_property(ptr, propname);
458 if(!prop || RNA_property_type(prop) != PROP_POINTER) {
459 printf("uiTemplateID: pointer property not found: %s\n", propname);
463 template= MEM_callocN(sizeof(TemplateID), "TemplateID");
465 template->prop= prop;
466 template->prv_rows = prv_rows;
467 template->prv_cols = prv_cols;
469 flag= UI_ID_BROWSE|UI_ID_RENAME|UI_ID_DELETE;
472 flag |= UI_ID_ADD_NEW;
476 flag |= UI_ID_PREVIEWS;
478 type= RNA_property_pointer_type(ptr, prop);
479 template->idlb= wich_libbase(CTX_data_main(C), RNA_type_to_ID_code(type));
481 /* create UI elements for this template
482 * - template_ID makes a copy of the template data and assigns it to the relevant buttons
485 uiLayoutRow(layout, 1);
486 template_ID(C, layout, template, type, flag, newop, openop, unlinkop);
493 void uiTemplateID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop)
495 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, 0, 0, 0);
498 void uiTemplateIDPreview(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *newop, char *openop, char *unlinkop, int rows, int cols)
500 ui_template_id(layout, C, ptr, propname, newop, openop, unlinkop, 1, rows, cols);
503 /************************ ID Chooser Template ***************************/
505 /* This is for selecting the type of ID-block to use, and then from the relevant type choosing the block to use
507 * - propname: property identifier for property that ID-pointer gets stored to
508 * - proptypename: property identifier for property used to determine the type of ID-pointer that can be used
510 void uiTemplateAnyID(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, char *proptypename, char *text)
512 PropertyRNA *propID, *propType;
515 /* get properties... */
516 propID= RNA_struct_find_property(ptr, propname);
517 propType= RNA_struct_find_property(ptr, proptypename);
519 if (!propID || RNA_property_type(propID) != PROP_POINTER) {
520 printf("uiTemplateAnyID: pointer property not found: %s\n", propname);
523 if (!propType || RNA_property_type(propType) != PROP_ENUM) {
524 printf("uiTemplateAnyID: pointer-type property not found: %s\n", proptypename);
528 /* Start drawing UI Elements using standard defines */
529 row= uiLayoutRow(layout, 1);
531 /* Label - either use the provided text, or will become "ID-Block:" */
533 uiItemL(row, text, 0);
535 uiItemL(row, "ID-Block:", 0);
537 /* ID-Type Selector - just have a menu of icons */
538 // FIXME: the icon-only setting doesn't work when we supply a blank name
539 uiItemFullR(row, "", 0, ptr, propType, 0, 0, UI_ITEM_R_ICON_ONLY);
541 /* ID-Block Selector - just use pointer widget... */
542 uiItemFullR(row, "", 0, ptr, propID, 0, 0, 0);
545 /********************* RNA Path Builder Template ********************/
549 /* This is creating/editing RNA-Paths
551 * - ptr: struct which holds the path property
552 * - propname: property identifier for property that path gets stored to
553 * - root_ptr: struct that path gets built from
555 void uiTemplatePathBuilder(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *root_ptr, char *text)
557 PropertyRNA *propPath;
560 /* check that properties are valid */
561 propPath= RNA_struct_find_property(ptr, propname);
562 if (!propPath || RNA_property_type(propPath) != PROP_STRING) {
563 printf("uiTemplatePathBuilder: path property not found: %s\n", propname);
567 /* Start drawing UI Elements using standard defines */
568 row= uiLayoutRow(layout, 1);
570 /* Path (existing string) Widget */
571 uiItemR(row, text, ICON_RNA, ptr, propname, 0);
573 // TODO: attach something to this to make allow searching of nested properties to 'build' the path
576 /************************ Modifier Template *************************/
578 #define ERROR_LIBDATA_MESSAGE "Can't edit external libdata"
582 #include "DNA_object_force.h"
583 #include "DNA_object_types.h"
584 #include "DNA_modifier_types.h"
585 #include "DNA_scene_types.h"
587 #include "BKE_depsgraph.h"
588 #include "BKE_DerivedMesh.h"
589 #include "BKE_global.h"
590 #include "BKE_modifier.h"
591 #include "BKE_object.h"
592 #include "BKE_particle.h"
593 #include "BKE_report.h"
595 #include "UI_resources.h"
598 #include "BLI_math.h"
599 #include "BLI_listbase.h"
601 #include "ED_object.h"
603 static void modifiers_setOnCage(bContext *C, void *ob_v, void *md_v)
606 ModifierData *md= md_v;
607 int i, cageIndex = modifiers_getCageIndex(ob, NULL, 0);
609 /* undo button operation */
610 md->mode ^= eModifierMode_OnCage;
612 for(i = 0, md=ob->modifiers.first; md; ++i, md=md->next) {
615 md->mode ^= eModifierMode_OnCage;
620 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
621 DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
624 static void modifiers_convertToReal(bContext *C, void *ob_v, void *md_v)
627 ModifierData *md = md_v;
628 ModifierData *nmd = modifier_new(md->type);
630 modifier_copyData(md, nmd);
631 nmd->mode &= ~eModifierMode_Virtual;
633 BLI_addhead(&ob->modifiers, nmd);
635 modifier_unique_name(&ob->modifiers, nmd);
637 ob->partype = PAROBJECT;
639 WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
640 DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
642 ED_undo_push(C, "Modifier convert to real");
645 static int modifier_can_delete(ModifierData *md)
647 // fluid particle modifier can't be deleted here
648 if(md->type == eModifierType_ParticleSystem)
649 if(((ParticleSystemModifierData *)md)->psys->part->type == PART_FLUID)
655 static uiLayout *draw_modifier(uiLayout *layout, Object *ob, ModifierData *md, int index, int cageIndex, int lastCageIndex)
657 ModifierTypeInfo *mti = modifierType_getInfo(md->type);
661 uiLayout *box, *column, *row;
662 uiLayout *result= NULL;
663 int isVirtual = (md->mode & eModifierMode_Virtual);
666 /* create RNA pointer */
667 RNA_pointer_create(&ob->id, &RNA_Modifier, md, &ptr);
669 column= uiLayoutColumn(layout, 1);
670 uiLayoutSetContextPointer(column, "modifier", &ptr);
672 /* rounded header ------------------------------------------------------------------- */
673 box= uiLayoutBox(column);
675 row= uiLayoutRow(box, 0);
676 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_EXPAND);
677 block= uiLayoutGetBlock(row);
680 /* VIRTUAL MODIFIER */
681 // XXX this is not used now, since these cannot be accessed via RNA
682 sprintf(str, "%s parent deform", md->name);
683 uiDefBut(block, LABEL, 0, str, 0, 0, 185, UI_UNIT_Y, NULL, 0.0, 0.0, 0.0, 0.0, "Modifier name");
685 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");
686 uiButSetFunc(but, modifiers_convertToReal, ob, md);
690 uiLayout *subrow, *col2;
692 /* Open/Close ................................. */
693 uiBlockSetEmboss(block, UI_EMBOSSN);
694 uiDefIconButBitI(block, ICONTOG, eModifierMode_Expanded, 0, ICON_TRIA_RIGHT, 0, 0, UI_UNIT_X, UI_UNIT_Y, &md->mode, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Modifier");
696 /* modifier-type icon */
697 uiItemL(row, "", RNA_struct_ui_icon(ptr.type));
698 uiBlockSetEmboss(block, UI_EMBOSS);
700 /* 'Middle Column' ............................
701 * - first row is the name of the modifier
702 * - second row is the visibility settings, since the layouts were not wide enough to show all
704 col2= uiLayoutColumn(row, 0);
706 subrow= uiLayoutRow(col2, 0);
708 uiItemR(subrow, "", 0, &ptr, "name", 0);
711 subrow= uiLayoutRow(col2, 1);
712 uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_EXPAND);
713 block= uiLayoutGetBlock(subrow);
714 /* Softbody not allowed in this situation, enforce! */
715 if ( ((md->type!=eModifierType_Softbody && md->type!=eModifierType_Collision) || !(ob->pd && ob->pd->deflect))
716 && (md->type!=eModifierType_Surface) )
718 uiItemR(subrow, "", ICON_SCENE, &ptr, "render", 0);
719 uiItemR(subrow, "", ICON_RESTRICT_VIEW_OFF, &ptr, "realtime", 0);
721 if (mti->flags & eModifierTypeFlag_SupportsEditmode)
722 uiItemR(subrow, "", ICON_EDITMODE_HLT, &ptr, "editmode", 0);
725 if ((ob->type==OB_MESH) && modifier_couldBeCage(md) && (index <= lastCageIndex))
727 but = uiDefIconButBitI(block, TOG, eModifierMode_OnCage, 0, ICON_MESH_DATA, 0, 0, 16, 20, &md->mode, 0.0, 0.0, 0.0, 0.0, "Apply modifier to editing cage during Editmode");
728 if (index < cageIndex)
729 uiButSetFlag(but, UI_BUT_DISABLED);
730 uiButSetFunc(but, modifiers_setOnCage, ob, md);
733 /* Up/Down + Delete ........................... */
734 block= uiLayoutGetBlock(row);
735 uiBlockBeginAlign(block);
736 uiItemO(row, "", ICON_TRIA_UP, "OBJECT_OT_modifier_move_up");
737 uiItemO(row, "", ICON_TRIA_DOWN, "OBJECT_OT_modifier_move_down");
738 uiBlockEndAlign(block);
740 uiBlockSetEmboss(block, UI_EMBOSSN);
742 if (modifier_can_delete(md))
743 uiItemO(row, "", ICON_X, "OBJECT_OT_modifier_remove");
745 uiBlockSetEmboss(block, UI_EMBOSS);
749 /* modifier settings (under the header) --------------------------------------------------- */
750 if (!isVirtual && (md->mode & eModifierMode_Expanded)) {
751 /* apply/convert/copy */
752 box= uiLayoutBox(column);
753 row= uiLayoutRow(box, 0);
755 if (!ELEM(md->type, eModifierType_Collision, eModifierType_Surface)) {
756 /* only here obdata, the rest of modifiers is ob level */
757 uiBlockSetButLock(block, object_data_is_libdata(ob), ERROR_LIBDATA_MESSAGE);
759 if (md->type==eModifierType_ParticleSystem) {
760 ParticleSystem *psys= ((ParticleSystemModifierData *)md)->psys;
762 if (!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
763 if(ELEM3(psys->part->ren_as, PART_DRAW_PATH, PART_DRAW_GR, PART_DRAW_OB) && psys->pathcache)
764 uiItemO(row, "Convert", 0, "OBJECT_OT_modifier_convert");
768 uiItemEnumO(row, "Apply", 0, "OBJECT_OT_modifier_apply", "apply_as", MODIFIER_APPLY_DATA);
770 if (modifier_sameTopology(md))
771 uiItemEnumO(row, "Apply as Shape", 0, "OBJECT_OT_modifier_apply", "apply_as", MODIFIER_APPLY_SHAPE);
774 uiBlockClearButLock(block);
775 uiBlockSetButLock(block, ob && ob->id.lib, ERROR_LIBDATA_MESSAGE);
777 if (!ELEM4(md->type, eModifierType_Fluidsim, eModifierType_Softbody, eModifierType_ParticleSystem, eModifierType_Cloth))
778 uiItemO(row, "Copy", 0, "OBJECT_OT_modifier_copy");
781 /* result is the layout block inside the box, that we return so that modifier settings can be drawn */
782 result= uiLayoutColumn(box, 0);
783 block= uiLayoutAbsoluteBlock(box);
788 box = uiLayoutBox(column);
789 row = uiLayoutRow(box, 0);
790 uiItemL(row, md->error, ICON_ERROR);
796 uiLayout *uiTemplateModifier(uiLayout *layout, PointerRNA *ptr)
799 ModifierData *md, *vmd;
800 int i, lastCageIndex, cageIndex;
802 /* verify we have valid data */
803 if(!RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
804 printf("uiTemplateModifier: expected modifier on object.\n");
811 if(!ob || !(GS(ob->id.name) == ID_OB)) {
812 printf("uiTemplateModifier: expected modifier on object.\n");
816 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
818 /* find modifier and draw it */
819 cageIndex = modifiers_getCageIndex(ob, &lastCageIndex, 0);
821 // XXX virtual modifiers are not accesible for python
822 vmd = modifiers_getVirtualModifierList(ob);
824 for(i=0; vmd; i++, vmd=vmd->next) {
826 return draw_modifier(layout, ob, md, i, cageIndex, lastCageIndex);
827 else if(vmd->mode & eModifierMode_Virtual)
834 /************************ Constraint Template *************************/
836 #include "DNA_action_types.h"
837 #include "DNA_constraint_types.h"
839 #include "BKE_action.h"
840 #include "BKE_constraint.h"
844 #define REDRAWBUTSOBJECT 3
845 #define REDRAWACTION 4
846 #define B_CONSTRAINT_TEST 5
847 #define B_CONSTRAINT_CHANGETARGET 6
848 #define B_CONSTRAINT_INF 7
852 void do_constraint_panels(bContext *C, void *arg, int event)
854 Scene *scene= CTX_data_scene(C);
855 Object *ob= CTX_data_active_object(C);
858 case B_CONSTRAINT_TEST:
859 // XXX allqueue(REDRAWVIEW3D, 0);
860 // XXX allqueue(REDRAWBUTSOBJECT, 0);
861 // XXX allqueue(REDRAWBUTSEDIT, 0);
862 break; // no handling
863 case B_CONSTRAINT_INF:
864 /* influence; do not execute actions for 1 dag_flush */
866 ob->pose->flag |= (POSE_LOCKED|POSE_DO_UNLOCK);
868 case B_CONSTRAINT_CHANGETARGET:
869 if (ob->pose) ob->pose->flag |= POSE_RECALC; // checks & sorts pose channels
870 DAG_scene_sort(scene);
876 object_test_constraints(ob);
878 if(ob->pose) update_pose_constraint_flags(ob->pose);
880 if(ob->type==OB_ARMATURE) DAG_id_flush_update(&ob->id, OB_RECALC_DATA|OB_RECALC_OB);
881 else DAG_id_flush_update(&ob->id, OB_RECALC_OB);
883 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
885 // XXX allqueue(REDRAWVIEW3D, 0);
886 // XXX allqueue(REDRAWBUTSOBJECT, 0);
887 // XXX allqueue(REDRAWBUTSEDIT, 0);
890 static void constraint_active_func(bContext *C, void *ob_v, void *con_v)
892 ED_object_constraint_set_active(ob_v, con_v);
895 static void verify_constraint_name_func (bContext *C, void *con_v, void *dummy)
897 Object *ob= CTX_data_active_object(C);
898 bConstraint *con= con_v;
903 ED_object_constraint_rename(ob, con, NULL);
904 ED_object_constraint_set_active(ob, con);
905 // XXX allqueue(REDRAWACTION, 0);
908 /* some commonly used macros in the constraints drawing code */
909 #define is_armature_target(target) (target && target->type==OB_ARMATURE)
910 #define is_armature_owner(ob) ((ob->type == OB_ARMATURE) && (ob->mode & OB_MODE_POSE))
911 #define is_geom_target(target) (target && (ELEM(target->type, OB_MESH, OB_LATTICE)) )
913 /* Helper function for draw constraint - draws constraint space stuff
914 * This function should not be called if no menus are required
915 * owner/target: -1 = don't draw menu; 0= not posemode, 1 = posemode
917 static void draw_constraint_spaceselect (uiBlock *block, bConstraint *con, short xco, short yco, short owner, short target)
919 short tarx, ownx, iconx;
921 short iconwidth = 20;
923 /* calculate sizes and placement of menus */
929 else if (target == -1) {
937 iconx = tarx + bwidth + 5;
938 ownx = tarx + bwidth + iconwidth + 10;
942 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Convert:", xco, yco, 80,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
946 uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Pose Space %x2|Local with Parent %x3|Local Space %x1",
947 tarx, yco, bwidth, 18, &con->tarspace, 0, 0, 0, 0, "Choose space that target is evaluated in");
949 else if (target == 0) {
950 uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Local (Without Parent) Space %x1",
951 tarx, yco, bwidth, 18, &con->tarspace, 0, 0, 0, 0, "Choose space that target is evaluated in");
954 if ((target != -1) && (owner != -1))
955 uiDefIconBut(block, LABEL, 0, ICON_ARROW_LEFTRIGHT,
956 iconx, yco, 20, 20, NULL, 0.0, 0.0, 0.0, 0.0, "");
960 uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Owner Space %t|World Space %x0|Pose Space %x2|Local with Parent %x3|Local Space %x1",
961 ownx, yco, bwidth, 18, &con->ownspace, 0, 0, 0, 0, "Choose space that owner is evaluated in");
963 else if (owner == 0) {
964 uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Owner Space %t|World Space %x0|Local (Without Parent) Space %x1",
965 ownx, yco, bwidth, 18, &con->ownspace, 0, 0, 0, 0, "Choose space that owner is evaluated in");
969 static void test_obpoin_but(bContext *C, char *name, ID **idpp)
971 ID *id= BLI_findstring(&CTX_data_main(C)->object, name, offsetof(ID, name) + 2);
972 *idpp= id; /* can be NULL */
975 id_lib_extern(id); /* checks lib data, sets correct flag for saving then */
978 /* draw panel showing settings for a constraint */
979 static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con)
981 bPoseChannel *pchan= get_active_posechannel(ob);
982 bConstraintTypeInfo *cti;
984 uiLayout *result= NULL, *col, *box, *row, *subrow;
989 short proxy_protected, xco=0, yco=0;
992 /* get constraint typeinfo */
993 cti= constraint_get_typeinfo(con);
995 /* exception for 'Null' constraint - it doesn't have constraint typeinfo! */
996 if (con->type == CONSTRAINT_TYPE_NULL)
997 strcpy(typestr, "Null");
999 strcpy(typestr, "Unknown");
1002 strcpy(typestr, cti->name);
1004 /* determine whether constraint is proxy protected or not */
1005 if (proxylocked_constraints_owner(ob, pchan))
1006 proxy_protected= (con->flag & CONSTRAINT_PROXY_LOCAL)==0;
1010 /* unless button has own callback, it adds this callback to button */
1011 block= uiLayoutGetBlock(layout);
1012 uiBlockSetHandleFunc(block, do_constraint_panels, NULL);
1013 uiBlockSetFunc(block, constraint_active_func, ob, con);
1015 RNA_pointer_create(&ob->id, &RNA_Constraint, con, &ptr);
1017 col= uiLayoutColumn(layout, 1);
1018 uiLayoutSetContextPointer(col, "constraint", &ptr);
1020 box= uiLayoutBox(col);
1021 row= uiLayoutRow(box, 0);
1023 block= uiLayoutGetBlock(box);
1025 subrow= uiLayoutRow(row, 0);
1026 uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_LEFT);
1028 /* Draw constraint header */
1029 uiBlockSetEmboss(block, UI_EMBOSSN);
1031 /* rounded header */
1032 rb_col= (con->flag & CONSTRAINT_ACTIVE)?50:20;
1035 uiDefIconButBitS(block, ICONTOG, CONSTRAINT_EXPAND, B_CONSTRAINT_TEST, ICON_TRIA_RIGHT, xco-10, yco, 20, 20, &con->flag, 0.0, 0.0, 0.0, 0.0, "Collapse/Expand Constraint");
1038 uiBlockSetEmboss(block, UI_EMBOSS);
1040 /* XXX if (con->flag & CONSTRAINT_DISABLE)
1041 uiBlockSetCol(block, TH_REDALERT);*/
1043 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, xco+10, yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
1045 if(proxy_protected == 0) {
1046 but = uiDefBut(block, TEX, B_CONSTRAINT_TEST, "", xco+120, yco, 85, 18, con->name, 0.0, 29.0, 0.0, 0.0, "Constraint name");
1047 uiButSetFunc(but, verify_constraint_name_func, con, con->name);
1050 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, con->name, xco+120, yco-1, 135, 19, NULL, 0.0, 0.0, 0.0, 0.0, "");
1052 // XXX uiBlockSetCol(block, TH_AUTO);
1054 subrow= uiLayoutRow(row, 0);
1055 uiLayoutSetAlignment(subrow, UI_LAYOUT_ALIGN_RIGHT);
1057 /* proxy-protected constraints cannot be edited, so hide up/down + close buttons */
1058 if (proxy_protected) {
1059 uiBlockSetEmboss(block, UI_EMBOSSN);
1061 /* draw a ghost icon (for proxy) and also a lock beside it, to show that constraint is "proxy locked" */
1062 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_GHOST, xco+244, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
1063 uiDefIconBut(block, BUT, B_CONSTRAINT_TEST, ICON_LOCKED, xco+262, yco, 19, 19, NULL, 0.0, 0.0, 0.0, 0.0, "Proxy Protected");
1065 uiBlockSetEmboss(block, UI_EMBOSS);
1068 short prev_proxylock, show_upbut, show_downbut;
1071 * Proxy-constraints are not allowed to occur after local (non-proxy) constraints
1072 * as that poses problems when restoring them, so disable the "up" button where
1073 * it may cause this situation.
1075 * Up/Down buttons should only be shown (or not greyed - todo) if they serve some purpose.
1077 if (proxylocked_constraints_owner(ob, pchan)) {
1079 prev_proxylock= (con->prev->flag & CONSTRAINT_PROXY_LOCAL) ? 0 : 1;
1087 show_upbut= ((prev_proxylock == 0) && (con->prev));
1088 show_downbut= (con->next) ? 1 : 0;
1090 if (show_upbut || show_downbut) {
1091 uiBlockBeginAlign(block);
1092 uiBlockSetEmboss(block, UI_EMBOSS);
1095 uiDefIconButO(block, BUT, "CONSTRAINT_OT_move_up", WM_OP_INVOKE_DEFAULT, ICON_TRIA_UP, xco+width-50, yco, 16, 18, "Move constraint up in constraint stack");
1098 uiDefIconButO(block, BUT, "CONSTRAINT_OT_move_down", WM_OP_INVOKE_DEFAULT, ICON_TRIA_DOWN, xco+width-50+18, yco, 16, 18, "Move constraint down in constraint stack");
1099 uiBlockEndAlign(block);
1102 /* Close 'button' - emboss calls here disable drawing of 'button' behind X */
1103 uiBlockSetEmboss(block, UI_EMBOSSN);
1104 uiDefIconButBitS(block, ICONTOGN, CONSTRAINT_OFF, B_CONSTRAINT_TEST, ICON_CHECKBOX_DEHLT, xco+243, yco, 19, 19, &con->flag, 0.0, 0.0, 0.0, 0.0, "enable/disable constraint");
1106 uiDefIconButO(block, BUT, "CONSTRAINT_OT_delete", WM_OP_INVOKE_DEFAULT, ICON_X, xco+262, yco, 19, 19, "Delete constraint");
1107 uiBlockSetEmboss(block, UI_EMBOSS);
1110 /* Set but-locks for protected settings (magic numbers are used here!) */
1111 if (proxy_protected)
1112 uiBlockSetButLock(block, 1, "Cannot edit Proxy-Protected Constraint");
1114 /* Draw constraint data */
1115 if ((con->flag & CONSTRAINT_EXPAND) == 0) {
1119 box= uiLayoutBox(col);
1120 block= uiLayoutAbsoluteBlock(box);
1122 switch (con->type) {
1123 #ifndef DISABLE_PYTHON
1124 case CONSTRAINT_TYPE_PYTHON:
1126 bPythonConstraint *data = con->data;
1127 bConstraintTarget *ct;
1129 int tarnum, theight;
1130 // static int pyconindex=0;
1133 theight = (data->tarnum)? (data->tarnum * 38) : (38);
1135 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Script:", xco+60, yco-24, 55, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
1137 /* do the scripts menu */
1138 /* XXX menustr = buildmenu_pyconstraints(data->text, &pyconindex);
1139 but2 = uiDefButI(block, MENU, B_CONSTRAINT_TEST, menustr,
1140 xco+120, yco-24, 150, 20, &pyconindex,
1141 0, 0, 0, 0, "Set the Script Constraint to use");
1142 uiButSetFunc(but2, validate_pyconstraint_cb, data, &pyconindex);
1143 MEM_freeN(menustr); */
1145 /* draw target(s) */
1146 if (data->flag & PYCON_USETARGETS) {
1147 /* Draw target parameters */
1148 for (ct=data->targets.first, tarnum=1; ct; ct=ct->next, tarnum++) {
1150 short yoffset= ((tarnum-1) * 38);
1153 sprintf(tarstr, "Target %d:", tarnum);
1154 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, tarstr, xco+45, yco-(48+yoffset), 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
1156 /* target space-selector - per target */
1157 if (is_armature_target(ct->tar)) {
1158 uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Pose Space %x3|Local with Parent %x4|Local Space %x1",
1159 xco+10, yco-(66+yoffset), 100, 18, &ct->space, 0, 0, 0, 0, "Choose space that target is evaluated in");
1162 uiDefButS(block, MENU, B_CONSTRAINT_TEST, "Target Space %t|World Space %x0|Local (Without Parent) Space %x1",
1163 xco+10, yco-(66+yoffset), 100, 18, &ct->space, 0, 0, 0, 0, "Choose space that target is evaluated in");
1166 uiBlockBeginAlign(block);
1168 uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", xco+120, yco-(48+yoffset), 150, 18, &ct->tar, "Target Object");
1171 if (is_armature_target(ct->tar)) {
1172 but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", xco+120, yco-(66+yoffset),150,18, &ct->subtarget, 0, 24, 0, 0, "Subtarget Bone");
1173 //uiButSetCompleteFunc(but, autocomplete_bone, (void *)ct->tar);
1175 else if (is_geom_target(ct->tar)) {
1176 but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "VG:", xco+120, yco-(66+yoffset),150,18, &ct->subtarget, 0, 24, 0, 0, "Name of Vertex Group defining 'target' points");
1177 //uiButSetCompleteFunc(but, autocomplete_vgroup, (void *)ct->tar);
1180 strcpy(ct->subtarget, "");
1182 uiBlockEndAlign(block);
1186 /* Draw indication that no target needed */
1187 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", xco+60, yco-48, 55, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
1188 uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Not Applicable", xco+120, yco-48, 150, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
1192 uiBlockBeginAlign(block);
1193 but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Options", xco, yco-(52+theight), (width/2),18, NULL, 0, 24, 0, 0, "Change some of the constraint's settings.");
1194 // XXX uiButSetFunc(but, BPY_pyconstraint_settings, data, NULL);
1196 but=uiDefBut(block, BUT, B_CONSTRAINT_TEST, "Refresh", xco+((width/2)+10), yco-(52+theight), (width/2),18, NULL, 0, 24, 0, 0, "Force constraint to refresh it's settings");
1197 uiBlockEndAlign(block);
1199 /* constraint space settings */
1200 draw_constraint_spaceselect(block, con, xco, yco-(73+theight), is_armature_owner(ob), -1);
1205 case CONSTRAINT_TYPE_NULL:
1207 uiItemL(box, "", 0);
1216 /* clear any locks set up for proxies/lib-linking */
1217 uiBlockClearButLock(block);
1222 uiLayout *uiTemplateConstraint(uiLayout *layout, PointerRNA *ptr)
1227 /* verify we have valid data */
1228 if(!RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
1229 printf("uiTemplateConstraint: expected constraint on object.\n");
1236 if(!ob || !(GS(ob->id.name) == ID_OB)) {
1237 printf("uiTemplateConstraint: expected constraint on object.\n");
1241 uiBlockSetButLock(uiLayoutGetBlock(layout), (ob && ob->id.lib), ERROR_LIBDATA_MESSAGE);
1243 /* hrms, the temporal constraint should not draw! */
1244 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
1245 bKinematicConstraint *data= con->data;
1246 if(data->flag & CONSTRAINT_IK_TEMP)
1250 return draw_constraint(layout, ob, con);
1254 /************************* Preview Template ***************************/
1256 #include "DNA_lamp_types.h"
1257 #include "DNA_material_types.h"
1258 #include "DNA_world_types.h"
1262 static void do_preview_buttons(bContext *C, void *arg, int event)
1266 WM_event_add_notifier(C, NC_MATERIAL|ND_SHADING, arg);
1271 void uiTemplatePreview(uiLayout *layout, ID *id, ID *parent, MTex *slot)
1273 uiLayout *row, *col;
1277 short *pr_texture= NULL;
1279 if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
1280 printf("uiTemplatePreview: expected ID of type material, texture, lamp or world.\n");
1284 /* decide what to render */
1288 if(id && (GS(id->name) == ID_TE)) {
1289 if(parent && (GS(parent->name) == ID_MA))
1290 pr_texture= &((Material*)parent)->pr_texture;
1291 else if(parent && (GS(parent->name) == ID_WO))
1292 pr_texture= &((World*)parent)->pr_texture;
1293 else if(parent && (GS(parent->name) == ID_LA))
1294 pr_texture= &((Lamp*)parent)->pr_texture;
1297 if(*pr_texture == TEX_PR_OTHER)
1299 else if(*pr_texture == TEX_PR_BOTH)
1305 block= uiLayoutGetBlock(layout);
1306 row= uiLayoutRow(layout, 0);
1307 col= uiLayoutColumn(row, 0);
1308 uiLayoutSetKeepAspect(col, 1);
1311 uiDefBut(block, BUT_EXTRA, 0, "", 0, 0, UI_UNIT_X*6, UI_UNIT_Y*6, pid, 0.0, 0.0, 0, 0, "");
1312 uiBlockSetDrawExtraFunc(block, ED_preview_draw, pparent, slot);
1313 uiBlockSetHandleFunc(block, do_preview_buttons, NULL);
1317 if(GS(pid->name) == ID_MA || (pparent && GS(pparent->name) == ID_MA)) {
1318 if(GS(pid->name) == ID_MA) ma= (Material*)pid;
1319 else ma= (Material*)pparent;
1321 uiLayoutColumn(row, 1);
1323 uiDefIconButC(block, ROW, B_MATPRV, ICON_MATPLANE, 0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_FLAT, 0, 0, "Preview type: Flat XY plane");
1324 uiDefIconButC(block, ROW, B_MATPRV, ICON_MATSPHERE, 0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_SPHERE, 0, 0, "Preview type: Sphere");
1325 uiDefIconButC(block, ROW, B_MATPRV, ICON_MATCUBE, 0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_CUBE, 0, 0, "Preview type: Cube");
1326 uiDefIconButC(block, ROW, B_MATPRV, ICON_MONKEY, 0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_MONKEY, 0, 0, "Preview type: Monkey");
1327 uiDefIconButC(block, ROW, B_MATPRV, ICON_HAIR, 0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_HAIR, 0, 0, "Preview type: Hair strands");
1328 uiDefIconButC(block, ROW, B_MATPRV, ICON_MAT_SPHERE_SKY, 0, 0,UI_UNIT_X*1.5,UI_UNIT_Y, &(ma->pr_type), 10, MA_SPHERE_A, 0, 0, "Preview type: Large sphere with sky");
1332 uiLayoutRow(layout, 1);
1334 uiDefButS(block, ROW, B_MATPRV, "Texture", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_TEXTURE, 0, 0, "");
1335 if(GS(parent->name) == ID_MA)
1336 uiDefButS(block, ROW, B_MATPRV, "Material", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1337 else if(GS(parent->name) == ID_LA)
1338 uiDefButS(block, ROW, B_MATPRV, "Lamp", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1339 else if(GS(parent->name) == ID_WO)
1340 uiDefButS(block, ROW, B_MATPRV, "World", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_OTHER, 0, 0, "");
1341 uiDefButS(block, ROW, B_MATPRV, "Both", 0, 0,UI_UNIT_X*10,UI_UNIT_Y, pr_texture, 10, TEX_PR_BOTH, 0, 0, "");
1346 /********************** ColorRamp Template **************************/
1348 #include "BKE_texture.h"
1350 typedef struct RNAUpdateCb {
1355 static void rna_update_cb(bContext *C, void *arg_cb, void *arg_unused)
1357 RNAUpdateCb *cb= (RNAUpdateCb*)arg_cb;
1359 /* we call update here on the pointer property, this way the
1360 owner of the curve mapping can still define it's own update
1361 and notifier, even if the CurveMapping struct is shared. */
1362 RNA_property_update(C, &cb->ptr, cb->prop);
1367 static int vergcband(const void *a1, const void *a2)
1369 const CBData *x1=a1, *x2=a2;
1371 if( x1->pos > x2->pos ) return 1;
1372 else if( x1->pos < x2->pos) return -1;
1376 static void colorband_pos_cb(bContext *C, void *cb_v, void *coba_v)
1378 ColorBand *coba= coba_v;
1381 if(coba->tot<2) return;
1383 for(a=0; a<coba->tot; a++) coba->data[a].cur= a;
1384 qsort(coba->data, coba->tot, sizeof(CBData), vergcband);
1385 for(a=0; a<coba->tot; a++) {
1386 if(coba->data[a].cur==coba->cur) {
1392 rna_update_cb(C, cb_v, NULL);
1395 static void colorband_add_cb(bContext *C, void *cb_v, void *coba_v)
1397 ColorBand *coba= coba_v;
1399 if(coba->tot < MAXCOLORBAND-1) coba->tot++;
1400 coba->cur= coba->tot-1;
1402 colorband_pos_cb(C, cb_v, coba_v);
1404 ED_undo_push(C, "Add colorband");
1407 static void colorband_del_cb(bContext *C, void *cb_v, void *coba_v)
1409 ColorBand *coba= coba_v;
1412 if(coba->tot<2) return;
1414 for(a=coba->cur; a<coba->tot; a++) {
1415 coba->data[a]= coba->data[a+1];
1417 if(coba->cur) coba->cur--;
1420 ED_undo_push(C, "Delete colorband");
1422 rna_update_cb(C, cb_v, NULL);
1426 /* offset aligns from bottom, standard width 300, height 115 */
1427 static void colorband_buttons_large(uiLayout *layout, uiBlock *block, ColorBand *coba, int xoffs, int yoffs, RNAUpdateCb *cb)
1432 if(coba==NULL) return;
1434 bt= uiDefBut(block, BUT, 0, "Add", 0+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Add a new color stop to the colorband");
1435 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1437 bt= uiDefBut(block, BUT, 0, "Delete", 60+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Delete the active position");
1438 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1440 uiDefButS(block, NUM, 0, "", 120+xoffs,100+yoffs,80, 20, &coba->cur, 0.0, (float)(MAX2(0, coba->tot-1)), 0, 0, "Choose active color stop");
1442 bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1443 210+xoffs, 100+yoffs, 90, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1444 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1445 uiBlockEndAlign(block);
1447 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, "");
1448 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1451 CBData *cbd= coba->data + coba->cur;
1453 /* better to use rna so we can animate them */
1455 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1456 uiItemR(layout, NULL, 0, &ptr, "color", 0);
1457 //uiItemR(layout, NULL, 0, &ptr, "position", 0);
1458 bt= uiDefButF(block, NUM, 0, "Pos:", 0+xoffs,40+yoffs,100, 20, &cbd->pos, 0.0, 1.0, 10, 0, "The position of the active color stop");
1459 uiButSetNFunc(bt, colorband_pos_cb, MEM_dupallocN(cb), coba);
1464 static void colorband_buttons_small(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, RNAUpdateCb *cb)
1467 float unit= (butr->xmax-butr->xmin)/14.0f;
1468 float xs= butr->xmin;
1471 bt= uiDefBut(block, BUT, 0, "Add", xs,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband");
1472 uiButSetNFunc(bt, colorband_add_cb, MEM_dupallocN(cb), coba);
1473 bt= uiDefBut(block, BUT, 0, "Delete", xs+2.0f*unit,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Delete the active position");
1474 uiButSetNFunc(bt, colorband_del_cb, MEM_dupallocN(cb), coba);
1477 CBData *cbd= coba->data + coba->cur;
1479 RNA_pointer_create(cb->ptr.id.data, &RNA_ColorRampElement, cbd, &ptr);
1480 uiItemR(layout, "", 0, &ptr, "color", 0);
1483 bt= uiDefButS(block, MENU, 0, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1484 xs+10.0f*unit, butr->ymin+20.0f, unit*4, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1485 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1487 bt= uiDefBut(block, BUT_COLORBAND, 0, "", xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, "");
1488 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1490 uiBlockEndAlign(block);
1493 static void colorband_buttons_layout(uiLayout *layout, uiBlock *block, ColorBand *coba, rctf *butr, int small, RNAUpdateCb *cb)
1496 colorband_buttons_small(layout, block, coba, butr, cb);
1498 colorband_buttons_large(layout, block, coba, 0, 0, cb);
1501 void uiTemplateColorRamp(uiLayout *layout, PointerRNA *ptr, char *propname, int expand)
1503 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1509 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1512 cptr= RNA_property_pointer_get(ptr, prop);
1513 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_ColorRamp))
1516 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1520 rect.xmin= 0; rect.xmax= 200;
1521 rect.ymin= 0; rect.ymax= 190;
1523 block= uiLayoutAbsoluteBlock(layout);
1524 colorband_buttons_layout(layout, block, cptr.data, &rect, !expand, cb);
1529 /********************* CurveMapping Template ************************/
1531 #include "DNA_color_types.h"
1532 #include "BKE_colortools.h"
1534 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *unused)
1536 CurveMapping *cumap = cumap_v;
1539 /* we allow 20 times zoom */
1540 if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1541 d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
1542 cumap->curr.xmin+= d;
1543 cumap->curr.xmax-= d;
1544 d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
1545 cumap->curr.ymin+= d;
1546 cumap->curr.ymax-= d;
1549 ED_region_tag_redraw(CTX_wm_region(C));
1552 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *unused)
1554 CurveMapping *cumap = cumap_v;
1557 /* we allow 20 times zoom, but dont view outside clip */
1558 if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
1559 d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
1561 if(cumap->flag & CUMA_DO_CLIP)
1562 if(cumap->curr.xmin-d < cumap->clipr.xmin)
1563 d1= cumap->curr.xmin - cumap->clipr.xmin;
1564 cumap->curr.xmin-= d1;
1567 if(cumap->flag & CUMA_DO_CLIP)
1568 if(cumap->curr.xmax+d > cumap->clipr.xmax)
1569 d1= -cumap->curr.xmax + cumap->clipr.xmax;
1570 cumap->curr.xmax+= d1;
1572 d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
1574 if(cumap->flag & CUMA_DO_CLIP)
1575 if(cumap->curr.ymin-d < cumap->clipr.ymin)
1576 d1= cumap->curr.ymin - cumap->clipr.ymin;
1577 cumap->curr.ymin-= d1;
1580 if(cumap->flag & CUMA_DO_CLIP)
1581 if(cumap->curr.ymax+d > cumap->clipr.ymax)
1582 d1= -cumap->curr.ymax + cumap->clipr.ymax;
1583 cumap->curr.ymax+= d1;
1586 ED_region_tag_redraw(CTX_wm_region(C));
1589 static void curvemap_buttons_setclip(bContext *C, void *cumap_v, void *unused)
1591 CurveMapping *cumap = cumap_v;
1593 curvemapping_changed(cumap, 0);
1596 static void curvemap_buttons_delete(bContext *C, void *cb_v, void *cumap_v)
1598 CurveMapping *cumap = cumap_v;
1600 curvemap_remove(cumap->cm+cumap->cur, SELECT);
1601 curvemapping_changed(cumap, 0);
1603 rna_update_cb(C, cb_v, NULL);
1606 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
1607 static uiBlock *curvemap_clipping_func(bContext *C, struct ARegion *ar, void *cumap_v)
1609 CurveMapping *cumap = cumap_v;
1613 block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS);
1615 /* use this for a fake extra empy space around the buttons */
1616 uiDefBut(block, LABEL, 0, "", -4, 16, 128, 106, NULL, 0, 0, 0, 0, "");
1618 bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",
1619 0,100,120,18, &cumap->flag, 0.0, 0.0, 10, 0, "");
1620 uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
1622 uiBlockBeginAlign(block);
1623 uiDefButF(block, NUM, 0, "Min X ", 0,74,120,18, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, "");
1624 uiDefButF(block, NUM, 0, "Min Y ", 0,56,120,18, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, "");
1625 uiDefButF(block, NUM, 0, "Max X ", 0,38,120,18, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, "");
1626 uiDefButF(block, NUM, 0, "Max Y ", 0,20,120,18, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, "");
1628 uiBlockSetDirection(block, UI_RIGHT);
1630 uiEndBlock(C, block);
1634 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
1636 CurveMapping *cumap = cumap_v;
1637 CurveMap *cuma= cumap->cm+cumap->cur;
1641 curvemap_reset(cuma, &cumap->clipr, CURVE_PRESET_LINE);
1642 curvemapping_changed(cumap, 0);
1645 cumap->curr= cumap->clipr;
1647 case 2: /* set vector */
1648 curvemap_sethandle(cuma, 1);
1649 curvemapping_changed(cumap, 0);
1651 case 3: /* set auto */
1652 curvemap_sethandle(cuma, 0);
1653 curvemapping_changed(cumap, 0);
1655 case 4: /* extend horiz */
1656 cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
1657 curvemapping_changed(cumap, 0);
1659 case 5: /* extend extrapolate */
1660 cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
1661 curvemapping_changed(cumap, 0);
1663 case 6: /* reset smooth */
1664 curvemap_reset(cuma, &cumap->clipr, CURVE_PRESET_SMOOTH);
1665 curvemapping_changed(cumap, 0);
1668 ED_region_tag_redraw(CTX_wm_region(C));
1671 static uiBlock *curvemap_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1674 short yco= 0, menuwidth=120;
1676 block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1677 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1679 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
1680 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
1681 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
1682 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
1683 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
1684 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
1686 uiBlockSetDirection(block, UI_RIGHT);
1687 uiTextBoundsBlock(block, 50);
1689 uiEndBlock(C, block);
1693 static uiBlock *curvemap_brush_tools_func(bContext *C, struct ARegion *ar, void *cumap_v)
1696 short yco= 0, menuwidth=120;
1698 block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
1699 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
1701 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
1702 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
1703 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
1704 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 6, "");
1706 uiBlockSetDirection(block, UI_RIGHT);
1707 uiTextBoundsBlock(block, 50);
1709 uiEndBlock(C, block);
1713 static void curvemap_buttons_redraw(bContext *C, void *arg1, void *arg2)
1715 ED_region_tag_redraw(CTX_wm_region(C));
1718 static void curvemap_buttons_reset(bContext *C, void *cb_v, void *cumap_v)
1720 CurveMapping *cumap = cumap_v;
1723 for(a=0; a<CM_TOT; a++)
1724 curvemap_reset(cumap->cm+a, &cumap->clipr, CURVE_PRESET_LINE);
1726 cumap->black[0]=cumap->black[1]=cumap->black[2]= 0.0f;
1727 cumap->white[0]=cumap->white[1]=cumap->white[2]= 1.0f;
1728 curvemapping_set_black_white(cumap, NULL, NULL);
1730 curvemapping_changed(cumap, 0);
1732 rna_update_cb(C, cb_v, NULL);
1735 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
1736 static void curvemap_buttons_layout(uiLayout *layout, PointerRNA *ptr, char labeltype, int levels, int brush, RNAUpdateCb *cb)
1738 CurveMapping *cumap= ptr->data;
1739 uiLayout *row, *sub, *split;
1742 float dx= UI_UNIT_X;
1745 block= uiLayoutGetBlock(layout);
1748 row= uiLayoutRow(layout, 0);
1750 if(labeltype=='v') {
1752 sub= uiLayoutRow(row, 1);
1753 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1755 if(cumap->cm[0].curve) {
1756 bt= uiDefButI(block, ROW, 0, "X", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1757 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1759 if(cumap->cm[1].curve) {
1760 bt= uiDefButI(block, ROW, 0, "Y", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1761 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1763 if(cumap->cm[2].curve) {
1764 bt= uiDefButI(block, ROW, 0, "Z", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1765 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1768 else if(labeltype=='c') {
1770 sub= uiLayoutRow(row, 1);
1771 uiLayoutSetAlignment(sub, UI_LAYOUT_ALIGN_LEFT);
1773 if(cumap->cm[3].curve) {
1774 bt= uiDefButI(block, ROW, 0, "C", 0, 0, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
1775 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1777 if(cumap->cm[0].curve) {
1778 bt= uiDefButI(block, ROW, 0, "R", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
1779 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1781 if(cumap->cm[1].curve) {
1782 bt= uiDefButI(block, ROW, 0, "G", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
1783 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1785 if(cumap->cm[2].curve) {
1786 bt= uiDefButI(block, ROW, 0, "B", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
1787 uiButSetFunc(bt, curvemap_buttons_redraw, NULL, NULL);
1791 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
1793 /* operation buttons */
1794 sub= uiLayoutRow(row, 1);
1796 uiBlockSetEmboss(block, UI_EMBOSSN);
1798 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMIN, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
1799 uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
1801 bt= uiDefIconBut(block, BUT, 0, ICON_ZOOMOUT, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
1802 uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
1805 bt= uiDefIconBlockBut(block, curvemap_brush_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, 18, "Tools");
1807 bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, 0, ICON_MODIFIER, 0, 0, dx, 18, "Tools");
1809 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1811 if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
1812 bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, 0, icon, 0, 0, dx, 18, "Clipping Options");
1813 uiButSetNFunc(bt, rna_update_cb, MEM_dupallocN(cb), NULL);
1815 bt= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
1816 uiButSetNFunc(bt, curvemap_buttons_delete, MEM_dupallocN(cb), cumap);
1818 uiBlockSetEmboss(block, UI_EMBOSS);
1820 uiBlockSetNFunc(block, rna_update_cb, MEM_dupallocN(cb), NULL);
1823 size= uiLayoutGetWidth(layout);
1824 row= uiLayoutRow(layout, 0);
1825 uiDefBut(block, BUT_CURVE, 0, "", 0, 0, size, MIN2(size, 200), cumap, 0.0f, 1.0f, 0, 0, "");
1827 /* black/white levels */
1829 split= uiLayoutSplit(layout, 0, 0);
1830 uiItemR(uiLayoutColumn(split, 0), NULL, 0, ptr, "black_level", UI_ITEM_R_EXPAND);
1831 uiItemR(uiLayoutColumn(split, 0), NULL, 0, ptr, "white_level", UI_ITEM_R_EXPAND);
1833 uiLayoutRow(layout, 0);
1834 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");
1835 uiButSetNFunc(bt, curvemap_buttons_reset, MEM_dupallocN(cb), cumap);
1838 uiBlockSetNFunc(block, NULL, NULL, NULL);
1841 void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, char *propname, int type, int levels, int brush)
1844 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1847 if(!prop || RNA_property_type(prop) != PROP_POINTER)
1850 cptr= RNA_property_pointer_get(ptr, prop);
1851 if(!cptr.data || !RNA_struct_is_a(cptr.type, &RNA_CurveMapping))
1854 cb= MEM_callocN(sizeof(RNAUpdateCb), "RNAUpdateCb");
1858 curvemap_buttons_layout(layout, &cptr, type, levels, brush, cb);
1863 /********************* ColorWheel Template ************************/
1865 #define WHEEL_SIZE 100
1867 void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, char *propname, int value_slider)
1869 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1870 uiBlock *block= uiLayoutGetBlock(layout);
1871 uiLayout *col, *row;
1874 printf("uiTemplateColorWheel: property not found: %s\n", propname);
1878 col = uiLayoutColumn(layout, 0);
1879 row= uiLayoutRow(col, 1);
1881 uiDefButR(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, propname, -1, 0.0, 0.0, 0, 0, "");
1886 uiDefButR(block, HSVCUBE, 0, "", WHEEL_SIZE+6, 0, 14, WHEEL_SIZE, ptr, propname, -1, 0.0, 0.0, 9, 0, "");
1888 /* maybe a switch for this?
1889 row= uiLayoutRow(col, 0);
1890 if(ELEM(RNA_property_subtype(prop), PROP_COLOR, PROP_COLOR_GAMMA) && RNA_property_array_length(ptr, prop) == 4) {
1891 but= uiDefAutoButR(block, ptr, prop, 3, "A:", 0, 0, 0, WHEEL_SIZE+20, UI_UNIT_Y);
1898 /********************* TriColor (ThemeWireColorSet) Template ************************/
1900 void uiTemplateTriColorSet(uiLayout *layout, PointerRNA *ptr, char *propname)
1902 PropertyRNA *prop= RNA_struct_find_property(ptr, propname);
1907 printf("uiTemplateTriColorSet: property not found: %s\n", propname);
1911 /* we lay out the data in a row as 3 color swatches */
1912 row= uiLayoutRow(layout, 1);
1914 /* nselected, selected, active color swatches */
1915 csPtr= RNA_property_pointer_get(ptr, prop);
1917 uiItemR(row, "", 0, &csPtr, "normal", 0);
1918 uiItemR(row, "", 0, &csPtr, "selected", 0);
1919 uiItemR(row, "", 0, &csPtr, "active", 0);
1922 /********************* Layer Buttons Template ************************/
1924 static void handle_layer_buttons(bContext *C, void *arg1, void *arg2)
1927 int cur = GET_INT_FROM_POINTER(arg2);
1928 wmWindow *win= CTX_wm_window(C);
1929 int i, tot, shift= win->eventstate->shift;
1932 tot= RNA_property_array_length(&but->rnapoin, but->rnaprop);
1934 /* Normally clicking only selects one layer */
1935 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, cur, 1);
1936 for(i = 0; i < tot; ++i) {
1938 RNA_property_boolean_set_index(&but->rnapoin, but->rnaprop, i, 0);
1944 // - for now, grouping of layers is determined by dividing up the length of
1945 // the array of layer bitflags
1947 void uiTemplateLayers(uiLayout *layout, PointerRNA *ptr, char *propname,
1948 PointerRNA *used_ptr, char *used_propname, int active_layer)
1950 uiLayout *uRow, *uCol;
1951 PropertyRNA *prop, *used_prop= NULL;
1952 int groups, cols, layers;
1953 int group, col, layer, row;
1954 int cols_per_group = 5;
1957 prop= RNA_struct_find_property(ptr, propname);
1959 printf("uiTemplateLayer: layers property not found: %s\n", propname);
1963 desc= RNA_property_description(prop);
1965 /* the number of layers determines the way we group them
1966 * - we want 2 rows only (for now)
1967 * - the number of columns (cols) is the total number of buttons per row
1968 * the 'remainder' is added to this, as it will be ok to have first row slightly wider if need be
1969 * - for now, only split into groups if group will have at least 5 items
1971 layers= RNA_property_array_length(ptr, prop);
1972 cols= (layers / 2) + (layers % 2);
1973 groups= ((cols / 2) < cols_per_group) ? (1) : (cols / cols_per_group);
1975 if(used_ptr && used_propname) {
1976 used_prop= RNA_struct_find_property(used_ptr, used_propname);
1978 printf("uiTemplateLayer: used layers property not found: %s\n", used_propname);
1982 if(RNA_property_array_length(used_ptr, used_prop) < layers)
1986 /* layers are laid out going across rows, with the columns being divided into groups */
1988 for (group= 0; group < groups; group++) {
1989 uCol= uiLayoutColumn(layout, 1);
1991 for (row= 0; row < 2; row++) {
1995 uRow= uiLayoutRow(uCol, 1);
1996 block= uiLayoutGetBlock(uRow);
1997 layer= groups*cols_per_group*row + cols_per_group*group;
1999 /* add layers as toggle buts */
2000 for (col= 0; (col < cols_per_group) && (layer < layers); col++, layer++) {
2002 int butlay = 1 << layer;
2004 if(active_layer & butlay)
2005 icon = ICON_LAYER_ACTIVE;
2006 else if(used_prop && RNA_property_boolean_get_index(used_ptr, used_prop, layer))
2007 icon = ICON_LAYER_USED;
2009 but= uiDefAutoButR(block, ptr, prop, layer, "", icon, 0, 0, 10, 10);
2010 uiButSetFunc(but, handle_layer_buttons, but, SET_INT_IN_POINTER(layer));
2018 /************************* List Template **************************/
2020 static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon)
2028 /* try ID, material or texture slot */
2029 if(RNA_struct_is_ID(itemptr->type)) {
2030 id= itemptr->id.data;
2032 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
2033 id= RNA_pointer_get(itemptr, "material").data;
2035 else if(RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
2036 id= RNA_pointer_get(itemptr, "texture").data;
2039 /* get icon from ID */
2041 icon= ui_id_icon_get(C, id, 1);
2050 static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i, int rnaicon, PointerRNA *activeptr, char *activepropname)
2053 uiBlock *block= uiLayoutGetBlock(layout);
2055 uiLayout *split, *overlap, *sub, *row;
2056 char *name, *namebuf;
2059 overlap= uiLayoutOverlap(layout);
2061 /* list item behind label & other buttons */
2062 sub= uiLayoutRow(overlap, 0);
2064 if(itemptr->type == &RNA_ShapeKey) {
2065 ob= (Object*)activeptr->data;
2066 if(ob->mode == OB_MODE_EDIT && !(ob->type == OB_MESH))
2067 uiLayoutSetEnabled(sub, 0);
2070 but= uiDefButR(block, LISTROW, 0, "", 0,0, UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
2071 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2073 sub= uiLayoutRow(overlap, 0);
2075 /* retrieve icon and name */
2076 icon= list_item_icon_get(C, itemptr, rnaicon);
2077 if(!icon || icon == ICON_DOT)
2080 namebuf= RNA_struct_name_get_alloc(itemptr, NULL, 0);
2081 name= (namebuf)? namebuf: "";
2083 /* hardcoded types */
2084 if(itemptr->type == &RNA_MeshTextureFaceLayer || itemptr->type == &RNA_MeshColorLayer) {
2085 uiItemL(sub, name, icon);
2086 uiBlockSetEmboss(block, UI_EMBOSSN);
2087 uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render", 0, 0, 0, 0, 0, NULL);
2088 uiBlockSetEmboss(block, UI_EMBOSS);
2090 else if(RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
2091 uiItemL(sub, name, icon);
2092 uiBlockSetEmboss(block, UI_EMBOSS);
2093 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
2095 else if(RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
2096 uiItemL(sub, name, icon);
2097 uiBlockSetEmboss(block, UI_EMBOSS);
2098 uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "enabled", 0, 0, 0, 0, 0, NULL);
2100 else if(itemptr->type == &RNA_ShapeKey) {
2101 ob= (Object*)activeptr->data;
2103 split= uiLayoutSplit(sub, 0.75f, 0);
2105 uiItemL(split, name, icon);
2107 uiBlockSetEmboss(block, UI_EMBOSSN);
2108 row= uiLayoutRow(split, 1);
2109 if(i == 0) uiItemL(row, "", 0);
2110 else uiItemR(row, "", 0, itemptr, "value", 0);
2112 if(ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH))
2113 uiLayoutSetActive(row, 0);
2114 //uiItemR(row, "", ICON_MUTE_IPO_OFF, itemptr, "mute", 0);
2115 uiBlockSetEmboss(block, UI_EMBOSS);
2118 uiItemL(sub, name, icon);
2125 void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, char *propname, PointerRNA *activeptr, char *activepropname, int rows, int maxrows, int listtype)
2127 //Scene *scene= CTX_data_scene(C);
2128 PropertyRNA *prop= NULL, *activeprop;
2129 PropertyType type, activetype;
2131 uiLayout *box, *row, *col;
2135 char *name, str[32];
2136 int rnaicon=0, icon=0, i= 0, activei= 0, len= 0, items, found, min, max;
2138 /* validate arguments */
2139 block= uiLayoutGetBlock(layout);
2143 printf("uiTemplateList: only works inside a panel.\n");
2147 if(!activeptr->data)
2151 prop= RNA_struct_find_property(ptr, propname);
2153 printf("uiTemplateList: property not found: %s\n", propname);
2158 activeprop= RNA_struct_find_property(activeptr, activepropname);
2160 printf("uiTemplateList: property not found: %s\n", activepropname);
2165 type= RNA_property_type(prop);
2166 if(type != PROP_COLLECTION) {
2167 printf("uiTemplateList: expected collection property.\n");
2172 activetype= RNA_property_type(activeprop);
2173 if(activetype != PROP_INT) {
2174 printf("uiTemplateList: expected integer property.\n");
2179 if(ptr->data && prop) {
2180 ptype= RNA_property_pointer_type(ptr, prop);
2181 rnaicon= RNA_struct_ui_icon(ptype);
2184 /* get active data */
2185 activei= RNA_property_int_get(activeptr, activeprop);
2187 if(listtype == 'i') {
2188 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2189 col= uiLayoutColumn(box, 1);
2190 row= uiLayoutRow(col, 0);
2192 if(ptr->data && prop) {
2193 /* create list items */
2194 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2197 row= uiLayoutRow(col, 0);
2199 icon= list_item_icon_get(C, &itemptr, rnaicon);
2200 but= uiDefIconButR(block, LISTROW, 0, icon, 0,0,UI_UNIT_X*10,UI_UNIT_Y, activeptr, activepropname, 0, 0, i, 0, 0, "");
2201 uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
2208 else if(listtype == 'c') {
2209 /* compact layout */
2212 row= uiLayoutRow(layout, 1);
2214 if(ptr->data && prop) {
2215 /* create list items */
2216 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2217 found= (activei == i);
2221 name= RNA_struct_name_get_alloc(&itemptr, NULL, 0);
2222 icon= list_item_icon_get(C, &itemptr, rnaicon);
2223 uiItemL(row, (name)? name: "", icon);
2234 /* if not found, add in dummy button */
2236 uiItemL(row, "", 0);
2238 /* next/prev button */
2239 sprintf(str, "%d :", i);
2240 but= uiDefIconTextButR(block, NUM, 0, 0, str, 0,0,UI_UNIT_X*5,UI_UNIT_Y, activeptr, activepropname, 0, 0, 0, 0, 0, "");
2242 uiButSetFlag(but, UI_BUT_DISABLED);
2250 if(pa->list_grip_size != 0)
2251 rows= pa->list_grip_size;
2254 box= uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
2255 row= uiLayoutRow(box, 0);
2256 col = uiLayoutColumn(row, 1);
2259 RNA_property_int_range(activeptr, activeprop, &min, &max);
2262 len= RNA_property_collection_length(ptr, prop);
2263 items= CLAMPIS(len, rows, MAX2(rows, maxrows));
2265 /* if list length changes and active is out of view, scroll to it */
2266 if(pa->list_last_len != len)
2267 if((activei < pa->list_scroll || activei >= pa->list_scroll+items))
2268 pa->list_scroll= activei;
2270 pa->list_scroll= MIN2(pa->list_scroll, len-items);
2271 pa->list_scroll= MAX2(pa->list_scroll, 0);
2272 pa->list_size= items;
2273 pa->list_last_len= len;
2275 if(ptr->data && prop) {
2276 /* create list items */
2277 RNA_PROP_BEGIN(ptr, itemptr, prop) {
2278 if(i >= pa->list_scroll && i<pa->list_scroll+items)
2279 list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activepropname);
2286 /* add dummy buttons to fill space */
2287 while(i < pa->list_scroll+items) {
2288 if(i >= pa->list_scroll)
2289 uiItemL(col, "", 0);
2295 col= uiLayoutColumn(row, 0);
2296 uiDefButI(block, SCROLL, 0, "", 0,0,UI_UNIT_X*0.75,UI_UNIT_Y*items, &pa->list_scroll, 0, len-items, items, 0, "");
2301 /************************* Operator Search Template **************************/
2303 static void operator_call_cb(bContext *C, void *arg1, void *arg2)
2305 wmOperatorType *ot= arg2;
2308 WM_operator_name_call(C, ot->idname, WM_OP_INVOKE_DEFAULT, NULL);
2311 static void operator_search_cb(const bContext *C, void *arg, char *str, uiSearchItems *items)
2313 wmOperatorType *ot = WM_operatortype_first();
2315 for(; ot; ot= ot->next) {
2317 if(BLI_strcasestr(ot->name, str)) {
2318 if(WM_operator_poll((bContext*)C, ot)) {
2320 int len= strlen(ot->name);
2322 /* display name for menu, can hold hotkey */
2323 BLI_strncpy(name, ot->name, 256);
2325 /* check for hotkey */
2327 if(WM_key_event_operator_string(C, ot->idname, WM_OP_EXEC_DEFAULT, NULL, &name[len+1], 256-len-1))
2331 if(0==uiSearchItemAdd(items, name, ot, 0))
2338 void uiTemplateOperatorSearch(uiLayout *layout)
2342 static char search[256]= "";
2344 block= uiLayoutGetBlock(layout);
2345 uiBlockSetCurLayout(block, layout);
2347 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 0, 0, UI_UNIT_X*6, UI_UNIT_Y, 0, 0, "");
2348 uiButSetSearchFunc(but, operator_search_cb, NULL, operator_call_cb, NULL);
2351 /************************* Running Jobs Template **************************/
2353 #define B_STOPRENDER 1
2354 #define B_STOPCAST 2
2355 #define B_STOPANIM 3
2357 static void do_running_jobs(bContext *C, void *arg, int event)
2364 WM_jobs_stop(CTX_wm_manager(C), CTX_wm_screen(C));
2367 WM_operator_name_call(C, "SCREEN_OT_animation_play", WM_OP_INVOKE_SCREEN, NULL);
2372 void uiTemplateRunningJobs(uiLayout *layout, bContext *C)
2374 bScreen *screen= CTX_wm_screen(C);
2375 Scene *scene= CTX_data_scene(C);
2376 wmWindowManager *wm= CTX_wm_manager(C);
2379 block= uiLayoutGetBlock(layout);
2380 uiBlockSetCurLayout(block, layout);
2382 uiBlockSetHandleFunc(block, do_running_jobs, NULL);
2384 if(WM_jobs_test(wm, scene))
2385 uiDefIconTextBut(block, BUT, B_STOPRENDER, ICON_CANCEL, "Render", 0,0,75,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop rendering");
2386 if(WM_jobs_test(wm, screen))
2387 uiDefIconTextBut(block, BUT, B_STOPCAST, ICON_CANCEL, "Capture", 0,0,85,UI_UNIT_Y, NULL, 0.0f, 0.0f, 0, 0, "Stop screencast");
2388 if(screen->animtimer)
2389 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");