1
1

Progress on input properties, currently crashes

This commit is contained in:
2023-04-12 16:48:59 -04:00
parent 8be481fbd8
commit 3ce788e015
4 changed files with 150 additions and 124 deletions

View File

@@ -87,7 +87,7 @@ static int run_node_group_exec(bContext *C, wmOperator *op)
bke::ModifierComputeContext compute_context{nullptr, "actually not a modifier"};
GeometrySet new_geometry = nodes::execute_geometry_nodes(
node_tree,
nullptr,
op->properties,
compute_context,
original_geometry,
[&](nodes::GeoNodesLFUserData &user_data) {
@@ -113,12 +113,29 @@ static int run_node_group_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
static int run_node_group_invoke(bContext *C, wmOperator *op, const wmEvent *event)
{
char name[MAX_ID_NAME];
RNA_string_get(op->ptr, "name", name);
const ID *id = BKE_libblock_find_name(CTX_data_main(C), ID_NT, name);
if (!id) {
return OPERATOR_CANCELLED;
}
const bNodeTree &node_tree = reinterpret_cast<const bNodeTree &>(*id);
nodes::update_input_properties_from_node_tree(node_tree, op->properties, *op->properties);
nodes::update_output_properties_from_node_tree(node_tree, op->properties, *op->properties);
return run_node_group_exec(C, op);
}
void CURVES_OT_node_group(wmOperatorType *ot)
{
ot->name = "Run Node Group";
ot->idname = __func__;
ot->description = "Execute a node group on curves"; // TODO: Retrieve from node group.
ot->invoke = run_node_group_invoke;
ot->exec = run_node_group_exec;
ot->poll = editable_curves_poll;

View File

@@ -378,127 +378,6 @@ static bool logging_enabled(const ModifierEvalContext *ctx)
static const std::string use_attribute_suffix = "_use_attribute";
static const std::string attribute_name_suffix = "_attribute_name";
static void update_input_properties_from_node_tree(const bNodeTree &tree,
const IDProperty *old_properties,
IDProperty &properties)
{
tree.ensure_topology_cache();
const Span<const bNodeSocket *> tree_inputs = tree.interface_inputs();
for (const int i : tree_inputs.index_range()) {
const bNodeSocket &socket = *tree_inputs[i];
IDProperty *new_prop = nodes::id_property_create_from_socket(socket).release();
if (new_prop == nullptr) {
/* Out of the set of supported input sockets, only
* geometry sockets aren't added to the modifier. */
BLI_assert(socket.type == SOCK_GEOMETRY);
continue;
}
new_prop->flag |= IDP_FLAG_OVERRIDABLE_LIBRARY;
if (socket.description[0] != '\0') {
IDPropertyUIData *ui_data = IDP_ui_data_ensure(new_prop);
ui_data->description = BLI_strdup(socket.description);
}
IDP_AddToGroup(&properties, new_prop);
if (old_properties != nullptr) {
const IDProperty *old_prop = IDP_GetPropertyFromGroup(old_properties, socket.identifier);
if (old_prop != nullptr) {
if (nodes::id_property_type_matches_socket(socket, *old_prop)) {
/* #IDP_CopyPropertyContent replaces the UI data as well, which we don't (we only
* want to replace the values). So release it temporarily and replace it after. */
IDPropertyUIData *ui_data = new_prop->ui_data;
new_prop->ui_data = nullptr;
IDP_CopyPropertyContent(new_prop, old_prop);
if (new_prop->ui_data != nullptr) {
IDP_ui_data_free(new_prop);
}
new_prop->ui_data = ui_data;
}
else if (old_prop->type == IDP_INT && new_prop->type == IDP_BOOLEAN) {
/* Support versioning from integer to boolean property values. The actual value is stored
* in the same variable for both types. */
new_prop->data.val = old_prop->data.val != 0;
}
}
}
if (nodes::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(&properties, use_attribute_prop);
IDProperty *attribute_prop = IDP_New(IDP_STRING, &idprop, attribute_name_id.c_str());
IDP_AddToGroup(&properties, attribute_prop);
if (old_properties == nullptr) {
if (socket.default_attribute_name && socket.default_attribute_name[0] != '\0') {
IDP_AssignString(attribute_prop, socket.default_attribute_name, MAX_NAME);
IDP_Int(use_attribute_prop) = 1;
}
}
else {
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);
}
}
}
}
}
static void update_output_properties_from_node_tree(const bNodeTree &tree,
const IDProperty *old_properties,
IDProperty &properties)
{
tree.ensure_topology_cache();
const Span<const bNodeSocket *> tree_outputs = tree.interface_outputs();
for (const int i : tree_outputs.index_range()) {
const bNodeSocket &socket = *tree_outputs[i];
if (!nodes::socket_type_has_attribute_toggle(socket)) {
continue;
}
const std::string idprop_name = socket.identifier + attribute_name_suffix;
IDProperty *new_prop = IDP_NewString("", idprop_name.c_str(), MAX_NAME);
if (socket.description[0] != '\0') {
IDPropertyUIData *ui_data = IDP_ui_data_ensure(new_prop);
ui_data->description = BLI_strdup(socket.description);
}
IDP_AddToGroup(&properties, new_prop);
if (old_properties == nullptr) {
if (socket.default_attribute_name && socket.default_attribute_name[0] != '\0') {
IDP_AssignString(new_prop, socket.default_attribute_name, MAX_NAME);
}
}
else {
IDProperty *old_prop = IDP_GetPropertyFromGroup(old_properties, idprop_name.c_str());
if (old_prop != nullptr) {
/* #IDP_CopyPropertyContent replaces the UI data as well, which we don't (we only
* want to replace the values). So release it temporarily and replace it after. */
IDPropertyUIData *ui_data = new_prop->ui_data;
new_prop->ui_data = nullptr;
IDP_CopyPropertyContent(new_prop, old_prop);
if (new_prop->ui_data != nullptr) {
IDP_ui_data_free(new_prop);
}
new_prop->ui_data = ui_data;
}
}
}
}
} // namespace blender
void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
@@ -519,8 +398,9 @@ void MOD_nodes_update_interface(Object *object, NodesModifierData *nmd)
}
IDProperty *new_properties = nmd->settings.properties;
update_input_properties_from_node_tree(*nmd->node_group, old_properties, *new_properties);
update_output_properties_from_node_tree(*nmd->node_group, old_properties, *new_properties);
nodes::update_input_properties_from_node_tree(*nmd->node_group, old_properties, *new_properties);
nodes::update_output_properties_from_node_tree(
*nmd->node_group, old_properties, *new_properties);
if (old_properties != nullptr) {
IDP_FreeProperty(old_properties);

View File

@@ -63,4 +63,12 @@ GeometrySet execute_geometry_nodes(const bNodeTree &btree,
GeometrySet input_geometry,
FunctionRef<void(nodes::GeoNodesLFUserData &)> fill_user_data);
void update_input_properties_from_node_tree(const bNodeTree &tree,
const IDProperty *old_properties,
IDProperty &properties);
void update_output_properties_from_node_tree(const bNodeTree &tree,
const IDProperty *old_properties,
IDProperty &properties);
} // namespace blender::nodes

View File

@@ -582,4 +582,125 @@ GeometrySet execute_geometry_nodes(
return output_geometry;
}
void update_input_properties_from_node_tree(const bNodeTree &tree,
const IDProperty *old_properties,
IDProperty &properties)
{
tree.ensure_topology_cache();
const Span<const bNodeSocket *> tree_inputs = tree.interface_inputs();
for (const int i : tree_inputs.index_range()) {
const bNodeSocket &socket = *tree_inputs[i];
IDProperty *new_prop = nodes::id_property_create_from_socket(socket).release();
if (new_prop == nullptr) {
/* Out of the set of supported input sockets, only
* geometry sockets aren't added to the modifier. */
BLI_assert(socket.type == SOCK_GEOMETRY);
continue;
}
new_prop->flag |= IDP_FLAG_OVERRIDABLE_LIBRARY;
if (socket.description[0] != '\0') {
IDPropertyUIData *ui_data = IDP_ui_data_ensure(new_prop);
ui_data->description = BLI_strdup(socket.description);
}
IDP_AddToGroup(&properties, new_prop);
if (old_properties != nullptr) {
const IDProperty *old_prop = IDP_GetPropertyFromGroup(old_properties, socket.identifier);
if (old_prop != nullptr) {
if (nodes::id_property_type_matches_socket(socket, *old_prop)) {
/* #IDP_CopyPropertyContent replaces the UI data as well, which we don't (we only
* want to replace the values). So release it temporarily and replace it after. */
IDPropertyUIData *ui_data = new_prop->ui_data;
new_prop->ui_data = nullptr;
IDP_CopyPropertyContent(new_prop, old_prop);
if (new_prop->ui_data != nullptr) {
IDP_ui_data_free(new_prop);
}
new_prop->ui_data = ui_data;
}
else if (old_prop->type == IDP_INT && new_prop->type == IDP_BOOLEAN) {
/* Support versioning from integer to boolean property values. The actual value is stored
* in the same variable for both types. */
new_prop->data.val = old_prop->data.val != 0;
}
}
}
if (nodes::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(&properties, use_attribute_prop);
IDProperty *attribute_prop = IDP_New(IDP_STRING, &idprop, attribute_name_id.c_str());
IDP_AddToGroup(&properties, attribute_prop);
if (old_properties == nullptr) {
if (socket.default_attribute_name && socket.default_attribute_name[0] != '\0') {
IDP_AssignString(attribute_prop, socket.default_attribute_name, MAX_NAME);
IDP_Int(use_attribute_prop) = 1;
}
}
else {
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);
}
}
}
}
}
void update_output_properties_from_node_tree(const bNodeTree &tree,
const IDProperty *old_properties,
IDProperty &properties)
{
tree.ensure_topology_cache();
const Span<const bNodeSocket *> tree_outputs = tree.interface_outputs();
for (const int i : tree_outputs.index_range()) {
const bNodeSocket &socket = *tree_outputs[i];
if (!nodes::socket_type_has_attribute_toggle(socket)) {
continue;
}
const std::string idprop_name = socket.identifier + attribute_name_suffix;
IDProperty *new_prop = IDP_NewString("", idprop_name.c_str(), MAX_NAME);
if (socket.description[0] != '\0') {
IDPropertyUIData *ui_data = IDP_ui_data_ensure(new_prop);
ui_data->description = BLI_strdup(socket.description);
}
IDP_AddToGroup(&properties, new_prop);
if (old_properties == nullptr) {
if (socket.default_attribute_name && socket.default_attribute_name[0] != '\0') {
IDP_AssignString(new_prop, socket.default_attribute_name, MAX_NAME);
}
}
else {
IDProperty *old_prop = IDP_GetPropertyFromGroup(old_properties, idprop_name.c_str());
if (old_prop != nullptr) {
/* #IDP_CopyPropertyContent replaces the UI data as well, which we don't (we only
* want to replace the values). So release it temporarily and replace it after. */
IDPropertyUIData *ui_data = new_prop->ui_data;
new_prop->ui_data = nullptr;
IDP_CopyPropertyContent(new_prop, old_prop);
if (new_prop->ui_data != nullptr) {
IDP_ui_data_free(new_prop);
}
new_prop->ui_data = ui_data;
}
}
}
}
} // namespace blender::nodes