2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 * The Original Code is Copyright (C) 2009 Blender Foundation.
19 * All rights reserved.
21 * Contributor(s): Blender Foundation
23 * ***** END GPL LICENSE BLOCK *****
30 #include "MEM_guardedalloc.h"
32 #include "DNA_action_types.h"
33 #include "DNA_color_types.h"
34 #include "DNA_listBase.h"
35 #include "DNA_material_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_screen_types.h"
38 #include "DNA_texture_types.h"
39 #include "DNA_windowmanager_types.h"
41 #include "BLI_blenlib.h"
43 #include "BKE_colortools.h"
44 #include "BKE_context.h"
45 #include "BKE_idprop.h"
46 #include "BKE_icons.h"
47 #include "BKE_library.h"
49 #include "BKE_texture.h"
50 #include "BKE_utildefines.h"
52 #include "RNA_access.h"
54 #include "UI_interface.h"
55 #include "UI_resources.h"
57 #include "ED_screen.h"
63 #include "interface_intern.h"
65 #define DEF_BUT_WIDTH 150
66 #define DEF_ICON_BUT_WIDTH 20
67 #define DEF_BUT_HEIGHT 20
69 /*************************** RNA Utilities ******************************/
71 uiBut *uiDefAutoButR(uiBlock *block, PointerRNA *ptr, PropertyRNA *prop, int index, char *name, int icon, int x1, int y1, int x2, int y2)
74 const char *propname= RNA_property_identifier(prop);
75 int arraylen= RNA_property_array_length(prop);
77 switch(RNA_property_type(prop)) {
81 if(arraylen && index == -1)
84 length= RNA_property_array_length(prop);
87 value= RNA_property_boolean_get_index(ptr, prop, index);
89 value= RNA_property_boolean_get(ptr, prop);
91 if(icon && name && strcmp(name, "") == 0)
92 but= uiDefIconButR(block, ICONTOG, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
94 but= uiDefIconTextButR(block, ICONTOG, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
96 but= uiDefButR(block, OPTION, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
101 if(arraylen && index == -1) {
102 if(RNA_property_subtype(prop) == PROP_COLOR)
103 but= uiDefButR(block, COL, 0, name, x1, y1, x2, y2, ptr, propname, 0, 0, 0, -1, -1, NULL);
105 else if(RNA_property_subtype(prop) == PROP_PERCENTAGE)
106 but= uiDefButR(block, NUMSLI, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
108 but= uiDefButR(block, NUM, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
111 but= uiDefButR(block, MENU, 0, NULL, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
114 if(icon && name && strcmp(name, "") == 0)
115 but= uiDefIconButR(block, TEX, 0, icon, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
117 but= uiDefIconTextButR(block, TEX, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
119 but= uiDefButR(block, TEX, 0, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
125 pptr= RNA_property_pointer_get(ptr, prop);
127 pptr.type= RNA_property_pointer_type(ptr, prop);
128 icon= RNA_struct_ui_icon(pptr.type);
132 but= uiDefIconTextButR(block, IDPOIN, 0, icon, name, x1, y1, x2, y2, ptr, propname, index, 0, 0, -1, -1, NULL);
135 case PROP_COLLECTION: {
137 sprintf(text, "%d items", RNA_property_collection_length(ptr, prop));
138 but= uiDefBut(block, LABEL, 0, text, x1, y1, x2, y2, NULL, 0, 0, 0, 0, NULL);
139 uiButSetFlag(but, UI_BUT_DISABLED);
150 void uiDefAutoButsRNA(const bContext *C, uiLayout *layout, PointerRNA *ptr, int columns)
152 uiLayout *split, *col;
155 uiItemL(layout, (char*)RNA_struct_ui_name(ptr->type), 0);
157 RNA_STRUCT_BEGIN(ptr, prop) {
158 if(strcmp(RNA_property_identifier(prop), "rna_type") == 0)
161 name= (char*)RNA_property_ui_name(prop);
164 col= uiLayoutColumn(layout, 1);
165 uiItemL(col, name, 0);
167 else if(columns == 2) {
168 split = uiLayoutSplit(layout, 0.5f);
170 uiItemL(uiLayoutColumn(split, 0), name, 0);
171 col= uiLayoutColumn(split, 0);
176 /* temp hack to show normal button for spin/screw */
177 if(strcmp(name, "Axis")==0) {
178 uiDefButR(uiLayoutGetBlock(col), BUT_NORMAL, 0, name, 0, 0, 100, 100, ptr, "axis", -1, 0, 0, -1, -1, NULL);
180 else uiItemFullR(col, "", 0, ptr, prop, -1, 0, 0, 0, 0);
185 /***************************** ID Utilities *******************************/
186 /* note, C code version, will be replaced with version in interface_templates.c */
188 typedef struct uiIDPoinParams {
196 static void idpoin_cb(bContext *C, void *arg_params, void *arg_event)
198 uiIDPoinParams *params= (uiIDPoinParams*)arg_params;
199 ListBase *lb= params->lb;
200 uiIDPoinFunc func= params->func;
201 ID *id= params->id, *idtest;
202 int nr, event= GET_INT_FROM_POINTER(arg_event);
204 if(event == UI_ID_BROWSE && params->browsenr == 32767)
205 event= UI_ID_ADD_NEW;
206 else if(event == UI_ID_BROWSE && params->browsenr == 32766)
211 if(id) test_idbutton(id->name+2);
215 /* ID can be NULL, if nothing was assigned yet */
216 if(lb->first==NULL) return;
218 if(params->browsenr== -2) {
219 /* XXX implement or find a replacement (ID can be NULL!)
220 * activate_databrowse((ID *)G.buts->lockpoin, GS(id->name), 0, B_MESHBROWSE, ¶ms->browsenr, do_global_buttons); */
223 if(params->browsenr < 0)
226 for(idtest=lb->first, nr=1; idtest; idtest=idtest->next, nr++) {
227 if(nr==params->browsenr) {
241 case UI_ID_FAKE_USER:
243 if(id->flag & LIB_FAKEUSER) id->us++;
255 if(!id || id->us < 1)
259 if(!id || id->us < 1)
262 case UI_ID_AUTO_NAME:
270 /* ***************************** ID Search browse menu ********************** */
272 static void id_search_call_cb(struct bContext *C, void *arg_params, void *item)
274 uiIDPoinParams *params= (uiIDPoinParams*)arg_params;
276 if(item && params->func)
277 params->func(C, item, UI_ID_BROWSE);
281 static void id_search_cb(const struct bContext *C, void *arg_params, char *str, uiSearchItems *items)
283 uiIDPoinParams *params= (uiIDPoinParams*)arg_params;
286 for(id= params->lb->first; id; id= id->next) {
293 case ID_MA: /* fall through */
294 case ID_TE: /* fall through */
295 case ID_IM: /* fall through */
296 case ID_WO: /* fall through */
297 case ID_LA: /* fall through */
298 iconid= BKE_icon_getid(id);
304 if(BLI_strcasestr(id->name+2, str)) {
305 if(0==uiSearchItemAdd(items, id->name+2, id, iconid))
311 static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_params)
313 static char search[256];
314 static uiIDPoinParams params;
316 wmWindow *win= CTX_wm_window(C);
320 /* clear initial search string, then all items show */
322 /* params is malloced, can be freed by parent button */
323 params= *((uiIDPoinParams*)arg_params);
325 block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
326 uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
328 /* fake button, it holds space for search items */
329 uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
331 but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, "");
332 uiButSetSearchFunc(but, id_search_cb, ¶ms, id_search_call_cb, NULL);
334 uiBoundsBlock(block, 6);
335 uiBlockSetDirection(block, UI_DOWN);
336 uiEndBlock(C, block);
338 event= *(win->eventstate); /* XXX huh huh? make api call */
339 event.type= EVT_BUT_OPEN;
341 event.customdata= but;
342 event.customdatafree= FALSE;
343 wm_event_add(win, &event);
348 /* ****************** */
350 int uiDefIDPoinButs(uiBlock *block, Main *bmain, ID *parid, ID *id, int id_code, short *pin_p, int x, int y, uiIDPoinFunc func, int events)
353 uiIDPoinParams *params, *dup_params;
355 int len, add_addbutton=0;
357 /* setup struct that we will pass on with the buttons */
358 params= MEM_callocN(sizeof(uiIDPoinParams), "uiIDPoinParams");
359 params->lb= wich_libbase(bmain, id_code);
361 params->id_code= id_code;
365 uiBlockBeginAlign(block);
369 uiBlockSetCol(block, TH_BUT_SETTING1);
371 if((events & UI_ID_PIN) && *pin_p)
372 uiBlockSetCol(block, TH_BUT_SETTING2);
376 if(id && (events & UI_ID_PIN)) {
377 but= uiDefIconButS(block, ICONTOG, (events & UI_ID_PIN), ICON_KEY_DEHLT, x, y ,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, pin_p, 0, 0, 0, 0, "Keeps this view displaying the current data regardless of what object is selected");
378 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_PIN));
379 x+= DEF_ICON_BUT_WIDTH;
383 if(events & UI_ID_BROWSE) {
384 uiDefBlockButN(block, id_search_menu, MEM_dupallocN(params), "", x, y, DEF_ICON_BUT_WIDTH, DEF_BUT_HEIGHT, "Browse ID data");
385 x+= DEF_ICON_BUT_WIDTH;
390 /* text button with name */
394 uiBlockSetCol(block, TH_BUT_SETTING1);
397 if((events & UI_ID_PIN) && *pin_p)
398 uiBlockSetCol(block, TH_BUT_SETTING2);
400 /* redalert overrides pin color
402 uiBlockSetCol(block, TH_REDALERT);
404 uiBlockSetButLock(block, id->lib!=0, "Can't edit external libdata");
407 text_idbutton(id, str1);
409 if(GS(id->name)==ID_IP) len= 110;
410 else if((y) && (GS(id->name)==ID_AC)) len= 100; // comes from button panel (poselib)
411 else if(y) len= 140; // comes from button panel
414 but= uiDefBut(block, TEX, 0, str1,x, y, (short)len, DEF_BUT_HEIGHT, id->name+2, 0.0, 21.0, 0, 0, "Displays current Datablock name. Click to change.");
415 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_RENAME));
419 uiBlockClearButLock(block);
421 /* lib make local button */
423 if(id->flag & LIB_INDIRECT) uiDefIconBut(block, BUT, 0, 0 /* XXX ICON_DATALIB */,x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Indirect Library Datablock. Cannot change.");
425 but= uiDefIconBut(block, BUT, 0, 0 /* XXX ICON_PARLIB */, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0,
426 (events & UI_ID_LOCAL)? "Direct linked Library Datablock. Click to make local.": "Direct linked Library Datablock, cannot make local.");
427 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ALONE));
430 x+= DEF_ICON_BUT_WIDTH;
433 /* number of users / make local button */
434 if((events & UI_ID_ALONE) && id->us>1) {
437 uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't make pinned data single-user");
439 sprintf(str1, "%d", id->us);
440 butwidth= (id->us<10)? DEF_ICON_BUT_WIDTH: DEF_ICON_BUT_WIDTH+10;
442 but= uiDefBut(block, BUT, 0, str1, x, y, butwidth, DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Displays number of users of this data. Click to make a single-user copy.");
443 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_ALONE));
446 uiBlockClearButLock(block);
450 if(events & UI_ID_DELETE) {
451 uiBlockSetButLock(block, (events & UI_ID_PIN) && *pin_p, "Can't unlink pinned data");
452 if(parid && parid->lib);
454 but= uiDefIconBut(block, BUT, 0, ICON_X, x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Deletes link to this Datablock");
455 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_DELETE));
456 x+= DEF_ICON_BUT_WIDTH;
459 uiBlockClearButLock(block);
462 /* auto name button */
463 if(events & UI_ID_AUTO_NAME) {
464 if(parid && parid->lib);
466 but= uiDefIconBut(block, BUT, 0, ICON_AUTO,x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, 0, 0, 0, 0, 0, "Generates an automatic name");
467 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_AUTO_NAME));
468 x+= DEF_ICON_BUT_WIDTH;
472 /* fake user button */
473 if(events & UI_ID_FAKE_USER) {
474 but= uiDefButBitS(block, TOG, LIB_FAKEUSER, 0, "F", x,y,DEF_ICON_BUT_WIDTH,DEF_BUT_HEIGHT, &id->flag, 0, 0, 0, 0, "Saves this datablock even if it has no users");
475 uiButSetNFunc(but, idpoin_cb, MEM_dupallocN(params), SET_INT_IN_POINTER(UI_ID_FAKE_USER));
476 x+= DEF_ICON_BUT_WIDTH;
480 else if(add_addbutton) {
481 if(parid) uiBlockSetButLock(block, parid->lib!=0, "Can't edit external libdata");
482 dup_params= MEM_dupallocN(params);
483 but= uiDefButS(block, TOG, 0, "Add New", x, y, 110, DEF_BUT_HEIGHT, &dup_params->browsenr, params->browsenr, 32767.0, 0, 0, "Add new data block");
484 uiButSetNFunc(but, idpoin_cb, dup_params, SET_INT_IN_POINTER(UI_ID_ADD_NEW));
488 uiBlockEndAlign(block);
495 /* ****************************** default button callbacks ******************* */
496 /* ************ LEGACY WARNING, only to get things work with 2.48 code! ****** */
498 void test_idbutton_cb(struct bContext *C, void *namev, void *arg2)
502 test_idbutton(name+2);
506 void test_scriptpoin_but(struct bContext *C, char *name, ID **idpp)
510 id= CTX_data_main(C)->text.first;
512 if( strcmp(name, id->name+2)==0 ) {
521 void test_actionpoin_but(struct bContext *C, char *name, ID **idpp)
525 id= CTX_data_main(C)->action.first;
527 if( strcmp(name, id->name+2)==0 ) {
538 void test_obpoin_but(struct bContext *C, char *name, ID **idpp)
542 // XXX if(idpp == (ID **)&(emptytex.object)) {
543 // error("You must add a texture first");
548 id= CTX_data_main(C)->object.first;
550 if( strcmp(name, id->name+2)==0 ) {
552 id_lib_extern(id); /* checks lib data, sets correct flag for saving then */
560 /* tests for an object of type OB_MESH */
561 void test_meshobpoin_but(struct bContext *C, char *name, ID **idpp)
565 id = CTX_data_main(C)->object.first;
567 Object *ob = (Object *)id;
568 if(ob->type == OB_MESH && strcmp(name, id->name + 2) == 0) {
570 /* checks lib data, sets correct flag for saving then */
579 void test_meshpoin_but(struct bContext *C, char *name, ID **idpp)
583 if( *idpp ) (*idpp)->us--;
585 id= CTX_data_main(C)->mesh.first;
587 if( strcmp(name, id->name+2)==0 ) {
597 void test_matpoin_but(struct bContext *C, char *name, ID **idpp)
601 if( *idpp ) (*idpp)->us--;
603 id= CTX_data_main(C)->mat.first;
605 if( strcmp(name, id->name+2)==0 ) {
615 void test_scenepoin_but(struct bContext *C, char *name, ID **idpp)
619 if( *idpp ) (*idpp)->us--;
621 id= CTX_data_main(C)->scene.first;
623 if( strcmp(name, id->name+2)==0 ) {
633 void test_grouppoin_but(struct bContext *C, char *name, ID **idpp)
637 if( *idpp ) (*idpp)->us--;
639 id= CTX_data_main(C)->group.first;
641 if( strcmp(name, id->name+2)==0 ) {
651 void test_texpoin_but(struct bContext *C, char *name, ID **idpp)
655 if( *idpp ) (*idpp)->us--;
657 id= CTX_data_main(C)->tex.first;
659 if( strcmp(name, id->name+2)==0 ) {
669 void test_imapoin_but(struct bContext *C, char *name, ID **idpp)
673 if( *idpp ) (*idpp)->us--;
675 id= CTX_data_main(C)->image.first;
677 if( strcmp(name, id->name+2)==0 ) {
687 /* autocomplete callback for buttons */
688 void autocomplete_bone(struct bContext *C, char *str, void *arg_v)
690 Object *ob= (Object *)arg_v;
692 if(ob==NULL || ob->pose==NULL) return;
694 /* search if str matches the beginning of name */
696 AutoComplete *autocpl= autocomplete_begin(str, 32);
699 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next)
700 autocomplete_do_name(autocpl, pchan->name);
702 autocomplete_end(autocpl, str);
706 /* autocomplete callback for buttons */
707 void autocomplete_vgroup(struct bContext *C, char *str, void *arg_v)
709 Object *ob= (Object *)arg_v;
713 /* search if str matches the beginning of a name */
715 AutoComplete *autocpl= autocomplete_begin(str, 32);
718 for(dg= ob->defbase.first; dg; dg= dg->next)
720 autocomplete_do_name(autocpl, dg->name);
722 autocomplete_end(autocpl, str);
727 /* ----------- custom button group ---------------------- */
729 static void curvemap_buttons_zoom_in(bContext *C, void *cumap_v, void *unused)
731 CurveMapping *cumap = cumap_v;
734 /* we allow 20 times zoom */
735 if( (cumap->curr.xmax - cumap->curr.xmin) > 0.04f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
736 d= 0.1154f*(cumap->curr.xmax - cumap->curr.xmin);
737 cumap->curr.xmin+= d;
738 cumap->curr.xmax-= d;
739 d= 0.1154f*(cumap->curr.ymax - cumap->curr.ymin);
740 cumap->curr.ymin+= d;
741 cumap->curr.ymax-= d;
745 static void curvemap_buttons_zoom_out(bContext *C, void *cumap_v, void *unused)
747 CurveMapping *cumap = cumap_v;
750 /* we allow 20 times zoom, but dont view outside clip */
751 if( (cumap->curr.xmax - cumap->curr.xmin) < 20.0f*(cumap->clipr.xmax - cumap->clipr.xmin) ) {
752 d= d1= 0.15f*(cumap->curr.xmax - cumap->curr.xmin);
754 if(cumap->flag & CUMA_DO_CLIP)
755 if(cumap->curr.xmin-d < cumap->clipr.xmin)
756 d1= cumap->curr.xmin - cumap->clipr.xmin;
757 cumap->curr.xmin-= d1;
760 if(cumap->flag & CUMA_DO_CLIP)
761 if(cumap->curr.xmax+d > cumap->clipr.xmax)
762 d1= -cumap->curr.xmax + cumap->clipr.xmax;
763 cumap->curr.xmax+= d1;
765 d= d1= 0.15f*(cumap->curr.ymax - cumap->curr.ymin);
767 if(cumap->flag & CUMA_DO_CLIP)
768 if(cumap->curr.ymin-d < cumap->clipr.ymin)
769 d1= cumap->curr.ymin - cumap->clipr.ymin;
770 cumap->curr.ymin-= d1;
773 if(cumap->flag & CUMA_DO_CLIP)
774 if(cumap->curr.ymax+d > cumap->clipr.ymax)
775 d1= -cumap->curr.ymax + cumap->clipr.ymax;
776 cumap->curr.ymax+= d1;
780 static void curvemap_buttons_setclip(bContext *C, void *cumap_v, void *unused)
782 CurveMapping *cumap = cumap_v;
784 curvemapping_changed(cumap, 0);
787 static void curvemap_buttons_delete(bContext *C, void *cumap_v, void *unused)
789 CurveMapping *cumap = cumap_v;
791 curvemap_remove(cumap->cm+cumap->cur, SELECT);
792 curvemapping_changed(cumap, 0);
795 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
796 static uiBlock *curvemap_clipping_func(struct bContext *C, struct ARegion *ar, void *cumap_v)
798 CurveMapping *cumap = cumap_v;
802 block= uiBeginBlock(C, ar, "curvemap_clipping_func", UI_EMBOSS);
804 /* use this for a fake extra empy space around the buttons */
805 uiDefBut(block, LABEL, 0, "", -4, 16, 128, 106, NULL, 0, 0, 0, 0, "");
807 bt= uiDefButBitI(block, TOG, CUMA_DO_CLIP, 1, "Use Clipping",
808 0,100,120,18, &cumap->flag, 0.0, 0.0, 10, 0, "");
809 uiButSetFunc(bt, curvemap_buttons_setclip, cumap, NULL);
811 uiBlockBeginAlign(block);
812 uiDefButF(block, NUM, 0, "Min X ", 0,74,120,18, &cumap->clipr.xmin, -100.0, cumap->clipr.xmax, 10, 0, "");
813 uiDefButF(block, NUM, 0, "Min Y ", 0,56,120,18, &cumap->clipr.ymin, -100.0, cumap->clipr.ymax, 10, 0, "");
814 uiDefButF(block, NUM, 0, "Max X ", 0,38,120,18, &cumap->clipr.xmax, cumap->clipr.xmin, 100.0, 10, 0, "");
815 uiDefButF(block, NUM, 0, "Max Y ", 0,20,120,18, &cumap->clipr.ymax, cumap->clipr.ymin, 100.0, 10, 0, "");
817 uiBlockSetDirection(block, UI_RIGHT);
819 uiEndBlock(C, block);
824 static void curvemap_tools_dofunc(bContext *C, void *cumap_v, int event)
826 CurveMapping *cumap = cumap_v;
827 CurveMap *cuma= cumap->cm+cumap->cur;
831 curvemap_reset(cuma, &cumap->clipr);
832 curvemapping_changed(cumap, 0);
835 cumap->curr= cumap->clipr;
837 case 2: /* set vector */
838 curvemap_sethandle(cuma, 1);
839 curvemapping_changed(cumap, 0);
841 case 3: /* set auto */
842 curvemap_sethandle(cuma, 0);
843 curvemapping_changed(cumap, 0);
845 case 4: /* extend horiz */
846 cuma->flag &= ~CUMA_EXTEND_EXTRAPOLATE;
847 curvemapping_changed(cumap, 0);
849 case 5: /* extend extrapolate */
850 cuma->flag |= CUMA_EXTEND_EXTRAPOLATE;
851 curvemapping_changed(cumap, 0);
854 ED_region_tag_redraw(CTX_wm_region(C));
857 static uiBlock *curvemap_tools_func(struct bContext *C, struct ARegion *ar, void *cumap_v)
860 short yco= 0, menuwidth=120;
862 block= uiBeginBlock(C, ar, "curvemap_tools_func", UI_EMBOSS);
863 uiBlockSetButmFunc(block, curvemap_tools_dofunc, cumap_v);
865 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset View", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 1, "");
866 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Vector Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 2, "");
867 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Auto Handle", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 3, "");
868 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Horizontal", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 4, "");
869 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Extend Extrapolated", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 5, "");
870 uiDefIconTextBut(block, BUTM, 1, ICON_BLANK1, "Reset Curve", 0, yco-=20, menuwidth, 19, NULL, 0.0, 0.0, 0, 0, "");
872 uiBlockSetDirection(block, UI_RIGHT);
873 uiTextBoundsBlock(block, 50);
875 uiEndBlock(C, block);
879 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
880 void curvemap_buttons(uiBlock *block, CurveMapping *cumap, char labeltype, short event, short redraw, rctf *rect)
883 float dx, fy= rect->ymax-18.0f;
887 yco= (short)(rect->ymax-18.0f);
889 /* curve choice options + tools/settings, 8 icons + spacer */
890 dx= (rect->xmax-rect->xmin)/(9.0f);
892 uiBlockBeginAlign(block);
893 if(labeltype=='v') { /* vector */
894 xco= (short)rect->xmin;
895 if(cumap->cm[0].curve)
896 uiDefButI(block, ROW, redraw, "X", xco, yco+2, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
897 xco= (short)(rect->xmin+1.0f*dx);
898 if(cumap->cm[1].curve)
899 uiDefButI(block, ROW, redraw, "Y", xco, yco+2, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
900 xco= (short)(rect->xmin+2.0f*dx);
901 if(cumap->cm[2].curve)
902 uiDefButI(block, ROW, redraw, "Z", xco, yco+2, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
904 else if(labeltype=='c') { /* color */
905 xco= (short)rect->xmin;
906 if(cumap->cm[3].curve)
907 uiDefButI(block, ROW, redraw, "C", xco, yco+2, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
908 xco= (short)(rect->xmin+1.0f*dx);
909 if(cumap->cm[0].curve)
910 uiDefButI(block, ROW, redraw, "R", xco, yco+2, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
911 xco= (short)(rect->xmin+2.0f*dx);
912 if(cumap->cm[1].curve)
913 uiDefButI(block, ROW, redraw, "G", xco, yco+2, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
914 xco= (short)(rect->xmin+3.0f*dx);
915 if(cumap->cm[2].curve)
916 uiDefButI(block, ROW, redraw, "B", xco, yco+2, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
918 /* else no channels ! */
919 uiBlockEndAlign(block);
921 xco= (short)(rect->xmin+4.5f*dx);
922 uiBlockSetEmboss(block, UI_EMBOSSN);
923 bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMIN, xco, yco, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
924 uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
926 xco= (short)(rect->xmin+5.25f*dx);
927 bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMOUT, xco, yco, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
928 uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
930 xco= (short)(rect->xmin+6.0f*dx);
931 bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, event, ICON_MODIFIER, xco, yco, dx, 18, "Tools");
933 xco= (short)(rect->xmin+7.0f*dx);
934 if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
935 bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, event, icon, xco, yco, dx, 18, "Clipping Options");
937 xco= (short)(rect->xmin+8.0f*dx);
938 bt= uiDefIconBut(block, BUT, event, ICON_X, xco, yco, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
939 uiButSetFunc(bt, curvemap_buttons_delete, cumap, NULL);
941 uiBlockSetEmboss(block, UI_EMBOSS);
943 uiDefBut(block, BUT_CURVE, event, "",
944 rect->xmin, rect->ymin, rect->xmax-rect->xmin, fy-rect->ymin,
945 cumap, 0.0f, 1.0f, 0, 0, "");
948 /* still unsure how this call evolves... we use labeltype for defining what curve-channels to show */
949 void curvemap_layout(uiLayout *layout, CurveMapping *cumap, char labeltype, short event, short redraw, rctf *rect)
954 float dx, fy= rect->ymax-18.0f;
957 block= uiLayoutGetBlock(layout);
959 /* curve choice options + tools/settings, 8 icons + spacer */
962 row= uiLayoutRow(layout, 0);
963 uiLayoutSetAlignment(row, UI_LAYOUT_ALIGN_RIGHT);
965 if(labeltype=='v') { /* vector */
966 row= uiLayoutRow(layout, 1);
968 if(cumap->cm[0].curve)
969 uiDefButI(block, ROW, redraw, "X", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
970 if(cumap->cm[1].curve)
971 uiDefButI(block, ROW, redraw, "Y", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
972 if(cumap->cm[2].curve)
973 uiDefButI(block, ROW, redraw, "Z", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
975 else if(labeltype=='c') { /* color */
976 row= uiLayoutRow(layout, 1);
978 if(cumap->cm[3].curve)
979 uiDefButI(block, ROW, redraw, "C", 0, 0, dx, 16, &cumap->cur, 0.0, 3.0, 0.0, 0.0, "");
980 if(cumap->cm[0].curve)
981 uiDefButI(block, ROW, redraw, "R", 0, 0, dx, 16, &cumap->cur, 0.0, 0.0, 0.0, 0.0, "");
982 if(cumap->cm[1].curve)
983 uiDefButI(block, ROW, redraw, "G", 0, 0, dx, 16, &cumap->cur, 0.0, 1.0, 0.0, 0.0, "");
984 if(cumap->cm[2].curve)
985 uiDefButI(block, ROW, redraw, "B", 0, 0, dx, 16, &cumap->cur, 0.0, 2.0, 0.0, 0.0, "");
988 row= uiLayoutRow(row, 1);
990 uiBlockSetEmboss(block, UI_EMBOSSN);
991 bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMIN, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom in");
992 uiButSetFunc(bt, curvemap_buttons_zoom_in, cumap, NULL);
994 bt= uiDefIconBut(block, BUT, redraw, ICON_ZOOMOUT, 0, 0, dx, 14, NULL, 0.0, 0.0, 0.0, 0.0, "Zoom out");
995 uiButSetFunc(bt, curvemap_buttons_zoom_out, cumap, NULL);
997 bt= uiDefIconBlockBut(block, curvemap_tools_func, cumap, event, ICON_MODIFIER, 0, 0, dx, 18, "Tools");
999 if(cumap->flag & CUMA_DO_CLIP) icon= ICON_CLIPUV_HLT; else icon= ICON_CLIPUV_DEHLT;
1000 bt= uiDefIconBlockBut(block, curvemap_clipping_func, cumap, event, icon, 0, 0, dx, 18, "Clipping Options");
1002 bt= uiDefIconBut(block, BUT, event, ICON_X, 0, 0, dx, 18, NULL, 0.0, 0.0, 0.0, 0.0, "Delete points");
1003 uiButSetFunc(bt, curvemap_buttons_delete, cumap, NULL);
1005 uiBlockSetEmboss(block, UI_EMBOSS);
1007 row= uiLayoutRow(layout, 0);
1008 uiDefBut(block, BUT_CURVE, event, "",
1009 rect->xmin, rect->ymin, rect->xmax-rect->xmin, fy-rect->ymin,
1010 cumap, 0.0f, 1.0f, 0, 0, "");
1016 static int vergcband(const void *a1, const void *a2)
1018 const CBData *x1=a1, *x2=a2;
1020 if( x1->pos > x2->pos ) return 1;
1021 else if( x1->pos < x2->pos) return -1;
1025 static void colorband_pos_cb(bContext *C, void *coba_v, void *unused_v)
1027 ColorBand *coba= coba_v;
1030 if(coba->tot<2) return;
1032 for(a=0; a<coba->tot; a++) coba->data[a].cur= a;
1033 qsort(coba->data, coba->tot, sizeof(CBData), vergcband);
1034 for(a=0; a<coba->tot; a++) {
1035 if(coba->data[a].cur==coba->cur) {
1036 // XXX if(coba->cur!=a) addqueue(curarea->win, REDRAW, 0); /* button cur */
1042 WM_event_add_notifier(C, NC_TEXTURE, NULL);
1045 static void colorband_cb(bContext *C, void *coba_v, void *unused_v)
1047 WM_event_add_notifier(C, NC_TEXTURE, NULL);
1050 static void colorband_add_cb(bContext *C, void *coba_v, void *unused_v)
1052 ColorBand *coba= coba_v;
1054 if(coba->tot < MAXCOLORBAND-1) coba->tot++;
1055 coba->cur= coba->tot-1;
1057 colorband_pos_cb(C, coba, NULL);
1058 ED_undo_push(C, "Add colorband");
1059 WM_event_add_notifier(C, NC_TEXTURE, NULL);
1062 static void colorband_del_cb(bContext *C, void *coba_v, void *unused_v)
1064 ColorBand *coba= coba_v;
1067 if(coba->tot<2) return;
1069 for(a=coba->cur; a<coba->tot; a++) {
1070 coba->data[a]= coba->data[a+1];
1072 if(coba->cur) coba->cur--;
1075 ED_undo_push(C, "Delete colorband");
1076 // XXX BIF_preview_changed(ID_TE);
1077 WM_event_add_notifier(C, NC_TEXTURE, NULL);
1081 /* offset aligns from bottom, standard width 300, height 115 */
1082 static void colorband_buttons_large(uiBlock *block, ColorBand *coba, int xoffs, int yoffs, int redraw)
1087 if(coba==NULL) return;
1089 bt= uiDefBut(block, BUT, redraw, "Add", 0+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Add a new color stop to the colorband");
1090 uiButSetFunc(bt, colorband_add_cb, coba, NULL);
1091 bt= uiDefBut(block, BUT, redraw, "Delete", 60+xoffs,100+yoffs,50,20, 0, 0, 0, 0, 0, "Delete the active position");
1092 uiDefButS(block, NUM, redraw, "", 120+xoffs,100+yoffs,80, 20, &coba->cur, 0.0, (float)(coba->tot-1), 0, 0, "Choose active color stop");
1094 uiButSetFunc(bt, colorband_del_cb, coba, NULL);
1096 bt= uiDefButS(block, MENU, redraw, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1097 210+xoffs, 100+yoffs, 90, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1098 uiButSetFunc(bt, colorband_cb, coba, NULL);
1099 uiBlockEndAlign(block);
1101 bt= uiDefBut(block, BUT_COLORBAND, redraw, "", xoffs,65+yoffs,300,30, coba, 0, 0, 0, 0, "");
1102 uiButSetFunc(bt, colorband_cb, coba, NULL);
1104 cbd= coba->data + coba->cur;
1106 bt= uiDefButF(block, NUM, redraw, "Pos:", 0+xoffs,40+yoffs,100, 20, &cbd->pos, 0.0, 1.0, 10, 0, "The position of the active color stop");
1107 uiButSetFunc(bt, colorband_pos_cb, coba, NULL);
1108 bt= uiDefButF(block, COL, redraw, "", 110+xoffs,40+yoffs,80,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop");
1109 uiButSetFunc(bt, colorband_cb, coba, NULL);
1110 bt= uiDefButF(block, NUMSLI, redraw, "A ", 200+xoffs,40+yoffs,100,20, &cbd->a, 0.0, 1.0, 10, 0, "The alpha value of the active color stop");
1111 uiButSetFunc(bt, colorband_cb, coba, NULL);
1115 static void colorband_buttons_small(uiBlock *block, ColorBand *coba, rctf *butr, int event)
1119 float unit= (butr->xmax-butr->xmin)/14.0f;
1120 float xs= butr->xmin;
1122 cbd= coba->data + coba->cur;
1125 bt= uiDefBut(block, BUT, event, "Add", xs,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Add a new color stop to the colorband");
1126 uiButSetFunc(bt, colorband_add_cb, coba, NULL);
1127 bt= uiDefBut(block, BUT, event, "Delete", xs+2.0f*unit,butr->ymin+20.0f,2.0f*unit,20, NULL, 0, 0, 0, 0, "Delete the active position");
1128 uiButSetFunc(bt, colorband_del_cb, coba, NULL);
1130 uiDefButF(block, COL, event, "", xs+4.0f*unit,butr->ymin+20.0f,2.0f*unit,20, &(cbd->r), 0, 0, 0, B_BANDCOL, "The color value for the active color stop");
1131 uiDefButF(block, NUMSLI, event, "A:", xs+6.0f*unit,butr->ymin+20.0f,4.0f*unit,20, &(cbd->a), 0.0f, 1.0f, 10, 2, "The alpha value of the active color stop");
1133 uiDefButS(block, MENU, event, "Interpolation %t|Ease %x1|Cardinal %x3|Linear %x0|B-Spline %x2|Constant %x4",
1134 xs+10.0f*unit, butr->ymin+20.0f, unit*4, 20, &coba->ipotype, 0.0, 0.0, 0, 0, "Set interpolation between color stops");
1136 uiDefBut(block, BUT_COLORBAND, event, "", xs,butr->ymin,butr->xmax-butr->xmin,20.0f, coba, 0, 0, 0, 0, "");
1137 uiBlockEndAlign(block);
1140 void colorband_buttons(uiBlock *block, ColorBand *coba, rctf *butr, int small)
1143 colorband_buttons_small(block, coba, butr, 0);
1145 colorband_buttons_large(block, coba, 0, 0, 0);