Geometry Nodes: Operators: Support more object types and modes #109526

Merged
Hans Goudey merged 21 commits from HooglyBoogly/blender:node-group-operators-more-types into main 2023-08-04 18:22:52 +02:00
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());
}