Eevee-Next: World Reflective Light #108149
|
@ -113,6 +113,9 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue,
|
|||
/* Shader evaluation kernels seems to use some amount of shared memory, so better
|
||||
* to avoid usage of maximum work group sizes for them. */
|
||||
const static size_t preferred_work_group_size_shader_evaluation = 256;
|
||||
/* NOTE(@nsirgien): 1024 currently may lead to issues with cryptomatte kernels, so
|
||||
* for now their work-group size is restricted to 512. */
|
||||
const static size_t preferred_work_group_size_cryptomatte = 512;
|
||||
const static size_t preferred_work_group_size_default = 1024;
|
||||
|
||||
size_t preferred_work_group_size = 0;
|
||||
|
@ -160,6 +163,10 @@ size_t oneapi_kernel_preferred_local_size(SyclQueue *queue,
|
|||
preferred_work_group_size = GPU_PARALLEL_PREFIX_SUM_DEFAULT_BLOCK_SIZE;
|
||||
break;
|
||||
|
||||
case DEVICE_KERNEL_CRYPTOMATTE_POSTPROCESS:
|
||||
preferred_work_group_size = preferred_work_group_size_cryptomatte;
|
||||
break;
|
||||
|
||||
case DEVICE_KERNEL_SHADER_EVAL_DISPLACE:
|
||||
case DEVICE_KERNEL_SHADER_EVAL_BACKGROUND:
|
||||
case DEVICE_KERNEL_SHADER_EVAL_CURVE_SHADOW_TRANSPARENCY:
|
||||
|
|
|
@ -237,10 +237,15 @@ class NewGeometryNodeTreeAssign(Operator):
|
|||
return geometry_modifier_poll(context)
|
||||
|
||||
def execute(self, context):
|
||||
snode = context.space_data
|
||||
if snode and snode.geometry_nodes_type == 'OPERATOR':
|
||||
group = geometry_node_group_empty_new()
|
||||
snode.node_tree = group
|
||||
return {'FINISHED'}
|
||||
else:
|
||||
modifier = get_context_modifier(context)
|
||||
if not modifier:
|
||||
return {'CANCELLED'}
|
||||
|
||||
group = geometry_node_group_empty_new()
|
||||
modifier.node_group = group
|
||||
|
||||
|
|
|
@ -139,9 +139,11 @@ class NODE_HT_header(Header):
|
|||
layout.prop(snode_id, "use_nodes")
|
||||
|
||||
elif snode.tree_type == 'GeometryNodeTree':
|
||||
layout.prop(snode, "geometry_nodes_type", text="")
|
||||
NODE_MT_editor_menus.draw_collapsible(context, layout)
|
||||
layout.separator_spacer()
|
||||
|
||||
if snode.geometry_nodes_type == 'MODIFIER':
|
||||
ob = context.object
|
||||
|
||||
row = layout.row()
|
||||
|
@ -157,7 +159,8 @@ class NODE_HT_header(Header):
|
|||
row.template_ID(active_modifier, "node_group", new="node.new_geometry_node_group_assign")
|
||||
else:
|
||||
row.template_ID(snode, "node_tree", new="node.new_geometry_nodes_modifier")
|
||||
|
||||
else:
|
||||
layout.template_ID(snode, "node_tree", new="node.new_geometry_node_group_assign")
|
||||
else:
|
||||
# Custom node tree is edited as independent ID block
|
||||
NODE_MT_editor_menus.draw_collapsible(context, layout)
|
||||
|
|
|
@ -1018,6 +1018,7 @@ class VIEW3D_MT_editor_menus(Menu):
|
|||
if mode_string == 'SCULPT_CURVES':
|
||||
layout.menu("VIEW3D_MT_select_sculpt_curves")
|
||||
layout.menu("VIEW3D_MT_sculpt_curves")
|
||||
layout.template_node_operator_asset_root_items()
|
||||
|
||||
else:
|
||||
layout.menu("VIEW3D_MT_object")
|
||||
|
@ -2153,6 +2154,8 @@ class VIEW3D_MT_select_sculpt_curves(Menu):
|
|||
layout.operator("curves.select_ends", text="Endpoints")
|
||||
layout.operator("sculpt_curves.select_grow", text="Grow")
|
||||
|
||||
layout.template_node_operator_asset_menu_items(catalog_path="Select")
|
||||
|
||||
|
||||
class VIEW3D_MT_mesh_add(Menu):
|
||||
bl_idname = "VIEW3D_MT_mesh_add"
|
||||
|
@ -3408,6 +3411,8 @@ class VIEW3D_MT_sculpt_curves(Menu):
|
|||
layout.separator()
|
||||
layout.operator("curves.convert_to_particle_system", text="Convert to Particle System")
|
||||
|
||||
layout.template_node_operator_asset_menu_items(catalog_path="Curves")
|
||||
|
||||
|
||||
class VIEW3D_MT_mask(Menu):
|
||||
bl_label = "Mask"
|
||||
|
|
|
@ -173,6 +173,8 @@ class AssetLibrary {
|
|||
|
||||
Vector<AssetLibraryReference> all_valid_asset_library_refs();
|
||||
|
||||
AssetLibraryReference all_library_reference();
|
||||
|
||||
} // namespace blender::asset_system
|
||||
|
||||
/**
|
||||
|
|
|
@ -359,4 +359,12 @@ Vector<AssetLibraryReference> all_valid_asset_library_refs()
|
|||
return result;
|
||||
}
|
||||
|
||||
AssetLibraryReference all_library_reference()
|
||||
{
|
||||
AssetLibraryReference all_library_ref{};
|
||||
all_library_ref.custom_library_index = -1;
|
||||
all_library_ref.type = ASSET_LIBRARY_ALL;
|
||||
return all_library_ref;
|
||||
}
|
||||
|
||||
} // namespace blender::asset_system
|
||||
|
|
|
@ -136,6 +136,10 @@ class bNodeTreeToDotOptionsForAnonymousAttributeInferencing : public bNodeTreeTo
|
|||
ss << socket.identifier << " [";
|
||||
bits::foreach_1_index(result_.required_fields_by_geometry_socket[socket.index_in_tree()],
|
||||
[&](const int i) { ss << i << ","; });
|
||||
ss << "] [";
|
||||
bits::foreach_1_index(
|
||||
result_.propagate_to_output_by_geometry_socket[socket.index_in_tree()],
|
||||
[&](const int i) { ss << result_.propagated_output_geometry_indices[i] << ","; });
|
||||
ss << "]";
|
||||
return ss.str();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
#include "BLI_string_ref.hh"
|
||||
|
||||
struct AssetLibrary;
|
||||
struct bScreen;
|
||||
|
||||
namespace blender::asset_system {
|
||||
class AssetCatalogTreeItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the catalogs of \a library are allowed to be editable, or if the UI should forbid
|
||||
|
@ -54,3 +59,16 @@ void ED_asset_catalog_move(
|
|||
AssetLibrary *library,
|
||||
blender::asset_system::CatalogID src_catalog_id,
|
||||
std::optional<blender::asset_system::CatalogID> dst_parent_catalog_id = std::nullopt);
|
||||
|
||||
namespace blender::ed::asset {
|
||||
|
||||
/**
|
||||
* Some code needs 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
|
||||
* directly, which is persistent until the library is reloaded and can safely be held by context.
|
||||
*/
|
||||
PointerRNA persistent_catalog_path_rna_pointer(const bScreen &owner_screen,
|
||||
const asset_system::AssetLibrary &library,
|
||||
const asset_system::AssetCatalogTreeItem &item);
|
||||
|
||||
} // namespace blender::ed::asset
|
||||
|
|
|
@ -10,7 +10,15 @@
|
|||
|
||||
#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 AssetLibraryReference;
|
||||
struct bContext;
|
||||
|
||||
namespace blender::asset_system {
|
||||
class AssetRepresentation;
|
||||
|
@ -30,3 +38,19 @@ 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 AssetLibraryReference &library_ref,
|
||||
const bContext &C,
|
||||
const AssetFilterSettings &filter_settings,
|
||||
FunctionRef<bool(const AssetMetaData &)> meta_data_filter = {});
|
||||
|
||||
} // namespace blender::ed::asset
|
||||
|
|
|
@ -17,6 +17,14 @@
|
|||
#include "DNA_ID_enums.h"
|
||||
#include "DNA_asset_types.h"
|
||||
|
||||
#include "RNA_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
namespace blender::asset_system {
|
||||
class AssetRepresentation;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -38,3 +46,13 @@ void ED_asset_handle_get_full_library_path(
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace blender::ed::asset {
|
||||
|
||||
PointerRNA create_asset_rna_ptr(const asset_system::AssetRepresentation *asset);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,7 @@ struct AssetLibraryReference;
|
|||
struct ID;
|
||||
struct bContext;
|
||||
struct wmNotifier;
|
||||
struct wmRegionListenerParams;
|
||||
|
||||
/**
|
||||
* Invoke asset list reading, potentially in a parallel job. Won't wait until the job is done,
|
||||
|
@ -80,3 +81,13 @@ int ED_assetlist_size(const struct AssetLibraryReference *library_reference);
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace blender::ed::asset {
|
||||
|
||||
void asset_reading_region_listen_fn(const wmRegionListenerParams *params);
|
||||
|
||||
} // namespace blender::ed::asset
|
||||
|
||||
#endif
|
||||
|
|
|
@ -9,10 +9,15 @@
|
|||
#include "AS_asset_library.hh"
|
||||
|
||||
#include "AS_asset_catalog.hh"
|
||||
#include "AS_asset_catalog_tree.hh"
|
||||
|
||||
#include "BKE_main.h"
|
||||
|
||||
#include "BLI_string_utils.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "ED_asset_catalog.h"
|
||||
#include "ED_asset_catalog.hh"
|
||||
|
||||
|
@ -201,3 +206,23 @@ bool ED_asset_catalogs_get_save_catalogs_when_file_is_saved()
|
|||
{
|
||||
return asset_system::AssetLibrary::save_catalogs_when_file_is_saved;
|
||||
}
|
||||
|
||||
namespace blender::ed::asset {
|
||||
|
||||
PointerRNA persistent_catalog_path_rna_pointer(const bScreen &owner_screen,
|
||||
const asset_system::AssetLibrary &library,
|
||||
const asset_system::AssetCatalogTreeItem &item)
|
||||
{
|
||||
const asset_system::AssetCatalog *catalog = library.catalog_service->find_catalog_by_path(
|
||||
item.catalog_path());
|
||||
if (!catalog) {
|
||||
return PointerRNA_NULL;
|
||||
}
|
||||
|
||||
const asset_system::AssetCatalogPath &path = catalog->path;
|
||||
return {&const_cast<ID &>(owner_screen.id),
|
||||
&RNA_AssetCatalogPath,
|
||||
const_cast<asset_system::AssetCatalogPath *>(&path)};
|
||||
}
|
||||
|
||||
} // namespace blender::ed::asset
|
||||
|
|
|
@ -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,62 @@ 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(
|
||||
const AssetLibraryReference &library_ref,
|
||||
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;
|
||||
|
||||
ED_assetlist_storage_fetch(&library_ref, &C);
|
||||
ED_assetlist_ensure_previews_job(&library_ref, &C);
|
||||
asset_system::AssetLibrary *library = ED_assetlist_library_get_once_available(library_ref);
|
||||
if (!library) {
|
||||
return {};
|
||||
}
|
||||
|
||||
ED_assetlist_iterate(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_filter(meta_data)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const asset_system::AssetCatalog *catalog = library->catalog_service->find_catalog(
|
||||
meta_data.catalog_id);
|
||||
if (catalog == nullptr) {
|
||||
return true;
|
||||
}
|
||||
assets_per_path.add(catalog->path, &asset);
|
||||
return true;
|
||||
});
|
||||
|
||||
asset_system::AssetCatalogTree catalogs_with_node_assets;
|
||||
asset_system::AssetCatalogTree &catalog_tree = *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 = 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
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "ED_asset_handle.h"
|
||||
|
||||
AssetRepresentation *ED_asset_handle_get_representation(const AssetHandle *asset)
|
||||
|
@ -64,3 +66,16 @@ void ED_asset_handle_get_full_library_path(const AssetHandle *asset_handle,
|
|||
|
||||
BLI_strncpy(r_full_lib_path, library_path.c_str(), FILE_MAX);
|
||||
}
|
||||
|
||||
namespace blender::ed::asset {
|
||||
|
||||
PointerRNA create_asset_rna_ptr(const asset_system::AssetRepresentation *asset)
|
||||
{
|
||||
PointerRNA ptr{};
|
||||
ptr.owner_id = nullptr;
|
||||
ptr.type = &RNA_AssetRepresentation;
|
||||
ptr.data = const_cast<asset_system::AssetRepresentation *>(asset);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
} // namespace blender::ed::asset
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "AS_asset_library.hh"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "BLI_map.hh"
|
||||
#include "BLI_utility_mixins.hh"
|
||||
|
@ -34,6 +35,7 @@
|
|||
#include "ED_asset_indexer.h"
|
||||
#include "ED_asset_list.h"
|
||||
#include "ED_asset_list.hh"
|
||||
#include "ED_screen.h"
|
||||
#include "asset_library_reference.hh"
|
||||
|
||||
namespace blender::ed::asset {
|
||||
|
@ -426,6 +428,20 @@ AssetListStorage::AssetListMap &AssetListStorage::global_storage()
|
|||
|
||||
/** \} */
|
||||
|
||||
void asset_reading_region_listen_fn(const wmRegionListenerParams *params)
|
||||
{
|
||||
const wmNotifier *wmn = params->notifier;
|
||||
ARegion *region = params->region;
|
||||
|
||||
switch (wmn->category) {
|
||||
case NC_ASSET:
|
||||
if (wmn->data == ND_ASSET_LIST_READING) {
|
||||
ED_region_tag_refresh_ui(region);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace blender::ed::asset
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -4,15 +4,21 @@
|
|||
|
||||
set(INC
|
||||
../include
|
||||
../../asset_system
|
||||
../../blenkernel
|
||||
../../blenlib
|
||||
../../blentranslation
|
||||
../../depsgraph
|
||||
../../functions
|
||||
../../makesdna
|
||||
../../makesrna
|
||||
../../nodes
|
||||
../../windowmanager
|
||||
../../../../intern/guardedalloc
|
||||
../../bmesh
|
||||
|
||||
# RNA_prototypes.h
|
||||
${CMAKE_BINARY_DIR}/source/blender/makesrna
|
||||
)
|
||||
|
||||
set(INC_SYS
|
||||
|
@ -21,6 +27,7 @@ set(INC_SYS
|
|||
set(SRC
|
||||
geometry_attributes.cc
|
||||
geometry_ops.cc
|
||||
node_group_operator.cc
|
||||
|
||||
geometry_intern.hh
|
||||
)
|
||||
|
@ -33,3 +40,6 @@ set(LIB
|
|||
)
|
||||
|
||||
blender_add_lib(bf_editor_geometry "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
|
||||
|
||||
# RNA_prototypes.h dna_type_offsets.h
|
||||
add_dependencies(bf_editor_geometry bf_rna)
|
||||
|
|
|
@ -22,4 +22,6 @@ void GEOMETRY_OT_color_attribute_duplicate(struct wmOperatorType *ot);
|
|||
void GEOMETRY_OT_attribute_convert(struct wmOperatorType *ot);
|
||||
void GEOMETRY_OT_color_attribute_convert(struct wmOperatorType *ot);
|
||||
|
||||
void GEOMETRY_OT_execute_node_group(struct wmOperatorType *ot);
|
||||
|
||||
} // namespace blender::ed::geometry
|
||||
|
|
|
@ -26,4 +26,5 @@ void ED_operatortypes_geometry(void)
|
|||
WM_operatortype_append(GEOMETRY_OT_color_attribute_duplicate);
|
||||
WM_operatortype_append(GEOMETRY_OT_attribute_convert);
|
||||
WM_operatortype_append(GEOMETRY_OT_color_attribute_convert);
|
||||
WM_operatortype_append(GEOMETRY_OT_execute_node_group);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,546 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup edcurves
|
||||
*/
|
||||
|
||||
#include "ED_curves.h"
|
||||
#include "ED_object.h"
|
||||
#include "ED_screen.h"
|
||||
#include "ED_select_utils.h"
|
||||
#include "ED_view3d.h"
|
||||
|
||||
#include "WM_api.h"
|
||||
|
||||
#include "BKE_asset.h"
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_compute_contexts.hh"
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_editmesh.h"
|
||||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_layer.h"
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_material.h"
|
||||
#include "BKE_mesh.hh"
|
||||
#include "BKE_mesh_wrapper.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_pointcloud.h"
|
||||
#include "BKE_report.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
|
||||
#include "DEG_depsgraph.h"
|
||||
#include "DEG_depsgraph_query.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_enum_types.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
#include "UI_resources.h"
|
||||
|
||||
#include "ED_asset.h"
|
||||
#include "ED_geometry.h"
|
||||
#include "ED_mesh.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "FN_lazy_function_execute.hh"
|
||||
|
||||
#include "NOD_geometry_nodes_execute.hh"
|
||||
#include "NOD_geometry_nodes_lazy_function.hh"
|
||||
|
||||
#include "AS_asset_catalog.hh"
|
||||
#include "AS_asset_catalog_path.hh"
|
||||
#include "AS_asset_catalog_tree.hh"
|
||||
#include "AS_asset_library.hh"
|
||||
#include "AS_asset_representation.hh"
|
||||
|
||||
#include "geometry_intern.hh"
|
||||
|
||||
namespace blender::ed::geometry {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Operator
|
||||
* \{ */
|
||||
|
||||
static const asset_system::AssetRepresentation *get_context_asset(const bContext &C)
|
||||
{
|
||||
return reinterpret_cast<const asset_system::AssetRepresentation *>(CTX_wm_asset(&C));
|
||||
}
|
||||
|
||||
static const bNodeTree *get_node_group(const bContext &C)
|
||||
{
|
||||
const asset_system::AssetRepresentation *asset = get_context_asset(C);
|
||||
if (!asset) {
|
||||
return nullptr;
|
||||
}
|
||||
bNodeTree *node_group = reinterpret_cast<bNodeTree *>(
|
||||
ED_asset_get_local_id_from_asset_or_append_and_reuse(CTX_data_main(&C), *asset, ID_NT));
|
||||
if (!node_group) {
|
||||
return nullptr;
|
||||
}
|
||||
if (node_group->type != NTREE_GEOMETRY) {
|
||||
return nullptr;
|
||||
}
|
||||
return node_group;
|
||||
}
|
||||
|
||||
class OperatorComputeContext : public ComputeContext {
|
||||
private:
|
||||
static constexpr const char *s_static_type = "OPERATOR";
|
||||
|
||||
std::string operator_name_;
|
||||
|
||||
public:
|
||||
OperatorComputeContext(std::string operator_name)
|
||||
: ComputeContext(s_static_type, nullptr), operator_name_(std::move(operator_name))
|
||||
{
|
||||
hash_.mix_in(s_static_type, strlen(s_static_type));
|
||||
hash_.mix_in(operator_name_.data(), operator_name_.size());
|
||||
}
|
||||
|
||||
private:
|
||||
void print_current_in_line(std::ostream &stream) const override
|
||||
{
|
||||
stream << "Operator: " << operator_name_;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Geometry nodes currently requires working on "evaluated" data-blocks (rather than "original"
|
||||
* data-blocks that are part of a #Main data-base). This could change in the future, but for now,
|
||||
* we need to create evaluated copies of geometry before passing it to geometry nodes. Implicit
|
||||
* sharing lets us avoid copying attribute data though.
|
||||
*/
|
||||
static bke::GeometrySet get_original_geometry_eval_copy(Object &object)
|
||||
{
|
||||
switch (object.type) {
|
||||
case OB_CURVES: {
|
||||
Curves *curves = BKE_curves_copy_for_eval(static_cast<const Curves *>(object.data));
|
||||
return bke::GeometrySet::create_with_curves(curves);
|
||||
}
|
||||
case OB_POINTCLOUD: {
|
||||
PointCloud *points = BKE_pointcloud_copy_for_eval(
|
||||
static_cast<const PointCloud *>(object.data));
|
||||
return bke::GeometrySet::create_with_pointcloud(points);
|
||||
}
|
||||
case OB_MESH: {
|
||||
const Mesh *mesh = static_cast<const Mesh *>(object.data);
|
||||
if (mesh->edit_mesh) {
|
||||
Mesh *mesh_copy = BKE_mesh_wrapper_from_editmesh(mesh->edit_mesh, nullptr, mesh);
|
||||
BKE_mesh_wrapper_ensure_mdata(mesh_copy);
|
||||
Mesh *final_copy = BKE_mesh_copy_for_eval(mesh_copy);
|
||||
BKE_id_free(nullptr, mesh_copy);
|
||||
return bke::GeometrySet::create_with_mesh(final_copy);
|
||||
}
|
||||
return bke::GeometrySet::create_with_mesh(BKE_mesh_copy_for_eval(mesh));
|
||||
}
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
static void store_result_geometry(Main &bmain, Object &object, bke::GeometrySet geometry)
|
||||
{
|
||||
switch (object.type) {
|
||||
case OB_CURVES: {
|
||||
Curves &curves = *static_cast<Curves *>(object.data);
|
||||
Curves *new_curves = geometry.get_curves_for_write();
|
||||
if (!new_curves) {
|
||||
curves.geometry.wrap() = {};
|
||||
break;
|
||||
}
|
||||
|
||||
/* Anonymous attributes shouldn't be available on the applied geometry. */
|
||||
new_curves->geometry.wrap().attributes_for_write().remove_anonymous();
|
||||
|
||||
curves.geometry.wrap() = std::move(new_curves->geometry.wrap());
|
||||
BKE_object_material_from_eval_data(&bmain, &object, &new_curves->id);
|
||||
break;
|
||||
}
|
||||
case OB_POINTCLOUD: {
|
||||
PointCloud &points = *static_cast<PointCloud *>(object.data);
|
||||
PointCloud *new_points =
|
||||
geometry.get_component_for_write<bke::PointCloudComponent>().release();
|
||||
if (!new_points) {
|
||||
CustomData_free(&points.pdata, points.totpoint);
|
||||
points.totpoint = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Anonymous attributes shouldn't be available on the applied geometry. */
|
||||
new_points->attributes_for_write().remove_anonymous();
|
||||
|
||||
BKE_object_material_from_eval_data(&bmain, &object, &new_points->id);
|
||||
BKE_pointcloud_nomain_to_pointcloud(new_points, &points);
|
||||
break;
|
||||
}
|
||||
case OB_MESH: {
|
||||
Mesh &mesh = *static_cast<Mesh *>(object.data);
|
||||
Mesh *new_mesh = geometry.get_component_for_write<bke::MeshComponent>().release();
|
||||
if (!new_mesh) {
|
||||
BKE_mesh_clear_geometry(&mesh);
|
||||
if (object.mode == OB_MODE_EDIT) {
|
||||
EDBM_mesh_make(&object, SCE_SELECT_VERTEX, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Anonymous attributes shouldn't be available on the applied geometry. */
|
||||
new_mesh->attributes_for_write().remove_anonymous();
|
||||
|
||||
BKE_object_material_from_eval_data(&bmain, &object, &new_mesh->id);
|
||||
BKE_mesh_nomain_to_mesh(new_mesh, &mesh, &object);
|
||||
if (object.mode == OB_MODE_EDIT) {
|
||||
EDBM_mesh_make(&object, SCE_SELECT_VERTEX, true);
|
||||
BKE_editmesh_looptri_and_normals_calc(mesh.edit_mesh);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int run_node_group_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
Depsgraph *depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
|
||||
Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
Object *active_object = CTX_data_active_object(C);
|
||||
if (!active_object) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
if (active_object->mode == OB_MODE_OBJECT) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
const eObjectMode mode = eObjectMode(active_object->mode);
|
||||
|
||||
const bNodeTree *node_tree = get_node_group(*C);
|
||||
if (!node_tree) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
const nodes::GeometryNodesLazyFunctionGraphInfo *lf_graph_info =
|
||||
nodes::ensure_geometry_nodes_lazy_function_graph(*node_tree);
|
||||
if (lf_graph_info == nullptr) {
|
||||
BKE_report(op->reports, RPT_ERROR, "Cannot evaluate node group");
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
uint objects_len = 0;
|
||||
Object **objects = BKE_view_layer_array_from_objects_in_mode_unique_data(
|
||||
scene, view_layer, CTX_wm_view3d(C), &objects_len, mode);
|
||||
|
||||
OperatorComputeContext compute_context(op->type->idname);
|
||||
|
||||
for (Object *object : Span(objects, objects_len)) {
|
||||
if (!ELEM(object->type, OB_CURVES, OB_POINTCLOUD, OB_MESH)) {
|
||||
continue;
|
||||
}
|
||||
nodes::GeoNodesOperatorData operator_eval_data{};
|
||||
operator_eval_data.depsgraph = depsgraph;
|
||||
operator_eval_data.self_object = object;
|
||||
|
||||
bke::GeometrySet geometry_orig = get_original_geometry_eval_copy(*object);
|
||||
|
||||
bke::GeometrySet new_geometry = nodes::execute_geometry_nodes_on_geometry(
|
||||
*node_tree,
|
||||
op->properties,
|
||||
compute_context,
|
||||
std::move(geometry_orig),
|
||||
[&](nodes::GeoNodesLFUserData &user_data) {
|
||||
user_data.operator_data = &operator_eval_data;
|
||||
user_data.log_socket_values = false;
|
||||
});
|
||||
|
||||
store_result_geometry(*bmain, *object, std::move(new_geometry));
|
||||
|
||||
DEG_id_tag_update(static_cast<ID *>(object->data), ID_RECALC_GEOMETRY);
|
||||
WM_event_add_notifier(C, NC_GEOM | ND_DATA, object->data);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(objects);
|
||||
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int run_node_group_invoke(bContext *C, wmOperator *op, const wmEvent * /*event*/)
|
||||
{
|
||||
const bNodeTree *node_tree = get_node_group(*C);
|
||||
if (!node_tree) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
|
||||
nodes::update_input_properties_from_node_tree(*node_tree, op->properties, *op->properties);
|
||||
nodes::update_output_properties_from_node_tree(*node_tree, op->properties, *op->properties);
|
||||
|
||||
return run_node_group_exec(C, op);
|
||||
}
|
||||
|
||||
static char *run_node_group_get_description(bContext *C,
|
||||
wmOperatorType * /*ot*/,
|
||||
PointerRNA * /*ptr*/)
|
||||
{
|
||||
const asset_system::AssetRepresentation *asset = get_context_asset(*C);
|
||||
if (!asset) {
|
||||
return nullptr;
|
||||
}
|
||||
const char *description = asset->get_metadata().description;
|
||||
if (!description) {
|
||||
return nullptr;
|
||||
}
|
||||
return BLI_strdup(description);
|
||||
}
|
||||
|
||||
static bool run_node_group_poll(bContext *C)
|
||||
{
|
||||
const asset_system::AssetRepresentation *asset = get_context_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;
|
||||
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;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Menu
|
||||
* \{ */
|
||||
|
||||
static bool asset_menu_poll(const bContext *C, MenuType * /*mt*/)
|
||||
{
|
||||
return CTX_wm_view3d(C);
|
||||
}
|
||||
|
||||
static asset::AssetItemTree &get_static_item_tree()
|
||||
{
|
||||
static asset::AssetItemTree tree;
|
||||
return tree;
|
||||
}
|
||||
|
||||
static bool all_loading_finished()
|
||||
{
|
||||
AssetLibraryReference all_library_ref = asset_system::all_library_reference();
|
||||
return ED_assetlist_is_loaded(&all_library_ref);
|
||||
}
|
||||
|
||||
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, "Operator");
|
||||
BLI_addtail(&type_filter.tags, &operator_tag);
|
||||
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 false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const AssetLibraryReference library = asset_system::all_library_reference();
|
||||
return asset::build_filtered_all_catalog_tree(library, C, type_filter, meta_data_filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Avoid adding a separate root catalog when the assets have already been added to one of the
|
||||
* builtin menus. The need to define the builtin menu labels here is non-ideal. We don't have
|
||||
* any UI introspection that can do this though.
|
||||
*/
|
||||
static Set<std::string> get_builtin_menus(const ObjectType object_type, const eObjectMode mode)
|
||||
{
|
||||
Set<std::string> menus;
|
||||
switch (object_type) {
|
||||
case OB_CURVES:
|
||||
menus.add_new("View");
|
||||
menus.add_new("Select");
|
||||
menus.add_new("Curves");
|
||||
break;
|
||||
case OB_MESH:
|
||||
switch (mode) {
|
||||
case OB_MODE_EDIT:
|
||||
menus.add_new("View");
|
||||
menus.add_new("Select");
|
||||
menus.add_new("Add");
|
||||
menus.add_new("Mesh");
|
||||
menus.add_new("Vertex");
|
||||
menus.add_new("Edge");
|
||||
menus.add_new("Face");
|
||||
menus.add_new("UV");
|
||||
break;
|
||||
case OB_MODE_SCULPT:
|
||||
menus.add_new("View");
|
||||
menus.add_new("Sculpt");
|
||||
menus.add_new("Mask");
|
||||
menus.add_new("Face Sets");
|
||||
break;
|
||||
case OB_MODE_VERTEX_PAINT:
|
||||
menus.add_new("View");
|
||||
menus.add_new("Paint");
|
||||
break;
|
||||
case OB_MODE_WEIGHT_PAINT:
|
||||
menus.add_new("View");
|
||||
menus.add_new("Weights");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return menus;
|
||||
}
|
||||
|
||||
static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
|
||||
{
|
||||
bScreen &screen = *CTX_wm_screen(C);
|
||||
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;
|
||||
}
|
||||
const auto &menu_path = *static_cast<const asset_system::AssetCatalogPath *>(menu_path_ptr.data);
|
||||
const Span<asset_system::AssetRepresentation *> assets = tree.assets_per_path.lookup(menu_path);
|
||||
asset_system::AssetCatalogTreeItem *catalog_item = tree.catalogs.find_item(menu_path);
|
||||
BLI_assert(catalog_item != nullptr);
|
||||
|
||||
if (assets.is_empty() && !catalog_item->has_children()) {
|
||||
return;
|
||||
}
|
||||
|
||||
uiLayout *layout = menu->layout;
|
||||
uiItemS(layout);
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
asset_system::AssetLibrary *all_library = ED_assetlist_library_get_once_available(
|
||||
asset_system::all_library_reference());
|
||||
if (!all_library) {
|
||||
return;
|
||||
}
|
||||
|
||||
catalog_item->foreach_child([&](asset_system::AssetCatalogTreeItem &child_item) {
|
||||
PointerRNA path_ptr = asset::persistent_catalog_path_rna_pointer(
|
||||
screen, *all_library, child_item);
|
||||
if (path_ptr.data == nullptr) {
|
||||
return;
|
||||
}
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr);
|
||||
uiItemM(col,
|
||||
"GEO_MT_node_operator_catalog_assets",
|
||||
IFACE_(child_item.get_name().c_str()),
|
||||
ICON_NONE);
|
||||
});
|
||||
}
|
||||
|
||||
MenuType node_group_operator_assets_menu()
|
||||
{
|
||||
MenuType type{};
|
||||
STRNCPY(type.idname, "GEO_MT_node_operator_catalog_assets");
|
||||
type.poll = asset_menu_poll;
|
||||
type.draw = node_add_catalog_assets_draw;
|
||||
type.listener = asset::asset_reading_region_listen_fn;
|
||||
return type;
|
||||
}
|
||||
|
||||
void ui_template_node_operator_asset_menu_items(uiLayout &layout,
|
||||
bContext &C,
|
||||
const StringRef catalog_path)
|
||||
{
|
||||
bScreen &screen = *CTX_wm_screen(&C);
|
||||
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 = ED_assetlist_library_get_once_available(
|
||||
asset_system::all_library_reference());
|
||||
if (!all_library) {
|
||||
return;
|
||||
}
|
||||
PointerRNA path_ptr = asset::persistent_catalog_path_rna_pointer(screen, *all_library, *item);
|
||||
if (path_ptr.data == nullptr) {
|
||||
return;
|
||||
}
|
||||
uiItemS(&layout);
|
||||
uiLayout *col = uiLayoutColumn(&layout, false);
|
||||
uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr);
|
||||
uiItemMContents(col, "GEO_MT_node_operator_catalog_assets");
|
||||
}
|
||||
|
||||
void ui_template_node_operator_asset_root_items(uiLayout &layout, bContext &C)
|
||||
{
|
||||
bScreen &screen = *CTX_wm_screen(&C);
|
||||
const Object *active_object = CTX_data_active_object(&C);
|
||||
if (!active_object) {
|
||||
return;
|
||||
}
|
||||
asset::AssetItemTree &tree = get_static_item_tree();
|
||||
tree = build_catalog_tree(C);
|
||||
|
||||
const bool loading_finished = all_loading_finished();
|
||||
if (tree.catalogs.is_empty() && loading_finished) {
|
||||
return;
|
||||
}
|
||||
if (!loading_finished) {
|
||||
uiItemL(&layout, IFACE_("Loading Asset Libraries"), ICON_INFO);
|
||||
}
|
||||
|
||||
asset_system::AssetLibrary *all_library = ED_assetlist_library_get_once_available(
|
||||
asset_system::all_library_reference());
|
||||
if (!all_library) {
|
||||
return;
|
||||
}
|
||||
|
||||
const Set<std::string> builtin_menus = get_builtin_menus(ObjectType(active_object->type),
|
||||
eObjectMode(active_object->mode));
|
||||
|
||||
tree.catalogs.foreach_root_item([&](asset_system::AssetCatalogTreeItem &item) {
|
||||
if (builtin_menus.contains(item.get_name())) {
|
||||
return;
|
||||
}
|
||||
PointerRNA path_ptr = asset::persistent_catalog_path_rna_pointer(screen, *all_library, item);
|
||||
if (path_ptr.data == nullptr) {
|
||||
return;
|
||||
}
|
||||
uiLayout *col = uiLayoutColumn(&layout, false);
|
||||
uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr);
|
||||
const char *text = IFACE_(item.get_name().c_str());
|
||||
uiItemM(col, "GEO_MT_node_operator_catalog_assets", text, ICON_NONE);
|
||||
});
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
} // namespace blender::ed::geometry
|
|
@ -8,9 +8,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "BKE_attribute.h"
|
||||
#include "DNA_customdata_types.h"
|
||||
|
||||
#include "BKE_attribute.h"
|
||||
#include "BKE_screen.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
# include "BLI_string_ref.hh"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -34,3 +40,18 @@ bool ED_geometry_attribute_convert(struct Mesh *mesh,
|
|||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
namespace blender::ed::geometry {
|
||||
|
||||
MenuType node_group_operator_assets_menu();
|
||||
|
||||
void ui_template_node_operator_asset_menu_items(uiLayout &layout,
|
||||
bContext &C,
|
||||
StringRef catalog_path);
|
||||
void ui_template_node_operator_asset_root_items(uiLayout &layout, bContext &C);
|
||||
|
||||
} // namespace blender::ed::geometry
|
||||
|
||||
#endif
|
||||
|
|
|
@ -123,7 +123,7 @@ static void dt_add_vcol_layers(const CustomData *cdata,
|
|||
}
|
||||
}
|
||||
}
|
||||
/* NOTE: #rna_enum_dt_layers_select_src_items enum is from rna_modifier.c. */
|
||||
/* NOTE: #rna_enum_dt_layers_select_src_items enum is from rna_modifier.cc. */
|
||||
static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *UNUSED(prop),
|
||||
|
@ -238,7 +238,7 @@ static const EnumPropertyItem *dt_layers_select_src_itemf(bContext *C,
|
|||
return item;
|
||||
}
|
||||
|
||||
/* NOTE: #rna_enum_dt_layers_select_dst_items enum is from `rna_modifier.c`. */
|
||||
/* NOTE: #rna_enum_dt_layers_select_dst_items enum is from `rna_modifier.cc`. */
|
||||
static const EnumPropertyItem *dt_layers_select_dst_itemf(bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *UNUSED(prop),
|
||||
|
@ -292,7 +292,7 @@ static const EnumPropertyItem *dt_layers_select_itemf(bContext *C,
|
|||
return dt_layers_select_src_itemf(C, ptr, prop, r_free);
|
||||
}
|
||||
|
||||
/* NOTE: rna_enum_dt_mix_mode_items enum is from `rna_modifier.c`. */
|
||||
/* NOTE: rna_enum_dt_mix_mode_items enum is from `rna_modifier.cc`. */
|
||||
static const EnumPropertyItem *dt_mix_mode_itemf(bContext *C,
|
||||
PointerRNA *ptr,
|
||||
PropertyRNA *UNUSED(prop),
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "BLT_translation.h"
|
||||
|
||||
#include "RNA_access.h"
|
||||
#include "RNA_prototypes.h"
|
||||
|
||||
#include "ED_asset.h"
|
||||
#include "ED_screen.h"
|
||||
|
@ -33,129 +32,25 @@ static bool node_add_menu_poll(const bContext *C, MenuType * /*mt*/)
|
|||
return CTX_wm_space_node(C);
|
||||
}
|
||||
|
||||
static void node_add_menu_assets_listen_fn(const wmRegionListenerParams *params)
|
||||
{
|
||||
const wmNotifier *wmn = params->notifier;
|
||||
ARegion *region = params->region;
|
||||
|
||||
switch (wmn->category) {
|
||||
case NC_ASSET:
|
||||
if (wmn->data == ND_ASSET_LIST_READING) {
|
||||
ED_region_tag_refresh_ui(region);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct AssetItemTree {
|
||||
asset_system::AssetCatalogTree catalogs;
|
||||
MultiValueMap<asset_system::AssetCatalogPath, asset_system::AssetRepresentation *>
|
||||
assets_per_path;
|
||||
};
|
||||
|
||||
static AssetLibraryReference all_library_reference()
|
||||
{
|
||||
AssetLibraryReference all_library_ref{};
|
||||
all_library_ref.custom_library_index = -1;
|
||||
all_library_ref.type = ASSET_LIBRARY_ALL;
|
||||
return all_library_ref;
|
||||
}
|
||||
|
||||
static bool all_loading_finished()
|
||||
{
|
||||
AssetLibraryReference all_library_ref = all_library_reference();
|
||||
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()
|
||||
static asset::AssetItemTree build_catalog_tree(const bContext &C, const bNodeTree &node_tree)
|
||||
{
|
||||
const AssetLibraryReference all_library_ref = 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
|
||||
* directly, which is persistent until the library is reloaded and can safely be held by context.
|
||||
*/
|
||||
static PointerRNA persistent_catalog_path_rna_pointer(
|
||||
bScreen &owner_screen,
|
||||
const asset_system::AssetLibrary &library,
|
||||
const asset_system::AssetCatalogTreeItem &item)
|
||||
{
|
||||
const asset_system::AssetCatalog *catalog = library.catalog_service->find_catalog_by_path(
|
||||
item.catalog_path());
|
||||
if (!catalog) {
|
||||
return PointerRNA_NULL;
|
||||
}
|
||||
|
||||
const asset_system::AssetCatalogPath &path = catalog->path;
|
||||
return {&owner_screen.id,
|
||||
&RNA_AssetCatalogPath,
|
||||
const_cast<asset_system::AssetCatalogPath *>(&path)};
|
||||
}
|
||||
|
||||
static 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 = 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) {
|
||||
if (tree_type == nullptr || IDP_Int(tree_type) != node_tree.type) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
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)};
|
||||
};
|
||||
const AssetLibraryReference library = asset_system::all_library_reference();
|
||||
return asset::build_filtered_all_catalog_tree(library, C, type_filter, meta_data_filter);
|
||||
}
|
||||
|
||||
static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
|
||||
|
@ -166,7 +61,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;
|
||||
|
@ -192,21 +87,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{
|
||||
nullptr, &RNA_AssetRepresentation, const_cast<asset_system::AssetRepresentation *>(asset)};
|
||||
PointerRNA asset_ptr = asset::create_asset_rna_ptr(asset);
|
||||
uiLayoutSetContextPointer(col, "asset", &asset_ptr);
|
||||
|
||||
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 = ED_assetlist_library_get_once_available(
|
||||
asset_system::all_library_reference());
|
||||
if (!all_library) {
|
||||
return;
|
||||
}
|
||||
|
||||
catalog_item->foreach_child([&](asset_system::AssetCatalogTreeItem &child_item) {
|
||||
PointerRNA path_ptr = persistent_catalog_path_rna_pointer(screen, *all_library, child_item);
|
||||
PointerRNA path_ptr = asset::persistent_catalog_path_rna_pointer(
|
||||
screen, *all_library, child_item);
|
||||
if (path_ptr.data == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
@ -222,15 +116,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;
|
||||
}
|
||||
|
@ -275,7 +172,8 @@ 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 = ED_assetlist_library_get_once_available(
|
||||
asset_system::all_library_reference());
|
||||
if (!all_library) {
|
||||
return;
|
||||
}
|
||||
|
@ -284,7 +182,7 @@ static void add_root_catalogs_draw(const bContext *C, Menu *menu)
|
|||
if (all_builtin_menus.contains(item.get_name())) {
|
||||
return;
|
||||
}
|
||||
PointerRNA path_ptr = persistent_catalog_path_rna_pointer(screen, *all_library, item);
|
||||
PointerRNA path_ptr = asset::persistent_catalog_path_rna_pointer(screen, *all_library, item);
|
||||
if (path_ptr.data == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
@ -300,7 +198,7 @@ MenuType add_catalog_assets_menu_type()
|
|||
STRNCPY(type.idname, "NODE_MT_node_add_catalog_assets");
|
||||
type.poll = node_add_menu_poll;
|
||||
type.draw = node_add_catalog_assets_draw;
|
||||
type.listener = node_add_menu_assets_listen_fn;
|
||||
type.listener = asset::asset_reading_region_listen_fn;
|
||||
return type;
|
||||
}
|
||||
|
||||
|
@ -310,40 +208,36 @@ MenuType add_root_catalogs_menu_type()
|
|||
STRNCPY(type.idname, "NODE_MT_node_add_root_catalogs");
|
||||
type.poll = node_add_menu_poll;
|
||||
type.draw = add_root_catalogs_draw;
|
||||
type.listener = node_add_menu_assets_listen_fn;
|
||||
type.listener = asset::asset_reading_region_listen_fn;
|
||||
return type;
|
||||
}
|
||||
|
||||
} // namespace blender::ed::space_node
|
||||
|
||||
/* Note: This is only necessary because Python can't set an asset catalog path context item. */
|
||||
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 = ED_assetlist_library_get_once_available(
|
||||
asset_system::all_library_reference());
|
||||
if (!all_library) {
|
||||
return;
|
||||
}
|
||||
|
||||
PointerRNA path_ptr = persistent_catalog_path_rna_pointer(screen, *all_library, *item);
|
||||
PointerRNA path_ptr = asset::persistent_catalog_path_rna_pointer(screen, *all_library, *item);
|
||||
if (path_ptr.data == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
uiItemS(layout);
|
||||
uiLayout *col = uiLayoutColumn(layout, false);
|
||||
uiLayoutSetContextPointer(col, "asset_catalog_path", &path_ptr);
|
||||
|
|
|
@ -93,9 +93,7 @@ static void gather_search_items_for_all_assets(const bContext &C,
|
|||
const bNodeType &group_node_type = *nodeTypeFind(node_tree.typeinfo->group_idname);
|
||||
nodes::GatherAddNodeSearchParams params(C, group_node_type, node_tree, search_items);
|
||||
|
||||
AssetLibraryReference library_ref{};
|
||||
library_ref.custom_library_index = -1;
|
||||
library_ref.type = ASSET_LIBRARY_ALL;
|
||||
const AssetLibraryReference library_ref = asset_system::all_library_reference();
|
||||
|
||||
AssetFilterSettings filter_settings{};
|
||||
filter_settings.id_types = FILTER_ID_NT;
|
||||
|
|
|
@ -128,7 +128,7 @@ static void get_context_path_node_geometry(const bContext &C,
|
|||
SpaceNode &snode,
|
||||
Vector<ui::ContextPathItem> &path)
|
||||
{
|
||||
if (snode.flag & SNODE_PIN) {
|
||||
if (snode.flag & SNODE_PIN || snode.geometry_nodes_type == SNODE_GEOMETRY_OPERATOR) {
|
||||
context_path_add_node_tree_and_node_groups(snode, path);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "BKE_viewer_path.h"
|
||||
#include "BKE_workspace.h"
|
||||
|
||||
#include "ED_geometry.h"
|
||||
#include "ED_object.h"
|
||||
#include "ED_outliner.h"
|
||||
#include "ED_render.h"
|
||||
|
@ -2222,5 +2223,8 @@ void ED_spacetype_view3d()
|
|||
art->regionid = RGN_TYPE_XR;
|
||||
BLI_addhead(&st->regiontypes, art);
|
||||
|
||||
WM_menutype_add(
|
||||
MEM_new<MenuType>(__func__, blender::ed::geometry::node_group_operator_assets_menu()));
|
||||
|
||||
BKE_spacetype_register(st);
|
||||
}
|
||||
|
|
|
@ -544,13 +544,8 @@ typedef enum eGPUTextureUsage {
|
|||
* OR, uses swizzle access masks. Mip-map base layer adjustment and texture channel swizzling
|
||||
* requires a texture view under-the-hood. */
|
||||
GPU_TEXTURE_USAGE_MIP_SWIZZLE_VIEW = (1 << 3),
|
||||
/* Whether a texture can be allocated without any backing memory. It is used as an
|
||||
* attachment to store data, but is not needed by any future passes.
|
||||
* This usage mode should be used in scenarios where an attachment has no previous
|
||||
* contents and is not stored after a render pass. */
|
||||
GPU_TEXTURE_USAGE_MEMORYLESS = (1 << 4),
|
||||
/* Whether the texture needs to be read from by the CPU. */
|
||||
GPU_TEXTURE_USAGE_HOST_READ = (1 << 5),
|
||||
GPU_TEXTURE_USAGE_HOST_READ = (1 << 4),
|
||||
/* Create a texture whose usage cannot be defined prematurely.
|
||||
* This is unoptimized and should not be used. */
|
||||
GPU_TEXTURE_USAGE_GENERAL = 0xFF,
|
||||
|
|
|
@ -1605,7 +1605,12 @@ typedef struct SpaceNode {
|
|||
/** Texture-from object, world or brush (#eSpaceNode_TexFrom). */
|
||||
short texfrom;
|
||||
/** Shader from object or world (#eSpaceNode_ShaderFrom). */
|
||||
short shaderfrom;
|
||||
char shaderfrom;
|
||||
/**
|
||||
* Whether to edit any geometry node group, or follow the active modifier context.
|
||||
* #SpaceNodeGeometryNodesType.
|
||||
*/
|
||||
char geometry_nodes_type;
|
||||
|
||||
/** Grease-pencil data. */
|
||||
struct bGPdata *gpd;
|
||||
|
@ -1649,6 +1654,12 @@ typedef enum eSpaceNode_ShaderFrom {
|
|||
SNODE_SHADER_LINESTYLE = 2,
|
||||
} eSpaceNode_ShaderFrom;
|
||||
|
||||
/** #SpaceNode.geometry_nodes_type */
|
||||
typedef enum SpaceNodeGeometryNodesType {
|
||||
SNODE_GEOMETRY_MODIFIER = 0,
|
||||
SNODE_GEOMETRY_OPERATOR = 1,
|
||||
} SpaceNodeGeometryNodesType;
|
||||
|
||||
/** #SpaceNode.insert_ofs_dir */
|
||||
enum {
|
||||
SNODE_INSERTOFS_DIR_RIGHT = 0,
|
||||
|
|
|
@ -51,7 +51,7 @@ set(DEFSRC
|
|||
rna_material.c
|
||||
rna_mesh.cc
|
||||
rna_meta.cc
|
||||
rna_modifier.c
|
||||
rna_modifier.cc
|
||||
rna_movieclip.c
|
||||
rna_nla.c
|
||||
rna_nodetree.cc
|
||||
|
|
|
@ -4581,7 +4581,7 @@ static RNAProcessItem PROCESS_ITEMS[] = {
|
|||
{"rna_material.c", "rna_material_api.c", RNA_def_material},
|
||||
{"rna_mesh.cc", "rna_mesh_api.cc", RNA_def_mesh},
|
||||
{"rna_meta.cc", "rna_meta_api.c", RNA_def_meta},
|
||||
{"rna_modifier.c", NULL, RNA_def_modifier},
|
||||
{"rna_modifier.cc", NULL, RNA_def_modifier},
|
||||
{"rna_gpencil_legacy_modifier.c", NULL, RNA_def_greasepencil_modifier},
|
||||
{"rna_shader_fx.c", NULL, RNA_def_shader_fx},
|
||||
{"rna_nla.c", NULL, RNA_def_nla},
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7435,6 +7435,20 @@ static void rna_def_space_node(BlenderRNA *brna)
|
|||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem geometry_nodes_type_items[] = {
|
||||
{SNODE_GEOMETRY_MODIFIER,
|
||||
"MODIFIER",
|
||||
0,
|
||||
"Modifier",
|
||||
"Edit node group from active object's active modifier"},
|
||||
{SNODE_GEOMETRY_OPERATOR,
|
||||
"OPERATOR",
|
||||
0,
|
||||
"Operator",
|
||||
"Edit any geometry node group for use as an operator"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
static const EnumPropertyItem backdrop_channels_items[] = {
|
||||
{SNODE_USE_ALPHA,
|
||||
"COLOR_ALPHA",
|
||||
|
@ -7489,6 +7503,13 @@ static void rna_def_space_node(BlenderRNA *brna)
|
|||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "geometry_nodes_type", PROP_ENUM, PROP_NONE);
|
||||
RNA_def_property_enum_sdna(prop, NULL, "geometry_nodes_type");
|
||||
RNA_def_property_enum_items(prop, geometry_nodes_type_items);
|
||||
RNA_def_property_ui_text(prop, "Geometry Nodes Type", "");
|
||||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_ID_ID);
|
||||
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NODE, NULL);
|
||||
|
||||
prop = RNA_def_property(srna, "id", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(prop, "ID", "Data-block whose nodes are being edited");
|
||||
|
|
|
@ -37,6 +37,8 @@ const EnumPropertyItem rna_enum_icon_items[] = {
|
|||
|
||||
# include "DNA_asset_types.h"
|
||||
|
||||
# include "ED_geometry.h"
|
||||
|
||||
const char *rna_translate_ui_text(
|
||||
const char *text, const char *text_ctxt, StructRNA *type, PropertyRNA *prop, bool translate)
|
||||
{
|
||||
|
@ -732,6 +734,19 @@ static uiLayout *rna_uiLayoutColumnWithHeading(
|
|||
return uiLayoutColumnWithHeading(layout, align, heading);
|
||||
}
|
||||
|
||||
static void rna_uiLayout_template_node_operator_asset_menu_items(uiLayout *layout,
|
||||
bContext *C,
|
||||
const char *catalog_path)
|
||||
{
|
||||
blender::ed::geometry::ui_template_node_operator_asset_menu_items(
|
||||
*layout, *C, blender::StringRef(catalog_path));
|
||||
}
|
||||
|
||||
static void rna_uiLayout_template_node_operator_root_items(uiLayout *layout, bContext *C)
|
||||
{
|
||||
blender::ed::geometry::ui_template_node_operator_asset_root_items(*layout, *C);
|
||||
}
|
||||
|
||||
static int rna_ui_get_rnaptr_icon(bContext *C, PointerRNA *ptr_icon)
|
||||
{
|
||||
return UI_icon_from_rnaptr(C, ptr_icon, RNA_struct_ui_icon(ptr_icon->type), false);
|
||||
|
@ -1805,6 +1820,17 @@ void RNA_api_ui_layout(StructRNA *srna)
|
|||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
parm = RNA_def_string(func, "catalog_path", nullptr, 0, "", "");
|
||||
|
||||
func = RNA_def_function(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", nullptr, 0, "", "");
|
||||
|
||||
func = RNA_def_function(srna,
|
||||
"template_node_operator_asset_root_items",
|
||||
"rna_uiLayout_template_node_operator_root_items");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
|
||||
func = RNA_def_function(srna, "template_texture_user", "uiTemplateTextureUser");
|
||||
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
|
||||
|
||||
|
|
|
@ -74,6 +74,13 @@ struct GeoNodesModifierData {
|
|||
const Set<ComputeContextHash> *socket_log_contexts = nullptr;
|
||||
};
|
||||
|
||||
struct GeoNodesOperatorData {
|
||||
/** The object currently effected by the operator. */
|
||||
const Object *self_object = nullptr;
|
||||
/** Current evaluated depsgraph. */
|
||||
Depsgraph *depsgraph = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* Custom user data that is passed to every geometry nodes related lazy-function evaluation.
|
||||
*/
|
||||
|
@ -82,6 +89,10 @@ struct GeoNodesLFUserData : public lf::UserData {
|
|||
* Data from the modifier that is being evaluated.
|
||||
*/
|
||||
GeoNodesModifierData *modifier_data = nullptr;
|
||||
/**
|
||||
* Data from execution as operator in 3D viewport.
|
||||
*/
|
||||
GeoNodesOperatorData *operator_data = nullptr;
|
||||
/**
|
||||
* Current compute context. This is different depending in the (nested) node group that is being
|
||||
* evaluated.
|
||||
|
|
|
@ -33,6 +33,12 @@ bNodeTreeType *ntreeType_Geometry;
|
|||
static void geometry_node_tree_get_from_context(
|
||||
const bContext *C, bNodeTreeType * /*treetype*/, bNodeTree **r_ntree, ID **r_id, ID **r_from)
|
||||
{
|
||||
const SpaceNode *snode = CTX_wm_space_node(C);
|
||||
if (snode->geometry_nodes_type == SNODE_GEOMETRY_OPERATOR) {
|
||||
*r_ntree = snode->nodetree;
|
||||
return;
|
||||
}
|
||||
|
||||
const Scene *scene = CTX_data_scene(C);
|
||||
ViewLayer *view_layer = CTX_data_view_layer(C);
|
||||
BKE_view_layer_synced_ensure(scene, view_layer);
|
||||
|
|
|
@ -3463,6 +3463,9 @@ Vector<const lf::FunctionNode *> GeometryNodesLazyFunctionSideEffectProvider::
|
|||
{
|
||||
GeoNodesLFUserData *user_data = dynamic_cast<GeoNodesLFUserData *>(context.user_data);
|
||||
BLI_assert(user_data != nullptr);
|
||||
if (!user_data->modifier_data) {
|
||||
return {};
|
||||
}
|
||||
const ComputeContextHash &context_hash = user_data->compute_context->hash();
|
||||
const GeoNodesModifierData &modifier_data = *user_data->modifier_data;
|
||||
return modifier_data.side_effect_nodes->lookup(context_hash);
|
||||
|
@ -3520,6 +3523,10 @@ destruct_ptr<lf::LocalUserData> GeoNodesLFUserData::get_local(LinearAllocator<>
|
|||
|
||||
GeoNodesLFLocalUserData::GeoNodesLFLocalUserData(GeoNodesLFUserData &user_data)
|
||||
{
|
||||
if (user_data.modifier_data == nullptr) {
|
||||
this->tree_logger = nullptr;
|
||||
return;
|
||||
}
|
||||
if (user_data.modifier_data->eval_log != nullptr) {
|
||||
this->tree_logger = &user_data.modifier_data->eval_log->get_local_tree_logger(
|
||||
*user_data.compute_context);
|
||||
|
|
Loading…
Reference in New Issue