diff --git a/source/blender/asset_system/AS_asset_library.hh b/source/blender/asset_system/AS_asset_library.hh index aaf33d1d6b6..442b1d96bdc 100644 --- a/source/blender/asset_system/AS_asset_library.hh +++ b/source/blender/asset_system/AS_asset_library.hh @@ -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; diff --git a/source/blender/asset_system/intern/asset_library.cc b/source/blender/asset_system/intern/asset_library.cc index 3c8e16b5c60..541bc2932d3 100644 --- a/source/blender/asset_system/intern/asset_library.cc +++ b/source/blender/asset_system/intern/asset_library.cc @@ -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)) { diff --git a/source/blender/editors/geometry/node_group_operator.cc b/source/blender/editors/geometry/node_group_operator.cc index f8d9a76008b..40c9d263f12 100644 --- a/source/blender/editors/geometry/node_group_operator.cc +++ b/source/blender/editors/geometry/node_group_operator.cc @@ -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 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( diff --git a/source/blender/makesrna/RNA_enum_items.h b/source/blender/makesrna/RNA_enum_items.h index 7ceb29fe086..31d53b7b734 100644 --- a/source/blender/makesrna/RNA_enum_items.h +++ b/source/blender/makesrna/RNA_enum_items.h @@ -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 diff --git a/source/blender/makesrna/intern/rna_asset.cc b/source/blender/makesrna/intern/rna_asset.cc index 089f17d1608..9488ee33090 100644 --- a/source/blender/makesrna/intern/rna_asset.cc +++ b/source/blender/makesrna/intern/rna_asset.cc @@ -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"