Geometry Nodes: sync bundle/closure nodes on first link
When using link-drag-search to create bundle or closure nodes, the newly created nodes are already synced automatically. Now this automatic syncing also happens when an empty node is first linked. If there are any sockets already, the automatic syncing does not happen as it can be unintentional. In this case the user can just click the sync icon in the node header to update the sockets. Pull Request: https://projects.blender.org/blender/blender/pulls/143744
This commit is contained in:
@@ -226,6 +226,8 @@ struct NodeInsertLinkParams {
|
||||
bNodeTree &ntree;
|
||||
bNode &node;
|
||||
bNodeLink &link;
|
||||
/** Optional context to allow for more advanced link insertion functionality. */
|
||||
bContext *C = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -286,7 +286,8 @@ static bNodeSocket *best_socket_input(bNodeTree *ntree, bNode *node, int num, in
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool snode_autoconnect_input(SpaceNode &snode,
|
||||
static bool snode_autoconnect_input(bContext &C,
|
||||
SpaceNode &snode,
|
||||
bNode *node_fr,
|
||||
bNodeSocket *sock_fr,
|
||||
bNode *node_to,
|
||||
@@ -302,14 +303,14 @@ static bool snode_autoconnect_input(SpaceNode &snode,
|
||||
bNodeLink &link = bke::node_add_link(*ntree, *node_fr, *sock_fr, *node_to, *sock_to);
|
||||
|
||||
if (link.fromnode->typeinfo->insert_link) {
|
||||
bke::NodeInsertLinkParams params{*ntree, *link.fromnode, link};
|
||||
bke::NodeInsertLinkParams params{*ntree, *link.fromnode, link, &C};
|
||||
if (!link.fromnode->typeinfo->insert_link(params)) {
|
||||
bke::node_remove_link(ntree, link);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (link.tonode->typeinfo->insert_link) {
|
||||
bke::NodeInsertLinkParams params{*ntree, *link.tonode, link};
|
||||
bke::NodeInsertLinkParams params{*ntree, *link.tonode, link, &C};
|
||||
if (!link.tonode->typeinfo->insert_link(params)) {
|
||||
bke::node_remove_link(ntree, link);
|
||||
return false;
|
||||
@@ -365,7 +366,10 @@ void update_multi_input_indices_for_removed_links(bNode &node)
|
||||
}
|
||||
}
|
||||
|
||||
static void snode_autoconnect(SpaceNode &snode, const bool allow_multiple, const bool replace)
|
||||
static void snode_autoconnect(bContext &C,
|
||||
SpaceNode &snode,
|
||||
const bool allow_multiple,
|
||||
const bool replace)
|
||||
{
|
||||
bNodeTree *ntree = snode.edittree;
|
||||
Vector<bNode *> sorted_nodes = get_selected_nodes(*ntree).extract_vector();
|
||||
@@ -401,7 +405,7 @@ static void snode_autoconnect(SpaceNode &snode, const bool allow_multiple, const
|
||||
continue;
|
||||
}
|
||||
|
||||
if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace)) {
|
||||
if (snode_autoconnect_input(C, snode, node_fr, sock_fr, node_to, sock_to, replace)) {
|
||||
// numlinks++;
|
||||
}
|
||||
}
|
||||
@@ -425,7 +429,7 @@ static void snode_autoconnect(SpaceNode &snode, const bool allow_multiple, const
|
||||
continue;
|
||||
}
|
||||
|
||||
if (snode_autoconnect_input(snode, node_fr, sock_fr, node_to, sock_to, replace)) {
|
||||
if (snode_autoconnect_input(C, snode, node_fr, sock_fr, node_to, sock_to, replace)) {
|
||||
// numlinks++;
|
||||
break;
|
||||
}
|
||||
@@ -1260,14 +1264,14 @@ static void add_dragged_links_to_tree(bContext &C, bNodeLinkDrag &nldrag)
|
||||
bNodeLink *new_link = MEM_mallocN<bNodeLink>(__func__);
|
||||
*new_link = link;
|
||||
if (link.fromnode->typeinfo->insert_link) {
|
||||
bke::NodeInsertLinkParams params{ntree, *link.fromnode, *new_link};
|
||||
bke::NodeInsertLinkParams params{ntree, *link.fromnode, *new_link, &C};
|
||||
if (!link.fromnode->typeinfo->insert_link(params)) {
|
||||
MEM_freeN(new_link);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (link.tonode->typeinfo->insert_link) {
|
||||
bke::NodeInsertLinkParams params{ntree, *link.tonode, *new_link};
|
||||
bke::NodeInsertLinkParams params{ntree, *link.tonode, *new_link, &C};
|
||||
if (!link.tonode->typeinfo->insert_link(params)) {
|
||||
MEM_freeN(new_link);
|
||||
continue;
|
||||
@@ -1660,7 +1664,7 @@ static wmOperatorStatus node_make_link_exec(bContext *C, wmOperator *op)
|
||||
|
||||
ED_preview_kill_jobs(CTX_wm_manager(C), &bmain);
|
||||
|
||||
snode_autoconnect(snode, true, replace);
|
||||
snode_autoconnect(*C, snode, true, replace);
|
||||
|
||||
/* Deselect sockets after linking. */
|
||||
node_deselect_all_input_sockets(node_tree, false);
|
||||
|
||||
@@ -12,6 +12,7 @@ struct ReportList;
|
||||
struct bContext;
|
||||
struct bNodeTree;
|
||||
struct Main;
|
||||
struct bNodeSocket;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
@@ -32,16 +33,20 @@ void node_can_sync_cache_clear(Main &bmain);
|
||||
|
||||
void sync_sockets_evaluate_closure(SpaceNode &snode,
|
||||
bNode &evaluate_closure_node,
|
||||
ReportList *reports);
|
||||
ReportList *reports,
|
||||
const bNodeSocket *src_closure_socket = nullptr);
|
||||
void sync_sockets_separate_bundle(SpaceNode &snode,
|
||||
bNode &separate_bundle_node,
|
||||
ReportList *reports);
|
||||
ReportList *reports,
|
||||
const bNodeSocket *src_bundle_socket = nullptr);
|
||||
void sync_sockets_combine_bundle(SpaceNode &snode,
|
||||
bNode &combine_bundle_node,
|
||||
ReportList *reports);
|
||||
ReportList *reports,
|
||||
const bNodeSocket *src_bundle_socket = nullptr);
|
||||
void sync_sockets_closure(SpaceNode &snode,
|
||||
bNode &closure_input_node,
|
||||
bNode &closure_output_node,
|
||||
ReportList *reports);
|
||||
ReportList *reports,
|
||||
const bNodeSocket *src_closure_socket = nullptr);
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
||||
@@ -181,6 +181,20 @@ static void node_free_storage(bNode *node)
|
||||
|
||||
static bool node_insert_link(bke::NodeInsertLinkParams ¶ms)
|
||||
{
|
||||
if (params.C && params.link.fromnode == ¶ms.node) {
|
||||
const NodeGeometryClosureOutput &storage = node_storage(params.node);
|
||||
if (storage.input_items.items_num == 0 && storage.output_items.items_num == 0) {
|
||||
SpaceNode *snode = CTX_wm_space_node(params.C);
|
||||
if (snode && snode->edittree == ¶ms.ntree) {
|
||||
bNode *input_node = bke::zone_type_by_node_type(GEO_NODE_CLOSURE_OUTPUT)
|
||||
->get_corresponding_input(params.ntree, params.node);
|
||||
if (input_node) {
|
||||
sync_sockets_closure(*snode, *input_node, params.node, nullptr, params.link.tosock);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return socket_items::try_add_item_via_any_extend_socket<ClosureOutputItemsAccessor>(
|
||||
params.ntree, params.node, params.node, params.link);
|
||||
}
|
||||
|
||||
@@ -67,6 +67,16 @@ static void node_free_storage(bNode *node)
|
||||
|
||||
static bool node_insert_link(bke::NodeInsertLinkParams ¶ms)
|
||||
{
|
||||
if (params.C && params.link.fromnode == ¶ms.node) {
|
||||
const NodeGeometryCombineBundle &storage = node_storage(params.node);
|
||||
if (storage.items_num == 0) {
|
||||
SpaceNode *snode = CTX_wm_space_node(params.C);
|
||||
if (snode && snode->edittree == ¶ms.ntree) {
|
||||
sync_sockets_combine_bundle(*snode, params.node, nullptr, params.link.tosock);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return socket_items::try_add_item_via_any_extend_socket<CombineBundleItemsAccessor>(
|
||||
params.ntree, params.node, params.node, params.link);
|
||||
}
|
||||
|
||||
@@ -77,6 +77,16 @@ static void node_free_storage(bNode *node)
|
||||
static bool node_insert_link(bke::NodeInsertLinkParams ¶ms)
|
||||
{
|
||||
if (params.link.tonode == ¶ms.node) {
|
||||
if (params.link.tosock == params.node.inputs.first) {
|
||||
const NodeGeometryEvaluateClosure &storage = node_storage(params.node);
|
||||
if (storage.input_items.items_num == 0 && storage.output_items.items_num == 0) {
|
||||
SpaceNode *snode = CTX_wm_space_node(params.C);
|
||||
if (snode && snode->edittree == ¶ms.ntree) {
|
||||
sync_sockets_evaluate_closure(*snode, params.node, nullptr, params.link.fromsock);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return socket_items::try_add_item_via_any_extend_socket<EvaluateClosureInputItemsAccessor>(
|
||||
params.ntree, params.node, params.node, params.link);
|
||||
}
|
||||
|
||||
@@ -71,6 +71,16 @@ static void node_free_storage(bNode *node)
|
||||
|
||||
static bool node_insert_link(bke::NodeInsertLinkParams ¶ms)
|
||||
{
|
||||
if (params.C && params.link.tonode == ¶ms.node) {
|
||||
const NodeGeometrySeparateBundle &storage = node_storage(params.node);
|
||||
if (storage.items_num == 0) {
|
||||
SpaceNode *snode = CTX_wm_space_node(params.C);
|
||||
if (snode && snode->edittree == ¶ms.ntree) {
|
||||
sync_sockets_separate_bundle(*snode, params.node, nullptr, params.link.fromsock);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return socket_items::try_add_item_via_any_extend_socket<SeparateBundleItemsAccessor>(
|
||||
params.ntree, params.node, params.node, params.link);
|
||||
}
|
||||
|
||||
@@ -53,18 +53,22 @@ struct ClosureSyncState {
|
||||
std::optional<nodes::ClosureSignature> source_signature;
|
||||
};
|
||||
|
||||
static BundleSyncState get_sync_state_separate_bundle(const SpaceNode &snode,
|
||||
const bNode &separate_bundle_node)
|
||||
static BundleSyncState get_sync_state_separate_bundle(
|
||||
const SpaceNode &snode,
|
||||
const bNode &separate_bundle_node,
|
||||
const bNodeSocket *src_bundle_socket = nullptr)
|
||||
{
|
||||
BLI_assert(separate_bundle_node.is_type("GeometryNodeSeparateBundle"));
|
||||
snode.edittree->ensure_topology_cache();
|
||||
const bNodeSocket &bundle_socket = separate_bundle_node.input_socket(0);
|
||||
if (!src_bundle_socket) {
|
||||
src_bundle_socket = &separate_bundle_node.input_socket(0);
|
||||
}
|
||||
|
||||
bke::ComputeContextCache compute_context_cache;
|
||||
const ComputeContext *current_context = ed::space_node::compute_context_for_edittree_socket(
|
||||
snode, compute_context_cache, bundle_socket);
|
||||
snode, compute_context_cache, *src_bundle_socket);
|
||||
const Vector<nodes::BundleSignature> source_signatures = gather_linked_origin_bundle_signatures(
|
||||
current_context, bundle_socket, compute_context_cache);
|
||||
current_context, *src_bundle_socket, compute_context_cache);
|
||||
if (source_signatures.is_empty()) {
|
||||
return {NodeSyncState::NoSyncSource};
|
||||
}
|
||||
@@ -80,18 +84,22 @@ static BundleSyncState get_sync_state_separate_bundle(const SpaceNode &snode,
|
||||
return {NodeSyncState::Synced};
|
||||
}
|
||||
|
||||
static BundleSyncState get_sync_state_combine_bundle(const SpaceNode &snode,
|
||||
const bNode &combine_bundle_node)
|
||||
static BundleSyncState get_sync_state_combine_bundle(
|
||||
const SpaceNode &snode,
|
||||
const bNode &combine_bundle_node,
|
||||
const bNodeSocket *src_bundle_socket = nullptr)
|
||||
{
|
||||
BLI_assert(combine_bundle_node.is_type("GeometryNodeCombineBundle"));
|
||||
snode.edittree->ensure_topology_cache();
|
||||
const bNodeSocket &bundle_socket = combine_bundle_node.output_socket(0);
|
||||
if (!src_bundle_socket) {
|
||||
src_bundle_socket = &combine_bundle_node.output_socket(0);
|
||||
}
|
||||
|
||||
bke::ComputeContextCache compute_context_cache;
|
||||
const ComputeContext *current_context = ed::space_node::compute_context_for_edittree_socket(
|
||||
snode, compute_context_cache, bundle_socket);
|
||||
snode, compute_context_cache, *src_bundle_socket);
|
||||
const Vector<nodes::BundleSignature> source_signatures = gather_linked_target_bundle_signatures(
|
||||
current_context, bundle_socket, compute_context_cache);
|
||||
current_context, *src_bundle_socket, compute_context_cache);
|
||||
if (source_signatures.is_empty()) {
|
||||
return {NodeSyncState::NoSyncSource};
|
||||
}
|
||||
@@ -107,18 +115,22 @@ static BundleSyncState get_sync_state_combine_bundle(const SpaceNode &snode,
|
||||
return {NodeSyncState::Synced};
|
||||
}
|
||||
|
||||
static ClosureSyncState get_sync_state_closure_output(const SpaceNode &snode,
|
||||
const bNode &closure_output_node)
|
||||
static ClosureSyncState get_sync_state_closure_output(
|
||||
const SpaceNode &snode,
|
||||
const bNode &closure_output_node,
|
||||
const bNodeSocket *src_closure_socket = nullptr)
|
||||
{
|
||||
snode.edittree->ensure_topology_cache();
|
||||
const bNodeSocket &closure_socket = closure_output_node.output_socket(0);
|
||||
if (!src_closure_socket) {
|
||||
src_closure_socket = &closure_output_node.output_socket(0);
|
||||
}
|
||||
|
||||
bke::ComputeContextCache compute_context_cache;
|
||||
const ComputeContext *current_context = ed::space_node::compute_context_for_edittree_socket(
|
||||
snode, compute_context_cache, closure_socket);
|
||||
snode, compute_context_cache, *src_closure_socket);
|
||||
const Vector<nodes::ClosureSignature> source_signatures =
|
||||
gather_linked_target_closure_signatures(
|
||||
current_context, closure_socket, compute_context_cache);
|
||||
current_context, *src_closure_socket, compute_context_cache);
|
||||
if (source_signatures.is_empty()) {
|
||||
return {NodeSyncState::NoSyncSource};
|
||||
}
|
||||
@@ -134,18 +146,22 @@ static ClosureSyncState get_sync_state_closure_output(const SpaceNode &snode,
|
||||
return {NodeSyncState::Synced};
|
||||
}
|
||||
|
||||
static ClosureSyncState get_sync_state_evaluate_closure(const SpaceNode &snode,
|
||||
const bNode &evaluate_closure_node)
|
||||
static ClosureSyncState get_sync_state_evaluate_closure(
|
||||
const SpaceNode &snode,
|
||||
const bNode &evaluate_closure_node,
|
||||
const bNodeSocket *src_closure_socket = nullptr)
|
||||
{
|
||||
snode.edittree->ensure_topology_cache();
|
||||
const bNodeSocket &closure_socket = evaluate_closure_node.input_socket(0);
|
||||
if (!src_closure_socket) {
|
||||
src_closure_socket = &evaluate_closure_node.input_socket(0);
|
||||
}
|
||||
|
||||
bke::ComputeContextCache compute_context_cache;
|
||||
const ComputeContext *current_context = ed::space_node::compute_context_for_edittree_socket(
|
||||
snode, compute_context_cache, closure_socket);
|
||||
snode, compute_context_cache, *src_closure_socket);
|
||||
const Vector<nodes::ClosureSignature> source_signatures =
|
||||
gather_linked_origin_closure_signatures(
|
||||
current_context, closure_socket, compute_context_cache);
|
||||
current_context, *src_closure_socket, compute_context_cache);
|
||||
if (source_signatures.is_empty()) {
|
||||
return {NodeSyncState::NoSyncSource};
|
||||
}
|
||||
@@ -163,9 +179,11 @@ static ClosureSyncState get_sync_state_evaluate_closure(const SpaceNode &snode,
|
||||
|
||||
void sync_sockets_separate_bundle(SpaceNode &snode,
|
||||
bNode &separate_bundle_node,
|
||||
ReportList *reports)
|
||||
ReportList *reports,
|
||||
const bNodeSocket *src_bundle_socket)
|
||||
{
|
||||
const BundleSyncState sync_state = get_sync_state_separate_bundle(snode, separate_bundle_node);
|
||||
const BundleSyncState sync_state = get_sync_state_separate_bundle(
|
||||
snode, separate_bundle_node, src_bundle_socket);
|
||||
switch (sync_state.state) {
|
||||
case NodeSyncState::Synced:
|
||||
return;
|
||||
@@ -200,9 +218,13 @@ void sync_sockets_separate_bundle(SpaceNode &snode,
|
||||
BKE_ntree_update_tag_node_property(snode.edittree, &separate_bundle_node);
|
||||
}
|
||||
|
||||
void sync_sockets_combine_bundle(SpaceNode &snode, bNode &combine_bundle_node, ReportList *reports)
|
||||
void sync_sockets_combine_bundle(SpaceNode &snode,
|
||||
bNode &combine_bundle_node,
|
||||
ReportList *reports,
|
||||
const bNodeSocket *src_bundle_socket)
|
||||
{
|
||||
const BundleSyncState sync_state = get_sync_state_combine_bundle(snode, combine_bundle_node);
|
||||
const BundleSyncState sync_state = get_sync_state_combine_bundle(
|
||||
snode, combine_bundle_node, src_bundle_socket);
|
||||
switch (sync_state.state) {
|
||||
case NodeSyncState::Synced:
|
||||
return;
|
||||
@@ -240,10 +262,11 @@ void sync_sockets_combine_bundle(SpaceNode &snode, bNode &combine_bundle_node, R
|
||||
|
||||
void sync_sockets_evaluate_closure(SpaceNode &snode,
|
||||
bNode &evaluate_closure_node,
|
||||
ReportList *reports)
|
||||
ReportList *reports,
|
||||
const bNodeSocket *src_closure_socket)
|
||||
{
|
||||
const ClosureSyncState sync_state = get_sync_state_evaluate_closure(snode,
|
||||
evaluate_closure_node);
|
||||
const ClosureSyncState sync_state = get_sync_state_evaluate_closure(
|
||||
snode, evaluate_closure_node, src_closure_socket);
|
||||
switch (sync_state.state) {
|
||||
case NodeSyncState::Synced:
|
||||
return;
|
||||
@@ -297,9 +320,11 @@ void sync_sockets_evaluate_closure(SpaceNode &snode,
|
||||
void sync_sockets_closure(SpaceNode &snode,
|
||||
bNode &closure_input_node,
|
||||
bNode &closure_output_node,
|
||||
ReportList *reports)
|
||||
ReportList *reports,
|
||||
const bNodeSocket *src_closure_socket)
|
||||
{
|
||||
const ClosureSyncState sync_state = get_sync_state_closure_output(snode, closure_output_node);
|
||||
const ClosureSyncState sync_state = get_sync_state_closure_output(
|
||||
snode, closure_output_node, src_closure_socket);
|
||||
switch (sync_state.state) {
|
||||
case NodeSyncState::Synced:
|
||||
return;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "NOD_geometry_nodes_closure_location.hh"
|
||||
#include "NOD_geometry_nodes_closure_signature.hh"
|
||||
#include "NOD_node_in_compute_context.hh"
|
||||
#include "NOD_trace_values.hh"
|
||||
|
||||
#include "BKE_compute_context_cache.hh"
|
||||
#include "BKE_node_tree_zones.hh"
|
||||
|
||||
Reference in New Issue
Block a user