Cleanup: Use Vector instead of linked list for data-block sorting utility

This commit is contained in:
Hans Goudey
2024-02-22 15:34:21 -05:00
parent 01dc67dcc9
commit fdc367f842
5 changed files with 49 additions and 66 deletions

View File

@@ -31,9 +31,9 @@
*/
#include "BLI_compiler_attrs.h"
#include "BLI_utildefines.h"
#include "BLI_set.hh"
#include "BLI_utildefines.h"
#include "BLI_vector.hh"
#include "DNA_userdef_enums.h"
@@ -662,9 +662,8 @@ bool BKE_id_is_editable(const Main *bmain, const ID *id);
/**
* Returns ordered list of data-blocks for display in the UI.
* Result is list of #LinkData of IDs that must be freed.
*/
void BKE_id_ordered_list(ListBase *ordered_lb, const ListBase *lb);
blender::Vector<ID *> BKE_id_ordered_list(const ListBase *lb);
/**
* Reorder ID in the list, before or after the "relative" ID.
*/

View File

@@ -77,6 +77,8 @@
# include "BLI_time_utildefines.h"
#endif
using blender::Vector;
using namespace blender::bke::id;
static CLG_LogRef LOG = {"bke.lib_id"};
@@ -2165,43 +2167,40 @@ static int *id_order_get(ID *id)
}
}
static int id_order_compare(const void *a, const void *b)
static bool id_order_compare(ID *a, ID *b)
{
ID *id_a = static_cast<ID *>(((LinkData *)a)->data);
ID *id_b = static_cast<ID *>(((LinkData *)b)->data);
int *order_a = id_order_get(id_a);
int *order_b = id_order_get(id_b);
int *order_a = id_order_get(a);
int *order_b = id_order_get(b);
if (order_a && order_b) {
if (*order_a < *order_b) {
return -1;
return true;
}
if (*order_a > *order_b) {
return 1;
return false;
}
}
return strcmp(id_a->name, id_b->name);
return strcmp(a->name, b->name) <= 0;
}
void BKE_id_ordered_list(ListBase *ordered_lb, const ListBase *lb)
Vector<ID *> BKE_id_ordered_list(const ListBase *lb)
{
BLI_listbase_clear(ordered_lb);
Vector<ID *> ordered;
LISTBASE_FOREACH (ID *, id, lb) {
BLI_addtail(ordered_lb, BLI_genericNodeN(id));
ordered.append(id);
}
BLI_listbase_sort(ordered_lb, id_order_compare);
std::sort(ordered.begin(), ordered.end(), id_order_compare);
int num = 0;
LISTBASE_FOREACH (LinkData *, link, ordered_lb) {
int *order = id_order_get(static_cast<ID *>(link->data));
if (order) {
*order = num++;
for (const int i : ordered.index_range()) {
if (int *order = id_order_get(ordered[i])) {
*order = i;
}
}
return ordered;
}
void BKE_id_reorder(const ListBase *lb, ID *id, ID *relative, bool after)

View File

@@ -97,6 +97,8 @@
#include "UI_string_search.hh"
#include "interface_intern.hh"
using blender::Vector;
/* we may want to make this optional, disable for now. */
// #define USE_OP_RESET_BUT
@@ -1659,11 +1661,7 @@ static void template_ID_tabs(const bContext *C,
uiBlock *block = uiLayoutGetBlock(layout);
const uiStyle *style = UI_style_get_dpi();
ListBase ordered;
BKE_id_ordered_list(&ordered, template_id->idlb);
LISTBASE_FOREACH (LinkData *, link, &ordered) {
ID *id = static_cast<ID *>(link->data);
for (ID *id : BKE_id_ordered_list(template_id->idlb)) {
const int name_width = UI_fontstyle_string_width(&style->widget, id->name + 2);
const int but_width = name_width + UI_UNIT_X;
@@ -1689,8 +1687,6 @@ static void template_ID_tabs(const bContext *C,
UI_but_drawflag_enable(tab, but_align);
}
BLI_freelistN(&ordered);
if (flag & UI_ID_ADD_NEW) {
const bool editable = RNA_property_editable(&template_id->ptr, template_id->prop);
uiBut *but;

View File

@@ -76,6 +76,8 @@
#include "screen_intern.h" /* own module include */
using blender::Vector;
#define KM_MODAL_CANCEL 1
#define KM_MODAL_APPLY 2
#define KM_MODAL_SNAP_ON 3
@@ -5788,34 +5790,26 @@ static int space_workspace_cycle_invoke(bContext *C, wmOperator *op, const wmEve
Main *bmain = CTX_data_main(C);
const eScreenCycle direction = eScreenCycle(RNA_enum_get(op->ptr, "direction"));
WorkSpace *workspace_src = WM_window_get_active_workspace(win);
WorkSpace *workspace_dst = nullptr;
ListBase ordered;
BKE_id_ordered_list(&ordered, &bmain->workspaces);
LISTBASE_FOREACH (LinkData *, link, &ordered) {
if (link->data == workspace_src) {
if (direction == SPACE_CONTEXT_CYCLE_PREV) {
workspace_dst = static_cast<WorkSpace *>((link->prev) ? link->prev->data : nullptr);
}
else {
workspace_dst = static_cast<WorkSpace *>((link->next) ? link->next->data : nullptr);
}
}
}
if (workspace_dst == nullptr) {
LinkData *link = static_cast<LinkData *>(
(direction == SPACE_CONTEXT_CYCLE_PREV) ? ordered.last : ordered.first);
workspace_dst = static_cast<WorkSpace *>(link->data);
}
BLI_freelistN(&ordered);
if (workspace_src == workspace_dst) {
Vector<ID *> ordered = BKE_id_ordered_list(&bmain->workspaces);
if (ordered.size() == 1) {
return OPERATOR_CANCELLED;
}
const int index = ordered.first_index_of(&workspace_src->id);
WorkSpace *workspace_dst = nullptr;
switch (direction) {
case SPACE_CONTEXT_CYCLE_PREV:
workspace_dst = reinterpret_cast<WorkSpace *>(index == 0 ? ordered.last() :
ordered[index - 1]);
break;
case SPACE_CONTEXT_CYCLE_NEXT:
workspace_dst = reinterpret_cast<WorkSpace *>(
index == ordered.index_range().last() ? ordered.first() : ordered[index + 1]);
break;
}
win->workspace_hook->temp_workspace_store = workspace_dst;
WM_event_add_notifier(C, NC_SCREEN | ND_WORKSPACE_SET, workspace_dst);
win->workspace_hook->temp_workspace_store = nullptr;

View File

@@ -45,6 +45,8 @@
#include "screen_intern.h"
using blender::Vector;
/* -------------------------------------------------------------------- */
/** \name Workspace API
*
@@ -242,23 +244,16 @@ bool ED_workspace_delete(WorkSpace *workspace, Main *bmain, bContext *C, wmWindo
return false;
}
ListBase ordered;
BKE_id_ordered_list(&ordered, &bmain->workspaces);
WorkSpace *prev = nullptr, *next = nullptr;
LISTBASE_FOREACH (LinkData *, link, &ordered) {
if (link->data == workspace) {
prev = static_cast<WorkSpace *>(link->prev ? link->prev->data : nullptr);
next = static_cast<WorkSpace *>(link->next ? link->next->data : nullptr);
break;
}
}
BLI_freelistN(&ordered);
BLI_assert((prev != nullptr) || (next != nullptr));
Vector<ID *> ordered = BKE_id_ordered_list(&bmain->workspaces);
const int index = ordered.first_index_of(&workspace->id);
WorkSpace *new_active = reinterpret_cast<WorkSpace *>(index == 0 ? ordered[1] :
ordered[index - 1]);
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
WorkSpace *workspace_active = WM_window_get_active_workspace(win);
if (workspace_active == workspace) {
ED_workspace_change((prev != nullptr) ? prev : next, C, wm, win);
ED_workspace_change(new_active, C, wm, win);
}
}