Brush Assets: Support adding shortcut to asset shelf items #117861

Merged
Hans Goudey merged 15 commits from HooglyBoogly/blender:brush-assets-shortcut into brush-assets-project 2024-02-07 19:02:47 +01:00
10 changed files with 102 additions and 49 deletions

View File

@ -6802,21 +6802,6 @@ def km_node_link_modal_map(_params):
return keymap
def km_asset_shelf_brushes(_params):
items = []
keymap = (
"Asset Shelf",
{"space_type": 'EMPTY', "region_type": 'WINDOW'},
{"items": items},
)
items.extend([
("brush.asset_select", {"type": 'LEFTMOUSE', "value": 'CLICK'}, None),
])
return keymap
# Fallback for gizmos that don't have custom a custom key-map.
def km_generic_gizmo(_params):
keymap = (
@ -8652,9 +8637,6 @@ def generate_keymaps(params=None):
km_curve_pen_modal_map(params),
km_node_link_modal_map(params),
# Asset Shelf Keymaps.
km_asset_shelf_brushes(params),
# Gizmos.
km_generic_gizmo(params),
km_generic_gizmo_drag(params),

View File

@ -8785,6 +8785,7 @@ class VIEW3D_PT_viewport_debug(Panel):
class BrushAssetShelf:
bl_space_type = "VIEW_3D"
bl_options = {'NO_ASSET_DRAG'}
bl_activate_operator = "BRUSH_OT_asset_select"
bl_default_preview_size = 40
@classmethod

View File

@ -523,6 +523,9 @@ struct AssetShelfType {
int space_type;
/** Operator to call when activating a grid view item. */
std::string activate_operator;
AssetShelfTypeFlag flag;
short default_preview_size;

View File

@ -23,6 +23,7 @@
#include "ED_asset_handle.hh"
#include "ED_asset_list.hh"
#include "ED_asset_menu_utils.hh"
#include "ED_asset_shelf.hh"
#include "UI_grid_view.hh"
@ -206,16 +207,17 @@ void AssetViewItem::disable_asset_drag()
void AssetViewItem::build_grid_tile(uiLayout &layout) const
{
PointerRNA file_ptr = RNA_pointer_create(
nullptr,
&RNA_FileSelectEntry,
/* XXX passing file pointer here, should be asset handle or asset representation. */
const_cast<FileDirEntry *>(asset_.file_data));
const AssetView &asset_view = reinterpret_cast<const AssetView &>(this->get_view());
const AssetShelfType &shelf_type = *asset_view.shelf_.type;
uiBlock *block = uiLayoutGetBlock(&layout);
UI_but_context_ptr_set(
block, reinterpret_cast<uiBut *>(view_item_but_), "active_file", &file_ptr);
ui::PreviewGridItem::build_grid_tile(layout);
wmOperatorType *ot = WM_operatortype_find(shelf_type.activate_operator.c_str(), true);
PointerRNA op_props = PointerRNA_NULL;
HooglyBoogly marked this conversation as resolved Outdated

This function does not check if ot is null (but WM_operator_properties_create does check).

This function does not check if `ot` is null (but `WM_operator_properties_create` does check).
if (ot) {
WM_operator_properties_create_ptr(&op_props, ot);
asset::operator_asset_reference_props_set(*handle_get_representation(&asset_), op_props);
}
ui::PreviewGridItem::build_grid_tile_button(layout, ot, &op_props);
}
void AssetViewItem::build_context_menu(bContext &C, uiLayout &column) const

View File

@ -19,6 +19,7 @@
#include "UI_resources.hh"
struct bContext;
struct PointerRNA;
struct uiBlock;
struct uiButViewItem;
struct uiLayout;
@ -204,6 +205,13 @@ class PreviewGridItem : public AbstractGridViewItem {
void build_grid_tile(uiLayout &layout) const override;
/**
* \note: Takes ownership of the operator properies defined in \a op_props.
*/
void build_grid_tile_button(uiLayout &layout,
HooglyBoogly marked this conversation as resolved
Review

Would add default arguments for convenience, but also to simply communicate that these are optional.

Would add default arguments for convenience, but also to simply communicate that these are optional.
const wmOperatorType *ot = nullptr,
const PointerRNA *op_props = nullptr) const;
/**
* Set a custom callback to execute when activating this view item. This way users don't have to
* sub-class #PreviewGridItem, just to implement custom activation behavior (a common thing to

View File

@ -2335,6 +2335,7 @@ static void ui_apply_but(
switch (but_type) {
case UI_BTYPE_BUT:
case UI_BTYPE_DECORATOR:
case UI_BTYPE_PREVIEW_TILE:
ui_apply_but_BUT(C, but, data);
break;
case UI_BTYPE_TEXT:

View File

@ -17,6 +17,8 @@
#include "WM_types.hh"
#include "RNA_access.hh"
#include "UI_interface.hh"
#include "interface_intern.hh"
@ -409,25 +411,44 @@ PreviewGridItem::PreviewGridItem(StringRef identifier, StringRef label, int prev
{
}
void PreviewGridItem::build_grid_tile(uiLayout &layout) const
void PreviewGridItem::build_grid_tile_button(uiLayout &layout,
const wmOperatorType *ot,
const PointerRNA *op_props) const
{
const GridViewStyle &style = this->get_view().get_style();
uiBlock *block = uiLayoutGetBlock(&layout);
uiBut *but = uiDefBut(block,
uiBut *but;
if (ot) {
but = uiDefButO_ptr(block,
UI_BTYPE_PREVIEW_TILE,
0,
const_cast<wmOperatorType *>(ot),
WM_OP_INVOKE_REGION_WIN,
hide_label_ ? "" : label,
0,
0,
style.tile_width,
style.tile_height,
nullptr,
0,
0,
0,
0,
"");
but->opptr = MEM_new<PointerRNA>(__func__, *op_props);
}
else {
but = uiDefBut(block,
UI_BTYPE_PREVIEW_TILE,
0,
hide_label_ ? "" : label,
0,
0,
style.tile_width,
style.tile_height,
nullptr,
0,
0,
0,
0,
"");
}
/* Draw icons that are not previews or images as normal icons with a fixed icon size. Otherwise
* they will be upscaled to the button size. Should probably be done by the widget code. */
const int is_preview_flag = (BKE_icon_is_preview(preview_icon_id) ||
@ -442,6 +463,11 @@ void PreviewGridItem::build_grid_tile(uiLayout &layout) const
but->emboss = UI_EMBOSS_NONE;
}
void PreviewGridItem::build_grid_tile(uiLayout &layout) const
{
this->build_grid_tile_button(layout);
}
void PreviewGridItem::set_on_activate_fn(ActivateFn fn)
{
activate_fn_ = fn;

View File

@ -45,6 +45,7 @@
#include "ED_asset_handle.hh"
#include "ED_asset_list.hh"
#include "ED_asset_mark_clear.hh"
#include "ED_asset_menu_utils.hh"
#include "ED_image.hh"
#include "ED_paint.hh"
#include "ED_screen.hh"
@ -987,21 +988,18 @@ static void PAINT_OT_brush_select(wmOperatorType *ot)
/**************************** Brush Assets **********************************/
static bool brush_asset_select_poll(bContext *C)
{
if (BKE_paint_get_active_from_context(C) == nullptr) {
return false;
}
return CTX_wm_asset(C) != nullptr;
}
static int brush_asset_select_exec(bContext *C, wmOperator *op)
{
using namespace blender;
using namespace blender::ed;
/* This operator currently covers both cases: the file/asset browser file list and the asset list
* used for the asset-view template. Once the asset list design is used by the Asset Browser,
* this can be simplified to just that case. */
blender::asset_system::AssetRepresentation *asset = CTX_wm_asset(C);
const asset_system::AssetRepresentation *asset =
asset::operator_asset_reference_props_get_asset_from_all_library(*C, *op->ptr, op->reports);
if (!asset) {
return OPERATOR_CANCELLED;
Review

Best do some report so this doesn't just fail silently.

Best do some report so this doesn't just fail silently.
Review

operator_asset_reference_props_get_asset_from_all_library handles the reports already

`operator_asset_reference_props_get_asset_from_all_library` handles the reports already
}
AssetWeakReference *brush_asset_reference = asset->make_weak_reference();
Brush *brush = BKE_brush_asset_runtime_ensure(CTX_data_main(C), brush_asset_reference);
@ -1023,12 +1021,14 @@ static int brush_asset_select_exec(bContext *C, wmOperator *op)
static void BRUSH_OT_asset_select(wmOperatorType *ot)
{
using namespace blender::ed;
ot->name = "Select Brush Asset";
ot->description = "Select a brush asset as current sculpt and paint tool";
ot->idname = "BRUSH_OT_asset_select";
ot->exec = brush_asset_select_exec;
ot->poll = brush_asset_select_poll;
asset::operator_asset_reference_props_register(*ot->srna);
}
/* FIXME Quick dirty hack to generate a weak ref from 'raw' paths.

View File

@ -1303,6 +1303,24 @@ static StructRNA *rna_AssetShelf_register(Main *bmain,
return srna;
}
static void rna_AssetShelf_activate_operator_get(PointerRNA *ptr, char *value)
{
AssetShelf *shelf = static_cast<AssetShelf *>(ptr->data);
strcpy(value, shelf->type->activate_operator.c_str());
}
static int rna_AssetShelf_activate_operator_length(PointerRNA *ptr)
{
AssetShelf *shelf = static_cast<AssetShelf *>(ptr->data);
return shelf->type->activate_operator.size();
}
static void rna_AssetShelf_activate_operator_set(PointerRNA *ptr, const char *value)
{
AssetShelf *shelf = static_cast<AssetShelf *>(ptr->data);
shelf->type->activate_operator = value;
}
static StructRNA *rna_AssetShelf_refine(PointerRNA *shelf_ptr)
{
AssetShelf *shelf = (AssetShelf *)shelf_ptr->data;
@ -2321,6 +2339,17 @@ static void rna_def_asset_shelf(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL | PROP_ENUM_FLAG);
RNA_def_property_ui_text(prop, "Options", "Options for this asset shelf type");
prop = RNA_def_property(srna, "bl_activate_operator", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop,
"rna_AssetShelf_activate_operator_get",
"rna_AssetShelf_activate_operator_length",
"rna_AssetShelf_activate_operator_set");
RNA_def_property_flag(prop, PROP_REGISTER_OPTIONAL);
RNA_def_property_ui_text(
prop,
"Activate Operator",
"Operator to call when activating an item with asset reference properties");
prop = RNA_def_property(srna, "bl_default_preview_size", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, nullptr, "type->default_preview_size");
RNA_def_property_range(prop, 32, 256);

View File

@ -204,11 +204,9 @@ wmKeyMap *WM_keymap_guess_from_context(const bContext *C)
wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
{
/* Op types purposely skipped for now:
* BRUSH_OT
* BOID_OT
* BUTTONS_OT
* CONSTRAINT_OT
* PAINT_OT
* ED_OT
* FLUID_OT
* TEXTURE_OT
@ -331,7 +329,7 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
km = WM_keymap_find_all(
wm, "Paint Face Mask (Weight, Vertex, Texture)", SPACE_EMPTY, RGN_TYPE_WINDOW);
}
else if (STRPREFIX(opname, "PAINT_OT")) {
else if (STRPREFIX(opname, "PAINT_OT") || STRPREFIX(opname, "BRUSH_OT")) {
/* check for relevant mode */
switch (CTX_data_mode_enum(C)) {
case CTX_MODE_PAINT_WEIGHT:
@ -346,6 +344,9 @@ wmKeyMap *WM_keymap_guess_opname(const bContext *C, const char *opname)
case CTX_MODE_SCULPT:
km = WM_keymap_find_all(wm, "Sculpt", SPACE_EMPTY, RGN_TYPE_WINDOW);
break;
case CTX_MODE_SCULPT_CURVES:
km = WM_keymap_find_all(wm, "Sculpt Curves", SPACE_EMPTY, RGN_TYPE_WINDOW);
break;
default:
break;
}