Geometry Nodes: Node group operators initial phase #108947

Merged
Hans Goudey merged 72 commits from node-group-operators into main 2023-06-29 13:58:01 +02:00
10 changed files with 154 additions and 154 deletions
Showing only changes of commit fe246cc83b - Show all commits

View File

@ -359,7 +359,7 @@ Vector<AssetLibraryReference> all_valid_asset_library_refs()
return result;
}
AssetLibraryReference all_library_reference()
AssetLibraryReference all_library_reference()
{
AssetLibraryReference all_library_ref{};
all_library_ref.custom_library_index = -1;
@ -367,5 +367,4 @@ Vector<AssetLibraryReference> all_valid_asset_library_refs()
return all_library_ref;
}
} // namespace blender::asset_system

View File

@ -10,7 +10,14 @@
#pragma once
#include "BLI_function_ref.hh"
#include "BLI_multi_value_map.hh"
#include "AS_asset_catalog_path.hh"
#include "AS_asset_catalog_tree.hh"
struct AssetFilterSettings;
struct bContext;
namespace blender::asset_system {
class AssetRepresentation;
@ -30,3 +37,18 @@ class AssetRepresentation;
*/
bool ED_asset_filter_matches_asset(const AssetFilterSettings *filter,
const blender::asset_system::AssetRepresentation &asset);
namespace blender::ed::asset {
struct AssetItemTree {
asset_system::AssetCatalogTree catalogs;
MultiValueMap<asset_system::AssetCatalogPath, asset_system::AssetRepresentation *>
assets_per_path;
};
AssetItemTree build_filtered_all_catalog_tree(
const bContext &C,
const AssetFilterSettings &filter_settings,
FunctionRef<bool(const AssetMetaData &)> meta_data_filter);
HooglyBoogly marked this conversation as resolved
Review

Would default this to nullptr. While in your case (geometry nodes stuff) it's necessary, I'm not sure if you'd need to filter by metadata usually.

Would default this to `nullptr`. While in your case (geometry nodes stuff) it's necessary, I'm not sure if you'd need to filter by metadata usually.
} // namespace blender::ed::asset

View File

@ -42,3 +42,13 @@ const struct EnumPropertyItem *ED_asset_library_reference_to_rna_enum_itemf(
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
namespace blender::ed::asset {
asset_system::AssetLibrary *get_all_library_once_available();
} // namespace blender::ed::asset
#endif

View File

@ -8,13 +8,20 @@
#include "AS_asset_representation.hh"
#include "BKE_asset.h"
#include "BKE_idtype.h"
#include "BLI_listbase.h"
#include "DNA_asset_types.h"
#include "AS_asset_catalog_tree.hh"
#include "AS_asset_library.hh"
#include "ED_asset_filter.hh"
#include "ED_asset_library.h"
#include "ED_asset_list.h"
#include "ED_asset_list.hh"
using namespace blender;
@ -41,3 +48,65 @@ bool ED_asset_filter_matches_asset(const AssetFilterSettings *filter,
/* Successfully passed through all filters. */
return true;
}
namespace blender::ed::asset {
AssetItemTree build_filtered_all_catalog_tree(
HooglyBoogly marked this conversation as resolved
Review

Would suggest letting this take an AssetLibraryReference as parameter, there's nothing specific to the all asset library here really.

Would suggest letting this take an `AssetLibraryReference` as parameter, there's nothing specific to the all asset library here really.
const bContext &C,
const AssetFilterSettings &filter_settings,
const FunctionRef<bool(const AssetMetaData &)> meta_data_filter)
{
MultiValueMap<asset_system::AssetCatalogPath, asset_system::AssetRepresentation *>
assets_per_path;
const AssetLibraryReference all_library_ref = asset_system::all_library_reference();
ED_assetlist_storage_fetch(&all_library_ref, &C);
ED_assetlist_ensure_previews_job(&all_library_ref, &C);
asset_system::AssetLibrary *all_library = get_all_library_once_available();
if (!all_library) {
return {};
}
ED_assetlist_iterate(all_library_ref, [&](asset_system::AssetRepresentation &asset) {
if (!ED_asset_filter_matches_asset(&filter_settings, asset)) {
return true;
}
const AssetMetaData &meta_data = asset.get_metadata();
if (BLI_uuid_is_nil(meta_data.catalog_id)) {
return true;
}
if (!meta_data_filter(meta_data)) {
return true;
}
const asset_system::AssetCatalog *catalog = all_library->catalog_service->find_catalog(
meta_data.catalog_id);
if (catalog == nullptr) {
return true;
}
assets_per_path.add(catalog->path, &asset);
return true;
});
HooglyBoogly marked this conversation as resolved
Review

This comment seems outdated because it talks about node groups while this function seems to be more general.

This comment seems outdated because it talks about node groups while this function seems to be more general.
/* Build an own tree without any of the catalogs that don't have proper node group assets. */
asset_system::AssetCatalogTree catalogs_with_node_assets;
asset_system::AssetCatalogTree &catalog_tree = *all_library->catalog_service->get_catalog_tree();
catalog_tree.foreach_item([&](asset_system::AssetCatalogTreeItem &item) {
if (assets_per_path.lookup(item.catalog_path()).is_empty()) {
return;
}
asset_system::AssetCatalog *catalog = all_library->catalog_service->find_catalog(
item.get_catalog_id());
if (catalog == nullptr) {
return;
}
catalogs_with_node_assets.insert_item(*catalog);
});
return {std::move(catalogs_with_node_assets), std::move(assets_per_path)};
}
} // namespace blender::ed::asset

View File

@ -21,7 +21,10 @@
#include "RNA_define.h"
#include "AS_asset_library.hh"
#include "ED_asset_library.h"
#include "ED_asset_list.hh"
int ED_asset_library_reference_to_enum_value(const AssetLibraryReference *library)
{
@ -127,3 +130,13 @@ const EnumPropertyItem *ED_asset_library_reference_to_rna_enum_itemf(const bool
RNA_enum_item_end(&item, &totitem);
return item;
}
namespace blender::ed::asset {
asset_system::AssetLibrary *get_all_library_once_available()
HooglyBoogly marked this conversation as resolved Outdated

Not sure if this function adds much, I'd just call the two lines in place. At least the location is weird, what does this have to do with the enum conversion? :)

Not sure if this function adds much, I'd just call the two lines in place. At least the location is weird, what does this have to do with the enum conversion? :)
{
const AssetLibraryReference all_library_ref = asset_system::all_library_reference();
return ED_assetlist_library_get_once_available(all_library_ref);
}
} // namespace blender::ed::asset

View File

@ -337,15 +337,9 @@ static void assets_listen_fn(const wmRegionListenerParams *params)
}
}
struct AssetItemTree {
asset_system::AssetCatalogTree catalogs;
MultiValueMap<asset_system::AssetCatalogPath, asset_system::AssetRepresentation *>
assets_per_path;
};
static AssetItemTree &get_item_tree()
static asset::AssetItemTree &get_static_item_tree()
{
static AssetItemTree tree;
static asset::AssetItemTree tree;
return tree;
}
@ -355,12 +349,6 @@ static bool all_loading_finished()
return ED_assetlist_is_loaded(&all_library_ref);
}
static asset_system::AssetLibrary *get_all_library_once_available()
{
const AssetLibraryReference all_library_ref = asset_system::all_library_reference();
return ED_assetlist_library_get_once_available(all_library_ref);
}
/**
* The menus want to pass catalog paths to context and for this they need persistent pointers to
* the paths. Rather than keeping some local path storage, get a pointer into the asset system
@ -395,67 +383,21 @@ static PointerRNA create_asset_rna_ptr(const asset_system::AssetRepresentation *
}
// TODO: SHOULD BE SHARED, AT LEAST GENERALIZED
static AssetItemTree build_catalog_tree(const bContext &C)
static asset::AssetItemTree build_catalog_tree(const bContext &C)
{
AssetFilterSettings type_filter{};
type_filter.id_types = FILTER_ID_NT;
AssetTag operator_tag;
STRNCPY(operator_tag.name, "edit_mode_operator");
BLI_addtail(&type_filter.tags, &operator_tag);
/* Find all the matching node group assets for every catalog path. */
MultiValueMap<asset_system::AssetCatalogPath, asset_system::AssetRepresentation *>
assets_per_path;
const AssetLibraryReference all_library_ref = asset_system::all_library_reference();
ED_assetlist_storage_fetch(&all_library_ref, &C);
ED_assetlist_ensure_previews_job(&all_library_ref, &C);
asset_system::AssetLibrary *all_library = get_all_library_once_available();
if (!all_library) {
return {};
}
ED_assetlist_iterate(all_library_ref, [&](asset_system::AssetRepresentation &asset) {
if (!ED_asset_filter_matches_asset(&type_filter, asset)) {
return true;
}
const AssetMetaData &meta_data = asset.get_metadata();
auto meta_data_filter = [&](const AssetMetaData &meta_data) {
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
if (tree_type == nullptr || IDP_Int(tree_type) != NTREE_GEOMETRY) {
return true;
return false;
}
if (BLI_uuid_is_nil(meta_data.catalog_id)) {
return true;
}
const asset_system::AssetCatalog *catalog = all_library->catalog_service->find_catalog(
meta_data.catalog_id);
if (catalog == nullptr) {
return true;
}
assets_per_path.add(catalog->path, &asset);
return true;
});
/* Build an own tree without any of the catalogs that don't have proper node group assets. */
asset_system::AssetCatalogTree catalogs_with_node_assets;
asset_system::AssetCatalogTree &catalog_tree = *all_library->catalog_service->get_catalog_tree();
catalog_tree.foreach_item([&](asset_system::AssetCatalogTreeItem &item) {
if (assets_per_path.lookup(item.catalog_path()).is_empty()) {
return;
}
asset_system::AssetCatalog *catalog = all_library->catalog_service->find_catalog(
item.get_catalog_id());
if (catalog == nullptr) {
return;
}
catalogs_with_node_assets.insert_item(*catalog);
});
return {std::move(catalogs_with_node_assets), std::move(assets_per_path)};
};
return asset::build_filtered_all_catalog_tree(C, type_filter, meta_data_filter);
}
/**
@ -510,7 +452,7 @@ static Set<std::string> get_builtin_menus(const ObjectType object_type, const eO
static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
{
bScreen &screen = *CTX_wm_screen(C);
AssetItemTree &tree = get_item_tree();
asset::AssetItemTree &tree = get_static_item_tree();
const PointerRNA menu_path_ptr = CTX_data_pointer_get(C, "asset_catalog_path");
if (RNA_pointer_is_null(&menu_path_ptr)) {
return;
@ -534,7 +476,7 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
uiItemO(col, IFACE_(asset->get_name().c_str()), ICON_NONE, "GEOMETRY_OT_execute_node_group");
}
asset_system::AssetLibrary *all_library = get_all_library_once_available();
asset_system::AssetLibrary *all_library = asset::get_all_library_once_available();
if (!all_library) {
return;
}
@ -568,12 +510,12 @@ void ui_template_node_operator_asset_menu_items(uiLayout &layout,
const StringRef catalog_path)
{
bScreen &screen = *CTX_wm_screen(&C);
AssetItemTree &tree = get_item_tree();
asset::AssetItemTree &tree = get_static_item_tree();
const asset_system::AssetCatalogTreeItem *item = tree.catalogs.find_root_item(catalog_path);
if (!item) {
return;
}
asset_system::AssetLibrary *all_library = get_all_library_once_available();
asset_system::AssetLibrary *all_library = asset::get_all_library_once_available();
if (!all_library) {
return;
}
@ -594,7 +536,7 @@ void ui_template_node_operator_asset_root_items(uiLayout &layout, bContext &C)
if (!active_object) {
return;
}
AssetItemTree &tree = get_item_tree();
asset::AssetItemTree &tree = get_static_item_tree();
tree = build_catalog_tree(C);
const bool loading_finished = all_loading_finished();
@ -605,7 +547,7 @@ void ui_template_node_operator_asset_root_items(uiLayout &layout, bContext &C)
uiItemL(&layout, IFACE_("Loading Asset Libraries"), ICON_INFO);
}
asset_system::AssetLibrary *all_library = get_all_library_once_available();
asset_system::AssetLibrary *all_library = asset::get_all_library_once_available();
if (!all_library) {
return;
}

View File

@ -47,24 +47,12 @@ static void node_add_menu_assets_listen_fn(const wmRegionListenerParams *params)
}
}
struct AssetItemTree {
asset_system::AssetCatalogTree catalogs;
MultiValueMap<asset_system::AssetCatalogPath, asset_system::AssetRepresentation *>
assets_per_path;
};
static bool all_loading_finished()
{
AssetLibraryReference all_library_ref = asset_system::all_library_reference();
return ED_assetlist_is_loaded(&all_library_ref);
}
static asset_system::AssetLibrary *get_all_library_once_available()
{
const AssetLibraryReference all_library_ref = asset_system::all_library_reference();
return ED_assetlist_library_get_once_available(all_library_ref);
}
/**
* The menus want to pass catalog paths to context and for this they need persistent pointers to
* the paths. Rather than keeping some local path storage, get a pointer into the asset system
@ -96,67 +84,18 @@ static PointerRNA create_asset_rna_ptr(const asset_system::AssetRepresentation *
return ptr;
}
static AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree *node_tree)
static asset::AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree &node_tree)
{
if (!node_tree) {
return {};
}
/* Find all the matching node group assets for every catalog path. */
MultiValueMap<asset_system::AssetCatalogPath, asset_system::AssetRepresentation *>
assets_per_path;
AssetFilterSettings type_filter{};
type_filter.id_types = FILTER_ID_NT;
const AssetLibraryReference all_library_ref = asset_system::all_library_reference();
ED_assetlist_storage_fetch(&all_library_ref, &C);
ED_assetlist_ensure_previews_job(&all_library_ref, &C);
asset_system::AssetLibrary *all_library = get_all_library_once_available();
if (!all_library) {
return {};
}
ED_assetlist_iterate(all_library_ref, [&](asset_system::AssetRepresentation &asset) {
if (!ED_asset_filter_matches_asset(&type_filter, asset)) {
return true;
}
const AssetMetaData &meta_data = asset.get_metadata();
auto meta_data_filter = [&](const AssetMetaData &meta_data) {
const IDProperty *tree_type = BKE_asset_metadata_idprop_find(&meta_data, "type");
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree->type) {
return true;
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
return false;
}
if (BLI_uuid_is_nil(meta_data.catalog_id)) {
return true;
}
const asset_system::AssetCatalog *catalog = all_library->catalog_service->find_catalog(
meta_data.catalog_id);
if (catalog == nullptr) {
return true;
}
assets_per_path.add(catalog->path, &asset);
return true;
});
/* Build an own tree without any of the catalogs that don't have proper node group assets. */
asset_system::AssetCatalogTree catalogs_with_node_assets;
asset_system::AssetCatalogTree &catalog_tree = *all_library->catalog_service->get_catalog_tree();
catalog_tree.foreach_item([&](asset_system::AssetCatalogTreeItem &item) {
if (assets_per_path.lookup(item.catalog_path()).is_empty()) {
return;
}
asset_system::AssetCatalog *catalog = all_library->catalog_service->find_catalog(
item.get_catalog_id());
if (catalog == nullptr) {
return;
}
catalogs_with_node_assets.insert_item(*catalog);
});
return {std::move(catalogs_with_node_assets), std::move(assets_per_path)};
};
return asset::build_filtered_all_catalog_tree(C, type_filter, meta_data_filter);
}
static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
@ -167,7 +106,7 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
BLI_assert_unreachable();
return;
}
AssetItemTree &tree = *snode.runtime->assets_for_menu;
asset::AssetItemTree &tree = *snode.runtime->assets_for_menu;
const bNodeTree *edit_tree = snode.edittree;
if (!edit_tree) {
return;
@ -198,7 +137,7 @@ static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
uiItemO(col, IFACE_(asset->get_name().c_str()), ICON_NONE, "NODE_OT_add_group_asset");
}
asset_system::AssetLibrary *all_library = get_all_library_once_available();
asset_system::AssetLibrary *all_library = asset::get_all_library_once_available();
if (!all_library) {
return;
}
@ -220,15 +159,18 @@ static void add_root_catalogs_draw(const bContext *C, Menu *menu)
{
bScreen &screen = *CTX_wm_screen(C);
SpaceNode &snode = *CTX_wm_space_node(C);
const bNodeTree *edit_tree = snode.edittree;
uiLayout *layout = menu->layout;
const bNodeTree *edit_tree = snode.edittree;
if (!edit_tree) {
return;
}
snode.runtime->assets_for_menu = std::make_shared<AssetItemTree>(
build_catalog_tree(*C, edit_tree));
snode.runtime->assets_for_menu = std::make_shared<asset::AssetItemTree>(
build_catalog_tree(*C, *edit_tree));
const bool loading_finished = all_loading_finished();
AssetItemTree &tree = *snode.runtime->assets_for_menu;
asset::AssetItemTree &tree = *snode.runtime->assets_for_menu;
if (tree.catalogs.is_empty() && loading_finished) {
return;
}
@ -273,7 +215,7 @@ static void add_root_catalogs_draw(const bContext *C, Menu *menu)
return menus;
}();
asset_system::AssetLibrary *all_library = get_all_library_once_available();
asset_system::AssetLibrary *all_library = asset::get_all_library_once_available();
if (!all_library) {
return;
}
@ -317,18 +259,19 @@ MenuType add_root_catalogs_menu_type()
void uiTemplateNodeAssetMenuItems(uiLayout *layout, bContext *C, const char *catalog_path)
{
using namespace blender;
using namespace blender::ed;
using namespace blender::ed::space_node;
bScreen &screen = *CTX_wm_screen(C);
SpaceNode &snode = *CTX_wm_space_node(C);
if (snode.runtime->assets_for_menu == nullptr) {
return;
}
AssetItemTree &tree = *snode.runtime->assets_for_menu;
asset::AssetItemTree &tree = *snode.runtime->assets_for_menu;
const asset_system::AssetCatalogTreeItem *item = tree.catalogs.find_root_item(catalog_path);
if (!item) {
return;
}
asset_system::AssetLibrary *all_library = get_all_library_once_available();
asset_system::AssetLibrary *all_library = asset::get_all_library_once_available();
if (!all_library) {
return;
}

View File

@ -35,9 +35,11 @@ extern "C" {
extern const char *node_context_dir[];
};
namespace blender::ed::space_node {
namespace blender::ed::asset {
struct AssetItemTree;
}
namespace blender::ed::space_node {
/** Temporary data used in node link drag modal operator. */
struct bNodeLinkDrag {
@ -112,7 +114,7 @@ struct SpaceNode_Runtime {
*
* Stored with a shared pointer so that it can be forward declared.
*/
std::shared_ptr<AssetItemTree> assets_for_menu;
std::shared_ptr<asset::AssetItemTree> assets_for_menu;
};
enum NodeResizeDirection {

View File

@ -7432,7 +7432,7 @@ static void rna_def_space_node(BlenderRNA *brna)
static const EnumPropertyItem geometry_nodes_type_items[] = {
{SNODE_GEOMETRY_MODIFIER, "MODIFIER", 0, "Modifier", ""},
{SNODE_GEOMETRY_OPERATOR, "OPERATOR", 0, "Operator", ""},
{0, NULL, 0, NULL, NULL},
{0, nullptr, 0, nullptr, nullptr},
};
static const EnumPropertyItem backdrop_channels_items[] = {

View File

@ -1824,7 +1824,7 @@ void RNA_api_ui_layout(StructRNA *srna)
"template_node_operator_asset_menu_items",
"rna_uiLayout_template_node_operator_asset_menu_items");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
parm = RNA_def_string(func, "catalog_path", NULL, 0, "", "");
parm = RNA_def_string(func, "catalog_path", nullptr, 0, "", "");
func = RNA_def_function(srna,
"template_node_operator_asset_root_items",