Fix #106208: data-block socket defaults not used for node group #107179
|
@ -158,6 +158,12 @@ class StringBuilder : public SocketDeclarationBuilder<String> {
|
|||
class IDSocketDeclaration : public SocketDeclaration {
|
||||
public:
|
||||
const char *idname;
|
||||
/**
|
||||
|
||||
* Get the default ID pointer for this socket. This is a function to avoid dangling pointers,
|
||||
* since bNode::id pointers are remapped as ID pointers change, but pointers in socket
|
||||
* declarations are not managed the same way.
|
||||
*/
|
||||
std::function<ID *(const bNode &node)> default_value_fn;
|
||||
|
||||
public:
|
||||
IDSocketDeclaration(const char *idname);
|
||||
|
|
|
@ -124,7 +124,41 @@ bool nodeGroupPoll(const bNodeTree *nodetree,
|
|||
|
||||
namespace blender::nodes {
|
||||
|
||||
static SocketDeclarationPtr declaration_for_interface_socket(const bNodeSocket &io_socket)
|
||||
static std::function<ID *(const bNode &node)> get_default_id_getter(const bNodeTree &ntree,
|
||||
const bNodeSocket &io_socket)
|
||||
{
|
||||
const int socket_index = io_socket.in_out == SOCK_IN ? BLI_findindex(&ntree.inputs, &io_socket) :
|
||||
BLI_findindex(&ntree.outputs, &io_socket);
|
||||
/* Avoid capturing pointers that can become dangling. */
|
||||
return [in_out = io_socket.in_out, socket_index](const bNode &node) -> ID * {
|
||||
if (node.id == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
if (GS(node.id->name) != ID_NT) {
|
||||
return nullptr;
|
||||
}
|
||||
const bNodeTree &ntree = *reinterpret_cast<const bNodeTree *>(node.id);
|
||||
const bNodeSocket *io_socket;
|
||||
if (in_out == SOCK_IN) {
|
||||
/* Better be safe than sorry when the underlying node group changed. */
|
||||
Hans Goudey
commented
Hmm, why would the socket index be out of bounds here? Does this function object live past some changes to the group interface? If so, maybe worth noting that in a comment. Hmm, why would the socket index be out of bounds here? Does this function object live past some changes to the group interface? If so, maybe worth noting that in a comment.
Jacques Lucke
commented
The problem is, I don't think we know for sure how long this will live currently. At least I don't know. The problem is, I don't think we know for sure how long this will live currently. At least I don't know.
Hans Goudey
commented
`save` -> `safe`
|
||||
if (socket_index < ntree.interface_inputs().size()) {
|
||||
io_socket = ntree.interface_inputs()[socket_index];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (socket_index < ntree.interface_outputs().size()) {
|
||||
io_socket = ntree.interface_outputs()[socket_index];
|
||||
}
|
||||
}
|
||||
if (io_socket == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
return *static_cast<ID **>(io_socket->default_value);
|
||||
};
|
||||
}
|
||||
|
||||
static SocketDeclarationPtr declaration_for_interface_socket(const bNodeTree &ntree,
|
||||
const bNodeSocket &io_socket)
|
||||
{
|
||||
SocketDeclarationPtr dst;
|
||||
switch (io_socket.type) {
|
||||
|
@ -184,24 +218,39 @@ static SocketDeclarationPtr declaration_for_interface_socket(const bNodeSocket &
|
|||
dst = std::move(decl);
|
||||
break;
|
||||
}
|
||||
case SOCK_OBJECT:
|
||||
dst = std::make_unique<decl::Object>();
|
||||
case SOCK_OBJECT: {
|
||||
auto value = std::make_unique<decl::Object>();
|
||||
value->default_value_fn = get_default_id_getter(ntree, io_socket);
|
||||
dst = std::move(value);
|
||||
break;
|
||||
case SOCK_IMAGE:
|
||||
dst = std::make_unique<decl::Image>();
|
||||
}
|
||||
case SOCK_IMAGE: {
|
||||
auto value = std::make_unique<decl::Image>();
|
||||
value->default_value_fn = get_default_id_getter(ntree, io_socket);
|
||||
dst = std::move(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_GEOMETRY:
|
||||
dst = std::make_unique<decl::Geometry>();
|
||||
break;
|
||||
case SOCK_COLLECTION:
|
||||
dst = std::make_unique<decl::Collection>();
|
||||
case SOCK_COLLECTION: {
|
||||
auto value = std::make_unique<decl::Collection>();
|
||||
value->default_value_fn = get_default_id_getter(ntree, io_socket);
|
||||
dst = std::move(value);
|
||||
break;
|
||||
case SOCK_TEXTURE:
|
||||
dst = std::make_unique<decl::Texture>();
|
||||
}
|
||||
case SOCK_TEXTURE: {
|
||||
auto value = std::make_unique<decl::Texture>();
|
||||
value->default_value_fn = get_default_id_getter(ntree, io_socket);
|
||||
dst = std::move(value);
|
||||
break;
|
||||
case SOCK_MATERIAL:
|
||||
dst = std::make_unique<decl::Material>();
|
||||
}
|
||||
case SOCK_MATERIAL: {
|
||||
auto value = std::make_unique<decl::Material>();
|
||||
value->default_value_fn = get_default_id_getter(ntree, io_socket);
|
||||
dst = std::move(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_CUSTOM:
|
||||
std::unique_ptr<decl::Custom> decl = std::make_unique<decl::Custom>();
|
||||
decl->idname_ = io_socket.idname;
|
||||
|
@ -232,10 +281,10 @@ void node_group_declare_dynamic(const bNodeTree & /*node_tree*/,
|
|||
r_declaration.skip_updating_sockets = false;
|
||||
|
||||
LISTBASE_FOREACH (const bNodeSocket *, input, &group->inputs) {
|
||||
r_declaration.inputs.append(declaration_for_interface_socket(*input));
|
||||
r_declaration.inputs.append(declaration_for_interface_socket(*group, *input));
|
||||
}
|
||||
LISTBASE_FOREACH (const bNodeSocket *, output, &group->outputs) {
|
||||
r_declaration.outputs.append(declaration_for_interface_socket(*output));
|
||||
r_declaration.outputs.append(declaration_for_interface_socket(*group, *output));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,7 +499,7 @@ static void group_input_declare_dynamic(const bNodeTree &node_tree,
|
|||
NodeDeclaration &r_declaration)
|
||||
{
|
||||
LISTBASE_FOREACH (const bNodeSocket *, input, &node_tree.inputs) {
|
||||
r_declaration.outputs.append(declaration_for_interface_socket(*input));
|
||||
r_declaration.outputs.append(declaration_for_interface_socket(node_tree, *input));
|
||||
r_declaration.outputs.last()->in_out = SOCK_OUT;
|
||||
}
|
||||
r_declaration.outputs.append(extend_declaration(SOCK_OUT));
|
||||
|
@ -461,7 +510,7 @@ static void group_output_declare_dynamic(const bNodeTree &node_tree,
|
|||
NodeDeclaration &r_declaration)
|
||||
{
|
||||
LISTBASE_FOREACH (const bNodeSocket *, input, &node_tree.outputs) {
|
||||
r_declaration.inputs.append(declaration_for_interface_socket(*input));
|
||||
r_declaration.inputs.append(declaration_for_interface_socket(node_tree, *input));
|
||||
r_declaration.inputs.last()->in_out = SOCK_IN;
|
||||
}
|
||||
r_declaration.inputs.append(extend_declaration(SOCK_IN));
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "NOD_socket_declarations.hh"
|
||||
#include "NOD_socket_declarations_geometry.hh"
|
||||
|
||||
#include "BKE_lib_id.h"
|
||||
#include "BKE_node.h"
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
|
@ -435,6 +436,13 @@ bNodeSocket &IDSocketDeclaration::build(bNodeTree &ntree, bNode &node) const
|
|||
{
|
||||
bNodeSocket &socket = *nodeAddSocket(
|
||||
&ntree, &node, this->in_out, this->idname, this->identifier.c_str(), this->name.c_str());
|
||||
if (this->default_value_fn) {
|
||||
ID *id = this->default_value_fn(node);
|
||||
/* Assumes that all ID sockets like #bNodeSocketValueObject and #bNodeSocketValueImage have the
|
||||
* ID pointer at the start of the struct. */
|
||||
*static_cast<ID **>(socket.default_value) = id;
|
||||
Iliya Katushenock
commented
C-style cast here C-style cast here
|
||||
id_us_plus(id);
|
||||
}
|
||||
this->set_common_flags(socket);
|
||||
return socket;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Maybe add
, since
bNode::idpointers are remapped as
IDpointers change, but pointers in socket declarations are not managed the same way.