Geometry Nodes: Operators: Support more object types and modes

Add support in the UI for the edit mode of curves, mesh, and point
cloud objects. It's possible to control for which mode sand object
types the asset is available with a dropdown in the node header.
To make this per-mode filtering possible, the static asset tree
cache is now unique per context mode.

See #101778

Pull Request: https://projects.blender.org/blender/blender/pulls/109526
This commit is contained in:
Hans Goudey
2023-08-04 18:22:45 +02:00
committed by Hans Goudey
parent d5eb51e911
commit fd9d22ba57
10 changed files with 332 additions and 23 deletions

View File

@@ -258,6 +258,24 @@ class NewGeometryNodeTreeAssign(Operator):
return {'FINISHED'}
class NewGeometryNodeGroupTool(Operator):
"""Create a new geometry node group for an tool"""
bl_idname = "node.new_geometry_node_group_tool"
bl_label = "New Geometry Node Tool Group"
bl_options = {'REGISTER', 'UNDO'}
@classmethod
def poll(cls, context):
return context.space_data.type == 'NODE_EDITOR' and context.space_data.geometry_nodes_type == 'TOOL'
def execute(self, context):
group = geometry_node_group_empty_new()
group.asset_mark()
group.is_tool = True
context.space_data.node_tree = group
return {'FINISHED'}
class SimulationZoneOperator:
input_node_type = 'GeometryNodeSimulationInput'
output_node_type = 'GeometryNodeSimulationOutput'
@@ -458,6 +476,7 @@ class RepeatZoneItemMoveOperator(RepeatZoneOperator, Operator):
classes = (
NewGeometryNodesModifier,
NewGeometryNodeTreeAssign,
NewGeometryNodeGroupTool,
MoveModifierToNodes,
SimulationZoneItemAddOperator,
SimulationZoneItemRemoveOperator,

View File

@@ -161,7 +161,9 @@ class NODE_HT_header(Header):
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")
layout.template_ID(snode, "node_tree", new="node.new_geometry_node_group_tool")
if snode.node_tree and snode.node_tree.asset_data:
layout.popover(panel="NODE_PT_geometry_node_asset_traits")
else:
# Custom node tree is edited as independent ID block
NODE_MT_editor_menus.draw_collapsible(context, layout)
@@ -430,6 +432,33 @@ class NODE_PT_material_slots(Panel):
row.operator("object.material_slot_deselect", text="Deselect")
class NODE_PT_geometry_node_asset_traits(Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'HEADER'
bl_label = "Asset"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
snode = context.space_data
group = snode.node_tree
col = layout.column(heading="Type")
col.prop(group, "is_tool")
col = layout.column(heading="Mode")
col.active = group.is_tool
col.prop(group, "is_mode_edit")
col.prop(group, "is_mode_sculpt")
col = layout.column(heading="Geometry")
col.active = group.is_tool
col.prop(group, "is_type_mesh")
col.prop(group, "is_type_curve")
if context.preferences.experimental.use_new_point_cloud_type:
col.prop(group, "is_type_point_cloud")
class NODE_PT_node_color_presets(PresetPanel, Panel):
"""Predefined node color"""
bl_label = "Color Presets"
@@ -1236,6 +1265,7 @@ classes = (
NODE_MT_context_menu,
NODE_MT_view_pie,
NODE_PT_material_slots,
NODE_PT_geometry_node_asset_traits,
NODE_PT_node_color_presets,
NODE_PT_active_node_generic,
NODE_PT_active_node_color,

View File

@@ -1020,9 +1020,12 @@ class VIEW3D_MT_editor_menus(Menu):
layout.menu("VIEW3D_MT_edit_mesh_edges")
layout.menu("VIEW3D_MT_edit_mesh_faces")
layout.menu("VIEW3D_MT_uv_map", text="UV")
layout.template_node_operator_asset_root_items()
elif mode_string in {'EDIT_CURVE', 'EDIT_SURFACE'}:
layout.menu("VIEW3D_MT_edit_curve_ctrlpoints")
layout.menu("VIEW3D_MT_edit_curve_segments")
elif mode_string in {'EDIT_CURVES', 'EDIT_POINT_CLOUD'}:
layout.template_node_operator_asset_root_items()
elif mode_string == 'EDIT_GREASE_PENCIL':
layout.menu("VIEW3D_MT_edit_greasepencil_stroke")
@@ -1032,6 +1035,7 @@ class VIEW3D_MT_editor_menus(Menu):
if mode_string == 'SCULPT':
layout.menu("VIEW3D_MT_mask")
layout.menu("VIEW3D_MT_face_sets")
layout.template_node_operator_asset_root_items()
if mode_string == 'SCULPT_CURVES':
layout.menu("VIEW3D_MT_select_sculpt_curves")
layout.menu("VIEW3D_MT_sculpt_curves")
@@ -1259,6 +1263,8 @@ class VIEW3D_MT_uv_map(Menu):
layout.operator("uv.reset")
layout.template_node_operator_asset_menu_items(catalog_path="UV")
# ********** View menus **********
@@ -1771,6 +1777,8 @@ class VIEW3D_MT_select_edit_mesh(Menu):
layout.operator("mesh.select_axis", text="Side of Active")
layout.operator("mesh.select_mirror")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_select_edit_curve(Menu):
bl_label = "Select"
@@ -2141,8 +2149,9 @@ class VIEW3D_MT_select_paint_mask_vertex(Menu):
class VIEW3D_MT_select_edit_point_cloud(Menu):
bl_label = "Select"
def draw(_self, _context):
pass
def draw(self, _context):
layout = self.layout
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_edit_curves_select_more_less(Menu):
@@ -2175,6 +2184,8 @@ class VIEW3D_MT_select_edit_curves(Menu):
layout.menu("VIEW3D_MT_edit_curves_select_more_less")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_select_sculpt_curves(Menu):
bl_label = "Select"
@@ -2215,6 +2226,8 @@ class VIEW3D_MT_mesh_add(Menu):
layout.operator("mesh.primitive_grid_add", text="Grid", icon='MESH_GRID')
layout.operator("mesh.primitive_monkey_add", text="Monkey", icon='MESH_MONKEY')
layout.template_node_operator_asset_menu_items(catalog_path="Add")
class VIEW3D_MT_curve_add(Menu):
bl_idname = "VIEW3D_MT_curve_add"
@@ -3550,6 +3563,7 @@ class VIEW3D_MT_mask(Menu):
layout.menu("VIEW3D_MT_random_mask", text="Random Mask")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_face_sets(Menu):
bl_label = "Face Sets"
@@ -3608,6 +3622,8 @@ class VIEW3D_MT_face_sets(Menu):
props = layout.operator("sculpt.face_sets_randomize_colors", text="Randomize Colors")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_sculpt_set_pivot(Menu):
bl_label = "Sculpt Set Pivot"
@@ -4107,6 +4123,8 @@ class VIEW3D_MT_edit_mesh(Menu):
layout.menu("VIEW3D_MT_edit_mesh_delete")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_edit_mesh_context_menu(Menu):
bl_label = ""
@@ -4426,6 +4444,8 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
layout.operator("object.vertex_parent_set")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_edit_mesh_edges(Menu):
bl_label = "Edge"
@@ -4486,6 +4506,8 @@ class VIEW3D_MT_edit_mesh_edges(Menu):
layout.operator("mesh.mark_freestyle_edge").clear = False
layout.operator("mesh.mark_freestyle_edge", text="Clear Freestyle Edge").clear = True
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_edit_mesh_faces_data(Menu):
bl_label = "Face Data"
@@ -4571,6 +4593,8 @@ class VIEW3D_MT_edit_mesh_faces(Menu):
layout.menu("VIEW3D_MT_edit_mesh_faces_data")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_edit_mesh_normals_select_strength(Menu):
bl_label = "Select by Face Strength"
@@ -5569,13 +5593,15 @@ class VIEW3D_MT_edit_curves(Menu):
layout.menu("VIEW3D_MT_transform")
layout.separator()
layout.operator("curves.delete")
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_edit_pointcloud(Menu):
bl_label = "Point Cloud"
def draw(_self, _context):
pass
def draw(self, context):
layout = self.layout
layout.template_node_operator_asset_menu_items(catalog_path=self.bl_label)
class VIEW3D_MT_object_mode_pie(Menu):

View File

@@ -254,6 +254,11 @@ static void ntree_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, cons
}
}
if (ntree_src->geometry_node_asset_traits) {
ntree_dst->geometry_node_asset_traits = MEM_new<GeometryNodeAssetTraits>(
__func__, *ntree_src->geometry_node_asset_traits);
}
if (ntree_src->nested_node_refs) {
ntree_dst->nested_node_refs = static_cast<bNestedNodeRef *>(
MEM_malloc_arrayN(ntree_src->nested_node_refs_num, sizeof(bNestedNodeRef), __func__));
@@ -324,6 +329,8 @@ static void ntree_free_data(ID *id)
BKE_libblock_free_data(&ntree->id, true);
}
MEM_delete(ntree->geometry_node_asset_traits);
if (ntree->nested_node_refs) {
MEM_freeN(ntree->nested_node_refs);
}
@@ -704,6 +711,8 @@ void ntreeBlendWrite(BlendWriter *writer, bNodeTree *ntree)
BLO_write_string(writer, panel->name);
}
BLO_write_struct(writer, GeometryNodeAssetTraits, ntree->geometry_node_asset_traits);
BLO_write_struct_array(
writer, bNestedNodeRef, ntree->nested_node_refs_num, ntree->nested_node_refs);
@@ -943,6 +952,7 @@ void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree)
BLO_read_data_address(reader, &ntree->panels_array[i]->name);
}
BLO_read_data_address(reader, &ntree->geometry_node_asset_traits);
BLO_read_data_address(reader, &ntree->nested_node_refs);
/* TODO: should be dealt by new generic cache handling of IDs... */
@@ -1157,6 +1167,11 @@ static void node_tree_asset_pre_save(void *asset_ptr, AssetMetaData *asset_data)
}
BKE_asset_metadata_idprop_ensure(asset_data, inputs.release());
BKE_asset_metadata_idprop_ensure(asset_data, outputs.release());
if (node_tree.geometry_node_asset_traits) {
auto property = idprop::create("geometry_node_asset_traits_flag",
node_tree.geometry_node_asset_traits->flag);
BKE_asset_metadata_idprop_ensure(asset_data, property.release());
}
}
} // namespace blender::bke

View File

@@ -546,24 +546,69 @@ static bool asset_menu_poll(const bContext *C, MenuType * /*mt*/)
return CTX_wm_view3d(C);
}
static asset::AssetItemTree &get_static_item_tree()
static GeometryNodeAssetTraitFlag asset_flag_for_context(const eContextObjectMode ctx_mode)
{
static asset::AssetItemTree tree;
return tree;
switch (ctx_mode) {
case CTX_MODE_EDIT_MESH:
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_EDIT | GEO_NODE_ASSET_MESH);
case CTX_MODE_EDIT_CURVES:
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_EDIT | GEO_NODE_ASSET_CURVE);
case CTX_MODE_EDIT_POINT_CLOUD:
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_EDIT | GEO_NODE_ASSET_POINT_CLOUD);
case CTX_MODE_SCULPT:
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_SCULPT | GEO_NODE_ASSET_MESH);
case CTX_MODE_SCULPT_CURVES:
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_SCULPT | GEO_NODE_ASSET_CURVE);
default:
BLI_assert_unreachable();
return GeometryNodeAssetTraitFlag(0);
}
}
static asset::AssetItemTree *get_static_item_tree(const bContext &C)
{
switch (eContextObjectMode(CTX_data_mode_enum(&C))) {
case CTX_MODE_EDIT_MESH: {
static asset::AssetItemTree tree;
return &tree;
}
case CTX_MODE_EDIT_CURVES: {
static asset::AssetItemTree tree;
return &tree;
}
case CTX_MODE_EDIT_POINT_CLOUD: {
static asset::AssetItemTree tree;
return &tree;
}
case CTX_MODE_SCULPT: {
static asset::AssetItemTree tree;
return &tree;
}
case CTX_MODE_SCULPT_CURVES: {
static asset::AssetItemTree tree;
return &tree;
}
default:
return nullptr;
}
}
static asset::AssetItemTree build_catalog_tree(const bContext &C)
{
const eContextObjectMode ctx_mode = eContextObjectMode(CTX_data_mode_enum(&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);
const GeometryNodeAssetTraitFlag flag = asset_flag_for_context(ctx_mode);
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;
}
const IDProperty *traits_flag = BKE_asset_metadata_idprop_find(
&meta_data, "geometry_node_asset_traits_flag");
if (traits_flag == nullptr || (IDP_Int(traits_flag) & flag) != flag) {
return false;
}
return true;
};
const AssetLibraryReference library = asset_system::all_library_reference();
@@ -580,6 +625,7 @@ static Set<std::string> get_builtin_menus(const ObjectType object_type, const eO
Set<std::string> menus;
switch (object_type) {
case OB_CURVES:
case OB_POINTCLOUD:
menus.add_new("View");
menus.add_new("Select");
menus.add_new("Curves");
@@ -622,14 +668,17 @@ static Set<std::string> get_builtin_menus(const ObjectType object_type, const eO
static void node_add_catalog_assets_draw(const bContext *C, Menu *menu)
{
bScreen &screen = *CTX_wm_screen(C);
asset::AssetItemTree &tree = get_static_item_tree();
asset::AssetItemTree *tree = get_static_item_tree(*C);
if (!tree) {
return;
}
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);
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()) {
@@ -693,8 +742,11 @@ void ui_template_node_operator_asset_menu_items(uiLayout &layout,
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);
asset::AssetItemTree *tree = get_static_item_tree(C);
if (!tree) {
return;
}
const asset_system::AssetCatalogTreeItem *item = tree->catalogs.find_root_item(catalog_path);
if (!item) {
return;
}
@@ -720,9 +772,12 @@ void ui_template_node_operator_asset_root_items(uiLayout &layout, bContext &C)
if (!active_object) {
return;
}
asset::AssetItemTree &tree = get_static_item_tree();
tree = build_catalog_tree(C);
if (tree.catalogs.is_empty()) {
asset::AssetItemTree *tree = get_static_item_tree(C);
if (!tree) {
return;
}
*tree = build_catalog_tree(C);
if (tree->catalogs.is_empty()) {
return;
}
@@ -735,7 +790,7 @@ void ui_template_node_operator_asset_root_items(uiLayout &layout, bContext &C)
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) {
tree->catalogs.foreach_root_item([&](asset_system::AssetCatalogTreeItem &item) {
if (builtin_menus.contains(item.get_name())) {
return;
}

View File

@@ -53,6 +53,7 @@ typedef struct bNodeSocketRuntimeHandle bNodeSocketRuntimeHandle;
struct AnimData;
struct Collection;
struct GeometryNodeAssetTraits;
struct ID;
struct Image;
struct ImBuf;
@@ -663,6 +664,8 @@ typedef struct bNodeTree {
int nested_node_refs_num;
bNestedNodeRef *nested_node_refs;
struct GeometryNodeAssetTraits *geometry_node_asset_traits;
/** Image representing what the node group does. */
struct PreviewImage *preview;
@@ -866,6 +869,20 @@ typedef struct bNodeSocketValueMaterial {
struct Material *value;
} bNodeSocketValueMaterial;
typedef struct GeometryNodeAssetTraits {
int flag;
} GeometryNodeAssetTraits;
typedef enum GeometryNodeAssetTraitFlag {
GEO_NODE_ASSET_TOOL = (1 << 0),
GEO_NODE_ASSET_EDIT = (1 << 1),
GEO_NODE_ASSET_SCULPT = (1 << 2),
GEO_NODE_ASSET_MESH = (1 << 3),
GEO_NODE_ASSET_CURVE = (1 << 4),
GEO_NODE_ASSET_POINT_CLOUD = (1 << 5),
} GeometryNodeAssetTraitFlag;
ENUM_OPERATORS(GeometryNodeAssetTraitFlag, GEO_NODE_ASSET_POINT_CLOUD);
/* Data structs, for `node->storage`. */
typedef enum CMPNodeMaskType {

View File

@@ -2120,6 +2120,81 @@ static bool compare_main_operation_supported(const EnumPropertyItem *item)
return !ELEM(item->value, NODE_COMPARE_COLOR_BRIGHTER, NODE_COMPARE_COLOR_DARKER);
}
static bool geometry_node_asset_trait_flag_get(PointerRNA *ptr,
const GeometryNodeAssetTraitFlag flag)
{
const bNodeTree *ntree = static_cast<const bNodeTree *>(ptr->data);
if (!ntree->geometry_node_asset_traits) {
return false;
}
return ntree->geometry_node_asset_traits->flag & flag;
}
static void geometry_node_asset_trait_flag_set(PointerRNA *ptr,
const GeometryNodeAssetTraitFlag flag,
const bool value)
{
bNodeTree *ntree = static_cast<bNodeTree *>(ptr->data);
if (!ntree->geometry_node_asset_traits) {
ntree->geometry_node_asset_traits = MEM_new<GeometryNodeAssetTraits>(__func__);
}
SET_FLAG_FROM_TEST(ntree->geometry_node_asset_traits->flag, value, flag);
}
static bool rna_GeometryNodeTree_is_tool_get(PointerRNA *ptr)
{
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_TOOL);
}
static void rna_GeometryNodeTree_is_tool_set(PointerRNA *ptr, bool value)
{
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_TOOL, value);
}
static bool rna_GeometryNodeTree_is_mode_edit_get(PointerRNA *ptr)
{
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_EDIT);
}
static void rna_GeometryNodeTree_is_mode_edit_set(PointerRNA *ptr, bool value)
{
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_EDIT, value);
}
static bool rna_GeometryNodeTree_is_mode_sculpt_get(PointerRNA *ptr)
{
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_SCULPT);
}
static void rna_GeometryNodeTree_is_mode_sculpt_set(PointerRNA *ptr, bool value)
{
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_SCULPT, value);
}
static bool rna_GeometryNodeTree_is_type_mesh_get(PointerRNA *ptr)
{
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_MESH);
}
static void rna_GeometryNodeTree_is_type_mesh_set(PointerRNA *ptr, bool value)
{
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_MESH, value);
}
static bool rna_GeometryNodeTree_is_type_curve_get(PointerRNA *ptr)
{
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_CURVE);
}
static void rna_GeometryNodeTree_is_type_curve_set(PointerRNA *ptr, bool value)
{
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_CURVE, value);
}
static bool rna_GeometryNodeTree_is_type_point_cloud_get(PointerRNA *ptr)
{
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_POINT_CLOUD);
}
static void rna_GeometryNodeTree_is_type_point_cloud_set(PointerRNA *ptr, bool value)
{
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_POINT_CLOUD, value);
}
static bool compare_rgba_operation_supported(const EnumPropertyItem *item)
{
return ELEM(item->value,
@@ -12316,12 +12391,56 @@ static void rna_def_texture_nodetree(BlenderRNA *brna)
static void rna_def_geometry_nodetree(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
srna = RNA_def_struct(brna, "GeometryNodeTree", "NodeTree");
RNA_def_struct_ui_text(
srna, "Geometry Node Tree", "Node tree consisting of linked nodes used for geometries");
RNA_def_struct_sdna(srna, "bNodeTree");
RNA_def_struct_ui_icon(srna, ICON_NODETREE);
prop = RNA_def_property(srna, "is_tool", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GEO_NODE_ASSET_TOOL);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Tool", "The node group is used as a tool");
RNA_def_property_boolean_funcs(
prop, "rna_GeometryNodeTree_is_tool_get", "rna_GeometryNodeTree_is_tool_set");
prop = RNA_def_property(srna, "is_mode_edit", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GEO_NODE_ASSET_EDIT);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Edit", "The node group is used in edit mode");
RNA_def_property_boolean_funcs(
prop, "rna_GeometryNodeTree_is_mode_edit_get", "rna_GeometryNodeTree_is_mode_edit_set");
prop = RNA_def_property(srna, "is_mode_sculpt", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GEO_NODE_ASSET_SCULPT);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Sculpt", "The node group is used in sculpt mode");
RNA_def_property_boolean_funcs(
prop, "rna_GeometryNodeTree_is_mode_sculpt_get", "rna_GeometryNodeTree_is_mode_sculpt_set");
prop = RNA_def_property(srna, "is_type_mesh", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GEO_NODE_ASSET_MESH);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Mesh", "The node group is used for meshes");
RNA_def_property_boolean_funcs(
prop, "rna_GeometryNodeTree_is_type_mesh_get", "rna_GeometryNodeTree_is_type_mesh_set");
prop = RNA_def_property(srna, "is_type_curve", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GEO_NODE_ASSET_CURVE);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Curves", "The node group is used for curves");
RNA_def_property_boolean_funcs(
prop, "rna_GeometryNodeTree_is_type_curve_get", "rna_GeometryNodeTree_is_type_curve_set");
prop = RNA_def_property(srna, "is_type_point_cloud", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", GEO_NODE_ASSET_POINT_CLOUD);
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Point Cloud", "The node group is used for point clouds");
RNA_def_property_boolean_funcs(prop,
"rna_GeometryNodeTree_is_type_point_cloud_get",
"rna_GeometryNodeTree_is_type_point_cloud_set");
}
static StructRNA *define_specific_node(BlenderRNA *brna,

View File

@@ -59,6 +59,10 @@ class LazyFunctionForSimulationInputNode final : public LazyFunction {
{
const GeoNodesLFUserData &user_data = *static_cast<const GeoNodesLFUserData *>(
context.user_data);
if (!user_data.modifier_data) {
params.set_default_remaining_outputs();
return;
}
const GeoNodesModifierData &modifier_data = *user_data.modifier_data;
if (modifier_data.current_simulation_state == nullptr) {
params.set_default_remaining_outputs();

View File

@@ -546,6 +546,10 @@ class LazyFunctionForSimulationOutputNode final : public LazyFunction {
void execute_impl(lf::Params &params, const lf::Context &context) const final
{
GeoNodesLFUserData &user_data = *static_cast<GeoNodesLFUserData *>(context.user_data);
if (!user_data.modifier_data) {
params.set_default_remaining_outputs();
return;
}
GeoNodesModifierData &modifier_data = *user_data.modifier_data;
EvalData &eval_data = *static_cast<EvalData *>(context.storage);
BLI_SCOPED_DEFER([&]() { eval_data.is_first_evaluation = false; });

View File

@@ -234,6 +234,18 @@ class LazyFunctionForGeometryNode : public LazyFunction {
std::destroy_at(s);
}
static const Object *get_self_object(const GeoNodesLFUserData &user_data)
{
if (user_data.modifier_data) {
return user_data.modifier_data->self_object;
}
if (user_data.operator_data) {
return user_data.operator_data->self_object;
}
BLI_assert_unreachable();
return nullptr;
}
void execute_impl(lf::Params &params, const lf::Context &context) const override
{
Storage *storage = static_cast<Storage *>(context.storage);
@@ -251,7 +263,7 @@ class LazyFunctionForGeometryNode : public LazyFunction {
const bNodeSocket &bsocket = node_.output_socket(output_bsocket_index);
AnonymousAttributeIDPtr attribute_id = MEM_new<NodeAnonymousAttributeID>(
__func__,
*user_data->modifier_data->self_object,
*this->get_self_object(*user_data),
*user_data->compute_context,
node_,
bsocket.identifier,
@@ -838,6 +850,10 @@ class LazyFunctionForViewerInputUsage : public LazyFunction {
{
GeoNodesLFUserData *user_data = dynamic_cast<GeoNodesLFUserData *>(context.user_data);
BLI_assert(user_data != nullptr);
if (!user_data->modifier_data) {
params.set_default_remaining_outputs();
return;
}
const ComputeContextHash &context_hash = user_data->compute_context->hash();
const GeoNodesModifierData &modifier_data = *user_data->modifier_data;
const Span<const lf::FunctionNode *> nodes_with_side_effects =
@@ -861,6 +877,10 @@ class LazyFunctionForSimulationInputsUsage : public LazyFunction {
void execute_impl(lf::Params &params, const lf::Context &context) const override
{
const GeoNodesLFUserData &user_data = *static_cast<GeoNodesLFUserData *>(context.user_data);
if (!user_data.modifier_data) {
params.set_default_remaining_outputs();
return;
}
const GeoNodesModifierData &modifier_data = *user_data.modifier_data;
params.set_output(0,
@@ -1328,7 +1348,7 @@ class LazyFunctionForSimulationZone : public LazyFunction {
GeoNodesLFUserData zone_user_data = user_data;
zone_user_data.compute_context = &compute_context;
if (user_data.modifier_data->socket_log_contexts) {
if (user_data.modifier_data && user_data.modifier_data->socket_log_contexts) {
zone_user_data.log_socket_values = user_data.modifier_data->socket_log_contexts->contains(
compute_context.hash());
}
@@ -1641,7 +1661,7 @@ class LazyFunctionForRepeatZone : public LazyFunction {
user_data.compute_context, repeat_output_bnode_, iteration};
GeoNodesLFUserData body_user_data = user_data;
body_user_data.compute_context = &body_compute_context;
if (user_data.modifier_data->socket_log_contexts) {
if (user_data.modifier_data && user_data.modifier_data->socket_log_contexts) {
body_user_data.log_socket_values = user_data.modifier_data->socket_log_contexts->contains(
body_compute_context.hash());
}