Geometry Nodes: Support node tools in object mode
Extend node tools to display tool assets in object mode as well as edit and sculpt modes. For consistency with existing Blender design, selection cannot be set and is just "true" in object mode because it can't be visualized. The visibility of tools can be customized per object type in object mode as well. See #101778 Pull Request: https://projects.blender.org/blender/blender/pulls/114819
This commit is contained in:
parent
6d18fe76b5
commit
3fcd9c9425
|
@ -55,11 +55,13 @@ def geometry_node_group_empty_tool_new(context):
|
|||
else:
|
||||
group.is_type_mesh = True
|
||||
|
||||
mode = context.object.mode if context.object else 'EDIT'
|
||||
mode = context.object.mode if context.object else 'OBJECT'
|
||||
if mode in {'SCULPT', 'SCULPT_CURVES'}:
|
||||
group.is_mode_sculpt = True
|
||||
else:
|
||||
elif mode == 'EDIT':
|
||||
group.is_mode_edit = True
|
||||
else:
|
||||
group.is_mode_object = True
|
||||
|
||||
return group
|
||||
|
||||
|
|
|
@ -472,6 +472,7 @@ class NODE_PT_geometry_node_tool_mode(Panel):
|
|||
group = snode.node_tree
|
||||
|
||||
modes = (
|
||||
("is_mode_object", "Object Mode", 'OBJECT_DATAMODE'),
|
||||
("is_mode_edit", "Edit Mode", 'EDITMODE_HLT'),
|
||||
("is_mode_sculpt", "Sculpt Mode", 'SCULPTMODE_HLT'),
|
||||
)
|
||||
|
|
|
@ -1169,9 +1169,12 @@ class VIEW3D_MT_editor_menus(Menu):
|
|||
layout.menu("VIEW3D_MT_select_sculpt_curves")
|
||||
layout.menu("VIEW3D_MT_sculpt_curves")
|
||||
layout.template_node_operator_asset_root_items()
|
||||
else:
|
||||
layout.template_node_operator_asset_root_items()
|
||||
|
||||
else:
|
||||
layout.menu("VIEW3D_MT_object")
|
||||
layout.template_node_operator_asset_root_items()
|
||||
|
||||
|
||||
# ********** Menu **********
|
||||
|
@ -2743,6 +2746,8 @@ class VIEW3D_MT_object(Menu):
|
|||
layout.operator("object.delete", text="Delete").use_global = False
|
||||
layout.operator("object.delete", text="Delete Global").use_global = True
|
||||
|
||||
layout.template_node_operator_asset_menu_items(catalog_path="Object")
|
||||
|
||||
|
||||
class VIEW3D_MT_object_animation(Menu):
|
||||
bl_label = "Animation"
|
||||
|
@ -3021,6 +3026,8 @@ class VIEW3D_MT_object_context_menu(Menu):
|
|||
layout.operator_context = 'EXEC_REGION_WIN'
|
||||
layout.operator("object.delete", text="Delete").use_global = False
|
||||
|
||||
layout.template_node_operator_asset_menu_items(catalog_path="Object")
|
||||
|
||||
|
||||
class VIEW3D_MT_object_shading(Menu):
|
||||
# XXX, this menu is a place to store shading operator in object mode
|
||||
|
@ -3098,6 +3105,8 @@ class VIEW3D_MT_object_apply(Menu):
|
|||
text="Parent Inverse",
|
||||
text_ctxt=i18n_contexts.default)
|
||||
|
||||
layout.template_node_operator_asset_menu_items(catalog_path="Object/Apply")
|
||||
|
||||
|
||||
class VIEW3D_MT_object_parent(Menu):
|
||||
bl_label = "Parent"
|
||||
|
@ -3180,6 +3189,7 @@ class VIEW3D_MT_object_quick_effects(Menu):
|
|||
layout.operator("object.quick_explode")
|
||||
layout.operator("object.quick_smoke")
|
||||
layout.operator("object.quick_liquid")
|
||||
layout.template_node_operator_asset_menu_items(catalog_path="Object/Quick Effects")
|
||||
|
||||
|
||||
class VIEW3D_MT_object_showhide(Menu):
|
||||
|
@ -3272,6 +3282,8 @@ class VIEW3D_MT_object_convert(Menu):
|
|||
if ob and ob.type == 'CURVES':
|
||||
layout.operator("curves.convert_to_particle_system", text="Particle System")
|
||||
|
||||
layout.template_node_operator_asset_menu_items(catalog_path="Object/Convert")
|
||||
|
||||
|
||||
class VIEW3D_MT_make_links(Menu):
|
||||
bl_label = "Link/Transfer Data"
|
||||
|
|
|
@ -287,6 +287,39 @@ static IDProperty *replace_inputs_evaluated_data_blocks(const IDProperty &op_pro
|
|||
return properties;
|
||||
}
|
||||
|
||||
static bool object_has_editable_data(const Main &bmain, const Object &object)
|
||||
{
|
||||
if (!ELEM(object.type, OB_CURVES, OB_POINTCLOUD, OB_MESH)) {
|
||||
return false;
|
||||
}
|
||||
if (!BKE_id_is_editable(&bmain, static_cast<const ID *>(object.data))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static Vector<Object *> gather_supported_objects(const bContext &C,
|
||||
const Main &bmain,
|
||||
const eObjectMode mode)
|
||||
{
|
||||
Vector<Object *> objects;
|
||||
Set<const ID *> unique_object_data;
|
||||
CTX_DATA_BEGIN (&C, Object *, object, selected_objects) {
|
||||
if (object->mode != mode) {
|
||||
continue;
|
||||
}
|
||||
if (!unique_object_data.add(static_cast<const ID *>(object->data))) {
|
||||
continue;
|
||||
}
|
||||
if (!object_has_editable_data(bmain, *object)) {
|
||||
continue;
|
||||
}
|
||||
objects.append(object);
|
||||
}
|
||||
CTX_DATA_END;
|
||||
return objects;
|
||||
}
|
||||
|
||||
static int run_node_group_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
Main *bmain = CTX_data_main(C);
|
||||
|
@ -296,9 +329,6 @@ static int run_node_group_exec(bContext *C, wmOperator *op)
|
|||
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_orig = get_node_group(*C, *op->ptr, op->reports);
|
||||
|
@ -306,13 +336,10 @@ static int run_node_group_exec(bContext *C, wmOperator *op)
|
|||
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);
|
||||
BLI_SCOPED_DEFER([&]() { MEM_SAFE_FREE(objects); });
|
||||
const Vector<Object *> objects = gather_supported_objects(*C, *bmain, mode);
|
||||
|
||||
Depsgraph *depsgraph = build_depsgraph_from_indirect_ids(
|
||||
*bmain, *scene, *view_layer, *node_tree_orig, {objects, objects_len}, *op->properties);
|
||||
*bmain, *scene, *view_layer, *node_tree_orig, objects, *op->properties);
|
||||
DEG_evaluate_on_refresh(depsgraph);
|
||||
BLI_SCOPED_DEFER([&]() { DEG_graph_free(depsgraph); });
|
||||
|
||||
|
@ -348,11 +375,9 @@ static int run_node_group_exec(bContext *C, wmOperator *op)
|
|||
|
||||
OperatorComputeContext compute_context(op->type->idname);
|
||||
|
||||
for (Object *object : Span(objects, objects_len)) {
|
||||
if (!ELEM(object->type, OB_CURVES, OB_POINTCLOUD, OB_MESH)) {
|
||||
continue;
|
||||
}
|
||||
for (Object *object : objects) {
|
||||
nodes::GeoNodesOperatorData operator_eval_data{};
|
||||
operator_eval_data.mode = mode;
|
||||
operator_eval_data.depsgraph = depsgraph;
|
||||
operator_eval_data.self_object = DEG_get_evaluated_object(depsgraph, object);
|
||||
operator_eval_data.scene = DEG_get_evaluated_scene(depsgraph);
|
||||
|
@ -600,72 +625,138 @@ static bool asset_menu_poll(const bContext *C, MenuType * /*mt*/)
|
|||
return CTX_wm_view3d(C);
|
||||
}
|
||||
|
||||
static GeometryNodeAssetTraitFlag asset_flag_for_context(const eContextObjectMode ctx_mode)
|
||||
static GeometryNodeAssetTraitFlag asset_flag_for_context(const ObjectType type,
|
||||
const eObjectMode mode)
|
||||
{
|
||||
switch (ctx_mode) {
|
||||
case CTX_MODE_EDIT_MESH:
|
||||
switch (type) {
|
||||
case OB_MESH: {
|
||||
switch (mode) {
|
||||
case OB_MODE_OBJECT:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_OBJECT | GEO_NODE_ASSET_MESH);
|
||||
case OB_MODE_EDIT:
|
||||
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:
|
||||
case OB_MODE_SCULPT:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_SCULPT | GEO_NODE_ASSET_MESH);
|
||||
case CTX_MODE_SCULPT_CURVES:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OB_CURVES: {
|
||||
switch (mode) {
|
||||
case OB_MODE_OBJECT:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_OBJECT | GEO_NODE_ASSET_CURVE);
|
||||
case OB_MODE_EDIT:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_EDIT | GEO_NODE_ASSET_CURVE);
|
||||
case OB_MODE_SCULPT_CURVES:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_SCULPT | GEO_NODE_ASSET_CURVE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OB_POINTCLOUD: {
|
||||
switch (mode) {
|
||||
case OB_MODE_OBJECT:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_OBJECT | GEO_NODE_ASSET_POINT_CLOUD);
|
||||
case OB_MODE_EDIT:
|
||||
return (GEO_NODE_ASSET_TOOL | GEO_NODE_ASSET_EDIT | GEO_NODE_ASSET_POINT_CLOUD);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
return GeometryNodeAssetTraitFlag(0);
|
||||
}
|
||||
}
|
||||
|
||||
static asset::AssetItemTree *get_static_item_tree(const eContextObjectMode mode)
|
||||
static GeometryNodeAssetTraitFlag asset_flag_for_context(const Object &active_object)
|
||||
{
|
||||
return asset_flag_for_context(ObjectType(active_object.type), eObjectMode(active_object.mode));
|
||||
}
|
||||
|
||||
static asset::AssetItemTree *get_static_item_tree(const ObjectType type, const eObjectMode mode)
|
||||
{
|
||||
switch (type) {
|
||||
case OB_MESH: {
|
||||
switch (mode) {
|
||||
case CTX_MODE_EDIT_MESH: {
|
||||
case OB_MODE_OBJECT: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
case CTX_MODE_EDIT_CURVES: {
|
||||
case OB_MODE_EDIT: {
|
||||
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: {
|
||||
case OB_MODE_SCULPT: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
case OB_CURVES: {
|
||||
switch (mode) {
|
||||
case OB_MODE_OBJECT: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
case OB_MODE_EDIT: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
case OB_MODE_SCULPT_CURVES: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
case OB_POINTCLOUD: {
|
||||
switch (mode) {
|
||||
case OB_MODE_OBJECT: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
case OB_MODE_EDIT: {
|
||||
static asset::AssetItemTree tree;
|
||||
return &tree;
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
static asset::AssetItemTree *get_static_item_tree(const bContext &C)
|
||||
static asset::AssetItemTree *get_static_item_tree(const Object &active_object)
|
||||
{
|
||||
return get_static_item_tree(eContextObjectMode(CTX_data_mode_enum(&C)));
|
||||
return get_static_item_tree(ObjectType(active_object.type), eObjectMode(active_object.mode));
|
||||
}
|
||||
|
||||
void clear_operator_asset_trees()
|
||||
{
|
||||
for (const int mode : IndexRange(CTX_MODE_NUM)) {
|
||||
if (asset::AssetItemTree *tree = get_static_item_tree(eContextObjectMode(mode)))
|
||||
for (const ObjectType type : {OB_MESH, OB_CURVES, OB_POINTCLOUD}) {
|
||||
for (const eObjectMode mode : {OB_MODE_OBJECT, OB_MODE_EDIT, OB_MODE_SCULPT_CURVES}) {
|
||||
if (asset::AssetItemTree *tree = get_static_item_tree(type, mode)) {
|
||||
*tree = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static asset::AssetItemTree build_catalog_tree(const bContext &C)
|
||||
static asset::AssetItemTree build_catalog_tree(const bContext &C, const Object &active_object)
|
||||
{
|
||||
const eContextObjectMode ctx_mode = eContextObjectMode(CTX_data_mode_enum(&C));
|
||||
AssetFilterSettings type_filter{};
|
||||
type_filter.id_types = FILTER_ID_NT;
|
||||
const GeometryNodeAssetTraitFlag flag = asset_flag_for_context(ctx_mode);
|
||||
const GeometryNodeAssetTraitFlag flag = asset_flag_for_context(active_object);
|
||||
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) {
|
||||
|
@ -703,6 +794,15 @@ static Set<std::string> get_builtin_menus(const ObjectType object_type, const eO
|
|||
break;
|
||||
case OB_MESH:
|
||||
switch (mode) {
|
||||
case OB_MODE_OBJECT:
|
||||
menus.add_new("View");
|
||||
menus.add_new("Select");
|
||||
menus.add_new("Add");
|
||||
menus.add_new("Object");
|
||||
menus.add_new("Object/Apply");
|
||||
menus.add_new("Object/Convert");
|
||||
menus.add_new("Object/Quick Effects");
|
||||
break;
|
||||
case OB_MODE_EDIT:
|
||||
menus.add_new("View");
|
||||
menus.add_new("Select");
|
||||
|
@ -752,7 +852,7 @@ static void catalog_assets_draw(const bContext *C, Menu *menu)
|
|||
if (!active_object) {
|
||||
return;
|
||||
}
|
||||
asset::AssetItemTree *tree = get_static_item_tree(*C);
|
||||
asset::AssetItemTree *tree = get_static_item_tree(*active_object);
|
||||
if (!tree) {
|
||||
return;
|
||||
}
|
||||
|
@ -822,9 +922,11 @@ MenuType node_group_operator_assets_menu()
|
|||
static bool unassigned_local_poll(const bContext &C)
|
||||
{
|
||||
Main &bmain = *CTX_data_main(&C);
|
||||
const GeometryNodeAssetTraitFlag flag = asset_flag_for_context(
|
||||
eContextObjectMode(CTX_data_mode_enum(&C)));
|
||||
|
||||
const Object *active_object = CTX_data_active_object(&C);
|
||||
if (!active_object) {
|
||||
return false;
|
||||
}
|
||||
const GeometryNodeAssetTraitFlag flag = asset_flag_for_context(*active_object);
|
||||
LISTBASE_FOREACH (const bNodeTree *, group, &bmain.nodetrees) {
|
||||
/* Assets are displayed in other menus, and non-local data-blocks aren't added to this menu. */
|
||||
if (group->id.library_weak_reference || group->id.asset_data) {
|
||||
|
@ -841,7 +943,11 @@ static bool unassigned_local_poll(const bContext &C)
|
|||
|
||||
static void catalog_assets_draw_unassigned(const bContext *C, Menu *menu)
|
||||
{
|
||||
asset::AssetItemTree *tree = get_static_item_tree(*C);
|
||||
const Object *active_object = CTX_data_active_object(C);
|
||||
if (!active_object) {
|
||||
return;
|
||||
}
|
||||
asset::AssetItemTree *tree = get_static_item_tree(*active_object);
|
||||
if (!tree) {
|
||||
return;
|
||||
}
|
||||
|
@ -860,8 +966,7 @@ static void catalog_assets_draw_unassigned(const bContext *C, Menu *menu)
|
|||
asset::operator_asset_reference_props_set(*asset, props_ptr);
|
||||
}
|
||||
|
||||
const GeometryNodeAssetTraitFlag flag = asset_flag_for_context(
|
||||
eContextObjectMode(CTX_data_mode_enum(C)));
|
||||
const GeometryNodeAssetTraitFlag flag = asset_flag_for_context(*active_object);
|
||||
|
||||
bool first = true;
|
||||
bool add_separator = !tree->unassigned_assets.is_empty();
|
||||
|
@ -919,7 +1024,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(C);
|
||||
const Object *active_object = CTX_data_active_object(&C);
|
||||
if (!active_object) {
|
||||
return;
|
||||
}
|
||||
asset::AssetItemTree *tree = get_static_item_tree(*active_object);
|
||||
if (!tree) {
|
||||
return;
|
||||
}
|
||||
|
@ -948,12 +1057,12 @@ void ui_template_node_operator_asset_root_items(uiLayout &layout, const bContext
|
|||
if (!active_object) {
|
||||
return;
|
||||
}
|
||||
asset::AssetItemTree *tree = get_static_item_tree(C);
|
||||
asset::AssetItemTree *tree = get_static_item_tree(*active_object);
|
||||
if (!tree) {
|
||||
return;
|
||||
}
|
||||
if (tree->assets_per_path.size() == 0) {
|
||||
*tree = build_catalog_tree(C);
|
||||
*tree = build_catalog_tree(C, *active_object);
|
||||
}
|
||||
|
||||
asset_system::AssetLibrary *all_library = ED_assetlist_library_get_once_available(
|
||||
|
|
|
@ -931,8 +931,9 @@ typedef enum GeometryNodeAssetTraitFlag {
|
|||
GEO_NODE_ASSET_CURVE = (1 << 4),
|
||||
GEO_NODE_ASSET_POINT_CLOUD = (1 << 5),
|
||||
GEO_NODE_ASSET_MODIFIER = (1 << 6),
|
||||
GEO_NODE_ASSET_OBJECT = (1 << 7),
|
||||
} GeometryNodeAssetTraitFlag;
|
||||
ENUM_OPERATORS(GeometryNodeAssetTraitFlag, GEO_NODE_ASSET_MODIFIER);
|
||||
ENUM_OPERATORS(GeometryNodeAssetTraitFlag, GEO_NODE_ASSET_OBJECT);
|
||||
|
||||
/* Data structs, for `node->storage`. */
|
||||
|
||||
|
|
|
@ -1802,6 +1802,15 @@ static void rna_GeometryNodeTree_is_modifier_set(PointerRNA *ptr, bool value)
|
|||
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_MODIFIER, value);
|
||||
}
|
||||
|
||||
static bool rna_GeometryNodeTree_is_mode_object_get(PointerRNA *ptr)
|
||||
{
|
||||
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_OBJECT);
|
||||
}
|
||||
static void rna_GeometryNodeTree_is_mode_object_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
geometry_node_asset_trait_flag_set(ptr, GEO_NODE_ASSET_OBJECT, value);
|
||||
}
|
||||
|
||||
static bool rna_GeometryNodeTree_is_mode_edit_get(PointerRNA *ptr)
|
||||
{
|
||||
return geometry_node_asset_trait_flag_get(ptr, GEO_NODE_ASSET_EDIT);
|
||||
|
@ -10272,6 +10281,14 @@ static void rna_def_geometry_nodetree(BlenderRNA *brna)
|
|||
prop, "rna_GeometryNodeTree_is_modifier_get", "rna_GeometryNodeTree_is_modifier_set");
|
||||
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, "rna_NodeTree_update_asset");
|
||||
|
||||
prop = RNA_def_property(srna, "is_mode_object", 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 object mode");
|
||||
RNA_def_property_boolean_funcs(
|
||||
prop, "rna_GeometryNodeTree_is_mode_object_get", "rna_GeometryNodeTree_is_mode_object_set");
|
||||
RNA_def_property_update(prop, NC_NODE | ND_DISPLAY, "rna_NodeTree_update_asset");
|
||||
|
||||
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);
|
||||
|
|
|
@ -166,6 +166,7 @@ struct GeoNodesModifierData {
|
|||
};
|
||||
|
||||
struct GeoNodesOperatorData {
|
||||
eObjectMode mode;
|
||||
/** The object currently effected by the operator. */
|
||||
const Object *self_object = nullptr;
|
||||
/** Current evaluated depsgraph. */
|
||||
|
|
|
@ -53,7 +53,12 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
if (!check_tool_context_and_error(params)) {
|
||||
return;
|
||||
}
|
||||
if (params.user_data()->operator_data->mode == OB_MODE_OBJECT) {
|
||||
params.set_output("Selection", true);
|
||||
}
|
||||
else {
|
||||
params.set_output("Selection", Field<bool>(std::make_shared<ToolSelectionFieldInput>()));
|
||||
}
|
||||
}
|
||||
|
||||
static void node_register()
|
||||
|
|
|
@ -37,6 +37,11 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
if (!check_tool_context_and_error(params)) {
|
||||
return;
|
||||
}
|
||||
if (params.user_data()->operator_data->mode == OB_MODE_OBJECT) {
|
||||
params.error_message_add(NodeWarningType::Error,
|
||||
"Selection control is not supported in object mode");
|
||||
return;
|
||||
}
|
||||
const Field<bool> selection = params.extract_input<Field<bool>>("Selection");
|
||||
const eAttrDomain domain = eAttrDomain(params.node().custom1);
|
||||
GeometrySet geometry = params.extract_input<GeometrySet>("Geometry");
|
||||
|
|
Loading…
Reference in New Issue