Fix #110516: Geometry nodes use attribute toggle boolean values broken #111433

Merged
Hans Goudey merged 1 commits from HooglyBoogly/blender:fix-input-use-attribute-bool into main 2023-08-24 13:36:32 +02:00
4 changed files with 54 additions and 31 deletions

View File

@ -48,6 +48,7 @@
#include "BKE_geometry_set.hh"
#include "BKE_global.h"
#include "BKE_gpencil_modifier_legacy.h"
#include "BKE_idprop.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_layer.h"
@ -3623,15 +3624,24 @@ static int geometry_nodes_input_attribute_toggle_exec(bContext *C, wmOperator *o
return OPERATOR_CANCELLED;
}
char prop_path[MAX_NAME];
RNA_string_get(op->ptr, "prop_path", prop_path);
char input_name[MAX_NAME];
RNA_string_get(op->ptr, "input_name", input_name);
PointerRNA mod_ptr;
RNA_pointer_create(&ob->id, &RNA_Modifier, nmd, &mod_ptr);
IDProperty *use_attribute = IDP_GetPropertyFromGroup(
nmd->settings.properties, std::string(input_name + std::string("_use_attribute")).c_str());
if (!use_attribute) {
return OPERATOR_CANCELLED;
}
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);
if (use_attribute->type == IDP_INT) {
IDP_Int(use_attribute) = !IDP_Int(use_attribute);
}
else if (use_attribute->type == IDP_BOOLEAN) {
IDP_Bool(use_attribute) = !IDP_Bool(use_attribute);
}
else {
return OPERATOR_CANCELLED;
}
DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
@ -3650,7 +3660,7 @@ void OBJECT_OT_geometry_nodes_input_attribute_toggle(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_INTERNAL;
RNA_def_string(ot->srna, "prop_path", nullptr, 0, "Prop Path", "");
RNA_def_string(ot->srna, "input_name", nullptr, 0, "Input Name", "");
RNA_def_string(ot->srna, "modifier_name", nullptr, MAX_NAME, "Modifier Name", "");
}

View File

@ -1121,8 +1121,6 @@ static void add_attribute_search_or_value_buttons(const bContext &C,
char socket_id_esc[sizeof(socket.identifier) * 2];
BLI_str_escape(socket_id_esc, socket.identifier, sizeof(socket_id_esc));
const std::string rna_path = "[\"" + std::string(socket_id_esc) + "\"]";
const std::string rna_path_use_attribute = "[\"" + std::string(socket_id_esc) +
nodes::input_use_attribute_suffix() + "\"]";
const std::string rna_path_attribute_name = "[\"" + std::string(socket_id_esc) +
nodes::input_attribute_name_suffix() + "\"]";
@ -1133,8 +1131,9 @@ static void add_attribute_search_or_value_buttons(const bContext &C,
uiLayout *name_row = uiLayoutRow(split, false);
uiLayoutSetAlignment(name_row, UI_LAYOUT_ALIGN_RIGHT);
const int use_attribute = RNA_int_get(md_ptr, rna_path_use_attribute.c_str()) != 0;
if (socket.type == SOCK_BOOLEAN && !use_attribute) {
const std::optional<StringRef> attribute_name = nodes::input_attribute_name_get(
*nmd.settings.properties, socket);
if (socket.type == SOCK_BOOLEAN && !attribute_name) {
uiItemL(name_row, "", ICON_NONE);
}
else {
@ -1147,7 +1146,7 @@ static void add_attribute_search_or_value_buttons(const bContext &C,
uiLayoutSetAlignment(prop_row, UI_LAYOUT_ALIGN_EXPAND);
}
if (use_attribute) {
if (attribute_name) {
add_attribute_search_button(C, prop_row, nmd, md_ptr, rna_path_attribute_name, socket, false);
uiItemL(layout, "", ICON_BLANK1);
}
@ -1167,7 +1166,7 @@ static void add_attribute_search_or_value_buttons(const bContext &C,
UI_ITEM_NONE,
&props);
RNA_string_set(&props, "modifier_name", nmd.modifier.name);
RNA_string_set(&props, "prop_path", rna_path_use_attribute.c_str());
RNA_string_set(&props, "input_name", socket.identifier);
}
/* Drawing the properties manually with #uiItemR instead of #uiDefAutoButsRNA allows using

View File

@ -30,6 +30,9 @@ namespace blender::nodes {
StringRef input_use_attribute_suffix();
StringRef input_attribute_name_suffix();
std::optional<StringRef> input_attribute_name_get(const IDProperty &props,
const bNodeSocket &io_input);
/**
* \return Whether using an attribute to input values of this type is supported.
*/

View File

@ -321,6 +321,31 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
}
}
std::optional<StringRef> input_attribute_name_get(const IDProperty &props,
const bNodeSocket &io_input)
{
IDProperty *use_attribute = IDP_GetPropertyFromGroup(
&props, (io_input.identifier + input_use_attribute_suffix()).c_str());
if (!use_attribute) {
return std::nullopt;
}
if (use_attribute->type == IDP_INT) {
if (IDP_Int(use_attribute) == 0) {
return std::nullopt;
}
}
if (use_attribute->type == IDP_BOOLEAN) {
if (!IDP_Bool(use_attribute)) {
return std::nullopt;
}
}
const IDProperty *property_attribute_name = IDP_GetPropertyFromGroup(
&props, (io_input.identifier + input_attribute_name_suffix()).c_str());
return IDP_String(property_attribute_name);
}
static void initialize_group_input(const bNodeTree &tree,
const IDProperty *properties,
const int input_index,
@ -348,23 +373,9 @@ static void initialize_group_input(const bNodeTree &tree,
return;
}
const IDProperty *property_use_attribute = IDP_GetPropertyFromGroup(
properties, (io_input.identifier + input_use_attribute_suffix()).c_str());
const IDProperty *property_attribute_name = IDP_GetPropertyFromGroup(
properties, (io_input.identifier + input_attribute_name_suffix()).c_str());
if (property_use_attribute == nullptr || property_attribute_name == nullptr) {
init_socket_cpp_value_from_property(*property, socket_data_type, 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)};
if (!bke::allow_procedural_attribute_access(attribute_name)) {
init_socket_cpp_value_from_property(*property, socket_data_type, r_value);
return;
}
fn::GField attribute_field = bke::AttributeFieldInput::Create(attribute_name,
const std::optional<StringRef> attribute_name = input_attribute_name_get(*properties, io_input);
if (attribute_name && bke::allow_procedural_attribute_access(*attribute_name)) {
fn::GField attribute_field = bke::AttributeFieldInput::Create(*attribute_name,
*socket_type.base_cpp_type);
const auto *value_or_field_cpp_type = fn::ValueOrFieldCPPType::get_from_self(
*socket_type.geometry_nodes_cpp_type);