Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc4
-rw-r--r--source/blender/editors/object/object_intern.h1
-rw-r--r--source/blender/editors/object/object_modifier.c51
-rw-r--r--source/blender/editors/object/object_ops.c1
-rw-r--r--source/blender/modifiers/intern/MOD_nodes.cc106
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);
}
}