Fix #106208: Initialize socket value by declaration callback if value is data block #106816
|
@ -7,8 +7,11 @@
|
|||
#include "RNA_types.h"
|
||||
|
||||
#include "BLI_color.hh"
|
||||
#include "BLI_function_ref.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
using BlenderObjectPtr = Object *;
|
||||
|
||||
namespace blender::nodes::decl {
|
||||
|
||||
class FloatBuilder;
|
||||
|
@ -162,22 +165,53 @@ class IDSocketDeclaration : public SocketDeclaration {
|
|||
public:
|
||||
IDSocketDeclaration(const char *idname);
|
||||
|
||||
virtual void construct_default_value(bNode &node, bNodeSocket &socket) const = 0;
|
||||
|
||||
bNodeSocket &build(bNodeTree &ntree, bNode &node) const override;
|
||||
bool matches(const bNodeSocket &socket) const override;
|
||||
bNodeSocket &update_or_build(bNodeTree &ntree, bNode &node, bNodeSocket &socket) const override;
|
||||
bool can_connect(const bNodeSocket &socket) const override;
|
||||
};
|
||||
|
||||
class ObjectBuilder;
|
||||
|
||||
class Object : public IDSocketDeclaration {
|
||||
public:
|
||||
using Builder = SocketDeclarationBuilder<Object>;
|
||||
std::function<BlenderObjectPtr(const bNode *node)> object_cb;
|
||||
|
||||
void construct_default_value(bNode &node, bNodeSocket &socket) const
|
||||
{
|
||||
printf("1!\n");
|
||||
if (!this->object_cb) {
|
||||
return;
|
||||
}
|
||||
printf("2!\n");
|
||||
printf("%p, %p, %p;\n", &socket, this->object_cb(&node), nullptr);
|
||||
printf("3!\n");
|
||||
socket.default_value_typed<bNodeSocketValueObject>()->value = this->object_cb(&node);
|
||||
printf("4!\n");
|
||||
}
|
||||
|
||||
friend ObjectBuilder;
|
||||
|
||||
public:
|
||||
using Builder = ObjectBuilder;
|
||||
|
||||
Object();
|
||||
};
|
||||
|
||||
class ObjectBuilder : public SocketDeclarationBuilder<Object> {
|
||||
public:
|
||||
ObjectBuilder &default_value_cb(std::function<BlenderObjectPtr(const bNode *node)> object_cb);
|
||||
};
|
||||
|
||||
class Material : public IDSocketDeclaration {
|
||||
public:
|
||||
using Builder = SocketDeclarationBuilder<Material>;
|
||||
void construct_default_value(bNode & /*node*/, bNodeSocket & /*socket*/) const
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Material();
|
||||
};
|
||||
|
@ -185,6 +219,10 @@ class Material : public IDSocketDeclaration {
|
|||
class Collection : public IDSocketDeclaration {
|
||||
public:
|
||||
using Builder = SocketDeclarationBuilder<Collection>;
|
||||
void construct_default_value(bNode & /*node*/, bNodeSocket & /*socket*/) const
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Collection();
|
||||
};
|
||||
|
@ -192,6 +230,10 @@ class Collection : public IDSocketDeclaration {
|
|||
class Texture : public IDSocketDeclaration {
|
||||
public:
|
||||
using Builder = SocketDeclarationBuilder<Texture>;
|
||||
void construct_default_value(bNode & /*node*/, bNodeSocket & /*socket*/) const
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Texture();
|
||||
};
|
||||
|
@ -199,7 +241,10 @@ class Texture : public IDSocketDeclaration {
|
|||
class Image : public IDSocketDeclaration {
|
||||
public:
|
||||
using Builder = SocketDeclarationBuilder<Image>;
|
||||
|
||||
void construct_default_value(bNode & /*node*/, bNodeSocket & /*socket*/) const
|
||||
{
|
||||
return;
|
||||
}
|
||||
Image();
|
||||
};
|
||||
|
||||
|
@ -367,6 +412,19 @@ inline ColorBuilder &ColorBuilder::default_value(const ColorGeometry4f value)
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #ColorBuilder Inline Methods
|
||||
* \{ */
|
||||
|
||||
inline ObjectBuilder &ObjectBuilder::default_value_cb(
|
||||
std::function<BlenderObjectPtr(const bNode *node)> object_cb)
|
||||
{
|
||||
decl_->object_cb = std::move(object_cb);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name #StringBuilder Inline Methods
|
||||
* \{ */
|
||||
|
|
|
@ -124,8 +124,10 @@ bool nodeGroupPoll(const bNodeTree *nodetree,
|
|||
|
||||
namespace blender::nodes {
|
||||
|
||||
static SocketDeclarationPtr declaration_for_interface_socket(const bNodeSocket &io_socket)
|
||||
static SocketDeclarationPtr declaration_for_interface_socket(const bNodeSocket &io_socket,
|
||||
const bNodeTree *node_group)
|
||||
{
|
||||
printf("= %p;\n", node_group);
|
||||
SocketDeclarationPtr dst;
|
||||
switch (io_socket.type) {
|
||||
case SOCK_FLOAT: {
|
||||
|
||||
|
@ -184,9 +186,28 @@ static SocketDeclarationPtr declaration_for_interface_socket(const bNodeSocket &
|
|||
dst = std::move(decl);
|
||||
break;
|
||||
}
|
||||
case SOCK_OBJECT:
|
||||
dst = std::make_unique<decl::Object>();
|
||||
break;
|
||||
case SOCK_OBJECT: {
|
||||
std::unique_ptr<decl::Object> decl = std::make_unique<decl::Object>();
|
||||
std::string socket_name = io_socket.name;
|
||||
decl->object_cb =
|
||||
[node_group, socket_name = std::move(socket_name)](const bNode * /*node*/) -> Object * {
|
||||
printf(" - %p\n", node_group);
|
||||
printf(" - 1\n");
|
||||
if (node_group == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
printf(" - 2\n");
|
||||
LISTBASE_FOREACH (const bNodeSocket *, input, &node_group->inputs) {
|
||||
if (StringRef(input->name) == StringRef(socket_name)) {
|
||||
return const_cast<Object *>(
|
||||
input->default_value_typed<bNodeSocketValueObject>()->value);
|
||||
}
|
||||
}
|
||||
printf(" - 3\n");
|
||||
return nullptr;
|
||||
};
|
||||
dst = std::move(decl);
|
||||
} break;
|
||||
case SOCK_IMAGE:
|
||||
dst = std::make_unique<decl::Image>();
|
||||
break;
|
||||
|
@ -232,10 +253,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(*input, group));
|
||||
}
|
||||
LISTBASE_FOREACH (const bNodeSocket *, output, &group->outputs) {
|
||||
r_declaration.outputs.append(declaration_for_interface_socket(*output));
|
||||
r_declaration.outputs.append(declaration_for_interface_socket(*output, group));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,7 +471,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(*input, &node_tree));
|
||||
r_declaration.outputs.last()->in_out = SOCK_OUT;
|
||||
}
|
||||
r_declaration.outputs.append(extend_declaration(SOCK_OUT));
|
||||
|
@ -461,7 +482,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(*input, &node_tree));
|
||||
r_declaration.inputs.last()->in_out = SOCK_IN;
|
||||
}
|
||||
r_declaration.inputs.append(extend_declaration(SOCK_IN));
|
||||
|
|
|
@ -436,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());
|
||||
this->set_common_flags(socket);
|
||||
|
||||
if (const auto *ptr = dynamic_cast<const Object *>(this)) {
|
||||
printf("Start\n");
|
||||
ptr->construct_default_value(node, socket);
|
||||
printf("End\n");
|
||||
}
|
||||
|
||||
return socket;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
I agree that we need to avoid ID pointers in the declarations. But this solves one problem by creating another: Now we have the
bNodeTree
bound in the callback.A weak pointer of some kind seems to be needed here, so that ID management code does not have to worry about references stored in node declarations.
Trees cause refresh on their own. That is, it must be safe.
It would be possible to add a requirement to the topology cache in order to find a node from the socket and take its pointer to the tree. But this can increase the overhead. Or we can pass a node. But at one point it may require also a tree as well ... there is not enough some context