UI: Use a map for block name lookups
Use a map to speed up search for UI block names. Time to redraw the node editor was decreased from around 75-120ms to 40-70ms in a tree with many Geometry Nodes. Differential Revision: https://developer.blender.org/D13225
This commit is contained in:
parent
55c82d8380
commit
0129178376
Notes:
blender-bot
2023-02-14 10:14:07 +01:00
Referenced by issue #93523, Not freed memory blocks in Menu Search
|
@ -731,8 +731,8 @@ 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);
|
||||
void UI_blocklist_free_inactive(const struct bContext *C, struct ListBase *lb);
|
||||
void UI_blocklist_free(const struct bContext *C, struct ARegion *region);
|
||||
void UI_blocklist_free_inactive(const struct bContext *C, struct ARegion *region);
|
||||
void UI_screen_free_active_but(const struct bContext *C, struct bScreen *screen);
|
||||
|
||||
void UI_block_region_set(uiBlock *block, struct ARegion *region);
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "DNA_workspace_types.h"
|
||||
|
||||
#include "BLI_alloca.h"
|
||||
#include "BLI_ghash.h"
|
||||
#include "BLI_listbase.h"
|
||||
#include "BLI_math.h"
|
||||
#include "BLI_rect.h"
|
||||
|
@ -3521,22 +3522,35 @@ void UI_blocklist_draw(const bContext *C, const ListBase *lb)
|
|||
}
|
||||
|
||||
/* can be called with C==NULL */
|
||||
void UI_blocklist_free(const bContext *C, ListBase *lb)
|
||||
void UI_blocklist_free(const bContext *C, ARegion *region)
|
||||
{
|
||||
ListBase *lb = ®ion->uiblocks;
|
||||
uiBlock *block;
|
||||
while ((block = BLI_pophead(lb))) {
|
||||
UI_block_free(C, block);
|
||||
}
|
||||
if (region->runtime.block_name_map != NULL) {
|
||||
BLI_ghash_free(region->runtime.block_name_map, NULL, NULL);
|
||||
region->runtime.block_name_map = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void UI_blocklist_free_inactive(const bContext *C, ListBase *lb)
|
||||
void UI_blocklist_free_inactive(const bContext *C, ARegion *region)
|
||||
{
|
||||
ListBase *lb = ®ion->uiblocks;
|
||||
|
||||
LISTBASE_FOREACH_MUTABLE (uiBlock *, block, lb) {
|
||||
if (!block->handle) {
|
||||
if (block->active) {
|
||||
block->active = false;
|
||||
}
|
||||
else {
|
||||
if (region->runtime.block_name_map != NULL) {
|
||||
uiBlock *b = BLI_ghash_lookup(region->runtime.block_name_map, block->name);
|
||||
if (b == block) {
|
||||
BLI_ghash_remove(region->runtime.block_name_map, b->name, NULL, NULL);
|
||||
}
|
||||
}
|
||||
BLI_remlink(lb, block);
|
||||
UI_block_free(C, block);
|
||||
}
|
||||
|
@ -3552,7 +3566,10 @@ void UI_block_region_set(uiBlock *block, ARegion *region)
|
|||
/* each listbase only has one block with this name, free block
|
||||
* if is already there so it can be rebuilt from scratch */
|
||||
if (lb) {
|
||||
oldblock = BLI_findstring(lb, block->name, offsetof(uiBlock, name));
|
||||
if (region->runtime.block_name_map == NULL) {
|
||||
region->runtime.block_name_map = BLI_ghash_str_new(__func__);
|
||||
}
|
||||
oldblock = (uiBlock *)BLI_ghash_lookup(region->runtime.block_name_map, block->name);
|
||||
|
||||
if (oldblock) {
|
||||
oldblock->active = false;
|
||||
|
@ -3562,6 +3579,7 @@ void UI_block_region_set(uiBlock *block, ARegion *region)
|
|||
|
||||
/* at the beginning of the list! for dynamical menus/blocks */
|
||||
BLI_addhead(lb, block);
|
||||
BLI_ghash_reinsert(region->runtime.block_name_map, block->name, block, NULL, NULL);
|
||||
}
|
||||
|
||||
block->oldblock = oldblock;
|
||||
|
|
|
@ -11340,8 +11340,7 @@ static void ui_region_handler_remove(bContext *C, void *UNUSED(userdata))
|
|||
return;
|
||||
}
|
||||
|
||||
UI_blocklist_free(C, ®ion->uiblocks);
|
||||
|
||||
UI_blocklist_free(C, region);
|
||||
bScreen *screen = CTX_wm_screen(C);
|
||||
if (screen == NULL) {
|
||||
return;
|
||||
|
|
|
@ -743,7 +743,7 @@ uiBlock *ui_popup_block_refresh(bContext *C,
|
|||
if (block_old) {
|
||||
block->oldblock = block_old;
|
||||
UI_block_update_from_old(C, block);
|
||||
UI_blocklist_free_inactive(C, ®ion->uiblocks);
|
||||
UI_blocklist_free_inactive(C, region);
|
||||
}
|
||||
|
||||
/* checks which buttons are visible, sets flags to prevent draw (do after region init) */
|
||||
|
|
|
@ -787,12 +787,14 @@ static MenuSearch_Data *menu_items_from_ui_create(
|
|||
}
|
||||
|
||||
if (region) {
|
||||
BLI_ghash_remove(region->runtime.block_name_map, sub_block->name, NULL, NULL);
|
||||
BLI_remlink(®ion->uiblocks, sub_block);
|
||||
}
|
||||
UI_block_free(nullptr, sub_block);
|
||||
}
|
||||
}
|
||||
if (region) {
|
||||
BLI_ghash_remove(region->runtime.block_name_map, block->name, NULL, NULL);
|
||||
BLI_remlink(®ion->uiblocks, block);
|
||||
}
|
||||
UI_block_free(nullptr, block);
|
||||
|
|
|
@ -594,7 +594,7 @@ void ED_region_do_draw(bContext *C, ARegion *region)
|
|||
|
||||
memset(®ion->drawrct, 0, sizeof(region->drawrct));
|
||||
|
||||
UI_blocklist_free_inactive(C, ®ion->uiblocks);
|
||||
UI_blocklist_free_inactive(C, region);
|
||||
|
||||
if (area) {
|
||||
const bScreen *screen = WM_window_get_active_screen(win);
|
||||
|
@ -1985,7 +1985,7 @@ void ED_area_init(wmWindowManager *wm, wmWindow *win, ScrArea *area)
|
|||
}
|
||||
else {
|
||||
/* prevent uiblocks to run */
|
||||
UI_blocklist_free(NULL, ®ion->uiblocks);
|
||||
UI_blocklist_free(NULL, region);
|
||||
}
|
||||
|
||||
/* Some AZones use View2D data which is only updated in region init, so call that first! */
|
||||
|
@ -3323,7 +3323,7 @@ bool ED_region_property_search(const bContext *C,
|
|||
}
|
||||
|
||||
/* Free the panels and blocks, as they are only used for search. */
|
||||
UI_blocklist_free(C, ®ion->uiblocks);
|
||||
UI_blocklist_free(C, region);
|
||||
UI_panels_free_instanced(C, region);
|
||||
BKE_area_region_panels_free(®ion->panels);
|
||||
|
||||
|
|
|
@ -1495,8 +1495,7 @@ ScrArea *ED_screen_state_toggle(bContext *C, wmWindow *win, ScrArea *area, const
|
|||
* switching screens with tooltip open because region and tooltip
|
||||
* are no longer in the same screen */
|
||||
LISTBASE_FOREACH (ARegion *, region, &area->regionbase) {
|
||||
UI_blocklist_free(C, ®ion->uiblocks);
|
||||
|
||||
UI_blocklist_free(C, region);
|
||||
if (region->regiontimer) {
|
||||
WM_event_remove_timer(wm, NULL, region->regiontimer);
|
||||
region->regiontimer = NULL;
|
||||
|
|
|
@ -445,7 +445,7 @@ static void property_search_all_tabs(const bContext *C,
|
|||
i,
|
||||
property_search_for_context(C, region_copy, &sbuts_copy));
|
||||
|
||||
UI_blocklist_free(C, ®ion_copy->uiblocks);
|
||||
UI_blocklist_free(C, region_copy);
|
||||
}
|
||||
|
||||
BKE_area_region_free(area_copy.type, region_copy);
|
||||
|
|
|
@ -458,6 +458,9 @@ typedef struct ARegion_Runtime {
|
|||
|
||||
/* The offset needed to not overlap with window scrollbars. Only used by HUD regions for now. */
|
||||
int offset_x, offset_y;
|
||||
|
||||
/* Maps uiBlock->name to uiBlock for faster lookups. */
|
||||
struct GHash *block_name_map;
|
||||
} ARegion_Runtime;
|
||||
|
||||
typedef struct ARegion {
|
||||
|
|
Loading…
Reference in New Issue