/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static void mat_livedb_draw_hierarchy(SpaceLDB *slivedb, ListBase *lb, int startx, int *starty) { LiveDbTreeElement *te; int y1, y2; if (lb->first == NULL) return; y1 = y2 = *starty; /* for vertical lines between objects */ if(startx == 14) y1 -= UI_UNIT_Y / 2; for (te = lb->first; te; te = te->next) { y2 = *starty; /* horizontal line */ if (TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) glRecti(startx, *starty, startx + UI_UNIT_X / 3, *starty - 1); else glRecti(startx, *starty, startx + UI_UNIT_X / 3, *starty - 1); if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) *starty -= UI_UNIT_Y; else *starty -= MAT_LIVEDB_UI_UNIT_Y; if (MAT_LIVEDB_ELEM_OPEN(te, slivedb)) mat_livedb_draw_hierarchy(slivedb, &te->subtree, startx + UI_UNIT_X, starty); } /* vertical line */ te = lb->last; if (te->parent || lb->first != lb->last) glRecti(startx, y1 + UI_UNIT_Y / 2, startx + 1, y2); } /* mat_livedb_draw_hierarchy() */
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static void mat_livedb_namebutton_cb(bContext *C, void *itemp, char *oldname) { Main *mainvar = CTX_data_main(C); SpaceLDB *slivedb = CTX_wm_space_mat_livedb(C); LiveDbItem *item = itemp; if (item) { if (TE_GET_TYPE(item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) { /* TODO: implement for categories */ } else { LiveDbItem *cur_item; size_t store_len = MEM_allocN_len(slivedb->treestore); int size_diff = strlen(new_name) - strlen(oldname); LiveDbItem *new_items = MEM_mallocN(store_len + size_diff, "ldb tree"); LiveDbItem *new_item = new_items; for(cur_item = (LiveDbItem*)slivedb->treestore; (((char*)cur_item + cur_item->size) - slivedb->treestore) <= store_len; cur_item = (LiveDbItem*)((char*)cur_item + cur_item->size)) { if(TE_GET_TYPE(cur_item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) { memcpy(new_item, cur_item, cur_item->size); } else { if(cur_item == item) { char *cur_name, *cur_new_name; new_item->size = cur_item->size + size_diff; new_item->type = cur_item->type; new_item->mat_item.id = cur_item->mat_item.id; strcpy(new_item->mat_item.name, new_name); cur_name = cur_item->mat_item.name + strlen(cur_item->mat_item.name) + 1; cur_new_name = new_item->mat_item.name + strlen(new_name) + 1; strcpy(cur_new_name, cur_name); cur_new_name = cur_new_name + strlen(cur_name) + 1; cur_name = cur_name + strlen(cur_name) + 1; strcpy(cur_new_name, cur_name); } else memcpy(new_item, cur_item, cur_item->size); } new_item = (LiveDbItem*)((char*)new_item + new_item->size); } new_name[0] = 0; MEM_freeN(slivedb->treestore); slivedb->treestore = (char*)new_items; mat_livedb_build_tree(mainvar, slivedb, 0); } } } /* mat_livedb_namebutton_cb() */
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static void mat_draw_rename_buttons(const bContext *C, uiBlock *block, ARegion *ar, SpaceLDB *slivedb, ListBase *lb) { LiveDbTreeElement *te; int spx, dx, CUR_UNIT_Y; for (te = lb->first; te; te = te->next) { if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) CUR_UNIT_Y = UI_UNIT_Y; else CUR_UNIT_Y = MAT_LIVEDB_UI_UNIT_Y; if (te->ys + 2 * CUR_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { if (*te->flag & TE_TEXTBUT) { uiBut *bt; if(new_name[0] == 0) strcpy(new_name, te->name); dx = (int)UI_fontstyle_string_width(UI_FSTYLE_WIDGET, te->name); if (dx < 5 * UI_UNIT_X) dx = 5 * UI_UNIT_X; spx = te->xs + 1.8f * UI_UNIT_X; if (spx + dx + 0.5f * UI_UNIT_X > ar->v2d.cur.xmax) dx = ar->v2d.cur.xmax - spx - 0.5f * UI_UNIT_X; bt = uiDefBut(block, UI_BTYPE_TEXT, LDB_NAMEBUTTON, "", spx, (int)te->ys + UI_UNIT_Y * 3, dx + UI_UNIT_X, UI_UNIT_Y - 1, (void *)new_name, 1.0, 255.0f, 0, 0, ""); UI_but_func_rename_set(bt, mat_livedb_namebutton_cb, te->item); /* returns false if button got removed */ if (!UI_but_active_only(C, ar, block, bt)) { *te->flag &= ~TE_TEXTBUT; new_name[0] = 0; } } } if (MAT_LIVEDB_ELEM_OPEN(te, slivedb)) mat_draw_rename_buttons(C, block, ar, slivedb, &te->subtree); } } /* mat_draw_rename_buttons() */
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static int do_mat_livedb_item_openclose(bContext *C, SpaceLDB *slivedb, LiveDbTreeElement *te, int all, const float mval[2]) { int CUR_UNIT_Y; if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) CUR_UNIT_Y = UI_UNIT_Y; else CUR_UNIT_Y = MAT_LIVEDB_UI_UNIT_Y; if (mval[1] > te->ys && mval[1] < te->ys + CUR_UNIT_Y) { /* all below close/open? */ if (all) { *te->flag &= ~TE_CLOSED; mat_livedb_set_flag(slivedb, &te->subtree, TE_CLOSED, !mat_livedb_has_one_flag(slivedb, &te->subtree, TE_CLOSED, 1)); } else { if (*te->flag & TE_CLOSED) *te->flag &= ~TE_CLOSED; else *te->flag |= TE_CLOSED; } return 1; } for (te = te->subtree.first; te; te = te->next) { if (do_mat_livedb_item_openclose(C, slivedb, te, all, mval)) return 1; } return 0; } /* do_mat_livedb_item_openclose() */
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static int do_mat_livedb_item_rename(bContext *C, ARegion *ar, SpaceLDB *slivedb, LiveDbTreeElement *te, const float mval[2]) { ReportList *reports; int CUR_UNIT_Y; if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) CUR_UNIT_Y = UI_UNIT_Y; else CUR_UNIT_Y = MAT_LIVEDB_UI_UNIT_Y; reports = CTX_wm_reports(C); if (mval[1] > te->ys && mval[1] < te->ys + CUR_UNIT_Y) { /* click on name */ if (mval[0] > te->xs + UI_UNIT_X * 2 && mval[0] < te->xend) { do_item_rename(ar, te, reports); return 1; } return 0; } for (te = te->subtree.first; te; te = te->next) { if (do_mat_livedb_item_rename(C, ar, slivedb, te, mval)) return 1; } return 0; } /* do_mat_livedb_item_rename() */
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static void do_item_rename(ARegion *ar, LiveDbTreeElement *te, ReportList *reports) { if (TE_GET_TYPE(te->item->type) != MAT_LDB_TREE_ITEM_TYPE_MATERIAL) BKE_report(reports, RPT_WARNING, "Can edit only the material names."); else { *te->flag |= TE_TEXTBUT; ED_region_tag_redraw(ar); } } /* do_item_rename() */
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static void mat_livedb_draw_content_count_icons(ListBase *lb, int xmax, int *offsx, int ys) { int cat_cnt = 0, mat_cnt = 0, string_width; LiveDbTreeElement *te; char cnt_str[16]; float ufac = UI_UNIT_X / 20.0f; if ((*offsx) - UI_UNIT_X > xmax) return; for (te = lb->first; te; te = te->next) { if (TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) ++cat_cnt; else ++mat_cnt; } if (cat_cnt > 0) { snprintf(cnt_str, 16, "%d", cat_cnt); string_width = UI_fontstyle_string_width(UI_FSTYLE_WIDGET, cnt_str); UI_draw_roundbox_corner_set(UI_CNR_ALL); glColor4ub(220, 220, 255, 100); UI_draw_roundbox((float) *offsx - 4.0f * ufac, (float)ys + 1.0f * ufac, (float)*offsx + UI_UNIT_X + string_width, (float)ys + UI_UNIT_Y - ufac, (float)UI_UNIT_Y / 2.0f - ufac); glEnable(GL_BLEND); /* roundbox disables */ UI_icon_draw((float)*offsx, (float)ys + 2 * ufac, ICON_FILE_FOLDER); (*offsx) += UI_UNIT_X; UI_ThemeColor(TH_TEXT); UI_fontstyle_draw_simple(UI_FSTYLE_WIDGET, (float)*offsx - 2 * ufac, (float)ys + 5 * ufac, cnt_str); offsx += (int)(UI_UNIT_X + string_width); } if (mat_cnt > 0) { snprintf(cnt_str, 16, "%d", mat_cnt); string_width = UI_fontstyle_string_width(UI_FSTYLE_WIDGET, cnt_str); UI_draw_roundbox_corner_set(UI_CNR_ALL); glColor4ub(220, 220, 255, 100); UI_draw_roundbox((float) *offsx - 4.0f * ufac, (float)ys + 1.0f * ufac, (float)*offsx + UI_UNIT_X + string_width, (float)ys + UI_UNIT_Y - ufac, (float)UI_UNIT_Y / 2.0f - ufac); glEnable(GL_BLEND); /* roundbox disables */ UI_icon_draw((float)*offsx, (float)ys + 2 * ufac, ICON_MATERIAL); (*offsx) += UI_UNIT_X; UI_ThemeColor(TH_TEXT); UI_fontstyle_draw_simple(UI_FSTYLE_WIDGET, (float)*offsx - 2 * ufac, (float)ys + 5 * ufac, cnt_str); offsx += (int)(UI_UNIT_X + string_width); } } /* mat_livedb_draw_content_count_icons() */
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static void mat_livedb_elem_draw_icon(float x, float y, LiveDbTreeElement *te) { switch (TE_GET_TYPE(te->item->type)) { case MAT_LDB_TREE_ITEM_TYPE_CATEGORY: UI_icon_draw(x, y, ICON_FILE_FOLDER); break; case MAT_LDB_TREE_ITEM_TYPE_MATERIAL: UI_icon_draw(x, y, ICON_MATERIAL_DATA); break; default: UI_icon_draw(x, y, ICON_DOT); break; } } /* mat_livedb_elem_draw_icon() */
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static void mat_livedb_height(SpaceLDB *slivedb, ListBase *lb, int *h) { LiveDbTreeElement *te = lb->first; while (te) { if (MAT_LIVEDB_ELEM_OPEN(te, slivedb)) mat_livedb_height(slivedb, &te->subtree, h); if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) *h += UI_UNIT_Y; else *h += MAT_LIVEDB_UI_UNIT_Y; te = te->next; } } /* mat_livedb_height() */
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static void mat_livedb_draw_mat_preview(uiBlock *block, Scene *scene, ARegion *ar, SpaceLDB *slivedb, ListBase *lb) { LiveDbTreeElement *te; char *file_path = (char*)BKE_appdir_folder_id_create(BLENDER_USER_DATAFILES, 0); strcat(file_path, "/livedb/"); strcat(file_path, slivedb->server_address); strcat(file_path, "/previews/"); BLI_path_native_slash(file_path); BLI_dir_create_recursive(file_path); for (te = lb->first; te; te = te->next) { if (TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_MATERIAL && te->ys + 2 * MAT_LIVEDB_UI_UNIT_Y >= ar->v2d.cur.ymin && te->ys <= ar->v2d.cur.ymax) { unsigned int width, height; char* buf = mat_livedb_get_mat_preview(slivedb->server_address, te->item->mat_item.id, &width, &height, file_path); if(buf) { if(width && height) { glEnable(GL_BLEND); glColor4f(0.0, 0.0, 0.0, 0.0); if (width != UI_UNIT_X || height != (MAT_LIVEDB_UI_UNIT_Y - 2)) { float facx = (float)(MAT_LIVEDB_UI_UNIT_Y - 2) / (float)width; float facy = (float)(MAT_LIVEDB_UI_UNIT_Y - 2) / (float)height; glPixelZoom(facx, facy); } glaDrawPixelsAuto((float)(ar->v2d.cur.xmax - MAT_LIVEDB_UI_UNIT_Y - 1), (float)te->ys + 1, width, height, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, buf); glPixelZoom(1.0f, 1.0f); glDisable(GL_BLEND); } MEM_freeN(buf); } } else if (MAT_LIVEDB_ELEM_OPEN(te, slivedb)) mat_livedb_draw_mat_preview(block, scene, ar, slivedb, &te->subtree); } } /* mat_livedb_draw_mat_preview() */
/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ static void mat_livedb_draw_tree_element(bContext *C, uiBlock *block, ARegion *ar, SpaceLDB *slivedb, LiveDbTreeElement *te, int startx, int *starty, int *row_num) { LiveDbTreeElement *ten; float ufac = UI_UNIT_X / 20.0f; int offsx = 0, active = 0; int CUR_UNIT_Y; if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) CUR_UNIT_Y = UI_UNIT_Y; else CUR_UNIT_Y = MAT_LIVEDB_UI_UNIT_Y; *starty -= CUR_UNIT_Y; ++ *row_num; if (*starty + 2 * CUR_UNIT_Y >= ar->v2d.cur.ymin && *starty <= ar->v2d.cur.ymax) { int xmax = ar->v2d.cur.xmax; unsigned char alpha = 128; /* icons can be ui buts, we don't want it to overlap with material previews */ if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_MATERIAL) xmax -= MAT_LIVEDB_UI_UNIT_Y; glEnable(GL_BLEND); if(*row_num % 2) { UI_ThemeColorShade(TH_BACK, 6); glRecti(0, *starty + 1, ar->v2d.cur.xmax, *starty + CUR_UNIT_Y - 1); } if (*te->flag & TE_SELECTED) { float col[4]; unsigned char col_circle[4]; UI_GetThemeColor3fv(TH_SELECT_HIGHLIGHT, col); glColor3fv(col); glRecti(0, *starty + 1, (int)ar->v2d.cur.xmax, *starty + CUR_UNIT_Y - 1); /* active circle */ UI_GetThemeColorType4ubv(TH_ACTIVE, SPACE_VIEW3D, col_circle); col_circle[3] = alpha; glColor4ubv((GLubyte *)col_circle); UI_draw_roundbox_corner_set(UI_CNR_ALL); UI_draw_roundbox((float)startx + UI_UNIT_X - ufac, (float)*starty + (TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY ? 1.0f : UI_UNIT_Y * 3), (float)startx + 2.0f * UI_UNIT_X - 2.0f * ufac, (float)*starty + CUR_UNIT_Y - 1.0f * ufac, UI_UNIT_Y / 2.0f - 1.0f * ufac); glEnable(GL_BLEND); /* roundbox disables it */ } /* start by highlighting search matches */ if (SEARCHING_MAT_LIVEDB(slivedb) && (*te->flag & TE_SEARCHMATCH)) { char col[4]; UI_GetThemeColorType4ubv(TH_MATCH, SPACE_MAT_LIVEDB, col); col[3] = alpha; glColor4ubv((GLubyte *)col); glRecti(startx, *starty + 1, ar->v2d.cur.xmax, *starty + CUR_UNIT_Y - 1); } /* open/close icon, only when sublevels */ if (te->subtree.first || (*te->flag & TE_LAZY_CLOSED)) { int icon_x; if (TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) icon_x = startx; else icon_x = startx + 5 * ufac; if (MAT_LIVEDB_ELEM_OPEN(te, slivedb)) UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_DOWN); else UI_icon_draw((float)icon_x, (float)*starty + 2 * ufac, ICON_DISCLOSURE_TRI_RIGHT); } offsx += UI_UNIT_X; /* Element type icon */ if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) mat_livedb_elem_draw_icon((float)startx + offsx, (float)*starty, te); else mat_livedb_elem_draw_icon((float)startx + offsx, (float)*starty + UI_UNIT_X * 3, te); offsx += UI_UNIT_X; glDisable(GL_BLEND); /* name */ if (active == 1) UI_ThemeColor(TH_TEXT_HI); else UI_ThemeColor(TH_TEXT); if(TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY) UI_fontstyle_draw_simple(UI_FSTYLE_WIDGET, startx + offsx, *starty + 5 * ufac, te->name); else { uiBut *bt; UI_fontstyle_draw_simple(UI_FSTYLE_WIDGET, startx + offsx, *starty + UI_UNIT_X * 3 + 5 * ufac, te->name); UI_fontstyle_draw_simple(UI_FSTYLE_WIDGET, startx + offsx, *starty + UI_UNIT_X * 2 + 5 * ufac, te->nick_name); UI_fontstyle_draw_simple(UI_FSTYLE_WIDGET, startx + offsx, *starty + UI_UNIT_X + 5 * ufac, te->copyright); bt = uiDefIconBut(block, UI_BTYPE_ICON_TOGGLE, 0, ICON_WORLD, xmax - UI_UNIT_X - 3, *starty + 1 * ufac, UI_UNIT_X, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5f, "Get item"); UI_but_func_set(bt, get_material_cb, (void*)slivedb->server_address, (void*)te->item->mat_item.id); UI_but_flag_enable(bt, UI_BUT_DRAG_LOCK); } offsx += (int)(UI_UNIT_X + UI_fontstyle_string_width(UI_FSTYLE_WIDGET, te->name)); /* Closed item, we draw the category-info icons */ if (TE_GET_TYPE(te->item->type) == MAT_LDB_TREE_ITEM_TYPE_CATEGORY && !MAT_LIVEDB_ELEM_OPEN(te, slivedb)) { if (te->subtree.first) { int tempx = startx + offsx; /* divider */ UI_ThemeColorShade(TH_BACK, -40); glRecti(tempx - 10.0f * ufac, *starty + 4.0f * ufac, tempx - 8.0f * ufac, *starty + CUR_UNIT_Y - 4.0f * ufac); glEnable(GL_BLEND); glPixelTransferf(GL_ALPHA_SCALE, 0.5); mat_livedb_draw_content_count_icons(&te->subtree, xmax, &tempx, *starty); glPixelTransferf(GL_ALPHA_SCALE, 1.0); glDisable(GL_BLEND); } } } /* store coord and continue, we need coordinates for elements outside view too */ te->xs = (float)startx; te->ys = (float)*starty; te->xend = startx + offsx; if (MAT_LIVEDB_ELEM_OPEN(te, slivedb)) { for (ten = te->subtree.first; ten; ten = ten->next) mat_livedb_draw_tree_element(C, block, ar, slivedb, ten, startx + UI_UNIT_X, starty, row_num); } else { for (ten = te->subtree.first; ten; ten = ten->next) mat_livedb_set_coord_tree_element(slivedb, te, startx, starty); } } /* mat_livedb_draw_tree_element() */