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:
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -546,6 +546,10 @@ class LazyFunctionForSimulationOutputNode final : public LazyFunction {
|
||||
void execute_impl(lf::Params ¶ms, 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; });
|
||||
|
||||
@@ -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 ¶ms, 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 ¶ms, 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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user