Nodes: Move data-block default values with link drag search
When creating nodes by dragging a link, it can be convenient to transfer values from input socket. For reference values, like images, this may be necessary to avoid unnecessary data-block users. This patch starts adding such a system. At this moment this only makes sense for one node (Image Input), but this can be extended to work with other reference types, different non-reference types and support auto-casting (if a float is transferred to the Integer Input node). See task: https://projects.blender.org/blender/blender/issues/102854 Original patch: https://archive.blender.org/developer/D16735 Pull Request: https://projects.blender.org/blender/blender/pulls/105972
This commit is contained in:
parent
e7f395dd20
commit
9726e4a0ad
|
@ -735,6 +735,18 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree,
|
|||
|
||||
bNode *node_copy(bNodeTree *dst_tree, const bNode &src_node, int flag, bool use_unique);
|
||||
|
||||
/**
|
||||
* Move socket default from \a src (input socket) to locations specified by \a dst (output socket).
|
||||
* Result value moved in specific location. (potentially multiple group nodes socket values, if \a
|
||||
* dst is a group input node).
|
||||
* \note Conceptually, the effect should be such that the evaluation of
|
||||
* this graph again returns the value in src.
|
||||
*/
|
||||
void node_socket_move_default_value(Main &bmain,
|
||||
bNodeTree &tree,
|
||||
bNodeSocket &src,
|
||||
bNodeSocket &dst);
|
||||
|
||||
/**
|
||||
* Free the node itself.
|
||||
*
|
||||
|
|
|
@ -2403,6 +2403,94 @@ bNode *node_copy_with_mapping(bNodeTree *dst_tree,
|
|||
return node_dst;
|
||||
}
|
||||
|
||||
static void for_each_node_group_instance(Main &bmain,
|
||||
const bNodeTree &node_group,
|
||||
const Span<int> tree_types_to_lookup,
|
||||
const FunctionRef<void(bNode &)> func)
|
||||
{
|
||||
LISTBASE_FOREACH (bNodeTree *, other_group, &bmain.nodetrees) {
|
||||
if (!tree_types_to_lookup.contains(other_group->type)) {
|
||||
continue;
|
||||
}
|
||||
if (other_group == &node_group) {
|
||||
continue;
|
||||
}
|
||||
|
||||
other_group->ensure_topology_cache();
|
||||
for (bNode *node : other_group->group_nodes()) {
|
||||
if (node->id == &node_group.id) {
|
||||
func(*node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void node_socket_move_default_value(Main &bmain,
|
||||
bNodeTree &tree,
|
||||
bNodeSocket &src,
|
||||
bNodeSocket &dst)
|
||||
{
|
||||
tree.ensure_topology_cache();
|
||||
|
||||
bNode &dst_node = dst.owner_node();
|
||||
bNode &src_node = src.owner_node();
|
||||
|
||||
if (src.is_multi_input()) {
|
||||
/* Multi input sockets no have value. */
|
||||
return;
|
||||
}
|
||||
if (ELEM(NODE_REROUTE, dst_node.type, src_node.type)) {
|
||||
/* Reroute node can't have ownership of socket value directly. */
|
||||
return;
|
||||
}
|
||||
if (dst.type != src.type) {
|
||||
/* It could be possible to support conversion in future. */
|
||||
return;
|
||||
}
|
||||
|
||||
ID **src_socket_value = nullptr;
|
||||
Vector<ID **> dst_values;
|
||||
switch (dst.type) {
|
||||
case SOCK_IMAGE: {
|
||||
Image **tmp_socket_value = &src.default_value_typed<bNodeSocketValueImage>()->value;
|
||||
src_socket_value = reinterpret_cast<ID **>(tmp_socket_value);
|
||||
if (*src_socket_value == nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (dst_node.type) {
|
||||
case GEO_NODE_IMAGE: {
|
||||
dst_values.append(&dst_node.id);
|
||||
break;
|
||||
}
|
||||
case NODE_GROUP_INPUT: {
|
||||
for_each_node_group_instance(bmain, tree, {NTREE_GEOMETRY}, [&](bNode &node_group) {
|
||||
bNodeSocket &socket = node_group.input_by_identifier(dst.identifier);
|
||||
Image **tmp_dst_value = &socket.default_value_typed<bNodeSocketValueImage>()->value;
|
||||
dst_values.append(reinterpret_cast<ID **>(tmp_dst_value));
|
||||
});
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (ID **dst_value : dst_values) {
|
||||
*dst_value = *src_socket_value;
|
||||
id_us_plus(*dst_value);
|
||||
}
|
||||
|
||||
id_us_min(*src_socket_value);
|
||||
*src_socket_value = nullptr;
|
||||
}
|
||||
|
||||
bNode *node_copy(bNodeTree *dst_tree, const bNode &src_node, const int flag, const bool use_unique)
|
||||
{
|
||||
Map<const bNodeSocket *, bNodeSocket *> socket_map;
|
||||
|
|
|
@ -114,6 +114,9 @@ static void add_group_input_node_fn(nodes::LinkSearchOpParams ¶ms)
|
|||
/* Unhide the socket for the new input in the new node and make a connection to it. */
|
||||
socket->flag &= ~SOCK_HIDDEN;
|
||||
nodeAddLink(¶ms.node_tree, &group_input, socket, ¶ms.node, ¶ms.socket);
|
||||
|
||||
bke::node_socket_move_default_value(
|
||||
*CTX_data_main(¶ms.C), params.node_tree, params.socket, *socket);
|
||||
}
|
||||
|
||||
static void add_existing_group_input_fn(nodes::LinkSearchOpParams ¶ms,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include "BLI_set.hh"
|
||||
|
||||
#include "BKE_context.h"
|
||||
#include "BKE_node.h"
|
||||
|
||||
#include "UI_interface.h"
|
||||
|
@ -55,6 +56,11 @@ void LinkSearchOpParams::connect_available_socket(bNode &new_node, StringRef soc
|
|||
return;
|
||||
}
|
||||
nodeAddLink(&node_tree, &new_node, new_node_socket, &node, &socket);
|
||||
if (in_out == SOCK_OUT) {
|
||||
/* If the old socket already contained a value, then transfer it to a new one, from
|
||||
* which this value will get there. */
|
||||
bke::node_socket_move_default_value(*CTX_data_main(&C), node_tree, socket, *new_node_socket);
|
||||
}
|
||||
}
|
||||
|
||||
bNode &LinkSearchOpParams::add_node(StringRef idname)
|
||||
|
|
Loading…
Reference in New Issue