2.5
Added search-browse to the Python ID template. Also added icon/button for 'Add new'. (Note, we need icon for it). Also fixed bug in search menu closing too quick on mouse-release, when mouse was close to bottom of menu button. And removed annoying warning if ID pointer was zero.
This commit is contained in:
@@ -1263,7 +1263,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
|
||||
|
||||
/* exit on LMB only on RELEASE for searchbox, to mimic other popups, and allow multiple menu levels */
|
||||
if(data->searchbox)
|
||||
inbox= BLI_in_rcti(&data->searchbox->winrct, event->x, event->y);
|
||||
inbox= ui_searchbox_inside(data->searchbox, event->x, event->y);
|
||||
|
||||
if(event->val==KM_PRESS) {
|
||||
mx= event->x;
|
||||
@@ -1287,6 +1287,7 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle
|
||||
}
|
||||
}
|
||||
else if(inbox) {
|
||||
printf("release inside \n");
|
||||
button_activate_state(C, but, BUTTON_STATE_EXIT);
|
||||
retval= WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
|
||||
@@ -357,6 +357,7 @@ void ui_tooltip_free(struct bContext *C, struct ARegion *ar);
|
||||
|
||||
/* searchbox for string button */
|
||||
ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBut *but);
|
||||
int ui_searchbox_inside(struct ARegion *ar, int x, int y);
|
||||
void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, int reset);
|
||||
void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, struct wmEvent *event);
|
||||
void ui_searchbox_apply(uiBut *but, struct ARegion *ar);
|
||||
|
||||
@@ -520,6 +520,14 @@ static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr)
|
||||
|
||||
}
|
||||
|
||||
/* x and y in screencoords */
|
||||
int ui_searchbox_inside(ARegion *ar, int x, int y)
|
||||
{
|
||||
uiSearchboxData *data= ar->regiondata;
|
||||
|
||||
return(BLI_in_rcti(&data->bbox, x-ar->winrct.xmin, y-ar->winrct.ymin));
|
||||
}
|
||||
|
||||
/* string validated to be of correct length (but->hardmax) */
|
||||
void ui_searchbox_apply(uiBut *but, ARegion *ar)
|
||||
{
|
||||
@@ -699,71 +707,80 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but)
|
||||
|
||||
/* compute position */
|
||||
|
||||
x1f= but->x1 - 5; /* align text with button */
|
||||
x2f= but->x2 + 5; /* symmetrical */
|
||||
if(but->block->flag & UI_BLOCK_LOOP) {
|
||||
/* this case is search menu inside other menu */
|
||||
/* we copy region size */
|
||||
|
||||
ar->winrct= butregion->winrct;
|
||||
|
||||
/* widget rect, in region coords */
|
||||
data->bbox.xmin= MENU_SHADOW_SIDE;
|
||||
data->bbox.xmax= (ar->winrct.xmax-ar->winrct.xmin) - MENU_SHADOW_SIDE;
|
||||
data->bbox.ymin= MENU_SHADOW_BOTTOM;
|
||||
data->bbox.ymax= (ar->winrct.ymax-ar->winrct.ymin) - MENU_SHADOW_BOTTOM;
|
||||
|
||||
/* check if button is lower half */
|
||||
if( but->y2 < (but->block->minx+but->block->maxx)/2 ) {
|
||||
y1f= but->y2;
|
||||
y2f= y1f + uiSearchBoxhHeight();
|
||||
data->bbox.ymin += (but->y2-but->y1);
|
||||
}
|
||||
else {
|
||||
y2f= but->y1;
|
||||
y1f= y2f - uiSearchBoxhHeight();
|
||||
data->bbox.ymax -= (but->y2-but->y1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
x1f= but->x1 - 5; /* align text with button */
|
||||
x2f= but->x2 + 5; /* symmetrical */
|
||||
y2f= but->y1;
|
||||
y1f= y2f - uiSearchBoxhHeight();
|
||||
}
|
||||
|
||||
/* minimal width */
|
||||
if(x2f - x1f < 150) x2f= x1f+150; // XXX arbitrary
|
||||
|
||||
/* copy to int, gets projected if possible too */
|
||||
x1= x1f; y1= y1f; x2= x2f; y2= y2f;
|
||||
|
||||
if(butregion) {
|
||||
if(butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) {
|
||||
UI_view2d_to_region_no_clip(&butregion->v2d, x1f, y1f, &x1, &y1);
|
||||
UI_view2d_to_region_no_clip(&butregion->v2d, x2f, y2f, &x2, &y2);
|
||||
/* minimal width */
|
||||
if(x2f - x1f < 150) x2f= x1f+150; // XXX arbitrary
|
||||
|
||||
/* copy to int, gets projected if possible too */
|
||||
x1= x1f; y1= y1f; x2= x2f; y2= y2f;
|
||||
|
||||
if(butregion) {
|
||||
if(butregion->v2d.cur.xmin != butregion->v2d.cur.xmax) {
|
||||
UI_view2d_to_region_no_clip(&butregion->v2d, x1f, y1f, &x1, &y1);
|
||||
UI_view2d_to_region_no_clip(&butregion->v2d, x2f, y2f, &x2, &y2);
|
||||
}
|
||||
|
||||
x1 += butregion->winrct.xmin;
|
||||
x2 += butregion->winrct.xmin;
|
||||
y1 += butregion->winrct.ymin;
|
||||
y2 += butregion->winrct.ymin;
|
||||
}
|
||||
|
||||
x1 += butregion->winrct.xmin;
|
||||
x2 += butregion->winrct.xmin;
|
||||
y1 += butregion->winrct.ymin;
|
||||
y2 += butregion->winrct.ymin;
|
||||
}
|
||||
|
||||
wm_window_get_size(CTX_wm_window(C), &winx, &winy);
|
||||
|
||||
if(x2 > winx) {
|
||||
/* super size */
|
||||
if(x2 > winx + x1) {
|
||||
x2= winx;
|
||||
x1= 0;
|
||||
wm_window_get_size(CTX_wm_window(C), &winx, &winy);
|
||||
|
||||
if(x2 > winx) {
|
||||
/* super size */
|
||||
if(x2 > winx + x1) {
|
||||
x2= winx;
|
||||
x1= 0;
|
||||
}
|
||||
else {
|
||||
x1 -= x2-winx;
|
||||
x2= winx;
|
||||
}
|
||||
}
|
||||
else {
|
||||
x1 -= x2-winx;
|
||||
x2= winx;
|
||||
if(y1 < 0) {
|
||||
y1 += 36;
|
||||
y2 += 36;
|
||||
}
|
||||
|
||||
/* widget rect, in region coords */
|
||||
data->bbox.xmin= MENU_SHADOW_SIDE;
|
||||
data->bbox.xmax= x2-x1 + MENU_SHADOW_SIDE;
|
||||
data->bbox.ymin= MENU_SHADOW_BOTTOM;
|
||||
data->bbox.ymax= y2-y1 + MENU_SHADOW_BOTTOM;
|
||||
|
||||
/* region bigger for shadow */
|
||||
ar->winrct.xmin= x1 - MENU_SHADOW_SIDE;
|
||||
ar->winrct.xmax= x2 + MENU_SHADOW_SIDE;
|
||||
ar->winrct.ymin= y1 - MENU_SHADOW_BOTTOM;
|
||||
ar->winrct.ymax= y2;
|
||||
}
|
||||
if(y1 < 0) {
|
||||
y1 += 36;
|
||||
y2 += 36;
|
||||
}
|
||||
|
||||
/* widget rect, in region coords */
|
||||
data->bbox.xmin= MENU_SHADOW_SIDE;
|
||||
data->bbox.xmax= x2-x1 + MENU_SHADOW_SIDE;
|
||||
data->bbox.ymin= MENU_SHADOW_BOTTOM;
|
||||
data->bbox.ymax= y2-y1 + MENU_SHADOW_BOTTOM;
|
||||
|
||||
/* region bigger for shadow */
|
||||
ar->winrct.xmin= x1 - MENU_SHADOW_SIDE;
|
||||
ar->winrct.xmax= x2 + MENU_SHADOW_SIDE;
|
||||
ar->winrct.ymin= y1 - MENU_SHADOW_BOTTOM;
|
||||
ar->winrct.ymax= y2;
|
||||
|
||||
/* adds subwindow */
|
||||
ED_region_init(C, ar);
|
||||
|
||||
@@ -78,9 +78,8 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
|
||||
{
|
||||
TemplateID *template= (TemplateID*)arg_litem;
|
||||
PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
|
||||
ID *idtest, *id= idptr.data;
|
||||
ListBase *lb= wich_libbase(CTX_data_main(C), template->idtype);
|
||||
int nr, event= GET_INT_FROM_POINTER(arg_event);
|
||||
ID *id= idptr.data;
|
||||
int event= GET_INT_FROM_POINTER(arg_event);
|
||||
|
||||
if(event == UI_ID_BROWSE && template->browse == 32767)
|
||||
event= UI_ID_ADD_NEW;
|
||||
@@ -88,31 +87,9 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
|
||||
event= UI_ID_OPEN;
|
||||
|
||||
switch(event) {
|
||||
case UI_ID_BROWSE: {
|
||||
if(template->browse== -2) {
|
||||
/* XXX implement or find a replacement
|
||||
* activate_databrowse((ID *)G.buts->lockpoin, GS(id->name), 0, B_MESHBROWSE, &template->browse, do_global_buttons); */
|
||||
return;
|
||||
}
|
||||
if(template->browse < 0)
|
||||
return;
|
||||
|
||||
for(idtest=lb->first, nr=1; idtest; idtest=idtest->next, nr++) {
|
||||
if(nr==template->browse) {
|
||||
if(id == idtest)
|
||||
return;
|
||||
|
||||
id= idtest;
|
||||
RNA_id_pointer_create(id, &idptr);
|
||||
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
|
||||
RNA_property_update(C, &template->ptr, template->prop);
|
||||
/* XXX */
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
case UI_ID_BROWSE:
|
||||
printf("warning, id browse shouldnt come here\n");
|
||||
break;
|
||||
}
|
||||
case UI_ID_DELETE:
|
||||
memset(&idptr, 0, sizeof(idptr));
|
||||
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
|
||||
@@ -148,10 +125,79 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event)
|
||||
}
|
||||
}
|
||||
|
||||
/* ID Search browse menu, assign */
|
||||
static void id_search_call_cb(struct bContext *C, void *arg_litem, void *item)
|
||||
{
|
||||
if(item) {
|
||||
TemplateID *template= (TemplateID*)arg_litem;
|
||||
PointerRNA idptr= RNA_property_pointer_get(&template->ptr, template->prop);
|
||||
|
||||
RNA_id_pointer_create(item, &idptr);
|
||||
RNA_property_pointer_set(&template->ptr, template->prop, idptr);
|
||||
RNA_property_update(C, &template->ptr, template->prop);
|
||||
}
|
||||
}
|
||||
|
||||
/* ID Search browse menu, do the search */
|
||||
static void id_search_cb(const struct bContext *C, void *arg_litem, char *str, uiSearchItems *items)
|
||||
{
|
||||
TemplateID *template= (TemplateID*)arg_litem;
|
||||
ListBase *lb= wich_libbase(CTX_data_main(C), template->idtype);
|
||||
ID *id;
|
||||
|
||||
for(id= lb->first; id; id= id->next) {
|
||||
|
||||
if(BLI_strcasestr(id->name+2, str)) {
|
||||
if(0==uiSearchItemAdd(items, id->name+2, id))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ID Search browse menu, open */
|
||||
static uiBlock *id_search_menu(bContext *C, ARegion *ar, void *arg_litem)
|
||||
{
|
||||
static char search[256];
|
||||
static TemplateID template;
|
||||
wmEvent event;
|
||||
wmWindow *win= CTX_wm_window(C);
|
||||
uiBlock *block;
|
||||
uiBut *but;
|
||||
|
||||
/* clear initial search string, then all items show */
|
||||
search[0]= 0;
|
||||
/* arg_litem is malloced, can be freed by parent button */
|
||||
template= *((TemplateID*)arg_litem);
|
||||
|
||||
block= uiBeginBlock(C, ar, "_popup", UI_EMBOSS);
|
||||
uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_RET_1);
|
||||
|
||||
/* fake button, it holds space for search items */
|
||||
uiDefBut(block, LABEL, 0, "", 10, 15, 150, uiSearchBoxhHeight(), NULL, 0, 0, 0, 0, NULL);
|
||||
|
||||
but= uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, 256, 10, 0, 150, 19, "");
|
||||
uiButSetSearchFunc(but, id_search_cb, &template, id_search_call_cb);
|
||||
|
||||
uiBoundsBlock(block, 6);
|
||||
uiBlockSetDirection(block, UI_DOWN);
|
||||
uiEndBlock(C, block);
|
||||
|
||||
event= *(win->eventstate); /* XXX huh huh? make api call */
|
||||
event.type= EVT_BUT_OPEN;
|
||||
event.val= KM_PRESS;
|
||||
event.customdata= but;
|
||||
event.customdatafree= FALSE;
|
||||
wm_event_add(win, &event);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
/* ****************** */
|
||||
|
||||
|
||||
static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template, StructRNA *type)
|
||||
{
|
||||
uiBut *but;
|
||||
TemplateID *duptemplate;
|
||||
PointerRNA idptr;
|
||||
ListBase *lb;
|
||||
|
||||
@@ -165,6 +211,7 @@ static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
if(template->flag & UI_ID_BROWSE) {
|
||||
/*
|
||||
char *extrastr, *str;
|
||||
|
||||
if((template->flag & UI_ID_ADD_NEW) && (template->flag & UI_ID_OPEN))
|
||||
@@ -183,6 +230,8 @@ static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template
|
||||
uiButSetNFunc(but, template_id_cb, duptemplate, SET_INT_IN_POINTER(UI_ID_BROWSE));
|
||||
|
||||
MEM_freeN(str);
|
||||
*/
|
||||
uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X, UI_UNIT_Y, "Browse ID data");
|
||||
}
|
||||
|
||||
/* text button with name */
|
||||
@@ -193,18 +242,31 @@ static void template_header_ID(bContext *C, uiBlock *block, TemplateID *template
|
||||
name[0]= '\0';
|
||||
but= uiDefButR(block, TEX, 0, name, 0, 0, UI_UNIT_X*6, UI_UNIT_Y, &idptr, "name", -1, 0, 0, -1, -1, NULL);
|
||||
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_RENAME));
|
||||
|
||||
/* delete button */
|
||||
if(template->flag & UI_ID_DELETE) {
|
||||
if(template->unlinkop[0]) {
|
||||
but= uiDefIconButO(block, BUT, template->unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
|
||||
}
|
||||
else {
|
||||
but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
|
||||
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
|
||||
}
|
||||
}
|
||||
|
||||
if(template->flag & UI_ID_ADD_NEW) {
|
||||
int w= idptr.data?UI_UNIT_X:UI_UNIT_X*6;
|
||||
|
||||
if(template->newop[0]) {
|
||||
but= uiDefIconTextButO(block, BUT, template->newop, WM_OP_EXEC_REGION_WIN, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL);
|
||||
}
|
||||
else {
|
||||
but= uiDefIconTextBut(block, BUT, 0, ICON_ZOOMIN, "Add New", 0, 0, w, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
|
||||
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_ADD_NEW));
|
||||
}
|
||||
}
|
||||
|
||||
/* delete button */
|
||||
if(idptr.data && (template->flag & UI_ID_DELETE)) {
|
||||
if(template->unlinkop[0]) {
|
||||
but= uiDefIconButO(block, BUT, template->unlinkop, WM_OP_EXEC_REGION_WIN, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL);
|
||||
}
|
||||
else {
|
||||
but= uiDefIconBut(block, BUT, 0, ICON_X, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, NULL);
|
||||
uiButSetNFunc(but, template_id_cb, MEM_dupallocN(template), SET_INT_IN_POINTER(UI_ID_DELETE));
|
||||
}
|
||||
}
|
||||
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
|
||||
@@ -1310,7 +1372,7 @@ void uiTemplatePreview(uiLayout *layout, ID *id)
|
||||
uiBlock *block;
|
||||
Material *ma;
|
||||
|
||||
if(!id || !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
|
||||
if(id && !ELEM4(GS(id->name), ID_MA, ID_TE, ID_WO, ID_LA)) {
|
||||
printf("uiTemplatePreview: expected ID of type material, texture, lamp or world.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -203,6 +203,7 @@ void uiDefAutoButsRNA_single(const bContext *C, uiLayout *layout, PointerRNA *pt
|
||||
|
||||
|
||||
/***************************** ID Utilities *******************************/
|
||||
/* note, C code version, will be replaced with version in interface_templates.c */
|
||||
|
||||
typedef struct uiIDPoinParams {
|
||||
uiIDPoinFunc func;
|
||||
|
||||
@@ -633,41 +633,42 @@ void BIF_previewrender_buts(Scene *scene, SpaceButs *sbuts)
|
||||
/* uses ROUNDBOX button in block to get the rect */
|
||||
void ED_preview_draw(const bContext *C, void *idp, rcti *rect)
|
||||
{
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
SpaceButs *sbuts= sa->spacedata.first;
|
||||
RenderResult rres;
|
||||
int newx= rect->xmax-rect->xmin, newy= rect->ymax-rect->ymin;
|
||||
int ok= 0;
|
||||
char name[32];
|
||||
|
||||
sprintf(name, "Preview %p", sa);
|
||||
BLI_lock_malloc_thread();
|
||||
RE_GetResultImage(RE_GetRender(name), &rres);
|
||||
if(idp) {
|
||||
ScrArea *sa= CTX_wm_area(C);
|
||||
SpaceButs *sbuts= sa->spacedata.first;
|
||||
RenderResult rres;
|
||||
int newx= rect->xmax-rect->xmin, newy= rect->ymax-rect->ymin;
|
||||
int ok= 0;
|
||||
char name[32];
|
||||
|
||||
sprintf(name, "Preview %p", sa);
|
||||
BLI_lock_malloc_thread();
|
||||
RE_GetResultImage(RE_GetRender(name), &rres);
|
||||
|
||||
if(rres.rectf) {
|
||||
|
||||
if( ABS(rres.rectx-newx)<2 && ABS(rres.recty-newy)<2 ) {
|
||||
/* correct size, then black outline matches */
|
||||
rect->xmax= rect->xmin + rres.rectx;
|
||||
rect->ymax= rect->ymin + rres.recty;
|
||||
|
||||
glaDrawPixelsSafe(rect->xmin, rect->ymin, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_FLOAT, rres.rectf);
|
||||
ok= 1;
|
||||
if(rres.rectf) {
|
||||
|
||||
if( ABS(rres.rectx-newx)<2 && ABS(rres.recty-newy)<2 ) {
|
||||
/* correct size, then black outline matches */
|
||||
rect->xmax= rect->xmin + rres.rectx;
|
||||
rect->ymax= rect->ymin + rres.recty;
|
||||
|
||||
glaDrawPixelsSafe(rect->xmin, rect->ymin, rres.rectx, rres.recty, rres.rectx, GL_RGBA, GL_FLOAT, rres.rectf);
|
||||
ok= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
BLI_unlock_malloc_thread();
|
||||
BLI_unlock_malloc_thread();
|
||||
|
||||
/* check for spacetype... */
|
||||
if(sbuts->spacetype==SPACE_BUTS && sbuts->preview) {
|
||||
sbuts->preview= 0;
|
||||
ok= 0;
|
||||
}
|
||||
|
||||
if(ok==0) {
|
||||
printf("added shader job\n");
|
||||
ED_preview_shader_job(C, sa, idp, newx, newy);
|
||||
}
|
||||
|
||||
/* check for spacetype... */
|
||||
if(sbuts->spacetype==SPACE_BUTS && sbuts->preview) {
|
||||
sbuts->preview= 0;
|
||||
ok= 0;
|
||||
}
|
||||
|
||||
if(ok==0) {
|
||||
printf("added shader job\n");
|
||||
ED_preview_shader_job(C, sa, idp, newx, newy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* *************************** Preview for 3d window *********************** */
|
||||
|
||||
Reference in New Issue
Block a user