diff options
author | Jacques Lucke <jacques@blender.org> | 2020-10-26 16:16:26 +0300 |
---|---|---|
committer | Jacques Lucke <jacques@blender.org> | 2020-10-26 16:16:26 +0300 |
commit | e04491073d91434a5c3a93ec36d94efd3b540eec (patch) | |
tree | d2133797119d0220c4d9ebe5ae654b43d0bc5b01 | |
parent | a5dda5996e6f7bc41ef8b9ca66ee3c76734b62c1 (diff) |
Geometry Nodes: support evaluation with more than one group input
Group inputs are not yet exposed in the modifier. For now I just added
a simple float setting that will be passed to every float input of the group.
Inputs of other types have some default value.
-rw-r--r-- | source/blender/makesdna/DNA_modifier_types.h | 4 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_modifier.c | 4 | ||||
-rw-r--r-- | source/blender/modifiers/intern/MOD_nodes.cc | 87 |
3 files changed, 63 insertions, 32 deletions
diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index 414c21fd428..a077e3c3f43 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -2222,6 +2222,10 @@ enum { typedef struct NodesModifierData { ModifierData modifier; struct bNodeTree *node_group; + + /* This property exists only temporary for testing purposes. */ + float test_float_input; + char _pad[4]; } NodesModifierData; typedef struct MeshToVolumeModifierData { diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 7715a35af76..af5892d8933 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -6941,6 +6941,10 @@ static void rna_def_modifier_nodes(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + prop = RNA_def_property(srna, "test_float_input", PROP_FLOAT, PROP_NONE); + RNA_def_property_ui_text(prop, "Float Input", "Temporary float input for testing purposes"); + RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update"); + RNA_define_lib_overridable(false); } # endif diff --git a/source/blender/modifiers/intern/MOD_nodes.cc b/source/blender/modifiers/intern/MOD_nodes.cc index 6d7fe559eab..5a368f7087f 100644 --- a/source/blender/modifiers/intern/MOD_nodes.cc +++ b/source/blender/modifiers/intern/MOD_nodes.cc @@ -257,42 +257,41 @@ class GeometryNodesEvaluator { void forward_to_inputs(const DOutputSocket &from_socket, GMutablePointer value_to_forward) { - Span<const DInputSocket *> linked_sockets = from_socket.linked_sockets(); - - Vector<const DInputSocket *> to_sockets_with_same_type; - Vector<const DInputSocket *> to_sockets_with_different_type; - for (const DInputSocket *linked_socket : linked_sockets) { - if (from_socket.typeinfo() == linked_socket->typeinfo()) { - to_sockets_with_same_type.append(linked_socket); - } - else { - to_sockets_with_different_type.append(linked_socket); - } - } + Span<const DInputSocket *> to_sockets_all = from_socket.linked_sockets(); const CPPType &from_type = *value_to_forward.type(); - for (const DInputSocket *to_socket : to_sockets_with_different_type) { + Vector<const DInputSocket *> to_sockets_same_type; + for (const DInputSocket *to_socket : to_sockets_all) { const CPPType &to_type = *socket_cpp_type_get(*to_socket->typeinfo()); - void *buffer = allocator_.allocate(to_type.size(), to_type.alignment()); - conversions_.convert(from_type, to_type, value_to_forward.get(), buffer); - value_by_input_.add_new(to_socket, GMutablePointer{to_type, buffer}); + if (from_type == to_type) { + to_sockets_same_type.append(to_socket); + } + else { + void *buffer = allocator_.allocate(to_type.size(), to_type.alignment()); + if (conversions_.is_convertible(from_type, to_type)) { + conversions_.convert(from_type, to_type, value_to_forward.get(), buffer); + } + else { + to_type.copy_to_uninitialized(to_type.default_value(), buffer); + } + value_by_input_.add_new(to_socket, GMutablePointer{to_type, buffer}); + } } - if (to_sockets_with_same_type.size() == 0) { + if (to_sockets_same_type.size() == 0) { /* This value is not further used, so destruct it. */ value_to_forward.destruct(); } - else if (to_sockets_with_same_type.size() == 1) { + else if (to_sockets_same_type.size() == 1) { /* This value is only used on one input socket, no need to copy it. */ - const DInputSocket *to_socket = to_sockets_with_same_type[0]; + const DInputSocket *to_socket = to_sockets_same_type[0]; value_by_input_.add_new(to_socket, value_to_forward); } else { /* Multiple inputs use the value, make a copy for every input except for one. */ - const DInputSocket *first_to_socket = to_sockets_with_same_type[0]; - Span<const DInputSocket *> other_to_sockets = to_sockets_with_same_type.as_span().drop_front( - 1); + const DInputSocket *first_to_socket = to_sockets_same_type[0]; + Span<const DInputSocket *> other_to_sockets = to_sockets_same_type.as_span().drop_front(1); const CPPType &type = *value_to_forward.type(); value_by_input_.add_new(first_to_socket, value_to_forward); @@ -311,20 +310,43 @@ class GeometryNodesEvaluator { * often than necessary. It's going to be replaced soon. */ static GeometryPtr compute_geometry(const DerivedNodeTree &tree, - const DOutputSocket *group_input, - GeometryPtr group_input_geometry, - const DInputSocket &socket_to_compute) + Span<const DOutputSocket *> group_input_sockets, + const DInputSocket &socket_to_compute, + GeometryPtr input_geometry, + NodesModifierData *nmd) { ResourceCollector resources; + LinearAllocator<> &allocator = resources.linear_allocator(); MultiFunctionByNode mf_by_node = get_multi_function_per_node(tree, resources); - /* Use this buffer so that it is not destructed when the scope ends. The evaluator is responsible - * for destructing it. */ - TypedBuffer<GeometryPtr> buffer; - new (buffer.ptr()) GeometryPtr(std::move(group_input_geometry)); - Map<const DOutputSocket *, GMutablePointer> group_inputs; - group_inputs.add_new(group_input, GMutablePointer{buffer.ptr()}); + + if (group_input_sockets.size() > 0) { + Span<const DOutputSocket *> remaining_input_sockets = group_input_sockets; + + /* If the group expects a geometry as first input, use the geometry that has been passed to + * modifier. */ + const DOutputSocket *first_input_socket = group_input_sockets[0]; + if (first_input_socket->bsocket()->type == SOCK_GEOMETRY) { + GeometryPtr *geometry_in = allocator.construct<GeometryPtr>(std::move(input_geometry)); + group_inputs.add_new(first_input_socket, geometry_in); + remaining_input_sockets = remaining_input_sockets.drop_front(1); + } + + /* Initialize remaining group inputs. */ + for (const DOutputSocket *socket : remaining_input_sockets) { + const CPPType &type = *socket_cpp_type_get(*socket->typeinfo()); + if (type.is<float>()) { + float *value_in = allocator.construct<float>(nmd->test_float_input); + group_inputs.add_new(socket, value_in); + } + else { + void *value_in = allocator.allocate(type.size(), type.alignment()); + type.copy_to_uninitialized(type.default_value(), value_in); + group_inputs.add_new(socket, {type, value_in}); + } + } + } Vector<const DInputSocket *> group_outputs; group_outputs.append(&socket_to_compute); @@ -377,7 +399,7 @@ static Mesh *modifyMesh(ModifierData *md, const ModifierEvalContext *UNUSED(ctx) input_geometry->mesh_set_and_keep_ownership(mesh); GeometryPtr new_geometry = compute_geometry( - tree, group_inputs[0], std::move(input_geometry), *group_outputs[0]); + tree, group_inputs, *group_outputs[0], std::move(input_geometry), nmd); make_geometry_mutable(new_geometry); Mesh *new_mesh = new_geometry->mesh_release(); if (new_mesh == nullptr) { @@ -397,6 +419,7 @@ static void panel_draw(const bContext *UNUSED(C), Panel *panel) uiLayoutSetPropDecorate(layout, false); uiItemR(layout, ptr, "node_group", 0, NULL, ICON_MESH_DATA); + uiItemR(layout, ptr, "test_float_input", 0, NULL, ICON_NONE); modifier_panel_end(layout, ptr); } |