UI: Asset Shelf (Experimental Feature) #104831

Closed
Julian Eisel wants to merge 399 commits from asset-shelf into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
7 changed files with 122 additions and 43 deletions
Showing only changes of commit d5c60f912f - Show all commits

View File

@ -104,9 +104,23 @@ static void asset_shelf_settings_clear_enabled_catalogs(AssetShelfSettings &shel
BLI_assert(BLI_listbase_is_empty(&shelf_settings.enabled_catalog_paths));
}
static void asset_shelf_settings_set_active_catalog(AssetShelfSettings &shelf_settings,
const asset_system::AssetCatalogPath &path)
{
MEM_delete(shelf_settings.active_catalog_path);
shelf_settings.active_catalog_path = BLI_strdupn(path.c_str(), path.length());
}
static bool asset_shelf_settings_is_active_catalog(const AssetShelfSettings &shelf_settings,
const asset_system::AssetCatalogPath &path)
{
return shelf_settings.active_catalog_path && shelf_settings.active_catalog_path == path.str();
}
void ED_asset_shelf_settings_free(AssetShelfSettings *shelf_settings)
{
asset_shelf_settings_clear_enabled_catalogs(*shelf_settings);
MEM_delete(shelf_settings->active_catalog_path);
}
void ED_asset_shelf_settings_blend_write(BlendWriter *writer,
@ -373,6 +387,50 @@ static uiBlock *asset_shelf_catalog_selector_block_draw(bContext *C,
/** \} */
/* -------------------------------------------------------------------- */
/** \name Catalog toggle buttons
* \{ */
static void add_catalog_toggle_buttons(AssetShelfSettings &shelf_settings, uiLayout &layout)
{
uiBlock *block = uiLayoutGetBlock(&layout);
const uiStyle *style = UI_style_get_dpi();
asset_shelf_settings_foreach_enabled_catalog_path(
shelf_settings, [&shelf_settings, block, style](const asset_system::AssetCatalogPath &path) {
const char *name = path.name().c_str();
const int string_width = UI_fontstyle_string_width(&style->widget, name);
const int pad_x = UI_UNIT_X * 0.3f;
const int but_width = std::min(string_width + 2 * pad_x, UI_UNIT_X * 8);
uiBut *but = uiDefBut(
block,
UI_BTYPE_TAB,
0,
name,
0,
0,
but_width,
UI_UNIT_Y,
nullptr,
0,
0,
0,
0,
"Enable catalog, making contained assets visible in the asset shelf");
UI_but_drawflag_enable(but, UI_BUT_ALIGN_TOP);
UI_but_func_set(but, [&shelf_settings, path](bContext &) {
asset_shelf_settings_set_active_catalog(shelf_settings, path);
});
UI_but_func_pushed_state_set(but, [&shelf_settings, path](const uiBut &) -> bool {
return asset_shelf_settings_is_active_catalog(shelf_settings, path);
});
});
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Asset Shelf Footer
*
@ -399,10 +457,7 @@ static void asset_shelf_footer_draw(const bContext *C, Header *header)
AssetShelfSettings *shelf_settings = get_asset_shelf_settings_from_context(C);
if (shelf_settings) {
asset_shelf_settings_foreach_enabled_catalog_path(
*shelf_settings, [layout](const asset_system::AssetCatalogPath &path) {
uiItemL(layout, path.name().c_str(), ICON_NONE);
});
add_catalog_toggle_buttons(*shelf_settings, *layout);
}
}

View File

@ -1748,8 +1748,6 @@ void UI_but_focus_on_enter_event(struct wmWindow *win, uiBut *but);
void UI_but_func_hold_set(uiBut *but, uiButHandleHoldFunc func, void *argN);
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, const void *arg);
struct PointerRNA *UI_but_extra_operator_icon_add(uiBut *but,
const char *opname,
wmOperatorCallContext opcontext,

View File

@ -17,6 +17,7 @@ namespace blender::nodes::geo_eval_log {
struct GeometryAttributeInfo;
}
struct bContext;
struct StructRNA;
struct uiBlock;
struct uiBut;
@ -54,6 +55,9 @@ void attribute_search_add_items(StringRefNull str,
} // namespace blender::ui
void UI_but_func_set(uiBut *but, std::function<void(bContext &)> func);
void UI_but_func_pushed_state_set(uiBut *but, std::function<bool(const uiBut &)> func);
/**
* Override this for all available view types.
*/

View File

@ -51,6 +51,7 @@
#include "BLT_translation.h"
#include "UI_interface.h"
#include "UI_interface.hh"
#include "UI_interface_icons.h"
#include "UI_view2d.h"
@ -749,6 +750,10 @@ static bool ui_but_equals_old(const uiBut *but, const uiBut *oldbut)
if (but->func != oldbut->func) {
return false;
}
if (but->apply_func.target<void(bContext &)>() !=
oldbut->apply_func.target<void(bContext &)>()) {
return false;
}
if (but->funcN != oldbut->funcN) {
return false;
}
@ -2181,7 +2186,7 @@ int ui_but_is_pushed_ex(uiBut *but, double *value)
{
int is_push = 0;
if (but->pushed_state_func) {
return but->pushed_state_func(but, but->pushed_state_arg);
return but->pushed_state_func(*but);
}
if (but->bit) {
@ -6001,6 +6006,11 @@ void UI_but_func_set(uiBut *but, uiButHandleFunc func, void *arg1, void *arg2)
but->func_arg2 = arg2;
}
void UI_but_func_set(uiBut *but, std::function<void(bContext &)> func)
{
but->apply_func = func;
}
void UI_but_funcN_set(uiBut *but, uiButHandleNFunc funcN, void *argN, void *arg2)
{
if (but->func_argN) {
@ -6033,10 +6043,9 @@ void UI_but_func_tooltip_set(uiBut *but, uiButToolTipFunc func, void *arg, uiFre
but->tip_arg_free = free_arg;
}
void UI_but_func_pushed_state_set(uiBut *but, uiButPushedStateFunc func, const void *arg)
void UI_but_func_pushed_state_set(uiBut *but, std::function<bool(const uiBut &)> func)
{
but->pushed_state_func = func;
but->pushed_state_arg = arg;
ui_but_update(but);
}

View File

@ -457,45 +457,47 @@ struct uiHandleButtonData {
};
struct uiAfterFunc {
uiAfterFunc *next, *prev;
uiAfterFunc *next = nullptr, *prev = nullptr;
uiButHandleFunc func;
void *func_arg1;
void *func_arg2;
uiButHandleFunc func = nullptr;
void *func_arg1 = nullptr;
void *func_arg2 = nullptr;
/** C++ version of #func above, without need for void pointer arguments. */
std::function<void(bContext &)> apply_func;
uiButHandleNFunc funcN;
void *func_argN;
uiButHandleNFunc funcN = nullptr;
void *func_argN = nullptr;
uiButHandleRenameFunc rename_func;
void *rename_arg1;
void *rename_orig;
uiButHandleRenameFunc rename_func = nullptr;
void *rename_arg1 = nullptr;
void *rename_orig = nullptr;
uiBlockHandleFunc handle_func;
void *handle_func_arg;
int retval;
uiBlockHandleFunc handle_func = nullptr;
void *handle_func_arg = nullptr;
int retval = 0;
uiMenuHandleFunc butm_func;
void *butm_func_arg;
int a2;
uiMenuHandleFunc butm_func = nullptr;
void *butm_func_arg = nullptr;
int a2 = 0;
wmOperator *popup_op;
wmOperatorType *optype;
wmOperator *popup_op = nullptr;
wmOperatorType *optype = nullptr;
wmOperatorCallContext opcontext;
PointerRNA *opptr;
PointerRNA *opptr = nullptr;
PointerRNA rnapoin;
PropertyRNA *rnaprop;
PointerRNA rnapoin = {};
PropertyRNA *rnaprop = nullptr;
void *search_arg;
uiFreeArgFunc search_arg_free_fn;
void *search_arg = nullptr;
uiFreeArgFunc search_arg_free_fn = nullptr;
uiBlockInteraction_CallbackData custom_interaction_callbacks;
uiBlockInteraction_Handle *custom_interaction_handle;
uiBlockInteraction_CallbackData custom_interaction_callbacks = {};
uiBlockInteraction_Handle *custom_interaction_handle = nullptr;
bContextStore *context;
bContextStore *context = nullptr;
char undostr[BKE_UNDO_STR_MAX];
char drawstr[UI_MAX_DRAW_STR];
char undostr[BKE_UNDO_STR_MAX] = "";
char drawstr[UI_MAX_DRAW_STR] = "";
};
static void button_activate_init(bContext *C,
@ -743,7 +745,7 @@ static ListBase UIAfterFuncs = {nullptr, nullptr};
static uiAfterFunc *ui_afterfunc_new()
{
uiAfterFunc *after = MEM_cnew<uiAfterFunc>(__func__);
uiAfterFunc *after = MEM_new<uiAfterFunc>(__func__);
BLI_addtail(&UIAfterFuncs, after);
@ -800,8 +802,9 @@ static void popup_check(bContext *C, wmOperator *op)
*/
static bool ui_afterfunc_check(const uiBlock *block, const uiBut *but)
{
return (but->func || but->funcN || but->rename_func || but->optype || but->rnaprop ||
block->handle_func || (but->type == UI_BTYPE_BUT_MENU && block->butm_func) ||
return (but->func || but->apply_func || but->funcN || but->rename_func || but->optype ||
but->rnaprop || block->handle_func ||
(but->type == UI_BTYPE_BUT_MENU && block->butm_func) ||
(block->handle && block->handle->popup_op));
}
@ -826,10 +829,11 @@ static void ui_apply_but_func(bContext *C, uiBut *but)
else {
after->func = but->func;
}
after->func_arg1 = but->func_arg1;
after->func_arg2 = but->func_arg2;
after->apply_func = but->apply_func;
after->funcN = but->funcN;
after->func_argN = (but->func_argN) ? MEM_dupallocN(but->func_argN) : nullptr;
@ -998,7 +1002,8 @@ static void ui_apply_but_funcs_after(bContext *C)
LISTBASE_FOREACH_MUTABLE (uiAfterFunc *, afterf, &funcs) {
uiAfterFunc after = *afterf; /* Copy to avoid memory leak on exit(). */
BLI_freelinkN(&funcs, afterf);
BLI_remlink(&funcs, afterf);
MEM_delete(afterf);
if (after.context) {
CTX_store_set(C, after.context);
@ -1040,6 +1045,9 @@ static void ui_apply_but_funcs_after(bContext *C)
if (after.func) {
after.func(C, after.func_arg1, after.func_arg2);
}
if (after.apply_func) {
after.apply_func(*C);
}
if (after.funcN) {
after.funcN(C, after.func_argN, after.func_arg2);
}

View File

@ -7,6 +7,8 @@
#pragma once
#include <functional>
#include "BLI_compiler_attrs.h"
#include "BLI_rect.h"
#include "BLI_vector.hh"
@ -199,6 +201,9 @@ struct uiBut {
uiButHandleFunc func = nullptr;
void *func_arg1 = nullptr;
void *func_arg2 = nullptr;
/** C++ version of #func above. Allows storing arbitrary data in a type safe way, no void
* pointer arguments.*/
std::function<void(bContext &)> apply_func;
uiButHandleNFunc funcN = nullptr;
void *func_argN = nullptr;
@ -275,8 +280,7 @@ struct uiBut {
double *editval = nullptr;
float *editvec = nullptr;
uiButPushedStateFunc pushed_state_func = nullptr;
const void *pushed_state_arg = nullptr;
std::function<bool(const uiBut &)> pushed_state_func;
/** Little indicator (e.g., counter) displayed on top of some icons. */
IconTextOverlay icon_overlay_text = {};

View File

@ -749,6 +749,7 @@ enum {
typedef struct AssetShelfSettings {
/* TODO make this per mode? (or use a custom identifier?) */
ListBase enabled_catalog_paths; /* #LinkData */
const char *active_catalog_path;
} AssetShelfSettings;
#ifdef __cplusplus