diff options
-rw-r--r-- | source/blender/blenkernel/intern/attribute_access.cc | 4 | ||||
-rw-r--r-- | source/blender/editors/object/object_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/object/object_modifier.c | 51 | ||||
-rw-r--r-- | source/blender/editors/object/object_ops.c | 1 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_nodes.cc | 106 |
5 files changed, 155 insertions, 8 deletions
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc index ee0477faefe..8c4f87be91f 100644 --- a/source/blender/blenkernel/intern/attribute_access.cc +++ b/source/blender/blenkernel/intern/attribute_access.cc @@ -1321,7 +1321,9 @@ const GVArray *AttributeFieldInput::get_varray_for_context(const fn::FieldContex const AttributeDomain domain = geometry_context->domain(); const CustomDataType data_type = cpp_type_to_custom_data_type(*type_); GVArrayPtr attribute = component.attribute_try_get_for_read(name_, domain, data_type); - return scope.add(std::move(attribute)); + if (attribute) { + return scope.add(std::move(attribute)); + } } return nullptr; } diff --git a/source/blender/editors/object/object_intern.h b/source/blender/editors/object/object_intern.h index b2d3216b101..50dd9322c5c 100644 --- a/source/blender/editors/object/object_intern.h +++ b/source/blender/editors/object/object_intern.h @@ -191,6 +191,7 @@ void OBJECT_OT_skin_radii_equalize(struct wmOperatorType *ot); void OBJECT_OT_skin_armature_create(struct wmOperatorType *ot); void OBJECT_OT_laplaciandeform_bind(struct wmOperatorType *ot); void OBJECT_OT_surfacedeform_bind(struct wmOperatorType *ot); +void OBJECT_OT_geometry_nodes_input_attribute_toggle(struct wmOperatorType *ot); /* object_gpencil_modifiers.c */ void OBJECT_OT_gpencil_modifier_add(struct wmOperatorType *ot); diff --git a/source/blender/editors/object/object_modifier.c b/source/blender/editors/object/object_modifier.c index 2a1a6696493..b9942bc563a 100644 --- a/source/blender/editors/object/object_modifier.c +++ b/source/blender/editors/object/object_modifier.c @@ -3242,3 +3242,54 @@ void OBJECT_OT_surfacedeform_bind(wmOperatorType *ot) } /** \} */ + +/* ------------------------------------------------------------------- */ +/** \name Toggle Value or Attribute Operator + * + * \note This operator basically only exists to provide a better tooltip for the toggle button, + * since it is stored as an IDProperty. It also stops the button from being highlighted when + * "use_attribute" is on, which isn't expected. + * \{ */ + +static int geometry_nodes_input_attribute_toggle_exec(bContext *C, wmOperator *op) +{ + Object *ob = ED_object_active_context(C); + + char modifier_name[MAX_NAME]; + RNA_string_get(op->ptr, "modifier_name", modifier_name); + NodesModifierData *nmd = (NodesModifierData *)BKE_modifiers_findby_name(ob, modifier_name); + if (nmd == NULL) { + return OPERATOR_CANCELLED; + } + + char prop_path[MAX_NAME]; + RNA_string_get(op->ptr, "prop_path", prop_path); + + PointerRNA mod_ptr; + RNA_pointer_create(&ob->id, &RNA_Modifier, nmd, &mod_ptr); + + const int old_value = RNA_int_get(&mod_ptr, prop_path); + const int new_value = !old_value; + RNA_int_set(&mod_ptr, prop_path, new_value); + + DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); + WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob); + return OPERATOR_FINISHED; +} + +void OBJECT_OT_geometry_nodes_input_attribute_toggle(wmOperatorType *ot) +{ + ot->name = "Input Attribute Toggle"; + ot->description = + "Switch between an attribute and a single value to define the data for every element"; + ot->idname = "OBJECT_OT_geometry_nodes_input_attribute_toggle"; + + ot->exec = geometry_nodes_input_attribute_toggle_exec; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL; + + RNA_def_string(ot->srna, "prop_path", NULL, 0, "Prop Path", ""); + RNA_def_string(ot->srna, "modifier_name", NULL, MAX_NAME, "Modifier Name", ""); +} + +/** \} */ diff --git a/source/blender/editors/object/object_ops.c b/source/blender/editors/object/object_ops.c index 4b8431be530..aa9ae082317 100644 --- a/source/blender/editors/object/object_ops.c +++ b/source/blender/editors/object/object_ops.c @@ -145,6 +145,7 @@ void ED_operatortypes_object(void) WM_operatortype_append(OBJECT_OT_skin_loose_mark_clear); WM_operatortype_append(OBJECT_OT_skin_radii_equalize); WM_operatortype_append(OBJECT_OT_skin_armature_create); + WM_operatortype_append(OBJECT_OT_geometry_nodes_input_attribute_toggle); /* grease pencil modifiers */ WM_operatortype_append(OBJECT_OT_gpencil_modifier_add); diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 3b952e1e649..011890f4d43 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -68,6 +68,8 @@ #include "UI_interface.h" #include "UI_resources.h" +#include "WM_types.h" + #include "RNA_access.h" #include "RNA_enum_types.h" @@ -291,6 +293,17 @@ static bool logging_enabled(const ModifierEvalContext *ctx) return true; } +static const std::string use_attribute_suffix = "_use_attribute"; +static const std::string attribute_name_suffix = "_attribute_name"; + +/** + * \return Whether using an attribute to input values of this type is supported. + */ +static bool socket_type_has_attribute_toggle(const bNodeSocket &socket) +{ + return ELEM(socket.type, SOCK_FLOAT, SOCK_VECTOR, SOCK_BOOLEAN, SOCK_RGBA, SOCK_INT); +} + static IDProperty *id_property_create_from_socket(const bNodeSocket &socket) { switch (socket.type) { @@ -546,6 +559,32 @@ void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd) new_prop->ui_data = ui_data; } } + + if (socket_type_has_attribute_toggle(*socket)) { + const std::string use_attribute_id = socket->identifier + use_attribute_suffix; + const std::string attribute_name_id = socket->identifier + attribute_name_suffix; + + IDPropertyTemplate idprop = {0}; + IDProperty *use_attribute_prop = IDP_New(IDP_INT, &idprop, use_attribute_id.c_str()); + IDP_AddToGroup(nmd->settings.properties, use_attribute_prop); + + IDProperty *attribute_prop = IDP_New(IDP_STRING, &idprop, attribute_name_id.c_str()); + IDP_AddToGroup(nmd->settings.properties, attribute_prop); + + if (old_properties != nullptr) { + IDProperty *old_prop_use_attribute = IDP_GetPropertyFromGroup(old_properties, + use_attribute_id.c_str()); + if (old_prop_use_attribute != nullptr) { + IDP_CopyPropertyContent(use_attribute_prop, old_prop_use_attribute); + } + + IDProperty *old_attribute_name_prop = IDP_GetPropertyFromGroup(old_properties, + attribute_name_id.c_str()); + if (old_attribute_name_prop != nullptr) { + IDP_CopyPropertyContent(attribute_prop, old_attribute_name_prop); + } + } + } } if (old_properties != nullptr) { @@ -601,8 +640,31 @@ static void initialize_group_input(NodesModifierData &nmd, return; } - init_socket_cpp_value_from_property( - *property, static_cast<eNodeSocketDatatype>(socket.type), r_value); + if (!socket_type_has_attribute_toggle(socket)) { + init_socket_cpp_value_from_property( + *property, static_cast<eNodeSocketDatatype>(socket.type), r_value); + } + + const IDProperty *property_use_attribute = IDP_GetPropertyFromGroup( + nmd.settings.properties, (socket.identifier + use_attribute_suffix).c_str()); + const IDProperty *property_attribute_name = IDP_GetPropertyFromGroup( + nmd.settings.properties, (socket.identifier + attribute_name_suffix).c_str()); + if (property_use_attribute == nullptr || property_attribute_name == nullptr) { + socket.typeinfo->get_geometry_nodes_cpp_value(socket, r_value); + return; + } + + const bool use_attribute = IDP_Int(property_use_attribute) != 0; + if (use_attribute) { + const StringRef attribute_name{IDP_String(property_attribute_name)}; + auto attribute_input = std::make_shared<blender::bke::AttributeFieldInput>( + attribute_name, *socket.typeinfo->get_base_cpp_type()); + new (r_value) blender::fn::GField(std::move(attribute_input), 0); + } + else { + init_socket_cpp_value_from_property( + *property, static_cast<eNodeSocketDatatype>(socket.type), r_value); + } } static Vector<SpaceSpreadsheet *> find_spreadsheet_editors(Main *bmain) @@ -912,13 +974,13 @@ static void modifyGeometrySet(ModifierData *md, * the node socket identifier for the property names, since they are unique, but also having * the correct label displayed in the UI. */ static void draw_property_for_socket(uiLayout *layout, + NodesModifierData *nmd, PointerRNA *bmain_ptr, PointerRNA *md_ptr, - const IDProperty *modifier_props, const bNodeSocket &socket) { /* The property should be created in #MOD_nodes_update_interface with the correct type. */ - IDProperty *property = IDP_GetPropertyFromGroup(modifier_props, socket.identifier); + IDProperty *property = IDP_GetPropertyFromGroup(nmd->settings.properties, socket.identifier); /* IDProperties can be removed with python, so there could be a situation where * there isn't a property for a socket or it doesn't have the correct type. */ @@ -959,8 +1021,38 @@ static void draw_property_for_socket(uiLayout *layout, uiItemPointerR(layout, md_ptr, rna_path, bmain_ptr, "textures", socket.name, ICON_TEXTURE); break; } - default: - uiItemR(layout, md_ptr, rna_path, 0, socket.name, ICON_NONE); + default: { + if (socket_type_has_attribute_toggle(socket) && + USER_EXPERIMENTAL_TEST(&U, use_geometry_nodes_fields)) { + const std::string rna_path_use_attribute = "[\"" + std::string(socket_id_esc) + + use_attribute_suffix + "\"]"; + const std::string rna_path_attribute_name = "[\"" + std::string(socket_id_esc) + + attribute_name_suffix + "\"]"; + + uiLayout *row = uiLayoutRow(layout, true); + const int use_attribute = RNA_int_get(md_ptr, rna_path_use_attribute.c_str()) != 0; + if (use_attribute) { + uiItemR(row, md_ptr, rna_path_attribute_name.c_str(), 0, socket.name, ICON_NONE); + } + else { + uiItemR(row, md_ptr, rna_path, 0, socket.name, ICON_NONE); + } + PointerRNA props; + uiItemFullO(row, + "object.geometry_nodes_input_attribute_toggle", + "", + ICON_SPREADSHEET, + nullptr, + WM_OP_INVOKE_DEFAULT, + 0, + &props); + RNA_string_set(&props, "modifier_name", nmd->modifier.name); + RNA_string_set(&props, "prop_path", rna_path_use_attribute.c_str()); + } + else { + uiItemR(layout, md_ptr, rna_path, 0, socket.name, ICON_NONE); + } + } } } @@ -991,7 +1083,7 @@ static void panel_draw(const bContext *C, Panel *panel) RNA_main_pointer_create(bmain, &bmain_ptr); LISTBASE_FOREACH (bNodeSocket *, socket, &nmd->node_group->inputs) { - draw_property_for_socket(layout, &bmain_ptr, ptr, nmd->settings.properties, *socket); + draw_property_for_socket(layout, nmd, &bmain_ptr, ptr, *socket); } } |