WIP: Closures and deferred evaluation for geometry nodes #107842

Draft
Lukas Tönne wants to merge 35 commits from LukasTonne/blender:geometry-nodes-closures into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
9 changed files with 192 additions and 0 deletions
Showing only changes of commit 651df82e39 - Show all commits

View File

@ -617,6 +617,16 @@ class NODE_MT_category_GEO_GROUP(Menu):
node_add_menu.draw_assets_for_catalog(layout, self.bl_label)
class NODE_MT_category_GEO_FUNCTION(Menu):
bl_idname = "NODE_MT_category_GEO_FUNCTION"
bl_label = "Function"
def draw(self, context):
layout = self.layout
node_add_menu.add_node_type(layout, "FunctionNodeBind")
node_add_menu.add_node_type(layout, "FunctionNodeEvaluate")
class NODE_MT_category_GEO_LAYOUT(Menu):
bl_idname = "NODE_MT_category_GEO_LAYOUT"
bl_label = "Layout"
@ -651,6 +661,7 @@ class NODE_MT_geometry_node_add_all(Menu):
layout.menu("NODE_MT_category_GEO_UTILITIES")
layout.separator()
layout.menu("NODE_MT_category_GEO_GROUP")
layout.menu("NODE_MT_category_GEO_FUNCTION")
layout.menu("NODE_MT_category_GEO_LAYOUT")
node_add_menu.draw_root_assets(layout)
@ -696,6 +707,7 @@ classes = (
NODE_MT_category_GEO_UTILITIES_MATH,
NODE_MT_category_GEO_UTILITIES_ROTATION,
NODE_MT_category_GEO_GROUP,
NODE_MT_category_GEO_FUNCTION,
NODE_MT_category_GEO_LAYOUT,
)

View File

@ -1608,6 +1608,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define FN_NODE_INPUT_INT 1220
#define FN_NODE_SEPARATE_COLOR 1221
#define FN_NODE_COMBINE_COLOR 1222
#define FN_NODE_BIND 1223
#define FN_NODE_EVALUATE 1224
/** \} */

View File

@ -4544,6 +4544,51 @@ static const EnumPropertyItem *rna_NodeConvertColorSpace_color_space_itemf(
return items;
}
static void rna_FunctionNodeBind_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
{
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = (bNode *)ptr->data;
BKE_ntree_update_tag_node_property(ntree, node);
ED_node_tree_propagate_change(NULL, bmain, ntree);
DEG_relations_tag_update(bmain);
}
static void rna_FunctionNodeBind_node_tree_set(PointerRNA *ptr,
const PointerRNA value,
struct ReportList *UNUSED(reports))
{
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNode *node = ptr->data;
bNodeTree *ngroup = value.data;
const char *disabled_hint = NULL;
if (nodeGroupPoll(ntree, ngroup, &disabled_hint)) {
if (node->id) {
id_us_min(node->id);
}
if (ngroup) {
id_us_plus(&ngroup->id);
}
node->id = &ngroup->id;
}
}
static bool rna_FunctionNodeBind_node_tree_poll(PointerRNA *ptr, const PointerRNA value)
{
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
bNodeTree *ngroup = value.data;
/* only allow node trees of the same type as the bind node's tree */
if (ngroup->type != ntree->type) {
return false;
}
const char *disabled_hint = NULL;
return nodeGroupPoll(ntree, ngroup, &disabled_hint);
}
#else
static const EnumPropertyItem prop_image_layer_items[] = {
@ -5200,6 +5245,25 @@ static void def_fn_combsep_color(StructRNA *srna)
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_socket_update");
}
static void def_fn_bind(StructRNA *srna)
{
PropertyRNA *prop;
prop = RNA_def_property(srna, "node_tree", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "id");
RNA_def_property_struct_type(prop, "NodeTree");
RNA_def_property_pointer_funcs(
prop, NULL, "rna_FunctionNodeBind_node_tree_set", NULL, "rna_FunctionNodeBind_node_tree_poll");
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Node Tree", "");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_FunctionNodeBind_update");
}
static void def_fn_evaluate(StructRNA *srna)
{
}
/* -- Shader Nodes ---------------------------------------------------------- */
static void def_sh_output(StructRNA *srna)

View File

@ -279,6 +279,8 @@ DefNode(FunctionNode, FN_NODE_SEPARATE_COLOR, def_fn_combsep_color, "SEPARATE_CO
DefNode(FunctionNode, FN_NODE_SLICE_STRING, 0, "SLICE_STRING", SliceString, "Slice String", "")
DefNode(FunctionNode, FN_NODE_STRING_LENGTH, 0, "STRING_LENGTH", StringLength, "String Length", "")
DefNode(FunctionNode, FN_NODE_VALUE_TO_STRING, 0, "VALUE_TO_STRING", ValueToString, "Value to String", "")
DefNode(FunctionNode, FN_NODE_BIND, def_fn_bind, "BIND", Bind, "Bind", "")
DefNode(FunctionNode, FN_NODE_EVALUATE, def_fn_evaluate, "EVALUATE", Evaluate, "Evaluate", "")
DefNode(GeometryNode, GEO_NODE_ACCUMULATE_FIELD, def_geo_accumulate_field, "ACCUMULATE_FIELD", AccumulateField, "Accumulate Field", "Add the values of an evaluated field together and output the running total for each element")
DefNode(GeometryNode, GEO_NODE_ATTRIBUTE_DOMAIN_SIZE, def_geo_attribute_domain_size, "ATTRIBUTE_DOMAIN_SIZE", AttributeDomainSize, "Domain Size", "Retrieve the number of elements in a geometry for each attribute domain")

View File

@ -21,9 +21,11 @@ set(INC_SYS
set(SRC
nodes/node_fn_align_euler_to_vector.cc
nodes/node_fn_bind.cc
nodes/node_fn_boolean_math.cc
nodes/node_fn_combine_color.cc
nodes/node_fn_compare.cc
nodes/node_fn_evaluate.cc
nodes/node_fn_float_to_int.cc
nodes/node_fn_input_bool.cc
nodes/node_fn_input_color.cc

View File

@ -7,9 +7,11 @@
void register_function_nodes()
{
register_node_type_fn_align_euler_to_vector();
register_node_type_fn_bind();
register_node_type_fn_boolean_math();
register_node_type_fn_combine_color();
register_node_type_fn_compare();
register_node_type_fn_evaluate();
register_node_type_fn_float_to_int();
register_node_type_fn_input_bool();
register_node_type_fn_input_color();

View File

@ -3,9 +3,11 @@
#pragma once
void register_node_type_fn_align_euler_to_vector();
void register_node_type_fn_bind();
void register_node_type_fn_boolean_math();
void register_node_type_fn_combine_color();
void register_node_type_fn_compare();
void register_node_type_fn_evaluate();
void register_node_type_fn_float_to_int();
void register_node_type_fn_input_bool();
void register_node_type_fn_input_color();

View File

@ -0,0 +1,64 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_listbase.h"
#include "BKE_node_runtime.hh"
#include "UI_interface.h"
#include "UI_resources.h"
#include "NOD_common.h"
#include "node_common.h"
#include "node_function_util.hh"
#include "node_function_util.hh"
namespace blender::nodes::node_fn_bind_cc {
static void node_declare(const bNodeTree &node_tree,
const bNode &node,
NodeDeclaration &r_declaration)
{
const bNodeTree *group = reinterpret_cast<const bNodeTree *>(node.id);
if (!group) {
return;
}
blender::nodes::node_group_declare_dynamic(node_tree, node, r_declaration);
if (!node.id) {
return;
}
if (ID_IS_LINKED(&group->id) && (group->id.tag & LIB_TAG_MISSING)) {
return;
}
const FieldInferencingInterface &field_interface = *group->runtime->field_inferencing_interface;
for (const int i : r_declaration.inputs.index_range()) {
r_declaration.inputs[i]->input_field_type = field_interface.inputs[i];
}
for (const int i : r_declaration.outputs.index_range()) {
r_declaration.outputs[i]->output_field_dependency = field_interface.outputs[i];
}
}
static void node_layout(uiLayout *layout, bContext *C, PointerRNA *ptr)
{
uiTemplateIDBrowse(
layout, C, ptr, "node_tree", nullptr, nullptr, nullptr, UI_TEMPLATE_ID_FILTER_ALL, nullptr);
}
} // namespace blender::nodes::node_fn_bind_cc
void register_node_type_fn_bind()
{
namespace file_ns = blender::nodes::node_fn_bind_cc;
static bNodeType ntype;
fn_node_type_base(&ntype, FN_NODE_BIND, "Bind", NODE_CLASS_GROUP);
ntype.poll_instance = node_group_poll_instance;
node_type_size(&ntype, 140, 60, 400);
ntype.declare_dynamic = file_ns::node_declare;
ntype.draw_buttons = file_ns::node_layout;
nodeRegisterType(&ntype);
}

View File

@ -0,0 +1,42 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_listbase.h"
#include "BLI_math_vector.h"
#include "BLI_string.h"
#include "RNA_enum_types.h"
#include "UI_interface.h"
#include "UI_resources.h"
#include "node_function_util.hh"
namespace blender::nodes::node_fn_evaluate_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.add_input<decl::Function>(N_("Function"));
}
static void node_update(bNodeTree *ntree, bNode *node)
{
}
static void node_layout(uiLayout *layout, bContext * /*C*/, PointerRNA *ptr)
{
}
} // namespace blender::nodes::node_fn_evaluate_cc
void register_node_type_fn_evaluate()
{
namespace file_ns = blender::nodes::node_fn_evaluate_cc;
static bNodeType ntype;
fn_node_type_base(&ntype, FN_NODE_EVALUATE, "Evaluate", NODE_CLASS_GROUP);
ntype.declare = file_ns::node_declare;
ntype.draw_buttons = file_ns::node_layout;
ntype.updatefunc = file_ns::node_update;
nodeRegisterType(&ntype);
}