Nodes: Move data-block default values with link drag search #105972
@ -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);
|
||||
mod_moder marked this conversation as resolved
Outdated
|
||||
|
||||
/**
|
||||
* 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()) {
|
||||
mod_moder marked this conversation as resolved
Outdated
Hans Goudey
commented
Better to find the socket with the identifier in case we change group nodes to not store all the (hidden) sockets in the future. Better to find the socket with the identifier in case we change group nodes to not store all the (hidden) sockets in the future.
Iliya Katushenock
commented
There is some confusion here, it seems. There is some confusion here, it seems.
Hidden sockets that are inaccessible to built-in nodes will be deleted.
But if the user just doesn't want to see them, we shouldn't want to delete them, does it seem redundant that the node declaration store the hidden states for all sockets of all nodes?
So, for group nodes, created sockets will always exist..
Hans Goudey
commented
My point is, it's just less fragile to use identifiers rather than indices, and it gives us more flexibility in the future, for very little downside. My point is, it's just less fragile to use identifiers rather than indices, and it gives us more flexibility in the future, for very little downside.
|
||||
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
Block a user
Sorry I should have found this this last time. I tried to update your PR directly but couldn't quite figure it out. This comment is a bit out of date. How about this?
I was thinking about expanding with a description of the cases that may now be.
But given the plans to expand this functionality, is it correct to talk about it in a comment in header file?
Maybe not, it's fine to keep it simple too. It's just nice to clarify that it doesn't just move to dst's default value