Compare commits
73 Commits
temp-enum-
...
property-s
Author | SHA1 | Date | |
---|---|---|---|
ef11238c74 | |||
1f768bbe41 | |||
ce6cf2b475 | |||
f957e09398 | |||
d58f361099 | |||
1b391f14fc | |||
b4b2185da0 | |||
8f548fd856 | |||
634bf8e4fc | |||
af146e7745 | |||
4b0a94661c | |||
8eda823dbc | |||
e40225577b | |||
d219d0efa1 | |||
cc1201dce3 | |||
1afdc92511 | |||
20ce4a77bd | |||
7d3d6ac085 | |||
304e9a0b9e | |||
31657ebbbe | |||
169ac2805e | |||
c914bff16d | |||
7758bb25e7 | |||
94272e8347 | |||
67d6d1363d | |||
b7d47e9892 | |||
6f5ca857fc | |||
71c6af4d59 | |||
2f68b79fa8 | |||
98c6349bca | |||
4c1095d33c | |||
847837c808 | |||
16bf1807a1 | |||
052baecc0d | |||
34c5245c32 | |||
42e5314727 | |||
7137e99ff3 | |||
f3e409c1bf | |||
92c201b493 | |||
7955c26f41 | |||
26450636cd | |||
f3b83271e6 | |||
136475dca3 | |||
544ac33b61 | |||
263e42a172 | |||
b7938c3768 | |||
be7a4f4a81 | |||
dbc9f1b0f3 | |||
f3caadec90 | |||
11b89dd56c | |||
5218fb969f | |||
411f425973 | |||
d4b9f41a56 | |||
66ac0448ef | |||
170a40c338 | |||
d2c00d1d7f | |||
cf99c25dbe | |||
c95d6de3b3 | |||
a33720329b | |||
9029c7be19 | |||
463c4ef39e | |||
c891ba0086 | |||
09e555142a | |||
4d5b6409ee | |||
712ccc2602 | |||
85fe4a18e8 | |||
8357b7fe46 | |||
13b283ca8e | |||
723f6e7f53 | |||
040931a9b2 | |||
a34c25046b | |||
e299727fba | |||
db76f34ed6 |
@@ -736,6 +736,8 @@ def km_property_editor(_params):
|
||||
{"properties": [("direction", 'PREV'), ], },),
|
||||
("screen.space_context_cycle", {"type": 'WHEELDOWNMOUSE', "value": 'PRESS', "ctrl": True},
|
||||
{"properties": [("direction", 'NEXT'), ], },),
|
||||
("buttons.start_filter", {"type": 'F', "value": 'PRESS', "ctrl": True}, None),
|
||||
("buttons.clear_filter", {"type": 'F', "value": 'PRESS', "alt": True}, None),
|
||||
# Modifier panels
|
||||
("object.modifier_remove", {"type": 'X', "value": 'PRESS'}, {"properties": [("report", True)]}),
|
||||
("object.modifier_remove", {"type": 'DEL', "value": 'PRESS'}, {"properties": [("report", True)]}),
|
||||
|
@@ -44,6 +44,7 @@ class OBJECT_PT_constraints(ObjectConstraintPanel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_search = False
|
||||
|
||||
layout.operator_menu_enum("object.constraint_add", "type", text="Add Object Constraint")
|
||||
|
||||
@@ -58,6 +59,7 @@ class BONE_PT_constraints(BoneConstraintPanel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_search = False
|
||||
|
||||
layout.operator_menu_enum("pose.constraint_add", "type", text="Add Bone Constraint")
|
||||
|
||||
|
@@ -39,6 +39,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel):
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
layout.use_property_search = False
|
||||
layout.operator_menu_enum("object.modifier_add", "type")
|
||||
layout.template_modifiers()
|
||||
|
||||
|
@@ -23,11 +23,20 @@ from bpy.types import Header, Panel
|
||||
class PROPERTIES_HT_header(Header):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
|
||||
def draw(self, _context):
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
view = context.space_data
|
||||
|
||||
layout.template_header()
|
||||
|
||||
layout.separator_spacer()
|
||||
layout.prop(view, "filter_text", icon='VIEWZOOM', text="")
|
||||
layout.separator_spacer()
|
||||
|
||||
row = layout.row()
|
||||
row.emboss = 'NONE'
|
||||
row.operator("buttons.toggle_pin", icon=('PINNED' if view.use_pin_id else 'UNPINNED'), text="")
|
||||
|
||||
|
||||
class PROPERTIES_PT_navigation_bar(Panel):
|
||||
bl_space_type = 'PROPERTIES'
|
||||
@@ -42,6 +51,10 @@ class PROPERTIES_PT_navigation_bar(Panel):
|
||||
|
||||
layout.scale_x = 1.4
|
||||
layout.scale_y = 1.4
|
||||
if view.filter_text:
|
||||
layout.prop_tabs_enum(view, "context", data_highlight=view,
|
||||
property_highlight="context_search_filter_active", icon_only=True)
|
||||
else:
|
||||
layout.prop_tabs_enum(view, "context", icon_only=True)
|
||||
|
||||
|
||||
|
@@ -157,6 +157,11 @@ enum {
|
||||
UI_BLOCK_POPOVER_ONCE = 1 << 22,
|
||||
/** Always show keymaps, even for non-menus. */
|
||||
UI_BLOCK_SHOW_SHORTCUT_ALWAYS = 1 << 23,
|
||||
/** All items have been removed from the block by the search filter. */
|
||||
UI_BLOCK_FILTERED_EMPTY = 1 << 24,
|
||||
/** The block is only used during the layout process and will not be drawn,
|
||||
* for the case of a subpanel of a closed panel. */
|
||||
UI_BLOCK_SEARCH_ONLY = 1 << 25,
|
||||
};
|
||||
|
||||
/** #uiPopupBlockHandle.menuretval */
|
||||
@@ -671,6 +676,9 @@ enum {
|
||||
void UI_block_theme_style_set(uiBlock *block, char theme_style);
|
||||
char UI_block_emboss_get(uiBlock *block);
|
||||
void UI_block_emboss_set(uiBlock *block, char emboss);
|
||||
bool UI_block_has_search_filter(const uiBlock *block);
|
||||
bool UI_block_is_search_only(const uiBlock *block);
|
||||
void UI_block_set_search_only(uiBlock *block, bool search_only);
|
||||
|
||||
void UI_block_free(const struct bContext *C, uiBlock *block);
|
||||
void UI_blocklist_free(const struct bContext *C, struct ListBase *lb);
|
||||
@@ -1685,6 +1693,8 @@ void UI_panels_scale(struct ARegion *region, float new_width);
|
||||
void UI_panel_label_offset(struct uiBlock *block, int *r_x, int *r_y);
|
||||
int UI_panel_size_y(const struct Panel *panel);
|
||||
bool UI_panel_is_dragging(const struct Panel *panel);
|
||||
bool UI_panel_is_search_filtered(const struct Panel *panel);
|
||||
bool UI_panel_is_active(const struct Panel *panel);
|
||||
|
||||
bool UI_panel_category_is_visible(const struct ARegion *region);
|
||||
void UI_panel_category_add(struct ARegion *region, const char *name);
|
||||
@@ -1708,6 +1718,8 @@ struct PointerRNA *UI_region_panel_custom_data_under_cursor(const struct bContex
|
||||
const struct wmEvent *event);
|
||||
void UI_panel_custom_data_set(struct Panel *panel, struct PointerRNA *custom_data);
|
||||
|
||||
void UI_region_panels_remove_handlers(const struct bContext *C, struct ARegion *region);
|
||||
|
||||
/* Polyinstantiated panels for representing a list of data. */
|
||||
struct Panel *UI_panel_add_instanced(struct ScrArea *area,
|
||||
struct ARegion *region,
|
||||
@@ -1894,6 +1906,7 @@ void uiLayoutSetUnitsY(uiLayout *layout, float unit);
|
||||
void uiLayoutSetEmboss(uiLayout *layout, char emboss);
|
||||
void uiLayoutSetPropSep(uiLayout *layout, bool is_sep);
|
||||
void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep);
|
||||
void uiLayoutSetPropSearch(uiLayout *layout, bool is_searchable);
|
||||
int uiLayoutGetLocalDir(const uiLayout *layout);
|
||||
|
||||
int uiLayoutGetOperatorContext(uiLayout *layout);
|
||||
@@ -1913,6 +1926,8 @@ float uiLayoutGetUnitsY(uiLayout *layout);
|
||||
int uiLayoutGetEmboss(uiLayout *layout);
|
||||
bool uiLayoutGetPropSep(uiLayout *layout);
|
||||
bool uiLayoutGetPropDecorate(uiLayout *layout);
|
||||
bool uiLayoutGetPropSearch(uiLayout *layout);
|
||||
void uiLayoutRootSetSearchOnly(uiLayout *layout, bool search_only);
|
||||
|
||||
/* layout specifiers */
|
||||
uiLayout *uiLayoutRow(uiLayout *layout, bool align);
|
||||
@@ -2358,7 +2373,10 @@ uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout)
|
||||
void uiItemL(uiLayout *layout, const char *name, int icon); /* label */
|
||||
void uiItemL_ex(
|
||||
uiLayout *layout, const char *name, int icon, const bool highlight, const bool redalert);
|
||||
uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon);
|
||||
uiBut *uiItemL_respect_property_split(uiLayout *layout,
|
||||
const char *text,
|
||||
int icon,
|
||||
uiLayout **r_layout);
|
||||
/* label icon for dragging */
|
||||
void uiItemLDrag(uiLayout *layout, struct PointerRNA *ptr, const char *name, int icon);
|
||||
/* menu */
|
||||
@@ -2410,6 +2428,8 @@ void uiItemTabsEnumR_prop(uiLayout *layout,
|
||||
struct bContext *C,
|
||||
struct PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
struct PointerRNA *ptr_highlight,
|
||||
PropertyRNA *prop_highlight,
|
||||
bool icon_only);
|
||||
|
||||
/* UI Operators */
|
||||
|
@@ -3425,12 +3425,20 @@ uiBlock *UI_block_begin(const bContext *C, ARegion *region, const char *name, ch
|
||||
|
||||
window = CTX_wm_window(C);
|
||||
scn = CTX_data_scene(C);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
|
||||
block = MEM_callocN(sizeof(uiBlock), "uiBlock");
|
||||
block->active = 1;
|
||||
block->emboss = emboss;
|
||||
block->evil_C = (void *)C; /* XXX */
|
||||
|
||||
/* Set the search filter for the properties editor. */
|
||||
if ((region && region->regiontype == RGN_TYPE_WINDOW) &&
|
||||
(area && area->spacetype == SPACE_PROPERTIES)) {
|
||||
SpaceProperties *sbuts = CTX_wm_space_properties(C);
|
||||
block->search_filter = sbuts->search_string;
|
||||
}
|
||||
|
||||
if (scn) {
|
||||
/* store display device name, don't lookup for transformations yet
|
||||
* block could be used for non-color displays where looking up for transformation
|
||||
@@ -3480,6 +3488,21 @@ void UI_block_theme_style_set(uiBlock *block, char theme_style)
|
||||
block->theme_style = theme_style;
|
||||
}
|
||||
|
||||
bool UI_block_has_search_filter(const uiBlock *block)
|
||||
{
|
||||
return block->search_filter != NULL && block->search_filter[0] != '\0';
|
||||
}
|
||||
|
||||
bool UI_block_is_search_only(const uiBlock *block)
|
||||
{
|
||||
return block->flag & UI_BLOCK_SEARCH_ONLY;
|
||||
}
|
||||
|
||||
void UI_block_set_search_only(uiBlock *block, bool search_only)
|
||||
{
|
||||
SET_FLAG_FROM_TEST(block->flag, search_only, UI_BLOCK_SEARCH_ONLY);
|
||||
}
|
||||
|
||||
static void ui_but_build_drawstr_float(uiBut *but, double value)
|
||||
{
|
||||
size_t slen = 0;
|
||||
|
@@ -79,6 +79,7 @@ enum {
|
||||
UI_HAS_ICON = (1 << 3),
|
||||
UI_HIDDEN = (1 << 4),
|
||||
UI_SELECT_DRAW = (1 << 5), /* Display selected, doesn't impact interaction. */
|
||||
UI_FILTERED = (1 << 12), /* Filtered by the search string, removed if in a layout. */
|
||||
/* warn: rest of uiBut->flag in UI_interface.h */
|
||||
};
|
||||
|
||||
@@ -273,6 +274,14 @@ struct uiBut {
|
||||
uiButPushedStateFunc pushed_state_func;
|
||||
void *pushed_state_arg;
|
||||
|
||||
/**
|
||||
* Used for property search, so that a button's label and decorator can be filtered and
|
||||
* unfiltered along with it. Due to the sometimes arbitrary nature of these values,
|
||||
* they aren't always filled.
|
||||
*/
|
||||
uiBut *label_but;
|
||||
uiBut *decorator_but;
|
||||
|
||||
/* pointer back */
|
||||
uiBlock *block;
|
||||
};
|
||||
@@ -393,7 +402,7 @@ struct uiBlock {
|
||||
|
||||
ListBase butstore; /* UI_butstore_* runtime function */
|
||||
|
||||
ListBase layouts;
|
||||
ListBase layouts; /* Note: Should be called layout_roots. */
|
||||
struct uiLayout *curlayout;
|
||||
|
||||
ListBase contexts;
|
||||
@@ -488,6 +497,8 @@ struct uiBlock {
|
||||
*/
|
||||
char display_device[64];
|
||||
|
||||
char *search_filter;
|
||||
|
||||
struct PieMenuData pie_data;
|
||||
};
|
||||
|
||||
@@ -777,6 +788,7 @@ extern void ui_draw_aligned_panel(struct uiStyle *style,
|
||||
const rcti *rect,
|
||||
const bool show_pin,
|
||||
const bool show_background);
|
||||
void ui_panel_set_search_filtered(struct Panel *panel, const bool value);
|
||||
|
||||
/* interface_draw.c */
|
||||
extern void ui_draw_dropshadow(
|
||||
|
@@ -85,6 +85,11 @@ typedef struct uiLayoutRoot {
|
||||
int type;
|
||||
int opcontext;
|
||||
|
||||
/** If true, the root will be removed as part of the property search process.
|
||||
* Necessary for cases like searching the contents of closed panels, where the
|
||||
* block-level tag isn't enough because there might be buttons in the header. */
|
||||
bool search_only;
|
||||
|
||||
int emw, emh;
|
||||
int padding;
|
||||
|
||||
@@ -140,6 +145,7 @@ enum {
|
||||
* Enabled by default, depends on 'UI_ITEM_PROP_SEP'. */
|
||||
UI_ITEM_PROP_DECORATE = 1 << 5,
|
||||
UI_ITEM_PROP_DECORATE_NO_PAD = 1 << 6,
|
||||
UI_ITEM_USE_SEARCH_FILTER = 1 << 7,
|
||||
};
|
||||
|
||||
typedef struct uiButtonItem {
|
||||
@@ -176,6 +182,8 @@ struct uiLayout {
|
||||
char emboss;
|
||||
/** for fixed width or height to avoid UI size changes */
|
||||
float units[2];
|
||||
|
||||
bool property_search_layout_temp_debug;
|
||||
};
|
||||
|
||||
typedef struct uiLayoutItemFlow {
|
||||
@@ -219,6 +227,8 @@ typedef struct uiLayoutItemRoot {
|
||||
|
||||
/** \} */
|
||||
|
||||
static uiBut *uiItemL_(uiLayout *layout, const char *name, int icon);
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Item
|
||||
* \{ */
|
||||
@@ -494,7 +504,8 @@ static void ui_item_array(uiLayout *layout,
|
||||
int toggle,
|
||||
bool icon_only,
|
||||
bool compact,
|
||||
bool show_text)
|
||||
bool show_text,
|
||||
uiBut *label_but)
|
||||
{
|
||||
const uiStyle *style = layout->root->style;
|
||||
uiBut *but;
|
||||
@@ -656,7 +667,10 @@ static void ui_item_array(uiLayout *layout,
|
||||
|
||||
/* special case, boolean array in a menu, this could be used in a more generic way too */
|
||||
if (ELEM(subtype, PROP_COLOR, PROP_COLOR_GAMMA) && !expand && ELEM(len, 3, 4)) {
|
||||
uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, 0, 0, w, UI_UNIT_Y);
|
||||
but = uiDefAutoButR(block, ptr, prop, -1, "", ICON_NONE, 0, 0, w, UI_UNIT_Y);
|
||||
if (label_but != NULL) {
|
||||
but->label_but = label_but;
|
||||
}
|
||||
}
|
||||
else {
|
||||
bool *boolarr = NULL;
|
||||
@@ -704,6 +718,13 @@ static void ui_item_array(uiLayout *layout,
|
||||
if ((a == 0) && (subtype == PROP_AXISANGLE)) {
|
||||
UI_but_unit_type_set(but, PROP_UNIT_ROTATION);
|
||||
}
|
||||
|
||||
/* Set the label button for the array item. */
|
||||
if (label_but != NULL) {
|
||||
but->label_but = label_but;
|
||||
label_but = label_but->next;
|
||||
BLI_assert(label_but != NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (boolarr) {
|
||||
@@ -746,7 +767,8 @@ static void ui_item_enum_expand_elem_exec(uiLayout *layout,
|
||||
const eButType but_type,
|
||||
const bool icon_only,
|
||||
const EnumPropertyItem *item,
|
||||
const bool is_first)
|
||||
const bool is_first,
|
||||
uiBut *label_but)
|
||||
{
|
||||
const char *name = (!uiname || uiname[0]) ? item->name : "";
|
||||
const int icon = item->icon;
|
||||
@@ -785,6 +807,10 @@ static void ui_item_enum_expand_elem_exec(uiLayout *layout,
|
||||
if (but_type == UI_BTYPE_TAB) {
|
||||
but->flag |= UI_BUT_DRAG_LOCK;
|
||||
}
|
||||
|
||||
if (label_but != NULL) {
|
||||
but->label_but = label_but;
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_item_enum_expand_exec(uiLayout *layout,
|
||||
@@ -794,7 +820,8 @@ static void ui_item_enum_expand_exec(uiLayout *layout,
|
||||
const char *uiname,
|
||||
const int h,
|
||||
const eButType but_type,
|
||||
const bool icon_only)
|
||||
const bool icon_only,
|
||||
uiBut *label_but)
|
||||
{
|
||||
/* XXX: The way this function currently handles uiname parameter
|
||||
* is insane and inconsistent with general UI API:
|
||||
@@ -804,7 +831,8 @@ static void ui_item_enum_expand_exec(uiLayout *layout,
|
||||
* this doubles the icon_only parameter.
|
||||
* - we *never* draw (i.e. really use) the enum label uiname, it is just used as a mere flag!
|
||||
*
|
||||
* Unfortunately, fixing this implies an API "soft break", so better to defer it for later... :/
|
||||
* Unfortunately, fixing this implies an API "soft break", so better to defer it for later...
|
||||
* :/
|
||||
* - mont29
|
||||
*/
|
||||
|
||||
@@ -870,7 +898,7 @@ static void ui_item_enum_expand_exec(uiLayout *layout,
|
||||
}
|
||||
|
||||
ui_item_enum_expand_elem_exec(
|
||||
layout, block, ptr, prop, uiname, h, but_type, icon_only, item, is_first);
|
||||
layout, block, ptr, prop, uiname, h, but_type, icon_only, item, is_first, label_but);
|
||||
}
|
||||
|
||||
UI_block_layout_set_current(block, layout);
|
||||
@@ -885,25 +913,47 @@ static void ui_item_enum_expand(uiLayout *layout,
|
||||
PropertyRNA *prop,
|
||||
const char *uiname,
|
||||
const int h,
|
||||
const bool icon_only)
|
||||
const bool icon_only,
|
||||
uiBut *label_but)
|
||||
{
|
||||
ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_ROW, icon_only);
|
||||
ui_item_enum_expand_exec(
|
||||
layout, block, ptr, prop, uiname, h, UI_BTYPE_ROW, icon_only, label_but);
|
||||
}
|
||||
static void ui_item_enum_expand_tabs(uiLayout *layout,
|
||||
bContext *C,
|
||||
uiBlock *block,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
PointerRNA *ptr_highlight,
|
||||
PropertyRNA *prop_highlight,
|
||||
const char *uiname,
|
||||
const int h,
|
||||
const bool icon_only)
|
||||
{
|
||||
uiBut *last = block->buttons.last;
|
||||
|
||||
ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_TAB, icon_only);
|
||||
ui_item_enum_expand_exec(layout, block, ptr, prop, uiname, h, UI_BTYPE_TAB, icon_only, NULL);
|
||||
BLI_assert(last != block->buttons.last);
|
||||
|
||||
const bool use_custom_highlight = (prop_highlight != NULL);
|
||||
|
||||
int custom_highlight_flag = 0; /* Max of 32 tabs. */
|
||||
if (use_custom_highlight) {
|
||||
BLI_assert(prop_highlight != NULL);
|
||||
BLI_assert(RNA_property_flag(prop_highlight) & PROP_ENUM_FLAG);
|
||||
custom_highlight_flag = RNA_property_enum_get(ptr_highlight, prop_highlight);
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (uiBut *tab = last ? last->next : block->buttons.first; tab; tab = tab->next) {
|
||||
UI_but_drawflag_enable(tab, ui_but_align_opposite_to_area_align_get(CTX_wm_region(C)));
|
||||
|
||||
if (use_custom_highlight) {
|
||||
if (!(custom_highlight_flag & (1 << i))) {
|
||||
tab->flag |= UI_BUT_INACTIVE;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -939,10 +989,12 @@ static uiBut *ui_item_with_label(uiLayout *layout,
|
||||
{
|
||||
uiLayout *sub = layout;
|
||||
uiBut *but = NULL;
|
||||
uiBut *label_but = NULL;
|
||||
PropertyType type;
|
||||
PropertySubType subtype;
|
||||
int prop_but_width = w_hint;
|
||||
#ifdef UI_PROP_DECORATE
|
||||
uiBut *decorator_but = NULL;
|
||||
uiLayout *layout_prop_decorate = NULL;
|
||||
const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
|
||||
const bool use_prop_decorate = use_prop_sep && (layout->item.flag & UI_ITEM_PROP_DECORATE) &&
|
||||
@@ -963,7 +1015,7 @@ static uiBut *ui_item_with_label(uiLayout *layout,
|
||||
#ifdef UI_PROP_DECORATE
|
||||
if (name[0]) {
|
||||
if (use_prop_sep) {
|
||||
layout_prop_decorate = uiItemL_respect_property_split(layout, name, 0);
|
||||
label_but = uiItemL_respect_property_split(layout, name, 0, &layout_prop_decorate);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
@@ -979,7 +1031,8 @@ static uiBut *ui_item_with_label(uiLayout *layout,
|
||||
else {
|
||||
w_label = w_hint / 3;
|
||||
}
|
||||
uiDefBut(block, UI_BTYPE_LABEL, 0, name, x, y, w_label, h, NULL, 0.0, 0.0, 0, 0, "");
|
||||
label_but = uiDefBut(
|
||||
block, UI_BTYPE_LABEL, 0, name, x, y, w_label, h, NULL, 0.0, 0.0, 0, 0, "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1057,10 +1110,15 @@ static uiBut *ui_item_with_label(uiLayout *layout,
|
||||
#ifdef UI_PROP_DECORATE
|
||||
/* Only for alignment. */
|
||||
if (use_prop_decorate) { /* Note that sep flag may have been unset meanwhile. */
|
||||
uiItemL(layout_prop_decorate ? layout_prop_decorate : sub, NULL, ICON_BLANK1);
|
||||
decorator_but = uiItemL_(layout_prop_decorate ? layout_prop_decorate : sub, NULL, ICON_BLANK1);
|
||||
}
|
||||
#endif /* UI_PROP_DECORATE */
|
||||
|
||||
/* Set the button's label and decorator even if they are NULL. They can be changed
|
||||
* further with the return value of this function anyway. */
|
||||
but->label_but = label_but;
|
||||
but->decorator_but = decorator_but;
|
||||
|
||||
UI_block_layout_set_current(block, layout);
|
||||
return but;
|
||||
}
|
||||
@@ -1901,28 +1959,34 @@ static uiLayout *ui_layout_heading_find(uiLayout *cur_layout)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void ui_layout_heading_label_add(uiLayout *layout,
|
||||
/**
|
||||
* \return The label button added.
|
||||
*/
|
||||
static uiBut *ui_layout_heading_label_add(uiLayout *layout,
|
||||
uiLayout *heading_layout,
|
||||
bool right_align,
|
||||
bool respect_prop_split)
|
||||
{
|
||||
const int prev_alignment = layout->alignment;
|
||||
uiBut *label_but = NULL;
|
||||
|
||||
if (right_align) {
|
||||
uiLayoutSetAlignment(layout, UI_LAYOUT_ALIGN_RIGHT);
|
||||
}
|
||||
|
||||
if (respect_prop_split) {
|
||||
uiItemL_respect_property_split(layout, heading_layout->heading, ICON_NONE);
|
||||
label_but = uiItemL_respect_property_split(layout, heading_layout->heading, ICON_NONE, NULL);
|
||||
}
|
||||
else {
|
||||
uiItemL(layout, heading_layout->heading, ICON_NONE);
|
||||
label_but = uiItemL_(layout, heading_layout->heading, ICON_NONE);
|
||||
}
|
||||
/* After adding the heading label, we have to mark it somehow as added, so it's not added again
|
||||
* for other items in this layout. For now just clear it. */
|
||||
heading_layout->heading[0] = '\0';
|
||||
|
||||
layout->alignment = prev_alignment;
|
||||
|
||||
return label_but;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1932,8 +1996,8 @@ static void ui_layout_heading_label_add(uiLayout *layout,
|
||||
*/
|
||||
static uiLayout *ui_item_prop_split_layout_hack(uiLayout *layout_parent, uiLayout *layout_split)
|
||||
{
|
||||
/* Tag item as using property split layout, this is inherited to children so they can get special
|
||||
* treatment if needed. */
|
||||
/* Tag item as using property split layout, this is inherited to children so they can get
|
||||
* special treatment if needed. */
|
||||
layout_parent->item.flag |= UI_ITEM_INSIDE_PROP_SEP;
|
||||
|
||||
if (layout_parent->item.type == ITEM_LAYOUT_ROW) {
|
||||
@@ -1959,9 +2023,9 @@ void uiItemFullR(uiLayout *layout,
|
||||
char namestr[UI_MAX_NAME_STR];
|
||||
const bool use_prop_sep = ((layout->item.flag & UI_ITEM_PROP_SEP) != 0);
|
||||
const bool inside_prop_sep = ((layout->item.flag & UI_ITEM_INSIDE_PROP_SEP) != 0);
|
||||
/* Columns can define a heading to insert. If the first item added to a split layout doesn't have
|
||||
* a label to display in the first column, the heading is inserted there. Otherwise it's inserted
|
||||
* as a new row before the first item. */
|
||||
/* Columns can define a heading to insert. If the first item added to a split layout doesn't
|
||||
* have a label to display in the first column, the heading is inserted there. Otherwise it's
|
||||
* inserted as a new row before the first item. */
|
||||
uiLayout *heading_layout = ui_layout_heading_find(layout);
|
||||
/* Although checkboxes use the split layout, they are an exception and should only place their
|
||||
* label in the second column, to not make that almost empty.
|
||||
@@ -2106,6 +2170,10 @@ void uiItemFullR(uiLayout *layout,
|
||||
}
|
||||
|
||||
uiBut *but = NULL;
|
||||
/* Store the label to assign it to the button afterwards. This is the first
|
||||
* label button if the item is an array and there are a series of buttons.
|
||||
* Decorators are assigned as they are built later on. */
|
||||
uiBut *label_but = NULL;
|
||||
|
||||
/* Split the label / property. */
|
||||
uiLayout *layout_parent = layout;
|
||||
@@ -2125,13 +2193,13 @@ void uiItemFullR(uiLayout *layout,
|
||||
layout = uiLayoutColumn(layout_row ? layout_row : layout, true);
|
||||
layout->space = 0;
|
||||
if (heading_layout) {
|
||||
ui_layout_heading_label_add(layout, heading_layout, false, false);
|
||||
label_but = ui_layout_heading_label_add(layout, heading_layout, false, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uiLayout *layout_split = uiLayoutSplit(
|
||||
layout_row ? layout_row : layout, UI_ITEM_PROP_SEP_DIVIDE, true);
|
||||
bool label_added = false;
|
||||
bool label_added = false; /* HANS-TODO: Replace with checking if label_but == NULL. */
|
||||
layout_split->space = 0;
|
||||
uiLayout *layout_sub = uiLayoutColumn(layout_split, true);
|
||||
layout_sub->space = 0;
|
||||
@@ -2152,7 +2220,7 @@ void uiItemFullR(uiLayout *layout,
|
||||
*s++ = str[0];
|
||||
*s++ = '\0';
|
||||
}
|
||||
but = uiDefBut(block,
|
||||
uiBut *new_label = uiDefBut(block,
|
||||
UI_BTYPE_LABEL,
|
||||
0,
|
||||
use_prefix ? name_with_suffix : str,
|
||||
@@ -2166,25 +2234,35 @@ void uiItemFullR(uiLayout *layout,
|
||||
0,
|
||||
0,
|
||||
"");
|
||||
but->drawflag |= UI_BUT_TEXT_RIGHT;
|
||||
but->drawflag &= ~UI_BUT_TEXT_LEFT;
|
||||
new_label->drawflag |= UI_BUT_TEXT_RIGHT;
|
||||
new_label->drawflag &= ~UI_BUT_TEXT_LEFT;
|
||||
|
||||
if (a == 0) {
|
||||
label_but = new_label;
|
||||
}
|
||||
label_added = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (name) {
|
||||
but = uiDefBut(
|
||||
label_but = uiDefBut(
|
||||
block, UI_BTYPE_LABEL, 0, name, 0, 0, w, UI_UNIT_Y, NULL, 0.0, 0.0, 0, 0, "");
|
||||
but->drawflag |= UI_BUT_TEXT_RIGHT;
|
||||
but->drawflag &= ~UI_BUT_TEXT_LEFT;
|
||||
label_but->drawflag |= UI_BUT_TEXT_RIGHT;
|
||||
label_but->drawflag &= ~UI_BUT_TEXT_LEFT;
|
||||
|
||||
label_added = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!label_added && heading_layout) {
|
||||
ui_layout_heading_label_add(layout_sub, heading_layout, true, false);
|
||||
label_but = ui_layout_heading_label_add(layout_sub, heading_layout, true, false);
|
||||
label_added = true;
|
||||
}
|
||||
|
||||
/* Add an empty label button so the empty column isn't removed during property search. */
|
||||
if (!label_added && !use_prop_sep_split_label) {
|
||||
label_but = uiItemL_(layout_sub, "", ICON_NONE);
|
||||
label_added = true;
|
||||
}
|
||||
|
||||
layout_split = ui_item_prop_split_layout_hack(layout_parent, layout_split);
|
||||
@@ -2227,7 +2305,7 @@ void uiItemFullR(uiLayout *layout,
|
||||
else if (heading_layout) {
|
||||
/* Could not add heading to split layout, fallback to inserting it to the layout with the
|
||||
* heading itself. */
|
||||
ui_layout_heading_label_add(heading_layout, heading_layout, false, false);
|
||||
label_but = ui_layout_heading_label_add(heading_layout, heading_layout, false, false);
|
||||
}
|
||||
|
||||
/* array property */
|
||||
@@ -2254,26 +2332,29 @@ void uiItemFullR(uiLayout *layout,
|
||||
toggle,
|
||||
icon_only,
|
||||
compact,
|
||||
!use_prop_sep_split_label);
|
||||
!use_prop_sep_split_label,
|
||||
label_but);
|
||||
}
|
||||
/* enum item */
|
||||
else if (type == PROP_ENUM && index == RNA_ENUM_VALUE) {
|
||||
if (icon && name[0] && !icon_only) {
|
||||
uiDefIconTextButR_prop(
|
||||
but = uiDefIconTextButR_prop(
|
||||
block, UI_BTYPE_ROW, 0, icon, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
|
||||
}
|
||||
else if (icon) {
|
||||
uiDefIconButR_prop(
|
||||
but = uiDefIconButR_prop(
|
||||
block, UI_BTYPE_ROW, 0, icon, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
|
||||
}
|
||||
else {
|
||||
uiDefButR_prop(
|
||||
but = uiDefButR_prop(
|
||||
block, UI_BTYPE_ROW, 0, name, 0, 0, w, h, ptr, prop, -1, 0, value, -1, -1, NULL);
|
||||
}
|
||||
BLI_assert(but != NULL);
|
||||
but->label_but = label_but;
|
||||
}
|
||||
/* expanded enum */
|
||||
else if (type == PROP_ENUM && expand) {
|
||||
ui_item_enum_expand(layout, block, ptr, prop, name, h, icon_only);
|
||||
ui_item_enum_expand(layout, block, ptr, prop, name, h, icon_only, label_but);
|
||||
}
|
||||
/* property with separate label */
|
||||
else if (type == PROP_ENUM || type == PROP_STRING || type == PROP_POINTER) {
|
||||
@@ -2287,6 +2368,8 @@ void uiItemFullR(uiLayout *layout,
|
||||
if (layout->activate_init) {
|
||||
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
|
||||
}
|
||||
BLI_assert(but != NULL);
|
||||
but->label_but = label_but;
|
||||
}
|
||||
/* single button */
|
||||
else {
|
||||
@@ -2317,6 +2400,8 @@ void uiItemFullR(uiLayout *layout,
|
||||
if (layout->activate_init) {
|
||||
UI_but_flag_enable(but, UI_BUT_ACTIVATE_ON_INIT);
|
||||
}
|
||||
|
||||
but->label_but = label_but;
|
||||
}
|
||||
|
||||
/* The resulting button may have the icon set since boolean button drawing
|
||||
@@ -2352,13 +2437,16 @@ void uiItemFullR(uiLayout *layout,
|
||||
|
||||
/* The icons are set in 'ui_but_anim_flag' */
|
||||
uiItemDecoratorR_prop(layout_col, ptr_dec, prop_dec, but_decorate->rnaindex);
|
||||
but = block->buttons.last;
|
||||
uiBut *decorator = block->buttons.last;
|
||||
but_decorate->decorator_but = decorator;
|
||||
|
||||
/* Order the decorator after the button we decorate, this is used so we can always
|
||||
* do a quick lookup. */
|
||||
BLI_remlink(&block->buttons, but);
|
||||
BLI_insertlinkafter(&block->buttons, but_decorate, but);
|
||||
but_decorate = but->next;
|
||||
BLI_remlink(&block->buttons, decorator);
|
||||
BLI_insertlinkafter(&block->buttons, but_decorate, decorator);
|
||||
|
||||
/* Assign decorator to the property's button so that they can be filtered together. */
|
||||
but_decorate = decorator->next;
|
||||
}
|
||||
BLI_assert(ELEM(i, 1, ui_decorate.len));
|
||||
|
||||
@@ -3187,29 +3275,43 @@ uiPropertySplitWrapper uiItemPropertySplitWrapperCreate(uiLayout *parent_layout)
|
||||
return split_wrapper;
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Helper to add a label and creates a property split layout if needed.
|
||||
*
|
||||
* \param r_layout: Returns a column to put decorators in if property separate is on, otherwise
|
||||
* returns the original layout.
|
||||
*/
|
||||
uiLayout *uiItemL_respect_property_split(uiLayout *layout, const char *text, int icon)
|
||||
uiBut *uiItemL_respect_property_split(uiLayout *layout,
|
||||
const char *text,
|
||||
int icon,
|
||||
uiLayout **r_layout)
|
||||
{
|
||||
uiBut *label_but;
|
||||
if (layout->item.flag & UI_ITEM_PROP_SEP) {
|
||||
uiBlock *block = uiLayoutGetBlock(layout);
|
||||
uiPropertySplitWrapper split_wrapper = uiItemPropertySplitWrapperCreate(layout);
|
||||
/* Further items added to 'layout' will automatically be added to split_wrapper.property_row */
|
||||
/* Further items added to 'layout' will automatically be added to split_wrapper.property_row
|
||||
*/
|
||||
|
||||
uiItemL_(split_wrapper.label_column, text, icon);
|
||||
label_but = uiItemL_(split_wrapper.label_column, text, icon);
|
||||
UI_block_layout_set_current(block, split_wrapper.property_row);
|
||||
|
||||
return split_wrapper.decorate_column;
|
||||
if (r_layout != NULL) {
|
||||
*r_layout = split_wrapper.decorate_column;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
char namestr[UI_MAX_NAME_STR];
|
||||
if (text) {
|
||||
text = ui_item_name_add_colon(text, namestr);
|
||||
}
|
||||
uiItemL_(layout, text, icon);
|
||||
label_but = uiItemL_(layout, text, icon);
|
||||
|
||||
return layout;
|
||||
if (r_layout != NULL) {
|
||||
*r_layout = layout;
|
||||
}
|
||||
}
|
||||
return label_but;
|
||||
}
|
||||
|
||||
void uiItemLDrag(uiLayout *layout, PointerRNA *ptr, const char *name, int icon)
|
||||
@@ -3497,13 +3599,19 @@ void uiItemMenuEnumR(
|
||||
uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
|
||||
}
|
||||
|
||||
void uiItemTabsEnumR_prop(
|
||||
uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop, bool icon_only)
|
||||
void uiItemTabsEnumR_prop(uiLayout *layout,
|
||||
bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *prop,
|
||||
PointerRNA *ptr_highlight,
|
||||
PropertyRNA *prop_highlight,
|
||||
bool icon_only)
|
||||
{
|
||||
uiBlock *block = layout->root->block;
|
||||
|
||||
UI_block_layout_set_current(block, layout);
|
||||
ui_item_enum_expand_tabs(layout, C, block, ptr, prop, NULL, UI_UNIT_Y, icon_only);
|
||||
ui_item_enum_expand_tabs(
|
||||
layout, C, block, ptr, prop, ptr_highlight, prop_highlight, NULL, UI_UNIT_Y, icon_only);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -4640,8 +4748,8 @@ static void ui_litem_init_from_parent(uiLayout *litem, uiLayout *layout, int ali
|
||||
litem->redalert = layout->redalert;
|
||||
litem->w = layout->w;
|
||||
litem->emboss = layout->emboss;
|
||||
litem->item.flag = (layout->item.flag &
|
||||
(UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE | UI_ITEM_INSIDE_PROP_SEP));
|
||||
litem->item.flag = (layout->item.flag & (UI_ITEM_PROP_SEP | UI_ITEM_PROP_DECORATE |
|
||||
UI_ITEM_INSIDE_PROP_SEP | UI_ITEM_USE_SEARCH_FILTER));
|
||||
|
||||
if (layout->child_items_layout) {
|
||||
BLI_addtail(&layout->child_items_layout->items, litem);
|
||||
@@ -4979,6 +5087,16 @@ void uiLayoutSetPropDecorate(uiLayout *layout, bool is_sep)
|
||||
SET_FLAG_FROM_TEST(layout->item.flag, is_sep, UI_ITEM_PROP_DECORATE);
|
||||
}
|
||||
|
||||
bool uiLayoutGetPropSearch(uiLayout *layout)
|
||||
{
|
||||
return (layout->item.flag & UI_ITEM_USE_SEARCH_FILTER) != 0;
|
||||
}
|
||||
|
||||
void uiLayoutSetPropSearch(uiLayout *layout, bool is_searchable)
|
||||
{
|
||||
SET_FLAG_FROM_TEST(layout->item.flag, is_searchable, UI_ITEM_USE_SEARCH_FILTER);
|
||||
}
|
||||
|
||||
bool uiLayoutGetActive(uiLayout *layout)
|
||||
{
|
||||
return layout->active;
|
||||
@@ -5047,6 +5165,435 @@ int uiLayoutGetEmboss(uiLayout *layout)
|
||||
return layout->emboss;
|
||||
}
|
||||
|
||||
void uiLayoutRootSetSearchOnly(uiLayout *layout, bool search_only)
|
||||
{
|
||||
layout->root->search_only = search_only;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Block Layout Search Filtering
|
||||
* \{ */
|
||||
|
||||
// #define PROPERTY_SEARCH_USE_TOOLTIPS
|
||||
// #define PROPERTY_SEARCH_USE_PANEL_LABELS
|
||||
#define DEBUG_LAYOUT_ROOTS
|
||||
|
||||
static void ui_layout_free(uiLayout *layout);
|
||||
|
||||
#ifdef DEBUG_LAYOUT_ROOTS
|
||||
|
||||
/* clang-format off */
|
||||
static const char *but_type_string(eButType type) {
|
||||
switch (type) {
|
||||
case UI_BTYPE_BUT: return "But";
|
||||
case UI_BTYPE_ROW: return "Row But";
|
||||
case UI_BTYPE_TEXT: return "Text";
|
||||
case UI_BTYPE_MENU: return "Menu";
|
||||
case UI_BTYPE_BUT_MENU: return "But Menu";
|
||||
case UI_BTYPE_NUM: return "Number";
|
||||
case UI_BTYPE_NUM_SLIDER: return "Number Slider";
|
||||
case UI_BTYPE_TOGGLE: return "Toggle";
|
||||
case UI_BTYPE_TOGGLE_N: return "Toggle N";
|
||||
case UI_BTYPE_ICON_TOGGLE: return "Icon Toggle";
|
||||
case UI_BTYPE_ICON_TOGGLE_N: return "Icon Toggle N";
|
||||
case UI_BTYPE_BUT_TOGGLE: return "But Toggle";
|
||||
case UI_BTYPE_CHECKBOX: return "Checkbox";
|
||||
case UI_BTYPE_CHECKBOX_N: return "Checkbox N";
|
||||
case UI_BTYPE_COLOR: return "Color";
|
||||
case UI_BTYPE_TAB: return "Tab";
|
||||
case UI_BTYPE_POPOVER: return "Popover";
|
||||
case UI_BTYPE_SCROLL: return "Scroll";
|
||||
case UI_BTYPE_BLOCK: return "Block";
|
||||
case UI_BTYPE_LABEL: return "Label";
|
||||
case UI_BTYPE_KEY_EVENT: return "Key Event";
|
||||
case UI_BTYPE_HSVCUBE: return "HSV Cube";
|
||||
case UI_BTYPE_PULLDOWN: return "Pulldown";
|
||||
case UI_BTYPE_ROUNDBOX: return "Roundbox";
|
||||
case UI_BTYPE_COLORBAND: return "Colorband";
|
||||
case UI_BTYPE_UNITVEC: return "Unit Vector";
|
||||
case UI_BTYPE_CURVE: return "Curve";
|
||||
case UI_BTYPE_CURVEPROFILE: return "Curve Profile";
|
||||
case UI_BTYPE_LISTBOX: return "Listbox";
|
||||
case UI_BTYPE_LISTROW: return "List Row";
|
||||
case UI_BTYPE_HSVCIRCLE: return "HSV Circle";
|
||||
case UI_BTYPE_TRACK_PREVIEW: return "Track Preview";
|
||||
case UI_BTYPE_SEARCH_MENU: return "Search Menu";
|
||||
case UI_BTYPE_EXTRA: return "Extra";
|
||||
case UI_BTYPE_HOTKEY_EVENT: return "Hotkey Event";
|
||||
case UI_BTYPE_IMAGE: return "Image";
|
||||
case UI_BTYPE_HISTOGRAM: return "Histogram";
|
||||
case UI_BTYPE_WAVEFORM: return "Waveform";
|
||||
case UI_BTYPE_VECTORSCOPE: return "Vectorscope";
|
||||
case UI_BTYPE_PROGRESS_BAR: return "Progress Bar";
|
||||
case UI_BTYPE_NODE_SOCKET: return "Node Socket";
|
||||
case UI_BTYPE_SEPR: return "Spacer";
|
||||
case UI_BTYPE_SEPR_LINE: return "Spacer Line";
|
||||
case UI_BTYPE_SEPR_SPACER: return "Dynamic Spacer";
|
||||
case UI_BTYPE_GRIP: return "Grip";
|
||||
default: return "Unkown Button Type";
|
||||
}
|
||||
}
|
||||
/* clang-format on */
|
||||
|
||||
/* Keep order the same as enum above. */
|
||||
const char *item_type_names[12] = {
|
||||
"Button", /* ITEM_BUTTON */
|
||||
"Row", /* ITEM_LAYOUT_ROW */
|
||||
"Column", /* ITEM_LAYOUT_COLUMN */
|
||||
"Column Flow", /* ITEM_LAYOUT_COLUMN_FLOW */
|
||||
"Row Flow", /* ITEM_LAYOUT_ROW_FLOW */
|
||||
"Grid Flow", /* ITEM_LAYOUT_GRID_FLOW */
|
||||
"Box", /* ITEM_LAYOUT_BOX */
|
||||
"Absolute", /* ITEM_LAYOUT_ABSOLUTE */
|
||||
"Split", /* ITEM_LAYOUT_SPLIT */
|
||||
"Overlap", /* ITEM_LAYOUT_OVERLAP */
|
||||
"Radial", /* ITEM_LAYOUT_RADIAL */
|
||||
"Root", /* ITEM_LAYOUT_ROOT */
|
||||
};
|
||||
|
||||
# define PRINT_DEFAULT "\x1B[0m"
|
||||
# define PRINT_GREEN "\x1B[32m"
|
||||
# define PRINT_RED "\x1B[31m"
|
||||
# define PRINT_WHITE "\x1B[37m"
|
||||
static void debug_print_button_item(uiButtonItem *button_item)
|
||||
{
|
||||
uiBut *but = button_item->but;
|
||||
|
||||
if (but == NULL) {
|
||||
printf("NULL BUT");
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s%s%s: ", PRINT_RED, but_type_string(but->type), PRINT_DEFAULT);
|
||||
|
||||
if (but->str && but->str[0]) {
|
||||
printf(but->str);
|
||||
}
|
||||
else if (!RNA_pointer_is_null(&but->rnapoin)) {
|
||||
printf(RNA_property_ui_name(but->rnaprop));
|
||||
}
|
||||
}
|
||||
|
||||
static void debug_print_layout(uiItem *item, int depth, bool child_items_layout)
|
||||
{
|
||||
uiItemType type = item->type;
|
||||
|
||||
printf("%s", PRINT_WHITE);
|
||||
for (int i = 0; i < depth; i++) {
|
||||
printf("| ");
|
||||
}
|
||||
printf("%s", PRINT_DEFAULT);
|
||||
|
||||
if (type == ITEM_BUTTON) {
|
||||
uiButtonItem *button_item = (uiButtonItem *)item;
|
||||
|
||||
debug_print_button_item(button_item);
|
||||
printf("\n");
|
||||
}
|
||||
else {
|
||||
printf("%s%s%s: ", PRINT_GREEN, item_type_names[item->type], PRINT_DEFAULT);
|
||||
uiLayout *layout = (uiLayout *)item;
|
||||
|
||||
printf("%s", PRINT_WHITE);
|
||||
if (layout->property_search_layout_temp_debug) {
|
||||
printf("(search layout)");
|
||||
}
|
||||
if (child_items_layout) {
|
||||
printf("(child_items_layout)");
|
||||
}
|
||||
printf("%s", PRINT_DEFAULT);
|
||||
|
||||
printf("\n");
|
||||
|
||||
if (layout->child_items_layout != NULL) {
|
||||
|
||||
debug_print_layout((uiItem *)layout->child_items_layout, depth + 1, true);
|
||||
}
|
||||
LISTBASE_FOREACH (uiItem *, child_item, &layout->items) {
|
||||
debug_print_layout(child_item, depth + 1, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* DEBUG_LAYOUT_ROOTS */
|
||||
|
||||
static void ui_layout_free_hide_buttons(uiLayout *layout)
|
||||
{
|
||||
LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
|
||||
if (item->type == ITEM_BUTTON) {
|
||||
uiButtonItem *button_item = (uiButtonItem *)item;
|
||||
BLI_assert(button_item->but != NULL);
|
||||
button_item->but->flag |= UI_HIDDEN;
|
||||
MEM_freeN(item);
|
||||
}
|
||||
else {
|
||||
ui_layout_free_hide_buttons((uiLayout *)item);
|
||||
}
|
||||
}
|
||||
|
||||
MEM_freeN(layout);
|
||||
}
|
||||
|
||||
static bool ui_button_search_tag(uiBut *but, char *search_filter)
|
||||
{
|
||||
if (but->optype != NULL) {
|
||||
if (BLI_strcasestr(but->optype->name, search_filter)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (but->rnaprop != NULL) {
|
||||
if (BLI_strcasestr(but->str, search_filter)) {
|
||||
return true;
|
||||
}
|
||||
if (BLI_strcasestr(RNA_property_ui_name(but->rnaprop), search_filter)) {
|
||||
return true;
|
||||
}
|
||||
#ifdef PROPERTY_SEARCH_USE_TOOLTIPS
|
||||
if (BLI_strcasestr(RNA_property_description(but->rnaprop), search_filter)) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tag all buttons with whether they matched the search filter or not.
|
||||
*
|
||||
* \note This doesn't actually remove any buttons, and buttons that were tagged might
|
||||
* not even be removed if they were in a layout with property search turned off.
|
||||
*/
|
||||
static void ui_block_search_filter_tag_buttons(uiBlock *block)
|
||||
{
|
||||
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
|
||||
/* Flag all label buttons, we don't want to re-display them. */
|
||||
if (but->type == UI_BTYPE_LABEL) {
|
||||
but->flag |= UI_FILTERED;
|
||||
}
|
||||
|
||||
/* Do the shorter check first, in case the check returns true. */
|
||||
if (ui_button_search_tag(but, block->search_filter)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
but->flag |= UI_FILTERED;
|
||||
}
|
||||
|
||||
/* Remove filter from labels and decorators that correspond to un-filtered buttons. */
|
||||
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
|
||||
if ((but->flag & UI_FILTERED) == 0) {
|
||||
uiBut *label_but = but->label_but;
|
||||
uiBut *decorator_but = but->decorator_but;
|
||||
if (label_but != NULL) {
|
||||
label_but->flag &= ~UI_FILTERED;
|
||||
}
|
||||
if (decorator_but != NULL) {
|
||||
decorator_but->flag &= ~UI_FILTERED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive implementation for #ui_block_search_filter_clean.
|
||||
*/
|
||||
static bool ui_layout_search_clean_recursive(uiLayout *layout)
|
||||
{
|
||||
/* Recursively clean sub-layouts. */
|
||||
bool all_children_empty = true;
|
||||
LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
|
||||
/* Deal with buttons after checking children. */
|
||||
if (item->type == ITEM_BUTTON) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool empty = ui_layout_search_clean_recursive((uiLayout *)item);
|
||||
all_children_empty &= empty;
|
||||
|
||||
if (empty) {
|
||||
BLI_assert(BLI_findindex(&layout->items, item) != -1);
|
||||
BLI_remlink(&layout->items, item);
|
||||
MEM_freeN(item);
|
||||
}
|
||||
}
|
||||
|
||||
/* Remove all search filtered button items. */
|
||||
bool layout_emptied = uiLayoutGetPropSearch(layout);
|
||||
if (uiLayoutGetPropSearch(layout)) {
|
||||
LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
|
||||
if (item->type == ITEM_BUTTON) {
|
||||
uiButtonItem *button_item = (uiButtonItem *)item;
|
||||
uiBut *but = button_item->but;
|
||||
if (but->flag & UI_FILTERED) {
|
||||
if (!((but->type == UI_BTYPE_ROUNDBOX) && !all_children_empty)) {
|
||||
but->flag |= UI_HIDDEN;
|
||||
BLI_remlink(&layout->items, item);
|
||||
MEM_freeN(item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
layout_emptied = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return layout_emptied && all_children_empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove buttons on layouts with property search set to true,
|
||||
* and remove layouts with no buttons and empty child layouts.
|
||||
*/
|
||||
static bool ui_block_layout_search_clean(uiBlock *block)
|
||||
{
|
||||
bool all_roots_empty = true;
|
||||
LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) {
|
||||
/* Find exceptions to search layout. */
|
||||
if (root->type == UI_LAYOUT_HEADER) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool empty = ui_layout_search_clean_recursive(root->layout);
|
||||
all_roots_empty &= empty;
|
||||
|
||||
/* If the root is empty, make sure it is freed along with all of its sublayouts. */
|
||||
if (empty) {
|
||||
BLI_assert(BLI_findindex(&block->layouts, root) != -1);
|
||||
BLI_remlink(&block->layouts, root);
|
||||
ui_layout_free_hide_buttons(root->layout);
|
||||
MEM_freeN(root);
|
||||
}
|
||||
}
|
||||
|
||||
return all_roots_empty;
|
||||
}
|
||||
|
||||
static void ui_layout_search_replace_labels(uiLayout *layout)
|
||||
{
|
||||
LISTBASE_FOREACH_MUTABLE (uiItem *, item, &layout->items) {
|
||||
if (item->type == ITEM_BUTTON) {
|
||||
uiButtonItem *button_item = (uiButtonItem *)item;
|
||||
uiBut *but = button_item->but;
|
||||
char name[MAX_NAME];
|
||||
if (but->rnaprop) {
|
||||
strcpy(name, RNA_property_ui_name(but->rnaprop));
|
||||
|
||||
/* Toggle buttons have no outside label and so their text is changed to the RNA name. */
|
||||
if (ELEM(but->type,
|
||||
UI_BTYPE_CHECKBOX,
|
||||
UI_BTYPE_TOGGLE_N,
|
||||
UI_BTYPE_ICON_TOGGLE_N,
|
||||
UI_BTYPE_CHECKBOX_N,
|
||||
UI_BTYPE_LABEL)) {
|
||||
strcpy(but->str, name);
|
||||
}
|
||||
else {
|
||||
/* Search for the label or heading associated with this button and
|
||||
* change it to the RNA name. */
|
||||
uiBut *label_but = but->label_but;
|
||||
if (label_but != NULL) {
|
||||
strcpy(label_but->str, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ui_layout_search_replace_labels((uiLayout *)item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_block_replace_labels(uiBlock *block)
|
||||
{
|
||||
LISTBASE_FOREACH (uiLayoutRoot *, root, &block->layouts) {
|
||||
/* Don't rebuild header layouts. */
|
||||
if (root->type == UI_LAYOUT_HEADER) {
|
||||
continue;
|
||||
}
|
||||
ui_layout_search_replace_labels(root->layout);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \return True if the block was emptied by property search and should be removed.
|
||||
*/
|
||||
static bool ui_block_search_layout(uiBlock *block)
|
||||
{
|
||||
/* Only continue if the block has the search filter set. */
|
||||
if (!(block->search_filter && block->search_filter[0])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LAYOUT_ROOTS
|
||||
if (block->panel && (block->panel->flag & PNL_SELECT)) {
|
||||
printf("\nBEFORE %s %p\n", block->name, block);
|
||||
LISTBASE_FOREACH (uiLayoutRoot *, root, &block->layouts) {
|
||||
debug_print_layout((uiItem *)root->layout, 0, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Also search based on panel labels. */
|
||||
bool panel_label_matches = false;
|
||||
#ifdef PROPERTY_SEARCH_USE_PANEL_LABELS
|
||||
if ((block->panel != NULL) && (block->panel->type != NULL)) {
|
||||
if (BLI_strcasestr(block->panel->type->label, block->search_filter)) {
|
||||
panel_label_matches = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Apply search filter. */
|
||||
if (!panel_label_matches) {
|
||||
ui_block_search_filter_tag_buttons(block);
|
||||
}
|
||||
|
||||
/* Remove filtered buttons and now-empty layouts. */
|
||||
bool all_roots_empty = ui_block_layout_search_clean(block);
|
||||
|
||||
/* Remove search only layout roots before the next step. */
|
||||
LISTBASE_FOREACH_MUTABLE (uiLayoutRoot *, root, &block->layouts) {
|
||||
if (root->search_only) {
|
||||
ui_layout_free_hide_buttons(root->layout);
|
||||
BLI_remlink(&block->layouts, root);
|
||||
MEM_freeN(root);
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace label button strings with RNA property names. */
|
||||
if (!all_roots_empty && !UI_block_is_search_only(block)) {
|
||||
ui_block_replace_labels(block);
|
||||
}
|
||||
|
||||
/* Set empty flags. */
|
||||
if (UI_block_is_search_only(block)) {
|
||||
/* Make sure all of the block's buttons are hidden. They might not have
|
||||
* been hidden if a layout wasn't searched. */
|
||||
LISTBASE_FOREACH (uiBut *, but, &block->buttons) {
|
||||
but->flag |= UI_HIDDEN;
|
||||
}
|
||||
}
|
||||
SET_FLAG_FROM_TEST(
|
||||
block->flag, all_roots_empty || UI_block_is_search_only(block), UI_BLOCK_FILTERED_EMPTY);
|
||||
if (block->panel != NULL) {
|
||||
ui_panel_set_search_filtered(block->panel, all_roots_empty);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_LAYOUT_ROOTS
|
||||
if (block->panel && (block->panel->flag & PNL_SELECT)) {
|
||||
printf("\nAFTER\n");
|
||||
LISTBASE_FOREACH (uiLayoutRoot *, root, &block->layouts) {
|
||||
debug_print_layout((uiItem *)root->layout, 0, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return all_roots_empty || UI_block_is_search_only(block);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
@@ -5340,7 +5887,7 @@ uiLayout *UI_block_layout(uiBlock *block,
|
||||
layout->item.type = (type == UI_LAYOUT_VERT_BAR) ? ITEM_LAYOUT_COLUMN : ITEM_LAYOUT_ROOT;
|
||||
|
||||
/* Only used when 'UI_ITEM_PROP_SEP' is set. */
|
||||
layout->item.flag = UI_ITEM_PROP_DECORATE;
|
||||
layout->item.flag = UI_ITEM_PROP_DECORATE | UI_ITEM_USE_SEARCH_FILTER;
|
||||
|
||||
layout->x = x;
|
||||
layout->y = y;
|
||||
@@ -5487,6 +6034,8 @@ void UI_block_layout_resolve(uiBlock *block, int *r_x, int *r_y)
|
||||
|
||||
block->curlayout = NULL;
|
||||
|
||||
ui_block_search_layout(block);
|
||||
|
||||
for (root = block->layouts.first; root; root = root->next) {
|
||||
ui_layout_add_padding_button(root);
|
||||
|
||||
@@ -5608,9 +6157,9 @@ static void ui_paneltype_draw_impl(bContext *C, PanelType *pt, uiLayout *layout,
|
||||
panel->layout = NULL;
|
||||
}
|
||||
|
||||
/* draw_header() is often used to add a checkbox to the header. If we add the label like below
|
||||
* the label is disconnected from the checkbox, adding a weird looking gap. As workaround, let
|
||||
* the checkbox add the label instead. */
|
||||
/* draw_header() is often used to add a checkbox to the header. If we add the label like
|
||||
* below the label is disconnected from the checkbox, adding a weird looking gap. As
|
||||
* workaround, let the checkbox add the label instead. */
|
||||
if (!ui_layout_has_panel_label(row, pt)) {
|
||||
uiItemL(row, CTX_IFACE_(pt->translation_context, pt->label), ICON_NONE);
|
||||
}
|
||||
|
@@ -69,12 +69,14 @@
|
||||
#define ANIMATION_TIME 0.30
|
||||
#define ANIMATION_INTERVAL 0.02
|
||||
|
||||
#define PNL_LAST_ADDED 1
|
||||
#define PNL_ACTIVE 2
|
||||
#define PNL_WAS_ACTIVE 4
|
||||
#define PNL_ANIM_ALIGN 8
|
||||
#define PNL_NEW_ADDED 16
|
||||
#define PNL_FIRST 32
|
||||
#define PNL_LAST_ADDED (1 << 0)
|
||||
#define PNL_ACTIVE (1 << 1)
|
||||
#define PNL_WAS_ACTIVE (1 << 2)
|
||||
#define PNL_ANIM_ALIGN (1 << 3)
|
||||
#define PNL_NEW_ADDED (1 << 4)
|
||||
#define PNL_FIRST (1 << 5)
|
||||
#define PNL_SEARCH_FILTERED (1 << 6)
|
||||
#define PNL_WAS_SEARCH_FILTERED (1 << 7)
|
||||
|
||||
/* only show pin header button for pinned panels */
|
||||
#define USE_PIN_HIDDEN
|
||||
@@ -182,6 +184,18 @@ static bool panel_active_animation_changed(ListBase *lb, Panel **pa_animation, b
|
||||
}
|
||||
}
|
||||
|
||||
/* Detect search filter flag changes */
|
||||
if ((panel->runtime_flag & PNL_WAS_SEARCH_FILTERED) &&
|
||||
!(panel->runtime_flag & PNL_SEARCH_FILTERED)) {
|
||||
*pa_animation = panel;
|
||||
return false;
|
||||
}
|
||||
if (!(panel->runtime_flag & PNL_WAS_SEARCH_FILTERED) &&
|
||||
(panel->runtime_flag & PNL_SEARCH_FILTERED)) {
|
||||
*pa_animation = panel;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((panel->runtime_flag & PNL_ACTIVE) && !(panel->flag & PNL_CLOSED)) {
|
||||
if (panel_active_animation_changed(&panel->children, pa_animation, no_animation)) {
|
||||
return true;
|
||||
@@ -258,6 +272,7 @@ static Panel *UI_panel_add_instanced_ex(ScrArea *area,
|
||||
|
||||
panel->runtime.list_index = list_index;
|
||||
panel->runtime.custom_data_ptr = custom_data;
|
||||
panel->runtime_flag |= PNL_NEW_ADDED;
|
||||
|
||||
/* Add the panel's children too. Although they aren't instanced panels, we can still use this
|
||||
* function to create them, as UI_panel_begin does other things we don't need to do. */
|
||||
@@ -801,7 +816,7 @@ void UI_panel_end(
|
||||
|
||||
/* Compute total panel size including children. */
|
||||
LISTBASE_FOREACH (Panel *, pachild, &panel->children) {
|
||||
if (pachild->runtime_flag & PNL_ACTIVE) {
|
||||
if (pachild->runtime_flag & PNL_ACTIVE && !UI_panel_is_search_filtered(pachild)) {
|
||||
width = max_ii(width, pachild->sizex);
|
||||
height += get_panel_real_size_y(pachild);
|
||||
}
|
||||
@@ -858,6 +873,45 @@ static void ui_offset_panel_block(uiBlock *block)
|
||||
block->rect.xmin = block->rect.ymin = 0.0;
|
||||
}
|
||||
|
||||
void ui_panel_set_search_filtered(struct Panel *panel, const bool value)
|
||||
{
|
||||
SET_FLAG_FROM_TEST(panel->runtime_flag, value, PNL_SEARCH_FILTERED);
|
||||
}
|
||||
|
||||
static void panel_is_search_filtered_recursive(const Panel *panel, bool *is_search_filtered)
|
||||
{
|
||||
*is_search_filtered = *is_search_filtered && (panel->runtime_flag & PNL_SEARCH_FILTERED);
|
||||
|
||||
/* If the panel is filtered (removed) we need to check that its children are too. */
|
||||
if (*is_search_filtered) {
|
||||
LISTBASE_FOREACH (const Panel *, child_panel, &panel->children) {
|
||||
panel_is_search_filtered_recursive(child_panel, is_search_filtered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find whether a panel and all of its subpanels have been filtered by property search.
|
||||
*
|
||||
* \note We maintain a separate flag for active and search filtered. This prevents the
|
||||
* search filtering from being too invasive to other code and makes animation of search
|
||||
* filtered panels possible.
|
||||
*/
|
||||
bool UI_panel_is_search_filtered(const Panel *panel)
|
||||
{
|
||||
bool is_search_filtered = true;
|
||||
panel_is_search_filtered_recursive(panel, &is_search_filtered);
|
||||
return is_search_filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a panel is currently active (displayed).
|
||||
*/
|
||||
bool UI_panel_is_active(const Panel *panel)
|
||||
{
|
||||
return panel->runtime_flag & PNL_ACTIVE;
|
||||
}
|
||||
|
||||
/**************************** drawing *******************************/
|
||||
|
||||
/* triangle 'icon' for panel header */
|
||||
@@ -1330,7 +1384,7 @@ static void align_sub_panels(Panel *panel)
|
||||
int ofsy = panel->ofsy + panel->sizey - panel->blocksizey;
|
||||
|
||||
LISTBASE_FOREACH (Panel *, pachild, &panel->children) {
|
||||
if (pachild->runtime_flag & PNL_ACTIVE) {
|
||||
if (pachild->runtime_flag & PNL_ACTIVE && !UI_panel_is_search_filtered(pachild)) {
|
||||
pachild->ofsx = panel->ofsx;
|
||||
pachild->ofsy = ofsy - get_panel_size_y(pachild);
|
||||
ofsy -= get_panel_real_size_y(pachild);
|
||||
@@ -1411,17 +1465,21 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co
|
||||
ps->panel->ofsy = -get_panel_size_y(ps->panel);
|
||||
ps->panel->ofsx += ps->panel->runtime.region_ofsx;
|
||||
|
||||
/* Keep track of the last visible panel separately so we don't add space for filtered panels. */
|
||||
PanelSort *ps_last_visible = ps;
|
||||
for (a = 0; a < tot - 1; a++, ps++) {
|
||||
psnext = ps + 1;
|
||||
|
||||
if (align == BUT_VERTICAL) {
|
||||
bool use_box = ps->panel->type && ps->panel->type->flag & PNL_DRAW_BOX;
|
||||
bool use_box = ps_last_visible->panel->type &&
|
||||
ps_last_visible->panel->type->flag & PNL_DRAW_BOX;
|
||||
bool use_box_next = psnext->panel->type && psnext->panel->type->flag & PNL_DRAW_BOX;
|
||||
psnext->panel->ofsx = ps->panel->ofsx;
|
||||
psnext->panel->ofsy = get_panel_real_ofsy(ps->panel) - get_panel_size_y(psnext->panel);
|
||||
|
||||
/* Extra margin for box style panels. */
|
||||
ps->panel->ofsx += (use_box) ? UI_PANEL_BOX_STYLE_MARGIN : 0.0f;
|
||||
psnext->panel->ofsx = ps_last_visible->panel->ofsx;
|
||||
psnext->panel->ofsy = get_panel_real_ofsy(ps_last_visible->panel) -
|
||||
get_panel_size_y(psnext->panel);
|
||||
|
||||
/* Extra Y margin for box style panels. */
|
||||
if (use_box || use_box_next) {
|
||||
psnext->panel->ofsy -= UI_PANEL_BOX_STYLE_MARGIN;
|
||||
}
|
||||
@@ -1431,10 +1489,20 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co
|
||||
psnext->panel->ofsy = ps->panel->ofsy + get_panel_size_y(ps->panel) -
|
||||
get_panel_size_y(psnext->panel);
|
||||
}
|
||||
|
||||
if (!UI_panel_is_search_filtered(psnext->panel)) {
|
||||
ps_last_visible = psnext;
|
||||
}
|
||||
}
|
||||
|
||||
/* Extra X margin for box-style panels. */
|
||||
if (align == BUT_VERTICAL) {
|
||||
ps = panelsort;
|
||||
for (a = 0; a < tot; a++, ps++) {
|
||||
if (ps->panel->type && ps->panel->type->flag & PNL_DRAW_BOX) {
|
||||
ps->panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN;
|
||||
}
|
||||
}
|
||||
/* Extra margin for the last panel if it's a box-style panel. */
|
||||
if (panelsort[tot - 1].panel->type && panelsort[tot - 1].panel->type->flag & PNL_DRAW_BOX) {
|
||||
panelsort[tot - 1].panel->ofsx += UI_PANEL_BOX_STYLE_MARGIN;
|
||||
}
|
||||
|
||||
/* we interpolate */
|
||||
@@ -1454,7 +1522,7 @@ static bool uiAlignPanelStep(ScrArea *area, ARegion *region, const float fac, co
|
||||
|
||||
/* set locations for tabbed and sub panels */
|
||||
LISTBASE_FOREACH (Panel *, panel, ®ion->panels) {
|
||||
if (panel->runtime_flag & PNL_ACTIVE) {
|
||||
if ((panel->runtime_flag & PNL_ACTIVE) && !UI_panel_is_search_filtered(panel)) {
|
||||
if (panel->children.first) {
|
||||
align_sub_panels(panel);
|
||||
}
|
||||
@@ -1478,7 +1546,7 @@ static void ui_panels_size(ScrArea *area, ARegion *region, int *r_x, int *r_y)
|
||||
|
||||
/* compute size taken up by panels, for setting in view2d */
|
||||
LISTBASE_FOREACH (Panel *, panel, ®ion->panels) {
|
||||
if (panel->runtime_flag & PNL_ACTIVE) {
|
||||
if (panel->runtime_flag & PNL_ACTIVE && !(panel->runtime_flag & PNL_SEARCH_FILTERED)) {
|
||||
int pa_sizex, pa_sizey;
|
||||
|
||||
if (align == BUT_VERTICAL) {
|
||||
@@ -1538,13 +1606,21 @@ static void ui_do_animate(bContext *C, Panel *panel)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set all panels as inactive, so that at the end of the panel layout building process
|
||||
* we know which ones are currently used. Also keep track of whether the panel was filtered
|
||||
* by property search so we can activate animation later if that changes.
|
||||
*/
|
||||
static void panel_list_clear_active(ListBase *lb)
|
||||
{
|
||||
/* set all panels as inactive, so that at the end we know
|
||||
* which ones were used */
|
||||
LISTBASE_FOREACH (Panel *, panel, lb) {
|
||||
if (panel->runtime_flag & PNL_ACTIVE) {
|
||||
bool was_search_filtered = panel->runtime_flag & PNL_SEARCH_FILTERED;
|
||||
panel->runtime_flag = PNL_WAS_ACTIVE;
|
||||
|
||||
if (was_search_filtered) {
|
||||
panel->runtime_flag |= PNL_WAS_SEARCH_FILTERED;
|
||||
}
|
||||
}
|
||||
else {
|
||||
panel->runtime_flag = 0;
|
||||
@@ -1600,23 +1676,27 @@ void UI_panels_end(const bContext *C, ARegion *region, int *r_x, int *r_y)
|
||||
ui_panels_size(area, region, r_x, r_y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw panels, selected on top, but not search filtered panels.
|
||||
*/
|
||||
void UI_panels_draw(const bContext *C, ARegion *region)
|
||||
{
|
||||
if (region->alignment != RGN_ALIGN_FLOAT) {
|
||||
UI_ThemeClearColor(TH_BACK);
|
||||
}
|
||||
|
||||
/* Draw panels, selected on top. Also in reverse order, because
|
||||
* UI blocks are added in reverse order and we need child panels
|
||||
* to draw on top. */
|
||||
/* Draw in reverse order, because UI blocks are added in reverse order
|
||||
* and we need child panels to draw on top. */
|
||||
LISTBASE_FOREACH_BACKWARD (uiBlock *, block, ®ion->uiblocks) {
|
||||
if (block->active && block->panel && !(block->panel->flag & PNL_SELECT)) {
|
||||
if (block->active && block->panel && !(block->panel->flag & PNL_SELECT) &&
|
||||
!UI_block_is_search_only(block) && !UI_panel_is_search_filtered(block->panel)) {
|
||||
UI_block_draw(C, block);
|
||||
}
|
||||
}
|
||||
|
||||
LISTBASE_FOREACH_BACKWARD (uiBlock *, block, ®ion->uiblocks) {
|
||||
if (block->active && block->panel && (block->panel->flag & PNL_SELECT)) {
|
||||
if (block->active && block->panel && (block->panel->flag & PNL_SELECT) &&
|
||||
!UI_block_is_search_only(block) && !UI_panel_is_search_filtered(block->panel)) {
|
||||
UI_block_draw(C, block);
|
||||
}
|
||||
}
|
||||
@@ -2801,6 +2881,13 @@ static void ui_handler_remove_panel(bContext *C, void *userdata)
|
||||
panel_activate_state(C, panel, PANEL_STATE_EXIT);
|
||||
}
|
||||
|
||||
void UI_region_panels_remove_handlers(const bContext *C, ARegion *region)
|
||||
{
|
||||
LISTBASE_FOREACH (Panel *, panel, ®ion->panels) {
|
||||
panel_activate_state(C, panel, PANEL_STATE_EXIT);
|
||||
}
|
||||
}
|
||||
|
||||
static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelState state)
|
||||
{
|
||||
uiHandlePanelData *data = panel->activedata;
|
||||
@@ -2828,7 +2915,7 @@ static void panel_activate_state(const bContext *C, Panel *panel, uiHandlePanelS
|
||||
}
|
||||
|
||||
if (state == PANEL_STATE_EXIT) {
|
||||
MEM_freeN(data);
|
||||
MEM_SAFE_FREE(data);
|
||||
panel->activedata = NULL;
|
||||
|
||||
WM_event_remove_ui_handler(
|
||||
|
@@ -860,7 +860,7 @@ static void template_ID(const bContext *C,
|
||||
|
||||
if (text) {
|
||||
/* Add label resepecting the separated layout property split state. */
|
||||
uiItemL_respect_property_split(layout, text, ICON_NONE);
|
||||
uiItemL_respect_property_split(layout, text, ICON_NONE, NULL);
|
||||
}
|
||||
|
||||
if (flag & UI_ID_BROWSE) {
|
||||
|
@@ -2365,7 +2365,8 @@ static void ed_panel_draw(const bContext *C,
|
||||
int w,
|
||||
int em,
|
||||
bool vertical,
|
||||
char *unique_panel_str)
|
||||
char *unique_panel_str,
|
||||
bool search_only)
|
||||
{
|
||||
const uiStyle *style = UI_style_get_dpi();
|
||||
|
||||
@@ -2378,6 +2379,7 @@ static void ed_panel_draw(const bContext *C,
|
||||
strncat(block_name, unique_panel_str, LIST_PANEL_UNIQUE_STR_LEN);
|
||||
}
|
||||
uiBlock *block = UI_block_begin(C, region, block_name, UI_EMBOSS);
|
||||
UI_block_set_search_only(block, search_only);
|
||||
|
||||
bool open;
|
||||
panel = UI_panel_begin(area, region, lb, block, pt, panel, &open);
|
||||
@@ -2397,6 +2399,7 @@ static void ed_panel_draw(const bContext *C,
|
||||
1,
|
||||
0,
|
||||
style);
|
||||
uiLayoutRootSetSearchOnly(panel->layout, search_only);
|
||||
|
||||
pt->draw_header_preset(C, panel);
|
||||
|
||||
@@ -2420,6 +2423,7 @@ static void ed_panel_draw(const bContext *C,
|
||||
1,
|
||||
0,
|
||||
style);
|
||||
uiLayoutSetPropSearch(layout, false);
|
||||
panel->layout = uiLayoutRow(layout, false);
|
||||
}
|
||||
/* Regular case: Normal panel with fixed size buttons. */
|
||||
@@ -2427,6 +2431,7 @@ static void ed_panel_draw(const bContext *C,
|
||||
panel->layout = UI_block_layout(
|
||||
block, UI_LAYOUT_HORIZONTAL, UI_LAYOUT_HEADER, labelx, labely, UI_UNIT_Y, 1, 0, style);
|
||||
}
|
||||
uiLayoutRootSetSearchOnly(panel->layout, search_only);
|
||||
|
||||
pt->draw_header(C, panel);
|
||||
|
||||
@@ -2438,7 +2443,7 @@ static void ed_panel_draw(const bContext *C,
|
||||
panel->labelofs = 0;
|
||||
}
|
||||
|
||||
if (open) {
|
||||
if (open || UI_block_has_search_filter(block) || search_only) {
|
||||
short panelContext;
|
||||
|
||||
/* panel context can either be toolbar region or normal panels region */
|
||||
@@ -2462,6 +2467,7 @@ static void ed_panel_draw(const bContext *C,
|
||||
em,
|
||||
0,
|
||||
style);
|
||||
uiLayoutRootSetSearchOnly(panel->layout, search_only || !open);
|
||||
|
||||
pt->draw(C, panel);
|
||||
|
||||
@@ -2476,7 +2482,7 @@ static void ed_panel_draw(const bContext *C,
|
||||
UI_block_end(C, block);
|
||||
|
||||
/* Draw child panels. */
|
||||
if (open) {
|
||||
if (open || UI_block_has_search_filter(block)) {
|
||||
LISTBASE_FOREACH (LinkData *, link, &pt->children) {
|
||||
PanelType *child_pt = link->data;
|
||||
Panel *child_panel = UI_panel_find_by_type(&panel->children, child_pt);
|
||||
@@ -2491,7 +2497,8 @@ static void ed_panel_draw(const bContext *C,
|
||||
w,
|
||||
em,
|
||||
vertical,
|
||||
unique_panel_str);
|
||||
unique_panel_str,
|
||||
!open);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2651,7 +2658,8 @@ void ED_region_panels_layout_ex(const bContext *C,
|
||||
(pt->flag & PNL_DRAW_BOX) ? w_box_panel : w,
|
||||
em,
|
||||
vertical,
|
||||
NULL);
|
||||
NULL,
|
||||
false);
|
||||
}
|
||||
|
||||
/* Draw "polyinstantaited" panels that don't have a 1 to 1 correspondence with their types. */
|
||||
@@ -2679,7 +2687,8 @@ void ED_region_panels_layout_ex(const bContext *C,
|
||||
(panel->type->flag & PNL_DRAW_BOX) ? w_box_panel : w,
|
||||
em,
|
||||
vertical,
|
||||
unique_panel_str);
|
||||
unique_panel_str,
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1101,27 +1101,18 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r
|
||||
|
||||
/************************* Drawing the Path ************************/
|
||||
|
||||
static void pin_cb(bContext *C, void *UNUSED(arg1), void *UNUSED(arg2))
|
||||
static bool buttons_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
|
||||
{
|
||||
SpaceProperties *sbuts = CTX_wm_space_properties(C);
|
||||
|
||||
if (sbuts->flag & SB_PIN_CONTEXT) {
|
||||
sbuts->pinid = buttons_context_id_path(C);
|
||||
}
|
||||
else {
|
||||
sbuts->pinid = NULL;
|
||||
}
|
||||
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
return sbuts->mainb != BCONTEXT_TOOL;
|
||||
}
|
||||
|
||||
void buttons_context_draw(const bContext *C, uiLayout *layout)
|
||||
static void buttons_panel_context_draw(const bContext *C, Panel *panel)
|
||||
{
|
||||
uiLayout *layout = panel->layout;
|
||||
SpaceProperties *sbuts = CTX_wm_space_properties(C);
|
||||
ButsContextPath *path = sbuts->path;
|
||||
uiLayout *row;
|
||||
uiBlock *block;
|
||||
uiBut *but;
|
||||
PointerRNA *ptr;
|
||||
char namebuf[128], *name;
|
||||
int a, icon;
|
||||
@@ -1182,65 +1173,11 @@ void buttons_context_draw(const bContext *C, uiLayout *layout)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uiItemSpacer(row);
|
||||
|
||||
block = uiLayoutGetBlock(row);
|
||||
UI_block_emboss_set(block, UI_EMBOSS_NONE);
|
||||
but = uiDefIconButBitC(block,
|
||||
UI_BTYPE_ICON_TOGGLE,
|
||||
SB_PIN_CONTEXT,
|
||||
0,
|
||||
ICON_UNPINNED,
|
||||
0,
|
||||
0,
|
||||
UI_UNIT_X,
|
||||
UI_UNIT_Y,
|
||||
&sbuts->flag,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
TIP_("Follow context or keep fixed data-block displayed"));
|
||||
UI_but_flag_disable(but, UI_BUT_UNDO); /* skip undo on screen buttons */
|
||||
UI_but_func_set(but, pin_cb, NULL, NULL);
|
||||
}
|
||||
|
||||
#ifdef USE_HEADER_CONTEXT_PATH
|
||||
static bool buttons_header_context_poll(const bContext *C, HeaderType *UNUSED(ht))
|
||||
#else
|
||||
static bool buttons_panel_context_poll(const bContext *C, PanelType *UNUSED(pt))
|
||||
#endif
|
||||
{
|
||||
SpaceProperties *sbuts = CTX_wm_space_properties(C);
|
||||
return (sbuts->mainb != BCONTEXT_TOOL);
|
||||
}
|
||||
|
||||
#ifdef USE_HEADER_CONTEXT_PATH
|
||||
static void buttons_header_context_draw(const bContext *C, Header *ptr)
|
||||
#else
|
||||
static void buttons_panel_context_draw(const bContext *C, Panel *ptr)
|
||||
#endif
|
||||
{
|
||||
buttons_context_draw(C, ptr->layout);
|
||||
}
|
||||
|
||||
void buttons_context_register(ARegionType *art)
|
||||
{
|
||||
#ifdef USE_HEADER_CONTEXT_PATH
|
||||
HeaderType *ht;
|
||||
|
||||
ht = MEM_callocN(sizeof(HeaderType), "spacetype buttons context header");
|
||||
strcpy(ht->idname, "BUTTONS_HT_context");
|
||||
ht->space_type = SPACE_PROPERTIES;
|
||||
ht->region_type = art->regionid;
|
||||
ht->poll = buttons_header_context_poll;
|
||||
ht->draw = buttons_header_context_draw;
|
||||
BLI_addtail(&art->headertypes, ht);
|
||||
#else
|
||||
PanelType *pt;
|
||||
|
||||
pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
|
||||
PanelType *pt = MEM_callocN(sizeof(PanelType), "spacetype buttons panel context");
|
||||
strcpy(pt->idname, "BUTTONS_PT_context");
|
||||
strcpy(pt->label, N_("Context")); /* XXX C panels unavailable through RNA bpy.types! */
|
||||
strcpy(pt->translation_context, BLT_I18NCONTEXT_DEFAULT_BPYRNA);
|
||||
@@ -1248,7 +1185,6 @@ void buttons_context_register(ARegionType *art)
|
||||
pt->draw = buttons_panel_context_draw;
|
||||
pt->flag = PNL_NO_HEADER;
|
||||
BLI_addtail(&art->paneltypes, pt);
|
||||
#endif
|
||||
}
|
||||
|
||||
ID *buttons_context_id_path(const bContext *C)
|
||||
|
@@ -37,9 +37,6 @@ struct bNodeTree;
|
||||
struct uiLayout;
|
||||
struct wmOperatorType;
|
||||
|
||||
/* Display the context path in the header instead of the main window */
|
||||
#define USE_HEADER_CONTEXT_PATH
|
||||
|
||||
/* context data */
|
||||
|
||||
typedef struct ButsContextPath {
|
||||
@@ -83,7 +80,6 @@ void buttons_context_compute(const struct bContext *C, struct SpaceProperties *s
|
||||
int buttons_context(const struct bContext *C,
|
||||
const char *member,
|
||||
struct bContextDataResult *result);
|
||||
void buttons_context_draw(const struct bContext *C, struct uiLayout *layout);
|
||||
void buttons_context_register(struct ARegionType *art);
|
||||
struct ID *buttons_context_id_path(const struct bContext *C);
|
||||
|
||||
@@ -93,6 +89,9 @@ extern const char *buttons_context_dir[]; /* doc access */
|
||||
void buttons_texture_context_compute(const struct bContext *C, struct SpaceProperties *sbuts);
|
||||
|
||||
/* buttons_ops.c */
|
||||
void BUTTONS_OT_start_filter(struct wmOperatorType *ot);
|
||||
void BUTTONS_OT_clear_filter(struct wmOperatorType *ot);
|
||||
void BUTTONS_OT_toggle_pin(struct wmOperatorType *ot);
|
||||
void BUTTONS_OT_file_browse(struct wmOperatorType *ot);
|
||||
void BUTTONS_OT_directory_browse(struct wmOperatorType *ot);
|
||||
void BUTTONS_OT_context_menu(struct wmOperatorType *ot);
|
||||
|
@@ -38,6 +38,7 @@
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_main.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
#include "WM_types.h"
|
||||
@@ -52,6 +53,95 @@
|
||||
|
||||
#include "buttons_intern.h" /* own include */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Start / Clear Seach Filter Operators
|
||||
*
|
||||
* \note Almost a duplicate of the file browser operator #FILE_OT_start_filter.
|
||||
* \{ */
|
||||
|
||||
static int buttons_start_filter_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
SpaceProperties *space = CTX_wm_space_properties(C);
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
ARegion *region = BKE_area_find_region_type(area, RGN_TYPE_HEADER);
|
||||
|
||||
ARegion *region_ctx = CTX_wm_region(C);
|
||||
CTX_wm_region_set(C, region);
|
||||
UI_textbutton_activate_rna(C, region, space, "filter_text");
|
||||
CTX_wm_region_set(C, region_ctx);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void BUTTONS_OT_start_filter(struct wmOperatorType *ot)
|
||||
{
|
||||
/* Identifiers. */
|
||||
ot->name = "Filter";
|
||||
ot->description = "Start entering filter text";
|
||||
ot->idname = "BUTTONS_OT_start_filter";
|
||||
|
||||
/* Callbacks. */
|
||||
ot->exec = buttons_start_filter_exec;
|
||||
ot->poll = ED_operator_buttons_active;
|
||||
}
|
||||
|
||||
static int buttons_clear_filter_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
ScrArea *area = CTX_wm_area(C);
|
||||
SpaceProperties *space = CTX_wm_space_properties(C);
|
||||
|
||||
strcpy(space->search_string, "");
|
||||
|
||||
ED_area_tag_redraw(area);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void BUTTONS_OT_clear_filter(struct wmOperatorType *ot)
|
||||
{
|
||||
/* Identifiers. */
|
||||
ot->name = "Clear Filter";
|
||||
ot->description = "Clear the search filter";
|
||||
ot->idname = "BUTTONS_OT_clear_filter";
|
||||
|
||||
/* Callbacks. */
|
||||
ot->exec = buttons_clear_filter_exec;
|
||||
ot->poll = ED_operator_buttons_active;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Pin ID Operator
|
||||
* \{ */
|
||||
|
||||
static int toggle_pin_exec(bContext *C, wmOperator *UNUSED(op))
|
||||
{
|
||||
SpaceProperties *sbuts = CTX_wm_space_properties(C);
|
||||
|
||||
sbuts->pinid = (sbuts->flag & SB_PIN_CONTEXT) ? NULL : buttons_context_id_path(C);
|
||||
|
||||
sbuts->flag ^= SB_PIN_CONTEXT;
|
||||
|
||||
ED_area_tag_redraw(CTX_wm_area(C));
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
void BUTTONS_OT_toggle_pin(wmOperatorType *ot)
|
||||
{
|
||||
/* Identifiers. */
|
||||
ot->name = "Toggle Pin ID";
|
||||
ot->description = "Keep the current data-block displayed";
|
||||
ot->idname = "BUTTONS_OT_toggle_pin";
|
||||
|
||||
/* Callbacks. */
|
||||
ot->exec = toggle_pin_exec;
|
||||
ot->poll = ED_operator_buttons_active;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Context Menu Operator
|
||||
* \{ */
|
||||
|
@@ -48,6 +48,7 @@
|
||||
#include "RNA_define.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "buttons_intern.h" /* own include */
|
||||
@@ -123,6 +124,7 @@ static SpaceLink *buttons_duplicate(SpaceLink *sl)
|
||||
/* clear or remove stuff from old */
|
||||
sbutsn->path = NULL;
|
||||
sbutsn->texuser = NULL;
|
||||
strcpy(sbutsn->search_string, "");
|
||||
|
||||
return (SpaceLink *)sbutsn;
|
||||
}
|
||||
@@ -143,6 +145,7 @@ static void buttons_main_region_init(wmWindowManager *wm, ARegion *region)
|
||||
*
|
||||
* \return The total number of items in the array returned.
|
||||
*/
|
||||
/* HANS-TODO: Use short for this. */
|
||||
int ED_buttons_tabs_list(SpaceProperties *sbuts, int *context_tabs_array)
|
||||
{
|
||||
int length = 0;
|
||||
@@ -297,17 +300,86 @@ static void buttons_main_region_layout_properties(const bContext *C,
|
||||
C, region, ®ion->type->paneltypes, contexts, sbuts->mainb, vertical, NULL);
|
||||
}
|
||||
|
||||
static void buttons_main_region_layout(const bContext *C, ARegion *region)
|
||||
static void main_region_layout(const bContext *C, SpaceProperties *sbuts, ARegion *region)
|
||||
{
|
||||
/* draw entirely, view changes should be handled here */
|
||||
SpaceProperties *sbuts = CTX_wm_space_properties(C);
|
||||
|
||||
if (sbuts->mainb == BCONTEXT_TOOL) {
|
||||
ED_view3d_buttons_region_layout_ex(C, region, "Tool");
|
||||
}
|
||||
else {
|
||||
buttons_main_region_layout_properties(C, sbuts, region);
|
||||
}
|
||||
}
|
||||
|
||||
static void property_search_all_tabs(const bContext *C,
|
||||
SpaceProperties *sbuts,
|
||||
ARegion *main_region)
|
||||
{
|
||||
sbuts->context_search_filter_active = 0;
|
||||
|
||||
/* Duplicate space and region so we don't change any data for this space. */
|
||||
ScrArea *area_copy = MEM_dupallocN(CTX_wm_area(C));
|
||||
ARegion *region_copy = BKE_area_region_copy(CTX_wm_area(C)->type, main_region);
|
||||
BKE_area_region_panels_free(®ion_copy->panels);
|
||||
bContext *C_copy = CTX_copy(C);
|
||||
CTX_wm_area_set(C_copy, area_copy);
|
||||
CTX_wm_region_set(C_copy, region_copy);
|
||||
SpaceProperties *sbuts_copy = MEM_dupallocN(sbuts);
|
||||
|
||||
int context_tabs_array[32];
|
||||
int tabs_tot = ED_buttons_tabs_list(sbuts, context_tabs_array);
|
||||
|
||||
/* Loop through the tabs added to the properties editor. */
|
||||
for (int i = 0; i < tabs_tot; i++) {
|
||||
if (context_tabs_array[i] == -1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Run the layout with this tab set active. */
|
||||
sbuts_copy->mainb = sbuts->mainbo = sbuts_copy->mainbuser = context_tabs_array[i];
|
||||
|
||||
/* Run the layout for the actual region if the tab matches to avoid doing it again later on. */
|
||||
const bool use_actual_region = sbuts->mainb == sbuts_copy->mainb;
|
||||
if (use_actual_region) {
|
||||
main_region_layout(C, sbuts, main_region);
|
||||
}
|
||||
else {
|
||||
main_region_layout(C_copy, sbuts_copy, region_copy);
|
||||
}
|
||||
|
||||
/* Store whether this tab has any unfiltered panels left. */
|
||||
bool has_unfiltered_panel = false;
|
||||
LISTBASE_FOREACH (
|
||||
Panel *, panel, use_actual_region ? &main_region->panels : ®ion_copy->panels) {
|
||||
has_unfiltered_panel |= !UI_panel_is_search_filtered(panel) && UI_panel_is_active(panel);
|
||||
}
|
||||
if (has_unfiltered_panel) {
|
||||
sbuts->context_search_filter_active |= (1 << i);
|
||||
}
|
||||
|
||||
/* Free data created during the layout process. */
|
||||
UI_region_panels_remove_handlers(C_copy, region_copy);
|
||||
BKE_area_region_panels_free(®ion_copy->panels);
|
||||
UI_blocklist_free(C_copy, ®ion_copy->uiblocks);
|
||||
}
|
||||
|
||||
BKE_area_region_free(CTX_wm_area(C_copy)->type, region_copy);
|
||||
MEM_freeN(region_copy);
|
||||
MEM_freeN(sbuts_copy);
|
||||
MEM_freeN(area_copy);
|
||||
MEM_freeN(C_copy);
|
||||
}
|
||||
|
||||
static void buttons_main_region_layout(const bContext *C, ARegion *region)
|
||||
{
|
||||
/* draw entirely, view changes should be handled here */
|
||||
SpaceProperties *sbuts = CTX_wm_space_properties(C);
|
||||
|
||||
if (sbuts->search_string != NULL && sbuts->search_string[0] != '\0') {
|
||||
property_search_all_tabs(C, sbuts, region);
|
||||
}
|
||||
else {
|
||||
main_region_layout(C, sbuts, region);
|
||||
}
|
||||
|
||||
sbuts->mainbo = sbuts->mainb;
|
||||
}
|
||||
@@ -330,6 +402,9 @@ static void buttons_main_region_listener(wmWindow *UNUSED(win),
|
||||
|
||||
static void buttons_operatortypes(void)
|
||||
{
|
||||
WM_operatortype_append(BUTTONS_OT_start_filter);
|
||||
WM_operatortype_append(BUTTONS_OT_clear_filter);
|
||||
WM_operatortype_append(BUTTONS_OT_toggle_pin);
|
||||
WM_operatortype_append(BUTTONS_OT_context_menu);
|
||||
WM_operatortype_append(BUTTONS_OT_file_browse);
|
||||
WM_operatortype_append(BUTTONS_OT_directory_browse);
|
||||
@@ -343,14 +418,6 @@ static void buttons_keymap(struct wmKeyConfig *keyconf)
|
||||
/* add handlers, stuff you only do once or on area/region changes */
|
||||
static void buttons_header_region_init(wmWindowManager *UNUSED(wm), ARegion *region)
|
||||
{
|
||||
#ifdef USE_HEADER_CONTEXT_PATH
|
||||
/* Reinsert context buttons header-type at the end of the list so it's drawn last. */
|
||||
HeaderType *context_ht = BLI_findstring(
|
||||
®ion->type->headertypes, "BUTTONS_HT_context", offsetof(HeaderType, idname));
|
||||
BLI_remlink(®ion->type->headertypes, context_ht);
|
||||
BLI_addtail(®ion->type->headertypes, context_ht);
|
||||
#endif
|
||||
|
||||
ED_region_header_init(region);
|
||||
}
|
||||
|
||||
@@ -390,10 +457,6 @@ static void buttons_header_region_message_subscribe(const bContext *UNUSED(C),
|
||||
if (sbuts->mainb == BCONTEXT_TOOL) {
|
||||
WM_msg_subscribe_rna_anon_prop(mbus, WorkSpace, tools, &msg_sub_value_region_tag_redraw);
|
||||
}
|
||||
|
||||
#ifdef USE_HEADER_CONTEXT_PATH
|
||||
WM_msg_subscribe_rna_anon_prop(mbus, SpaceProperties, context, &msg_sub_value_region_tag_redraw);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void buttons_navigation_bar_region_init(wmWindowManager *wm, ARegion *region)
|
||||
@@ -727,9 +790,7 @@ void ED_spacetype_buttons(void)
|
||||
art->draw = ED_region_panels_draw;
|
||||
art->listener = buttons_main_region_listener;
|
||||
art->keymapflag = ED_KEYMAP_UI | ED_KEYMAP_FRAMES;
|
||||
#ifndef USE_HEADER_CONTEXT_PATH
|
||||
buttons_context_register(art);
|
||||
#endif
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
/* Register the panel types from modifiers. The actual panels are built per modifier rather than
|
||||
@@ -765,9 +826,6 @@ void ED_spacetype_buttons(void)
|
||||
art->init = buttons_header_region_init;
|
||||
art->draw = buttons_header_region_draw;
|
||||
art->message_subscribe = buttons_header_region_message_subscribe;
|
||||
#ifdef USE_HEADER_CONTEXT_PATH
|
||||
buttons_context_register(art);
|
||||
#endif
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
/* regions: navigation bar */
|
||||
|
@@ -423,7 +423,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
|
||||
col = uiLayoutColumn(layout, true);
|
||||
/* keyframe itself */
|
||||
{
|
||||
uiItemL_respect_property_split(col, IFACE_("Key Frame"), ICON_NONE);
|
||||
uiItemL_respect_property_split(col, IFACE_("Key Frame"), ICON_NONE, NULL);
|
||||
but = uiDefButR(block,
|
||||
UI_BTYPE_NUM,
|
||||
B_REDR,
|
||||
@@ -441,7 +441,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
|
||||
-1,
|
||||
NULL);
|
||||
|
||||
uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE);
|
||||
uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE, NULL);
|
||||
but = uiDefButR(block,
|
||||
UI_BTYPE_NUM,
|
||||
B_REDR,
|
||||
@@ -468,7 +468,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
|
||||
if ((prevbezt) && (prevbezt->ipo == BEZT_IPO_BEZ)) {
|
||||
|
||||
col = uiLayoutColumn(layout, true);
|
||||
uiItemL_respect_property_split(col, IFACE_("Left Handle Type"), ICON_NONE);
|
||||
uiItemL_respect_property_split(col, IFACE_("Left Handle Type"), ICON_NONE, NULL);
|
||||
but = uiDefButR(block,
|
||||
UI_BTYPE_MENU,
|
||||
B_REDR,
|
||||
@@ -487,7 +487,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
|
||||
"Type of left handle");
|
||||
UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt);
|
||||
|
||||
uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE);
|
||||
uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE, NULL);
|
||||
but = uiDefButR(block,
|
||||
UI_BTYPE_NUM,
|
||||
B_REDR,
|
||||
@@ -506,7 +506,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
|
||||
NULL);
|
||||
UI_but_func_set(but, graphedit_activekey_left_handle_coord_cb, fcu, bezt);
|
||||
|
||||
uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE);
|
||||
uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE, NULL);
|
||||
but = uiDefButR(block,
|
||||
UI_BTYPE_NUM,
|
||||
B_REDR,
|
||||
@@ -532,7 +532,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
|
||||
/* NOTE: special update callbacks are needed on the coords here due to T39911 */
|
||||
|
||||
col = uiLayoutColumn(layout, true);
|
||||
uiItemL_respect_property_split(col, IFACE_("Right Handle Type"), ICON_NONE);
|
||||
uiItemL_respect_property_split(col, IFACE_("Right Handle Type"), ICON_NONE, NULL);
|
||||
but = uiDefButR(block,
|
||||
UI_BTYPE_MENU,
|
||||
B_REDR,
|
||||
@@ -551,7 +551,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
|
||||
"Type of right handle");
|
||||
UI_but_func_set(but, graphedit_activekey_handles_cb, fcu, bezt);
|
||||
|
||||
uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE);
|
||||
uiItemL_respect_property_split(col, IFACE_("Frame"), ICON_NONE, NULL);
|
||||
but = uiDefButR(block,
|
||||
UI_BTYPE_NUM,
|
||||
B_REDR,
|
||||
@@ -570,7 +570,7 @@ static void graph_panel_key_properties(const bContext *C, Panel *panel)
|
||||
NULL);
|
||||
UI_but_func_set(but, graphedit_activekey_right_handle_coord_cb, fcu, bezt);
|
||||
|
||||
uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE);
|
||||
uiItemL_respect_property_split(col, IFACE_("Value"), ICON_NONE, NULL);
|
||||
but = uiDefButR(block,
|
||||
UI_BTYPE_NUM,
|
||||
B_REDR,
|
||||
|
@@ -147,9 +147,12 @@ typedef struct SpaceProperties {
|
||||
|
||||
/** Context tabs. */
|
||||
short mainb, mainbo, mainbuser;
|
||||
/** Bitfield flag (in the same order as the tabs) for whether each tab has properties
|
||||
* that match the search filter. Only valid when #search_string is set. */
|
||||
int context_search_filter_active;
|
||||
/** Preview is signal to refresh. */
|
||||
short preview;
|
||||
char _pad[5];
|
||||
char _pad[1];
|
||||
char flag;
|
||||
|
||||
/** Runtime. */
|
||||
@@ -158,6 +161,9 @@ typedef struct SpaceProperties {
|
||||
int pathflag, dataicon;
|
||||
ID *pinid;
|
||||
|
||||
/** For filtering properties displayed in the space. */
|
||||
char search_string[64];
|
||||
|
||||
void *texuser;
|
||||
} SpaceProperties;
|
||||
|
||||
|
@@ -4469,6 +4469,22 @@ static void rna_def_space_properties(BlenderRNA *brna)
|
||||
prop = RNA_def_property(srna, "use_pin_id", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", SB_PIN_CONTEXT);
|
||||
RNA_def_property_ui_text(prop, "Pin ID", "Use the pinned context");
|
||||
|
||||
/* Property search. */
|
||||
prop = RNA_def_property(srna, "context_search_filter_active", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_items(prop, buttons_context_items);
|
||||
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
|
||||
RNA_def_property_enum_funcs(
|
||||
prop, NULL, "rna_SpaceProperties_context_set", "rna_SpaceProperties_context_itemf");
|
||||
RNA_def_property_ui_text(prop, "", "");
|
||||
RNA_def_property_update(
|
||||
prop, NC_SPACE | ND_SPACE_PROPERTIES, "rna_SpaceProperties_context_update");
|
||||
|
||||
prop = RNA_def_property(srna, "filter_text", PROP_STRING, PROP_NONE);
|
||||
RNA_def_property_string_sdna(prop, NULL, "search_string");
|
||||
RNA_def_property_ui_text(prop, "Display Filter", "Live search filtering string");
|
||||
RNA_def_property_flag(prop, PROP_TEXTEDIT_UPDATE);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_PROPERTIES, NULL);
|
||||
}
|
||||
|
||||
static void rna_def_space_image(BlenderRNA *brna)
|
||||
|
@@ -1151,6 +1151,16 @@ static void rna_UILayout_property_decorate_set(PointerRNA *ptr, bool value)
|
||||
uiLayoutSetPropDecorate(ptr->data, value);
|
||||
}
|
||||
|
||||
static bool rna_UILayout_property_search_get(PointerRNA *ptr)
|
||||
{
|
||||
return uiLayoutGetPropSearch(ptr->data);
|
||||
}
|
||||
|
||||
static void rna_UILayout_property_search_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
uiLayoutSetPropSearch(ptr->data, value);
|
||||
}
|
||||
|
||||
#else /* RNA_RUNTIME */
|
||||
|
||||
static void rna_def_ui_layout(BlenderRNA *brna)
|
||||
@@ -1267,6 +1277,12 @@ static void rna_def_ui_layout(BlenderRNA *brna)
|
||||
prop = RNA_def_property(srna, "use_property_decorate", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(
|
||||
prop, "rna_UILayout_property_decorate_get", "rna_UILayout_property_decorate_set");
|
||||
|
||||
prop = RNA_def_property(srna, "use_property_search", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(
|
||||
prop, "rna_UILayout_property_search_get", "rna_UILayout_property_search_set");
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Use Property Search", "Whether to use the region's property search if available");
|
||||
}
|
||||
|
||||
static void rna_def_panel(BlenderRNA *brna)
|
||||
|
@@ -216,8 +216,13 @@ static void rna_uiItemMenuEnumR(uiLayout *layout,
|
||||
uiItemMenuEnumR_prop(layout, ptr, prop, name, icon);
|
||||
}
|
||||
|
||||
static void rna_uiItemTabsEnumR(
|
||||
uiLayout *layout, bContext *C, struct PointerRNA *ptr, const char *propname, bool icon_only)
|
||||
static void rna_uiItemTabsEnumR(uiLayout *layout,
|
||||
bContext *C,
|
||||
struct PointerRNA *ptr,
|
||||
const char *propname,
|
||||
struct PointerRNA *ptr_highlight,
|
||||
const char *propname_highlight,
|
||||
bool icon_only)
|
||||
{
|
||||
PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
|
||||
|
||||
@@ -230,7 +235,31 @@ static void rna_uiItemTabsEnumR(
|
||||
return;
|
||||
}
|
||||
|
||||
uiItemTabsEnumR_prop(layout, C, ptr, prop, icon_only);
|
||||
/* Get the highlight property used to gray out some of the tabs. */
|
||||
PropertyRNA *prop_highlight = NULL;
|
||||
if (!RNA_pointer_is_null(ptr_highlight)) {
|
||||
prop_highlight = RNA_struct_find_property(ptr_highlight, propname_highlight);
|
||||
if (!prop_highlight) {
|
||||
RNA_warning("property not found: %s.%s",
|
||||
RNA_struct_identifier(ptr_highlight->type),
|
||||
propname_highlight);
|
||||
return;
|
||||
}
|
||||
if (RNA_property_type(prop_highlight) != PROP_ENUM) {
|
||||
RNA_warning("property is not an enum: %s.%s",
|
||||
RNA_struct_identifier(ptr_highlight->type),
|
||||
propname_highlight);
|
||||
return;
|
||||
}
|
||||
if (!(RNA_property_flag(prop_highlight) & PROP_ENUM_FLAG)) {
|
||||
RNA_warning("property must be a bitfield enum: %s.%s",
|
||||
RNA_struct_identifier(ptr_highlight->type),
|
||||
propname_highlight);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uiItemTabsEnumR_prop(layout, C, ptr, prop, ptr_highlight, prop_highlight, icon_only);
|
||||
}
|
||||
|
||||
static void rna_uiItemEnumR_string(uiLayout *layout,
|
||||
@@ -920,6 +949,11 @@ void RNA_api_ui_layout(StructRNA *srna)
|
||||
func = RNA_def_function(srna, "prop_tabs_enum", "rna_uiItemTabsEnumR");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
api_ui_item_rna_common(func);
|
||||
parm = RNA_def_pointer(
|
||||
func, "data_highlight", "AnyType", "", "Data from which to take highlight property");
|
||||
RNA_def_parameter_flags(parm, PROP_NEVER_NULL, PARM_RNAPTR);
|
||||
parm = RNA_def_string(
|
||||
func, "property_highlight", NULL, 0, "", "Identifier of highlight property in data");
|
||||
RNA_def_boolean(func, "icon_only", false, "", "Draw only icons in tabs, no text");
|
||||
|
||||
func = RNA_def_function(srna, "prop_enum", "rna_uiItemEnumR_string");
|
||||
|
Reference in New Issue
Block a user