Refactor: Retrieve node operator asset with property

In order to more reliably pass the asset to the operator, use a string
property with the full asset path instead of using a context pointer.
This is required to support the quick favorites menu, shortcuts, and
to draw operator inputs in the redo panel. In all of those situations
the original context isn't available. This also feels safer, since we
rely less on storing pointers to data with a less-defined lifetime.

Pull Request: https://projects.blender.org/blender/blender/pulls/110018
This commit is contained in:
Hans Goudey
2023-08-01 14:54:58 +02:00
committed by Hans Goudey
parent 63e2832057
commit 65591b2c8c
5 changed files with 142 additions and 28 deletions

View File

@@ -166,6 +166,8 @@ class AssetLibrary {
*/
AssetIdentifier asset_identifier_from_library(StringRef relative_asset_path);
std::string resolve_asset_weak_reference_to_full_path(const AssetWeakReference &asset_reference);
eAssetLibraryType library_type() const;
StringRefNull name() const;
StringRefNull root_path() const;

View File

@@ -302,6 +302,13 @@ AssetIdentifier AssetLibrary::asset_identifier_from_library(StringRef relative_a
return AssetIdentifier(root_path_, relative_asset_path);
}
std::string AssetLibrary::resolve_asset_weak_reference_to_full_path(
const AssetWeakReference &asset_reference)
{
AssetLibraryService *service = AssetLibraryService::get();
return service->resolve_asset_weak_reference_to_full_path(asset_reference);
}
void AssetLibrary::refresh_catalog_simplename(AssetMetaData *asset_data)
{
if (BLI_uuid_is_nil(asset_data->catalog_id)) {

View File

@@ -39,6 +39,7 @@
#include "DEG_depsgraph_query.h"
#include "RNA_access.h"
#include "RNA_define.h"
#include "RNA_enum_types.h"
#include "UI_interface.h"
@@ -69,9 +70,92 @@ namespace blender::ed::geometry {
/** \name Operator
* \{ */
static const bNodeTree *get_node_group(const bContext &C)
/**
* #AssetLibrary::resolve_asset_weak_reference_to_full_path() currently does not support local
* assets.
*/
static const asset_system::AssetRepresentation *get_local_asset_from_relative_identifier(
const bContext &C, const StringRefNull relative_identifier, ReportList *reports)
{
const asset_system::AssetRepresentation *asset = CTX_wm_asset(&C);
AssetLibraryReference library_ref{};
library_ref.type = ASSET_LIBRARY_LOCAL;
ED_assetlist_storage_fetch(&library_ref, &C);
ED_assetlist_ensure_previews_job(&library_ref, &C);
const asset_system::AssetRepresentation *matching_asset = nullptr;
ED_assetlist_iterate(library_ref, [&](asset_system::AssetRepresentation &asset) {
if (asset.get_identifier().library_relative_identifier() == relative_identifier) {
matching_asset = &asset;
return false;
}
return true;
});
if (reports && !matching_asset) {
if (ED_assetlist_is_loaded(&library_ref)) {
BKE_reportf(
reports, RPT_ERROR, "No asset found at path \"%s\"", relative_identifier.c_str());
}
else {
BKE_report(reports, RPT_WARNING, "Asset loading is unfinished");
}
}
return matching_asset;
}
static const asset_system::AssetRepresentation *find_asset_from_weak_ref(
const bContext &C, const AssetWeakReference &weak_ref, ReportList *reports)
{
if (weak_ref.asset_library_type == ASSET_LIBRARY_LOCAL) {
return get_local_asset_from_relative_identifier(
C, weak_ref.relative_asset_identifier, reports);
}
const AssetLibraryReference library_ref = asset_system::all_library_reference();
ED_assetlist_storage_fetch(&library_ref, &C);
ED_assetlist_ensure_previews_job(&library_ref, &C);
asset_system::AssetLibrary *all_library = ED_assetlist_library_get_once_available(
asset_system::all_library_reference());
if (!all_library) {
BKE_report(reports, RPT_WARNING, "Asset loading is unfinished");
}
const std::string full_path = all_library->resolve_asset_weak_reference_to_full_path(weak_ref);
const asset_system::AssetRepresentation *matching_asset = nullptr;
ED_assetlist_iterate(library_ref, [&](asset_system::AssetRepresentation &asset) {
if (asset.get_identifier().full_path() == full_path) {
matching_asset = &asset;
return false;
}
return true;
});
if (reports && !matching_asset) {
if (ED_assetlist_is_loaded(&library_ref)) {
BKE_reportf(reports, RPT_ERROR, "No asset found at path \"%s\"", full_path.c_str());
}
}
return matching_asset;
}
/** \note Does not check asset type or meta data. */
static const asset_system::AssetRepresentation *get_asset(const bContext &C,
PointerRNA &ptr,
ReportList *reports)
{
AssetWeakReference weak_ref{};
weak_ref.asset_library_type = RNA_enum_get(&ptr, "asset_library_type");
weak_ref.asset_library_identifier = RNA_string_get_alloc(
&ptr, "asset_library_identifier", nullptr, 0, nullptr);
weak_ref.relative_asset_identifier = RNA_string_get_alloc(
&ptr, "relative_asset_identifier", nullptr, 0, nullptr);
return find_asset_from_weak_ref(C, weak_ref, reports);
}
static const bNodeTree *get_node_group(const bContext &C, PointerRNA &ptr, ReportList *reports)
{
const asset_system::AssetRepresentation *asset = get_asset(C, ptr, reports);
if (!asset) {
return nullptr;
}
@@ -82,6 +166,9 @@ static const bNodeTree *get_node_group(const bContext &C)
return nullptr;
}
if (node_group->type != NTREE_GEOMETRY) {
if (reports) {
BKE_report(reports, RPT_ERROR, "Asset is not a geometry node group");
}
return nullptr;
}
return node_group;
@@ -217,7 +304,7 @@ static int run_node_group_exec(bContext *C, wmOperator *op)
}
const eObjectMode mode = eObjectMode(active_object->mode);
const bNodeTree *node_tree = get_node_group(*C);
const bNodeTree *node_tree = get_node_group(*C, *op->ptr, op->reports);
if (!node_tree) {
return OPERATOR_CANCELLED;
}
@@ -268,7 +355,7 @@ static int run_node_group_exec(bContext *C, wmOperator *op)
static int run_node_group_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
{
const bNodeTree *node_tree = get_node_group(*C);
const bNodeTree *node_tree = get_node_group(*C, *op->ptr, op->reports);
if (!node_tree) {
return OPERATOR_CANCELLED;
}
@@ -279,11 +366,9 @@ static int run_node_group_invoke(bContext *C, wmOperator *op, const wmEvent * /*
return run_node_group_exec(C, op);
}
static char *run_node_group_get_description(bContext *C,
wmOperatorType * /*ot*/,
PointerRNA * /*ptr*/)
static char *run_node_group_get_description(bContext *C, wmOperatorType * /*ot*/, PointerRNA *ptr)
{
const asset_system::AssetRepresentation *asset = CTX_wm_asset(C);
const asset_system::AssetRepresentation *asset = get_asset(*C, *ptr, nullptr);
if (!asset) {
return nullptr;
}
@@ -294,34 +379,33 @@ static char *run_node_group_get_description(bContext *C,
return BLI_strdup(description);
}
static bool run_node_group_poll(bContext *C)
{
const asset_system::AssetRepresentation *asset = CTX_wm_asset(C);
if (!asset) {
return false;
}
const Object *object = CTX_data_active_object(C);
if (object->type != OB_CURVES) {
return false;
}
if (object->mode != OB_MODE_SCULPT_CURVES) {
return false;
}
return true;
}
void GEOMETRY_OT_execute_node_group(wmOperatorType *ot)
{
ot->name = "Run Node Group";
ot->idname = __func__;
ot->description = "Execute a node group on geometry";
ot->poll = run_node_group_poll;
/* A proper poll is not possible, since it doesn't have access to the operator's properties. */
ot->invoke = run_node_group_invoke;
ot->exec = run_node_group_exec;
ot->get_description = run_node_group_get_description;
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
PropertyRNA *prop;
prop = RNA_def_enum(ot->srna,
"asset_library_type",
rna_enum_aset_library_type_items,
ASSET_LIBRARY_LOCAL,
"Asset Library Type",
"");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_string(
ot->srna, "asset_library_identifier", nullptr, 0, "Asset Library Identifier", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
prop = RNA_def_string(
ot->srna, "relative_asset_identifier", nullptr, 0, "Relative Asset Identifier", "");
RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE);
}
/** \} */
@@ -430,9 +514,20 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
for (const asset_system::AssetRepresentation *asset : assets) {
uiLayout *col = uiLayoutColumn(layout, false);
PointerRNA asset_ptr = asset::create_asset_rna_ptr(asset);
uiLayoutSetContextPointer(col, "asset", &asset_ptr);
uiItemO(col, IFACE_(asset->get_name().c_str()), ICON_NONE, "GEOMETRY_OT_execute_node_group");
wmOperatorType *ot = WM_operatortype_find("GEOMETRY_OT_execute_node_group", true);
const std::unique_ptr<AssetWeakReference> weak_ref = asset->make_weak_reference();
PointerRNA props_ptr;
uiItemFullO_ptr(col,
ot,
IFACE_(asset->get_name().c_str()),
ICON_NONE,
nullptr,
WM_OP_INVOKE_DEFAULT,
eUI_Item_Flag(0),
&props_ptr);
RNA_enum_set(&props_ptr, "asset_library_type", weak_ref->asset_library_type);
RNA_string_set(&props_ptr, "asset_library_identifier", weak_ref->asset_library_identifier);
RNA_string_set(&props_ptr, "relative_asset_identifier", weak_ref->relative_asset_identifier);
}
asset_system::AssetLibrary *all_library = ED_assetlist_library_get_once_available(

View File

@@ -258,6 +258,8 @@ DEF_ENUM(rna_enum_nla_mode_extend_items)
DEF_ENUM(rna_enum_nla_mode_blend_items)
DEF_ENUM(rna_enum_keyblock_type_items)
DEF_ENUM(rna_enum_aset_library_type_items)
#endif
#undef DEF_ENUM

View File

@@ -17,6 +17,14 @@
#include "rna_internal.h"
const EnumPropertyItem rna_enum_aset_library_type_items[] = {
{ASSET_LIBRARY_LOCAL, "LOCAL", 0, "Local", ""},
{ASSET_LIBRARY_ALL, "ALL", 0, "All", ""},
{ASSET_LIBRARY_ESSENTIALS, "ESSENTIALS", 0, "Essentials", ""},
{ASSET_LIBRARY_CUSTOM, "CUSTOM", 0, "Custom", ""},
{0, nullptr, 0, nullptr, nullptr},
};
#ifdef RNA_RUNTIME
# include "AS_asset_library.h"