Eevee-Next: World Reflective Light #108149

Merged
Jeroen Bakker merged 33 commits from Jeroen-Bakker/blender:eevee-next-world-shader into main 2023-06-29 15:25:04 +02:00
36 changed files with 1703 additions and 893 deletions
Showing only changes of commit a9f1372ddd - Show all commits

View File

@ -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:

View File

@ -237,12 +237,17 @@ class NewGeometryNodeTreeAssign(Operator):
return geometry_modifier_poll(context)
def execute(self, context):
modifier = get_context_modifier(context)
if not modifier:
return {'CANCELLED'}
group = geometry_node_group_empty_new()
modifier.node_group = group
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
return {'FINISHED'}

View File

@ -139,25 +139,28 @@ 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()
ob = context.object
if snode.geometry_nodes_type == 'MODIFIER':
ob = context.object
row = layout.row()
if snode.pin:
row.enabled = False
row.template_ID(snode, "node_tree", new="node.new_geometry_node_group_assign")
elif ob:
active_modifier = ob.modifiers.active
if active_modifier and active_modifier.type == 'NODES':
if active_modifier.node_group:
row.template_ID(active_modifier, "node_group", new="object.geometry_node_tree_copy_assign")
row = layout.row()
if snode.pin:
row.enabled = False
row.template_ID(snode, "node_tree", new="node.new_geometry_node_group_assign")
elif ob:
active_modifier = ob.modifiers.active
if active_modifier and active_modifier.type == 'NODES':
if active_modifier.node_group:
row.template_ID(active_modifier, "node_group", new="object.geometry_node_tree_copy_assign")
else:
row.template_ID(active_modifier, "node_group", new="node.new_geometry_node_group_assign")
else:
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")
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)

View File

@ -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"

View File

@ -173,6 +173,8 @@ class AssetLibrary {
Vector<AssetLibraryReference> all_valid_asset_library_refs();
AssetLibraryReference all_library_reference();
} // namespace blender::asset_system
/**

View File

@ -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

View File

@ -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();
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

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,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

View File

@ -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

View File

@ -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
/* -------------------------------------------------------------------- */

View File

@ -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)

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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),

View File

@ -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) {
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)};
};
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);

View File

@ -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;

View File

@ -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 {

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

@ -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);
}

View File

@ -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,

View File

@ -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,

View File

@ -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

View File

@ -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},

View File

@ -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");

View File

@ -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);

View File

@ -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.

View File

@ -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);

View File

@ -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);