UI: Tabs categories for panels (D75)
- works by defining panel categories, currently restricted to the toolbar. - no panels define bl_categories yet, so no user visible changes since tabs only show when there are multiple. - panel pinning is available in rmb menu or alt+lmb.
This commit is contained in:
parent
2231b565f0
commit
a621d1e488
Notes:
blender-bot
2024-04-11 14:26:06 +02:00
Referenced by issue #37601, Implement Vertical Tabs for Toolbars and other regions
|
@ -171,6 +171,7 @@ typedef struct PanelType {
|
|||
char label[BKE_ST_MAXNAME]; /* for panel header */
|
||||
char translation_context[BKE_ST_MAXNAME];
|
||||
char context[BKE_ST_MAXNAME]; /* for buttons window */
|
||||
char category[BKE_ST_MAXNAME]; /* for category tabs */
|
||||
int space_type;
|
||||
int region_type;
|
||||
|
||||
|
|
|
@ -173,6 +173,8 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
|
|||
newar->prev = newar->next = NULL;
|
||||
newar->handlers.first = newar->handlers.last = NULL;
|
||||
newar->uiblocks.first = newar->uiblocks.last = NULL;
|
||||
newar->panels_category.first = newar->panels_category.last = NULL;
|
||||
newar->panels_category_active.first = newar->panels_category_active.last = NULL;
|
||||
newar->ui_lists.first = newar->ui_lists.last = NULL;
|
||||
newar->swinid = 0;
|
||||
|
||||
|
@ -306,6 +308,8 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
|
|||
}
|
||||
}
|
||||
BLI_freelistN(&ar->ui_lists);
|
||||
BLI_freelistN(&ar->panels_category);
|
||||
BLI_freelistN(&ar->panels_category_active);
|
||||
}
|
||||
|
||||
/* not area itself */
|
||||
|
|
|
@ -6125,6 +6125,8 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
|
|||
pa->type = NULL;
|
||||
}
|
||||
|
||||
link_list(fd, &ar->panels_category_active);
|
||||
|
||||
link_list(fd, &ar->ui_lists);
|
||||
|
||||
for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next) {
|
||||
|
@ -6161,6 +6163,7 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
|
|||
ar->v2d.tab_num = 0;
|
||||
ar->v2d.tab_cur = 0;
|
||||
ar->v2d.sms = NULL;
|
||||
ar->panels_category.first = ar->panels_category.last = NULL;
|
||||
ar->handlers.first = ar->handlers.last = NULL;
|
||||
ar->uiblocks.first = ar->uiblocks.last = NULL;
|
||||
ar->headerstr = NULL;
|
||||
|
|
|
@ -2488,6 +2488,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
|
|||
SpaceLink *sl;
|
||||
Panel *pa;
|
||||
uiList *ui_list;
|
||||
PanelCategoryStack *pc_act;
|
||||
ARegion *ar;
|
||||
|
||||
writestruct(wd, DATA, "ScrArea", 1, sa);
|
||||
|
@ -2498,6 +2499,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
|
|||
for (pa= ar->panels.first; pa; pa= pa->next)
|
||||
writestruct(wd, DATA, "Panel", 1, pa);
|
||||
|
||||
for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next)
|
||||
writestruct(wd, DATA, "PanelCategoryStack", 1, pc_act);
|
||||
|
||||
for (ui_list = ar->ui_lists.first; ui_list; ui_list = ui_list->next)
|
||||
write_uilist(wd, ui_list);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ struct ListBase;
|
|||
struct ARegion;
|
||||
struct ARegionType;
|
||||
struct ScrArea;
|
||||
struct wmEvent;
|
||||
struct wmWindow;
|
||||
struct wmWindowManager;
|
||||
struct wmOperator;
|
||||
|
@ -176,6 +177,8 @@ enum {
|
|||
#define UI_PANEL_WIDTH 340
|
||||
#define UI_COMPACT_PANEL_WIDTH 160
|
||||
|
||||
#define UI_PANEL_CATEGORY_MARGIN_WIDTH (U.widget_unit * 0.9f)
|
||||
|
||||
/* but->drawflag - these flags should only affect how the button is drawn. */
|
||||
/* Note: currently, these flags _are not passed_ to the widget's state() or draw() functions
|
||||
* (except for the 'align' ones)!
|
||||
|
@ -665,10 +668,23 @@ void uiBeginPanels(const struct bContext *C, struct ARegion *ar);
|
|||
void uiEndPanels(const struct bContext *C, struct ARegion *ar, int *x, int *y);
|
||||
void uiDrawPanels(const struct bContext *C, struct ARegion *ar);
|
||||
|
||||
struct Panel *uiBeginPanel(struct ScrArea *sa, struct ARegion *ar, uiBlock *block, struct PanelType *pt, int *open);
|
||||
struct Panel *uiPanelFindByType(struct ARegion *ar, struct PanelType *pt);
|
||||
struct Panel *uiBeginPanel(struct ScrArea *sa, struct ARegion *ar, uiBlock *block,
|
||||
struct PanelType *pt, struct Panel *pa, bool *r_open);
|
||||
void uiEndPanel(uiBlock *block, int width, int height);
|
||||
void uiScalePanels(struct ARegion *ar, float new_width);
|
||||
|
||||
bool UI_panel_category_is_visible(struct ARegion *ar);
|
||||
void UI_panel_category_add(struct ARegion *ar, const char *name);
|
||||
struct PanelCategoryDyn *UI_panel_category_find(struct ARegion *ar, const char *idname);
|
||||
struct PanelCategoryStack *UI_panel_category_active_find(struct ARegion *ar, const char *idname);
|
||||
const char *UI_panel_category_active_get(struct ARegion *ar, bool set_fallback);
|
||||
void UI_panel_category_active_set(struct ARegion *ar, const char *idname);
|
||||
struct PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(struct ARegion *ar, const int x, const int y);
|
||||
struct PanelCategoryDyn *UI_panel_category_find_mouse_over(struct ARegion *ar, const struct wmEvent *event);
|
||||
void UI_panel_category_clear_all(struct ARegion *ar);
|
||||
void UI_panel_category_draw_all(struct ARegion *ar, const char *category_id_active);
|
||||
|
||||
/* Handlers
|
||||
*
|
||||
* Handlers that can be registered in regions, areas and windows for
|
||||
|
|
|
@ -1209,7 +1209,7 @@ void uiDrawBlock(const bContext *C, uiBlock *block)
|
|||
if (block->flag & UI_BLOCK_LOOP)
|
||||
ui_draw_menu_back(&style, block, &rect);
|
||||
else if (block->panel)
|
||||
ui_draw_aligned_panel(&style, block, &rect);
|
||||
ui_draw_aligned_panel(&style, block, &rect, UI_panel_category_is_visible(ar));
|
||||
|
||||
/* widgets */
|
||||
for (but = block->buttons.first; but; but = but->next) {
|
||||
|
|
|
@ -5272,6 +5272,25 @@ static void popup_add_shortcut_func(bContext *C, void *arg1, void *UNUSED(arg2))
|
|||
uiPupBlock(C, menu_add_shortcut, but);
|
||||
}
|
||||
|
||||
/**
|
||||
* menu to chow when right clicking on the panel header
|
||||
*/
|
||||
void ui_panel_menu(bContext *C, ARegion *ar, Panel *pa)
|
||||
{
|
||||
bScreen *sc = CTX_wm_screen(C);
|
||||
PointerRNA ptr;
|
||||
uiPopupMenu *pup;
|
||||
uiLayout *layout;
|
||||
|
||||
RNA_pointer_create(&sc->id, &RNA_Panel, pa, &ptr);
|
||||
|
||||
pup = uiPupMenuBegin(C, IFACE_("Panel"), ICON_NONE);
|
||||
layout = uiPupMenuLayout(pup);
|
||||
if (UI_panel_category_is_visible(ar)) {
|
||||
uiItemR(layout, &ptr, "use_pin", 0, "Pin" UI_SEP_CHAR_S "Alt+Left Mouse", ICON_NONE);
|
||||
}
|
||||
uiPupMenuEnd(C, pup);
|
||||
}
|
||||
|
||||
static bool ui_but_menu(bContext *C, uiBut *but)
|
||||
{
|
||||
|
|
|
@ -124,14 +124,6 @@ enum {
|
|||
#define PNL_GRID (UI_UNIT_Y / 5) /* 4 default */
|
||||
#define PNL_HEADER (UI_UNIT_Y + 4) /* 24 default */
|
||||
|
||||
/* panel->flag */
|
||||
#define PNL_SELECT 1
|
||||
#define PNL_CLOSEDX 2
|
||||
#define PNL_CLOSEDY 4
|
||||
#define PNL_CLOSED 6
|
||||
/*#define PNL_TABBED 8*/ /*UNUSED*/
|
||||
#define PNL_OVERLAP 16
|
||||
|
||||
/* Button text selection:
|
||||
* extension direction, selextend, inside ui_do_but_TEX */
|
||||
#define EXTEND_LEFT 1
|
||||
|
@ -505,7 +497,7 @@ struct AutoComplete;
|
|||
|
||||
/* interface_panel.c */
|
||||
extern int ui_handler_panel_region(struct bContext *C, const struct wmEvent *event, struct ARegion *ar);
|
||||
extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, const rcti *rect);
|
||||
extern void ui_draw_aligned_panel(struct uiStyle *style, uiBlock *block, const rcti *rect, const bool show_pin);
|
||||
|
||||
/* interface_draw.c */
|
||||
extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
|
||||
|
@ -531,6 +523,7 @@ extern bool ui_button_is_active(struct ARegion *ar);
|
|||
extern int ui_button_open_menu_direction(uiBut *but);
|
||||
extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, int restore);
|
||||
void ui_button_clipboard_free(void);
|
||||
void ui_panel_menu(struct bContext *C, ARegion *ar, Panel *pa);
|
||||
|
||||
/* interface_widgets.c */
|
||||
void ui_draw_anti_tria(float x1, float y1, float x2, float y2, float x3, float y3);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_math_color_blend.h"
|
||||
#include "BLI_utildefines.h"
|
||||
|
||||
#include "BLF_translation.h"
|
||||
|
@ -53,12 +54,15 @@
|
|||
#include "BIF_gl.h"
|
||||
#include "BIF_glutil.h"
|
||||
|
||||
#include "BLF_api.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
|
||||
#include "ED_screen.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_interface_icons.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "interface_intern.h"
|
||||
|
@ -75,6 +79,9 @@
|
|||
#define PNL_NEW_ADDED 16
|
||||
#define PNL_FIRST 32
|
||||
|
||||
/* only show pin header button for pinned panels */
|
||||
#define USE_PIN_HIDDEN
|
||||
|
||||
typedef enum uiHandlePanelState {
|
||||
PANEL_STATE_DRAG,
|
||||
PANEL_STATE_DRAG_SCALE,
|
||||
|
@ -188,23 +195,36 @@ static void ui_panel_copy_offset(Panel *pa, Panel *papar)
|
|||
pa->ofsy = papar->ofsy + papar->sizey - pa->sizey;
|
||||
}
|
||||
|
||||
Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int *open)
|
||||
Panel *uiPanelFindByType(ARegion *ar, PanelType *pt)
|
||||
{
|
||||
Panel *pa, *patab, *palast, *panext;
|
||||
Panel *pa;
|
||||
|
||||
const char *idname = pt->idname;
|
||||
const char *tabname = pt->idname;
|
||||
|
||||
for (pa = ar->panels.first; pa; pa = pa->next) {
|
||||
if (STREQLEN(pa->panelname, idname, UI_MAX_NAME_STR)) {
|
||||
if (STREQLEN(pa->tabname, tabname, UI_MAX_NAME_STR)) {
|
||||
return pa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \note \a pa should be return value from #uiPanelFindByType and can be NULL.
|
||||
*/
|
||||
Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, Panel *pa, bool *r_open)
|
||||
{
|
||||
Panel *patab, *palast, *panext;
|
||||
const char *drawname = CTX_IFACE_(pt->translation_context, pt->label);
|
||||
char *idname = pt->idname;
|
||||
char *tabname = pt->idname;
|
||||
char *hookname = NULL;
|
||||
int newpanel;
|
||||
const bool newpanel = (pa == NULL);
|
||||
int align = panel_aligned(sa, ar);
|
||||
|
||||
/* check if Panel exists, then use that one */
|
||||
for (pa = ar->panels.first; pa; pa = pa->next)
|
||||
if (strncmp(pa->panelname, idname, UI_MAX_NAME_STR) == 0)
|
||||
if (strncmp(pa->tabname, tabname, UI_MAX_NAME_STR) == 0)
|
||||
break;
|
||||
|
||||
newpanel = (pa == NULL);
|
||||
|
||||
if (!newpanel) {
|
||||
pa->type = pt;
|
||||
|
@ -279,12 +299,12 @@ Panel *uiBeginPanel(ScrArea *sa, ARegion *ar, uiBlock *block, PanelType *pt, int
|
|||
block->panel = pa;
|
||||
pa->runtime_flag |= PNL_ACTIVE | PNL_LAST_ADDED;
|
||||
|
||||
*open = 0;
|
||||
*r_open = false;
|
||||
|
||||
if (pa->paneltab) return pa;
|
||||
if (pa->flag & PNL_CLOSED) return pa;
|
||||
|
||||
*open = 1;
|
||||
*r_open = true;
|
||||
|
||||
return pa;
|
||||
}
|
||||
|
@ -497,7 +517,7 @@ static void ui_draw_aligned_panel_header(uiStyle *style, uiBlock *block, const r
|
|||
}
|
||||
|
||||
/* panel integrated in buttonswindow, tool/property lists etc */
|
||||
void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect)
|
||||
void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect, const bool show_pin)
|
||||
{
|
||||
Panel *panel = block->panel;
|
||||
rcti headrect;
|
||||
|
@ -542,6 +562,21 @@ void ui_draw_aligned_panel(uiStyle *style, uiBlock *block, const rcti *rect)
|
|||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
/* draw optional pin icon */
|
||||
|
||||
#ifdef USE_PIN_HIDDEN
|
||||
if (show_pin && (block->panel->flag & PNL_PIN))
|
||||
#else
|
||||
if (show_pin)
|
||||
#endif
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
UI_icon_draw_aspect(headrect.xmax - ((PNL_ICON * 2.2f) / block->aspect), headrect.ymin + (5.0f / block->aspect),
|
||||
(panel->flag & PNL_PIN) ? ICON_PINNED : ICON_UNPINNED,
|
||||
block->aspect / U.pixelsize, 1.0f);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
/* horizontal title */
|
||||
if (!(panel->flag & PNL_CLOSEDX)) {
|
||||
ui_draw_aligned_panel_header(style, block, &headrect, 'h');
|
||||
|
@ -710,6 +745,7 @@ static int uiAlignPanelStep(ScrArea *sa, ARegion *ar, float fac, int drag)
|
|||
PanelSort *ps, *panelsort, *psnext;
|
||||
int a, tot = 0, done;
|
||||
int align = panel_aligned(sa, ar);
|
||||
bool has_category_tabs = UI_panel_category_is_visible(ar);
|
||||
|
||||
/* count active, not tabbed panels */
|
||||
for (pa = ar->panels.first; pa; pa = pa->next)
|
||||
|
@ -759,6 +795,12 @@ static int uiAlignPanelStep(ScrArea *sa, ARegion *ar, float fac, int drag)
|
|||
ps->pa->ofsx = 0;
|
||||
ps->pa->ofsy = -get_panel_size_y(ps->pa);
|
||||
|
||||
if (has_category_tabs) {
|
||||
if (align == BUT_VERTICAL) {
|
||||
ps->pa->ofsx += UI_PANEL_CATEGORY_MARGIN_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
for (a = 0; a < tot - 1; a++, ps++) {
|
||||
psnext = ps + 1;
|
||||
|
||||
|
@ -1047,13 +1089,32 @@ static void ui_do_drag(const bContext *C, const wmEvent *event, Panel *panel)
|
|||
|
||||
/* this function is supposed to call general window drawing too */
|
||||
/* also it supposes a block has panel, and isn't a menu */
|
||||
static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, int my, int event, int ctrl)
|
||||
static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, int my, int event, short ctrl, short alt)
|
||||
{
|
||||
ScrArea *sa = CTX_wm_area(C);
|
||||
ARegion *ar = CTX_wm_region(C);
|
||||
Panel *pa;
|
||||
#ifdef USE_PIN_HIDDEN
|
||||
const bool show_pin = UI_panel_category_is_visible(ar) && (block->panel->flag & PNL_PIN);
|
||||
#else
|
||||
const bool show_pin = UI_panel_category_is_visible(ar);
|
||||
#endif
|
||||
|
||||
int align = panel_aligned(sa, ar), button = 0;
|
||||
|
||||
rctf rect_drag, rect_pin;
|
||||
float rect_leftmost;
|
||||
|
||||
|
||||
/* drag and pin rect's */
|
||||
rect_drag = block->rect;
|
||||
rect_drag.xmin = block->rect.xmax - (PNL_ICON * 1.5f);
|
||||
rect_pin = rect_drag;
|
||||
if (show_pin) {
|
||||
BLI_rctf_translate(&rect_pin, -PNL_ICON, 0.0f);
|
||||
}
|
||||
rect_leftmost = rect_pin.xmin;
|
||||
|
||||
/* mouse coordinates in panel space! */
|
||||
|
||||
/* XXX weak code, currently it assumes layout style for location of widgets */
|
||||
|
@ -1063,6 +1124,10 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
|
|||
button = 1;
|
||||
else if (event == AKEY)
|
||||
button = 1;
|
||||
else if (ELEM3(event, 0, RETKEY, LEFTMOUSE) && alt) {
|
||||
block->panel->flag ^= PNL_PIN;
|
||||
button = 2;
|
||||
}
|
||||
else if (block->panel->flag & PNL_CLOSEDX) {
|
||||
if (my >= block->rect.ymax) button = 1;
|
||||
}
|
||||
|
@ -1071,7 +1136,7 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
|
|||
if (mx <= block->rect.xmax - 8 - PNL_ICON) button = 2;
|
||||
//else if (mx <= block->rect.xmin + 10 + 2 * PNL_ICON + 2) button = 1;
|
||||
}
|
||||
else if (mx <= block->rect.xmax - PNL_ICON - 12) {
|
||||
else if (mx < rect_leftmost) {
|
||||
button = 1;
|
||||
}
|
||||
|
||||
|
@ -1112,9 +1177,402 @@ static void ui_handle_panel_header(const bContext *C, uiBlock *block, int mx, in
|
|||
else
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
else if (mx <= (block->rect.xmax - PNL_ICON - 12) + PNL_ICON + 2) {
|
||||
else if (BLI_rctf_isect_x(&rect_drag, mx)) {
|
||||
panel_activate_state(C, block->panel, PANEL_STATE_DRAG);
|
||||
}
|
||||
else if (show_pin && BLI_rctf_isect_x(&rect_pin, mx)) {
|
||||
block->panel->flag ^= PNL_PIN;
|
||||
ED_region_tag_redraw(ar);
|
||||
}
|
||||
}
|
||||
|
||||
bool UI_panel_category_is_visible(ARegion *ar)
|
||||
{
|
||||
/* more then one */
|
||||
return ar->panels_category.first && ar->panels_category.first != ar->panels_category.last;
|
||||
}
|
||||
|
||||
PanelCategoryDyn *UI_panel_category_find(ARegion *ar, const char *idname)
|
||||
{
|
||||
return BLI_findstring(&ar->panels_category, idname, offsetof(PanelCategoryDyn, idname));
|
||||
}
|
||||
|
||||
PanelCategoryStack *UI_panel_category_active_find(ARegion *ar, const char *idname)
|
||||
{
|
||||
return BLI_findstring(&ar->panels_category_active, idname, offsetof(PanelCategoryStack, idname));
|
||||
}
|
||||
|
||||
const char *UI_panel_category_active_get(ARegion *ar, bool set_fallback)
|
||||
{
|
||||
PanelCategoryStack *pc_act;
|
||||
|
||||
for (pc_act = ar->panels_category_active.first; pc_act; pc_act = pc_act->next) {
|
||||
if (UI_panel_category_find(ar, pc_act->idname)) {
|
||||
return pc_act->idname;
|
||||
}
|
||||
}
|
||||
|
||||
if (set_fallback) {
|
||||
PanelCategoryDyn *pc_dyn = ar->panels_category.first;
|
||||
if (pc_dyn) {
|
||||
UI_panel_category_active_set(ar, pc_dyn->idname);
|
||||
return pc_dyn->idname;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void UI_panel_category_active_set(ARegion *ar, const char *idname)
|
||||
{
|
||||
ListBase *lb = &ar->panels_category_active;
|
||||
PanelCategoryStack *pc_act = UI_panel_category_active_find(ar, idname);
|
||||
|
||||
if (pc_act) {
|
||||
BLI_remlink(lb, pc_act);
|
||||
}
|
||||
else {
|
||||
pc_act = MEM_callocN(sizeof(PanelCategoryStack), __func__);
|
||||
BLI_strncpy(pc_act->idname, idname, sizeof(pc_act->idname));
|
||||
}
|
||||
|
||||
BLI_addhead(lb, pc_act);
|
||||
|
||||
|
||||
/* validate all active panels, we could do this on load,
|
||||
* they are harmless - but we should remove somewhere.
|
||||
* (addons could define own and gather cruft over time) */
|
||||
{
|
||||
PanelCategoryStack *pc_act_next;
|
||||
/* intentionally skip first */
|
||||
pc_act_next = pc_act->next;
|
||||
while ((pc_act = pc_act_next)) {
|
||||
pc_act_next = pc_act->next;
|
||||
if (!BLI_findstring(&ar->type->paneltypes, pc_act->idname, offsetof(PanelType, category))) {
|
||||
BLI_remlink(lb, pc_act);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PanelCategoryDyn *UI_panel_category_find_mouse_over_ex(ARegion *ar, const int x, const int y)
|
||||
{
|
||||
PanelCategoryDyn *ptd;
|
||||
|
||||
for (ptd = ar->panels_category.first; ptd; ptd = ptd->next) {
|
||||
if (BLI_rcti_isect_pt(&ptd->rect, x, y)) {
|
||||
return ptd;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PanelCategoryDyn *UI_panel_category_find_mouse_over(ARegion *ar, const wmEvent *event)
|
||||
{
|
||||
return UI_panel_category_find_mouse_over_ex(ar, event->mval[0], event->mval[1]);
|
||||
}
|
||||
|
||||
|
||||
void UI_panel_category_add(ARegion *ar, const char *name)
|
||||
{
|
||||
PanelCategoryDyn *pc_dyn = MEM_callocN(sizeof(*pc_dyn), __func__);
|
||||
BLI_addtail(&ar->panels_category, pc_dyn);
|
||||
|
||||
BLI_strncpy(pc_dyn->idname, name, sizeof(pc_dyn->idname));
|
||||
|
||||
/* 'pc_dyn->rect' must be set on draw */
|
||||
}
|
||||
|
||||
void UI_panel_category_clear_all(ARegion *ar)
|
||||
{
|
||||
BLI_freelistN(&ar->panels_category);
|
||||
}
|
||||
|
||||
/* based on uiDrawBox, check on making a version which allows us to skip some sides */
|
||||
static void ui_panel_category_draw_tab(int mode, float minx, float miny, float maxx, float maxy, float rad,
|
||||
int roundboxtype,
|
||||
const bool use_highlight, const bool use_shadow,
|
||||
const unsigned char highlight_fade[3])
|
||||
{
|
||||
float vec[4][2] = {
|
||||
{0.195, 0.02},
|
||||
{0.55, 0.169},
|
||||
{0.831, 0.45},
|
||||
{0.98, 0.805}};
|
||||
int a;
|
||||
|
||||
/* mult */
|
||||
for (a = 0; a < 4; a++) {
|
||||
mul_v2_fl(vec[a], rad);
|
||||
}
|
||||
|
||||
(void)use_shadow;
|
||||
(void)use_highlight;
|
||||
|
||||
glBegin(mode);
|
||||
|
||||
/* start with corner right-top */
|
||||
if (use_highlight) {
|
||||
if (roundboxtype & UI_CNR_TOP_RIGHT) {
|
||||
glVertex2f(maxx, maxy - rad);
|
||||
for (a = 0; a < 4; a++) {
|
||||
glVertex2f(maxx - vec[a][1], maxy - rad + vec[a][0]);
|
||||
}
|
||||
glVertex2f(maxx - rad, maxy);
|
||||
}
|
||||
else {
|
||||
glVertex2f(maxx, maxy);
|
||||
}
|
||||
|
||||
/* corner left-top */
|
||||
if (roundboxtype & UI_CNR_TOP_LEFT) {
|
||||
glVertex2f(minx + rad, maxy);
|
||||
for (a = 0; a < 4; a++) {
|
||||
glVertex2f(minx + rad - vec[a][0], maxy - vec[a][1]);
|
||||
}
|
||||
glVertex2f(minx, maxy - rad);
|
||||
}
|
||||
else {
|
||||
glVertex2f(minx, maxy);
|
||||
}
|
||||
}
|
||||
|
||||
if (use_highlight && !use_shadow) {
|
||||
if (highlight_fade) {
|
||||
glColor3ubv(highlight_fade);
|
||||
}
|
||||
glVertex2f(minx, miny + rad);
|
||||
glEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
/* corner left-bottom */
|
||||
if (roundboxtype & UI_CNR_BOTTOM_LEFT) {
|
||||
glVertex2f(minx, miny + rad);
|
||||
for (a = 0; a < 4; a++) {
|
||||
glVertex2f(minx + vec[a][1], miny + rad - vec[a][0]);
|
||||
}
|
||||
glVertex2f(minx + rad, miny);
|
||||
}
|
||||
else {
|
||||
glVertex2f(minx, miny);
|
||||
}
|
||||
|
||||
/* corner right-bottom */
|
||||
|
||||
if (roundboxtype & UI_CNR_BOTTOM_RIGHT) {
|
||||
glVertex2f(maxx - rad, miny);
|
||||
for (a = 0; a < 4; a++) {
|
||||
glVertex2f(maxx - rad + vec[a][0], miny + vec[a][1]);
|
||||
}
|
||||
glVertex2f(maxx, miny + rad);
|
||||
}
|
||||
else {
|
||||
glVertex2f(maxx, miny);
|
||||
}
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw vertical tabs on the left side of the region,
|
||||
* one tab per category.
|
||||
*/
|
||||
void UI_panel_category_draw_all(ARegion *ar, const char *category_id_active)
|
||||
{
|
||||
/* no tab outlines for */
|
||||
#define USE_FLAT_INACTIVE
|
||||
View2D *v2d = &ar->v2d;
|
||||
uiStyle *style = UI_GetStyle();
|
||||
const int fontid = style->widget.uifont_id;
|
||||
|
||||
PanelCategoryDyn *pc_dyn;
|
||||
const float zoom = 1.0f / ((uiBlock *)ar->uiblocks.first)->aspect;
|
||||
const int px = max_ii(1.0, (int)U.pixelsize + 0.5f);
|
||||
const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH * zoom;
|
||||
const float dpi_fac = UI_DPI_FAC;
|
||||
const int tab_v_pad_text = ((px * 3) * dpi_fac) * zoom; /* pading of tabs around text */
|
||||
const int tab_v_pad = (2 + (2 * px * dpi_fac)) * zoom; /* padding between tabs */
|
||||
const float tab_curve_radius = (px * 2) * dpi_fac;
|
||||
const int roundboxtype = UI_CNR_TOP_LEFT | UI_CNR_BOTTOM_LEFT;
|
||||
bool do_scaletabs = false;
|
||||
#ifdef USE_FLAT_INACTIVE
|
||||
bool is_active_prev = false;
|
||||
#endif
|
||||
float scaletabs = 1.0f;
|
||||
/* same for all tabs */
|
||||
const int rct_xmin = v2d->mask.xmin + (3 * px);
|
||||
const int rct_xmax = v2d->mask.xmin + category_tabs_width;
|
||||
const int text_v_ofs = (rct_xmax - rct_xmin) * 0.3f;
|
||||
|
||||
int y_ofs = tab_v_pad;
|
||||
|
||||
/* Primary theme colors */
|
||||
unsigned char theme_col_back[4];
|
||||
unsigned char theme_col_text[4];
|
||||
unsigned char theme_col_text_hi[4];
|
||||
|
||||
/* Secondary theme colors */
|
||||
unsigned char theme_col_tab_bg[4];
|
||||
unsigned char theme_col_tab_inactive[4];
|
||||
unsigned char theme_col_tab_outline[4];
|
||||
unsigned char theme_col_tab_divider[4]; /* line that divides tabs from the main area */
|
||||
unsigned char theme_col_tab_highlight[4];
|
||||
unsigned char theme_col_tab_highlight_inactive[4];
|
||||
|
||||
|
||||
UI_GetThemeColor4ubv(TH_BACK, theme_col_back);
|
||||
UI_GetThemeColor4ubv(TH_TEXT, theme_col_text);
|
||||
UI_GetThemeColor4ubv(TH_TEXT_HI, theme_col_text_hi);
|
||||
|
||||
|
||||
blend_color_interpolate_byte(theme_col_tab_bg, theme_col_back, theme_col_text, 0.12f);
|
||||
blend_color_interpolate_byte(theme_col_tab_inactive, theme_col_back, theme_col_text, 0.1f);
|
||||
blend_color_interpolate_byte(theme_col_tab_outline, theme_col_back, theme_col_text, 0.3f);
|
||||
blend_color_interpolate_byte(theme_col_tab_divider, theme_col_back, theme_col_text, 0.3f);
|
||||
|
||||
blend_color_interpolate_byte(theme_col_tab_highlight, theme_col_back, theme_col_text_hi, 0.2f);
|
||||
blend_color_interpolate_byte(theme_col_tab_highlight_inactive, theme_col_tab_inactive, theme_col_text_hi, 0.12f);
|
||||
|
||||
|
||||
BLF_enable(fontid, BLF_ROTATION);
|
||||
BLF_rotation(fontid, M_PI / 2);
|
||||
//uiStyleFontSet(&style->widget);
|
||||
BLF_size(fontid, (style->widget.points * U.pixelsize) * zoom, U.dpi);
|
||||
|
||||
BLI_assert(UI_panel_category_is_visible(ar));
|
||||
|
||||
|
||||
/* calculate tab rect's and check if we need to scale down */
|
||||
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
|
||||
rcti *rct = &pc_dyn->rect;
|
||||
const char *category_id = pc_dyn->idname;
|
||||
const char *category_id_draw = IFACE_(category_id);
|
||||
const int category_width = BLF_width(fontid, category_id_draw, BLF_DRAW_STR_DUMMY_MAX);
|
||||
|
||||
rct->xmin = rct_xmin;
|
||||
rct->xmax = rct_xmax;
|
||||
|
||||
rct->ymin = v2d->mask.ymax - (y_ofs + category_width + (tab_v_pad_text * 2));
|
||||
rct->ymax = v2d->mask.ymax - (y_ofs);
|
||||
|
||||
y_ofs += category_width + tab_v_pad + (tab_v_pad_text * 2);
|
||||
}
|
||||
|
||||
if (y_ofs > BLI_rcti_size_y(&v2d->mask)) {
|
||||
scaletabs = (float)BLI_rcti_size_y(&v2d->mask) / (float)y_ofs;
|
||||
|
||||
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
|
||||
rcti *rct = &pc_dyn->rect;
|
||||
rct->ymin = ((rct->ymin - v2d->mask.ymax) * scaletabs) + v2d->mask.ymax;
|
||||
rct->ymax = ((rct->ymax - v2d->mask.ymax) * scaletabs) + v2d->mask.ymax;
|
||||
}
|
||||
|
||||
do_scaletabs = true;
|
||||
}
|
||||
|
||||
|
||||
/* begin drawing */
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
|
||||
/* draw the background */
|
||||
glColor3ubv(theme_col_tab_bg);
|
||||
glRecti(v2d->mask.xmin, v2d->mask.ymin, v2d->mask.xmin + category_tabs_width, v2d->mask.ymax);
|
||||
|
||||
for (pc_dyn = ar->panels_category.first; pc_dyn; pc_dyn = pc_dyn->next) {
|
||||
const rcti *rct = &pc_dyn->rect;
|
||||
const char *category_id = pc_dyn->idname;
|
||||
const char *category_id_draw = IFACE_(category_id);
|
||||
int category_width = BLI_rcti_size_y(rct) - (tab_v_pad_text * 2);
|
||||
size_t category_draw_len = BLF_DRAW_STR_DUMMY_MAX;
|
||||
// int category_width = BLF_width(fontid, category_id_draw, BLF_DRAW_STR_DUMMY_MAX);
|
||||
|
||||
const bool is_active = STREQ(category_id, category_id_active);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
#ifdef USE_FLAT_INACTIVE
|
||||
if (is_active)
|
||||
#endif
|
||||
{
|
||||
glColor3ubv(is_active ? theme_col_back : theme_col_tab_inactive);
|
||||
ui_panel_category_draw_tab(GL_POLYGON, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
|
||||
tab_curve_radius - px, roundboxtype, true, true, NULL);
|
||||
|
||||
/* tab outline */
|
||||
glColor3ubv(theme_col_tab_outline);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin - px, rct->ymin - px, rct->xmax - px, rct->ymax + px,
|
||||
tab_curve_radius, roundboxtype, true, true, NULL);
|
||||
/* tab highlight (3d look) */
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glColor3ubv(is_active ? theme_col_tab_highlight : theme_col_tab_highlight_inactive);
|
||||
ui_panel_category_draw_tab(GL_LINE_STRIP, rct->xmin, rct->ymin, rct->xmax, rct->ymax,
|
||||
tab_curve_radius, roundboxtype, true, false,
|
||||
is_active ? theme_col_back : theme_col_tab_inactive);
|
||||
glShadeModel(GL_FLAT);
|
||||
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
|
||||
/* tab blackline */
|
||||
if (!is_active) {
|
||||
glColor3ubv(theme_col_tab_divider);
|
||||
glRecti(v2d->mask.xmin + category_tabs_width - px,
|
||||
rct->ymin - tab_v_pad,
|
||||
v2d->mask.xmin + category_tabs_width,
|
||||
rct->ymax + tab_v_pad);
|
||||
}
|
||||
|
||||
if (do_scaletabs) {
|
||||
category_draw_len = BLF_width_to_strlen(fontid, category_id_draw, category_draw_len,
|
||||
category_width, NULL);
|
||||
}
|
||||
|
||||
BLF_position(fontid, rct->xmax - text_v_ofs, rct->ymin + tab_v_pad_text, 0.0f);
|
||||
|
||||
glColor3ubv(theme_col_text);
|
||||
BLF_draw(fontid, category_id_draw, category_draw_len);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
/* tab blackline remaining (last tab) */
|
||||
if (pc_dyn->prev == NULL) {
|
||||
glColor3ubv(theme_col_tab_divider);
|
||||
glRecti(v2d->mask.xmin + category_tabs_width - px,
|
||||
rct->ymax + px,
|
||||
v2d->mask.xmin + category_tabs_width,
|
||||
v2d->mask.ymax);
|
||||
}
|
||||
if (pc_dyn->next == NULL) {
|
||||
glColor3ubv(theme_col_tab_divider);
|
||||
glRecti(v2d->mask.xmin + category_tabs_width - px,
|
||||
0,
|
||||
v2d->mask.xmin + category_tabs_width,
|
||||
rct->ymin);
|
||||
}
|
||||
|
||||
#ifdef USE_FLAT_INACTIVE
|
||||
/* draw line between inactive tabs */
|
||||
if (is_active == false && is_active_prev == false && pc_dyn->prev) {
|
||||
glColor3ubv(theme_col_tab_divider);
|
||||
glRecti(v2d->mask.xmin + (category_tabs_width / 5),
|
||||
rct->ymax + px,
|
||||
(v2d->mask.xmin + category_tabs_width) - (category_tabs_width / 5),
|
||||
rct->ymax + (px * 3));
|
||||
}
|
||||
|
||||
is_active_prev = is_active;
|
||||
#endif
|
||||
}
|
||||
|
||||
glDisable(GL_LINE_SMOOTH);
|
||||
|
||||
BLF_disable(fontid, BLF_ROTATION);
|
||||
|
||||
#undef USE_FLAT_INACTIVE
|
||||
}
|
||||
|
||||
/* XXX should become modal keymap */
|
||||
|
@ -1125,8 +1583,27 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
|
|||
uiBlock *block;
|
||||
Panel *pa;
|
||||
int retval, mx, my;
|
||||
bool has_category_tabs = UI_panel_category_is_visible(ar);
|
||||
|
||||
retval = WM_UI_HANDLER_CONTINUE;
|
||||
|
||||
if (has_category_tabs) {
|
||||
if (event->val == KM_PRESS) {
|
||||
if (event->type == LEFTMOUSE) {
|
||||
PanelCategoryDyn *pc_dyn = UI_panel_category_find_mouse_over(ar, event);
|
||||
if (pc_dyn) {
|
||||
UI_panel_category_active_set(ar, pc_dyn->idname);
|
||||
ED_region_tag_redraw(ar);
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (retval == WM_UI_HANDLER_BREAK) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
for (block = ar->uiblocks.last; block; block = block->prev) {
|
||||
bool inside = false, inside_header = false, inside_scale = false;
|
||||
|
||||
|
@ -1171,10 +1648,10 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
|
|||
|
||||
if (pa->flag & PNL_CLOSEDY) {
|
||||
if ((block->rect.ymax <= my) && (block->rect.ymax + PNL_HEADER >= my))
|
||||
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl);
|
||||
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->alt);
|
||||
}
|
||||
else
|
||||
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl);
|
||||
ui_handle_panel_header(C, block, mx, my, event->type, event->ctrl, event->alt);
|
||||
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
continue;
|
||||
|
@ -1192,7 +1669,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
|
|||
/* open close on header */
|
||||
if (ELEM(event->type, RETKEY, PADENTER)) {
|
||||
if (inside_header) {
|
||||
ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl);
|
||||
ui_handle_panel_header(C, block, mx, my, RETKEY, event->ctrl, event->alt);
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
break;
|
||||
}
|
||||
|
@ -1202,7 +1679,7 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
|
|||
retval = WM_UI_HANDLER_BREAK;
|
||||
|
||||
if (inside_header) {
|
||||
ui_handle_panel_header(C, block, mx, my, 0, event->ctrl);
|
||||
ui_handle_panel_header(C, block, mx, my, 0, event->ctrl, event->alt);
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
break;
|
||||
}
|
||||
|
@ -1213,6 +1690,13 @@ int ui_handler_panel_region(bContext *C, const wmEvent *event, ARegion *ar)
|
|||
}
|
||||
|
||||
}
|
||||
else if (event->type == RIGHTMOUSE) {
|
||||
if (inside_header) {
|
||||
ui_panel_menu(C, ar, block->panel);
|
||||
retval = WM_UI_HANDLER_BREAK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (event->type == ESCKEY) {
|
||||
/*XXX 2.50*/
|
||||
#if 0
|
||||
|
|
|
@ -1568,11 +1568,17 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
|
|||
Panel *panel;
|
||||
View2D *v2d = &ar->v2d;
|
||||
View2DScrollers *scrollers;
|
||||
int x, y, xco, yco, w, em, triangle, open;
|
||||
int x, y, xco, yco, w, em, triangle;
|
||||
bool is_context_new = 0;
|
||||
int redo;
|
||||
int scroll;
|
||||
|
||||
bool use_category_tabs = (ar->regiontype == RGN_TYPE_TOOLS); /* XXX, should use some better check? */
|
||||
/* offset panels for small vertical tab area */
|
||||
const char *category = NULL;
|
||||
const int category_tabs_width = UI_PANEL_CATEGORY_MARGIN_WIDTH;
|
||||
int margin_x = 0;
|
||||
|
||||
BLI_SMALLSTACK_DECLARE(pt_stack, PanelType *);
|
||||
|
||||
if (contextnr >= 0)
|
||||
|
@ -1612,6 +1618,31 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
|
|||
}
|
||||
|
||||
|
||||
/* collect categories */
|
||||
if (use_category_tabs) {
|
||||
UI_panel_category_clear_all(ar);
|
||||
|
||||
/* gather unique categories */
|
||||
BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
|
||||
{
|
||||
if (pt->category[0]) {
|
||||
if (!UI_panel_category_find(ar, pt->category)) {
|
||||
UI_panel_category_add(ar, pt->category);
|
||||
}
|
||||
}
|
||||
}
|
||||
BLI_SMALLSTACK_ITER_END;
|
||||
|
||||
if (!UI_panel_category_is_visible(ar)) {
|
||||
use_category_tabs = false;
|
||||
}
|
||||
else {
|
||||
category = UI_panel_category_active_get(ar, true);
|
||||
margin_x = category_tabs_width;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* sortof hack - but we cannot predict the height of panels, until it's being generated */
|
||||
/* the layout engine works with fixed width (from v2d->cur), which is being set at end of the loop */
|
||||
/* in case scroller settings (hide flags) differ from previous, the whole loop gets done again */
|
||||
|
@ -1625,6 +1656,8 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
|
|||
w = UI_PANEL_WIDTH;
|
||||
em = (ar->type->prefsizex) ? 10 : 20;
|
||||
}
|
||||
|
||||
w -= margin_x;
|
||||
|
||||
/* create panels */
|
||||
uiBeginPanels(C, ar);
|
||||
|
@ -1634,8 +1667,19 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
|
|||
|
||||
BLI_SMALLSTACK_ITER_BEGIN(pt_stack, pt)
|
||||
{
|
||||
bool open;
|
||||
|
||||
panel = uiPanelFindByType(ar, pt);
|
||||
|
||||
if (pt->category[0] && !STREQ(category, pt->category)) {
|
||||
if ((panel == NULL) || ((panel->flag & PNL_PIN) == 0)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* draw panel */
|
||||
block = uiBeginBlock(C, ar, pt->idname, UI_EMBOSS);
|
||||
panel = uiBeginPanel(sa, ar, block, pt, &open);
|
||||
panel = uiBeginPanel(sa, ar, block, pt, panel, &open);
|
||||
|
||||
/* bad fixed values */
|
||||
triangle = (int)(UI_UNIT_Y * 1.1f);
|
||||
|
@ -1745,6 +1789,10 @@ void ED_region_panels(const bContext *C, ARegion *ar, int vertical, const char *
|
|||
/* restore view matrix */
|
||||
UI_view2d_view_restore(C);
|
||||
|
||||
if (use_category_tabs) {
|
||||
UI_panel_category_draw_all(ar, category);
|
||||
}
|
||||
|
||||
/* scrollers */
|
||||
scrollers = UI_view2d_scrollers_calc(C, v2d, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
|
||||
UI_view2d_scrollers_draw(C, v2d, scrollers);
|
||||
|
|
|
@ -112,6 +112,36 @@ typedef struct Panel { /* the part from uiBlock that needs saved in file */
|
|||
void *activedata; /* runtime for panel manipulation */
|
||||
} Panel;
|
||||
|
||||
|
||||
/* Notes on Panel Catogories:
|
||||
*
|
||||
* ar->panels_category (PanelCategoryDyn) is a runtime only list of categories collected during draw.
|
||||
*
|
||||
* ar->panels_category_active (PanelCategoryStack) is basically a list of strings (category id's).
|
||||
*
|
||||
* Clicking on a tab moves it to the front of ar->panels_category_active,
|
||||
* If the context changes so this tab is no longer displayed,
|
||||
* then the first-most tab in ar->panels_category_active is used.
|
||||
*
|
||||
* This way you can change modes and always have the tab you last clicked on.
|
||||
*/
|
||||
|
||||
/* region level tabs */
|
||||
#
|
||||
#
|
||||
typedef struct PanelCategoryDyn {
|
||||
struct PanelCategoryDyn *next, *prev;
|
||||
char idname[64];
|
||||
rcti rect;
|
||||
} PanelCategoryDyn;
|
||||
|
||||
/* region stack of active tabs */
|
||||
typedef struct PanelCategoryStack {
|
||||
struct PanelCategoryStack *next, *prev;
|
||||
char idname[64];
|
||||
} PanelCategoryStack;
|
||||
|
||||
|
||||
/* uiList dynamic data... */
|
||||
/* These two Lines with # tell makesdna this struct can be excluded. */
|
||||
#
|
||||
|
@ -209,8 +239,10 @@ typedef struct ARegion {
|
|||
|
||||
ListBase uiblocks; /* uiBlock */
|
||||
ListBase panels; /* Panel */
|
||||
ListBase panels_category_active; /* Stack of panel categories */
|
||||
ListBase ui_lists; /* uiList */
|
||||
ListBase handlers; /* wmEventHandler */
|
||||
ListBase panels_category; /* Panel categories runtime */
|
||||
|
||||
struct wmTimer *regiontimer; /* blend in/out */
|
||||
|
||||
|
@ -244,6 +276,16 @@ typedef struct ARegion {
|
|||
#define SCREENNORMAL 0
|
||||
#define SCREENFULL 1
|
||||
|
||||
/* Panel->flag */
|
||||
enum {
|
||||
PNL_SELECT = (1 << 0),
|
||||
PNL_CLOSEDX = (1 << 1),
|
||||
PNL_CLOSEDY = (1 << 2),
|
||||
PNL_CLOSED = (PNL_CLOSEDX | PNL_CLOSEDY),
|
||||
/*PNL_TABBED = (1 << 3), */ /*UNUSED*/
|
||||
PNL_OVERLAP = (1 << 4),
|
||||
PNL_PIN = (1 << 5),
|
||||
};
|
||||
|
||||
/* Panel->snap - for snapping to screen edges */
|
||||
#define PNL_SNAP_NONE 0
|
||||
|
|
|
@ -980,6 +980,11 @@ static void rna_def_panel(BlenderRNA *brna)
|
|||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
|
||||
RNA_define_verify_sdna(TRUE);
|
||||
|
||||
prop = RNA_def_property(srna, "bl_category", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "type->category");
|
||||
RNA_def_property_string_default(prop, BLF_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
|
||||
|
||||
prop = RNA_def_property(srna, "bl_space_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "type->space_type");
|
||||
RNA_def_property_enum_items(prop, space_type_items);
|
||||
|
@ -1004,6 +1009,12 @@ static void rna_def_panel(BlenderRNA *brna)
|
|||
RNA_def_property_enum_items(prop, panel_flag_items);
|
||||
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
|
||||
RNA_def_property_ui_text(prop, "Options", "Options for this panel type");
|
||||
|
||||
prop = RNA_def_property(srna, "use_pin", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", PNL_PIN);
|
||||
RNA_def_property_ui_text(prop, "Pin", "");
|
||||
/* XXX, should only tag region for redraw */
|
||||
RNA_def_property_update(prop, NC_WINDOW, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_uilist(BlenderRNA *brna)
|
||||
|
|
Loading…
Reference in New Issue