WIP: Closures and deferred evaluation for geometry nodes #107842
|
@ -694,6 +694,12 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket
|
|||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value.value, IDWALK_CB_USER);
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
bNodeSocketValueFunction &default_value =
|
||||
*sock->default_value_typed<bNodeSocketValueFunction>();
|
||||
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, default_value.value, IDWALK_CB_USER);
|
||||
break;
|
||||
}
|
||||
case SOCK_FLOAT:
|
||||
case SOCK_VECTOR:
|
||||
case SOCK_RGBA:
|
||||
|
@ -704,7 +710,6 @@ static void library_foreach_node_socket(LibraryForeachIDData *data, bNodeSocket
|
|||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_FUNCTION:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -844,13 +849,15 @@ static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *so
|
|||
case SOCK_MATERIAL:
|
||||
BLO_write_struct(writer, bNodeSocketValueMaterial, sock->default_value);
|
||||
break;
|
||||
case SOCK_FUNCTION:
|
||||
BLO_write_struct(writer, bNodeSocketValueFunction, sock->default_value);
|
||||
break;
|
||||
case SOCK_CUSTOM:
|
||||
/* Custom node sockets where default_value is defined uses custom properties for storage. */
|
||||
break;
|
||||
case __SOCK_MESH:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_FUNCTION:
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
}
|
||||
|
@ -1319,6 +1326,11 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock
|
|||
reader, lib, &sock->default_value_typed<bNodeSocketValueMaterial>()->value);
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
BLO_read_id_address(
|
||||
reader, lib, &sock->default_value_typed<bNodeSocketValueFunction>()->value);
|
||||
break;
|
||||
}
|
||||
case SOCK_FLOAT:
|
||||
case SOCK_VECTOR:
|
||||
case SOCK_RGBA:
|
||||
|
@ -1329,7 +1341,6 @@ static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSock
|
|||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_FUNCTION:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1413,6 +1424,10 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock)
|
|||
BLO_expand(expander, sock->default_value_typed<bNodeSocketValueMaterial>()->value);
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
BLO_expand(expander, sock->default_value_typed<bNodeSocketValueFunction>()->value);
|
||||
break;
|
||||
}
|
||||
case SOCK_FLOAT:
|
||||
case SOCK_VECTOR:
|
||||
case SOCK_RGBA:
|
||||
|
@ -1423,7 +1438,6 @@ static void expand_node_socket(BlendExpander *expander, bNodeSocket *sock)
|
|||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_FUNCTION:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2070,6 +2084,12 @@ static void socket_id_user_increment(bNodeSocket *sock)
|
|||
id_us_plus(reinterpret_cast<ID *>(default_value.value));
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
bNodeSocketValueFunction &default_value =
|
||||
*sock->default_value_typed<bNodeSocketValueFunction>();
|
||||
id_us_plus(reinterpret_cast<ID *>(default_value.value));
|
||||
break;
|
||||
}
|
||||
case SOCK_FLOAT:
|
||||
case SOCK_VECTOR:
|
||||
case SOCK_RGBA:
|
||||
|
@ -2080,7 +2100,6 @@ static void socket_id_user_increment(bNodeSocket *sock)
|
|||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_FUNCTION:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2117,6 +2136,12 @@ static bool socket_id_user_decrement(bNodeSocket *sock)
|
|||
id_us_min(reinterpret_cast<ID *>(default_value.value));
|
||||
return default_value.value != nullptr;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
bNodeSocketValueFunction &default_value =
|
||||
*sock->default_value_typed<bNodeSocketValueFunction>();
|
||||
id_us_min(reinterpret_cast<ID *>(default_value.value));
|
||||
return default_value.value != nullptr;
|
||||
}
|
||||
case SOCK_FLOAT:
|
||||
case SOCK_VECTOR:
|
||||
case SOCK_RGBA:
|
||||
|
@ -2127,7 +2152,6 @@ static bool socket_id_user_decrement(bNodeSocket *sock)
|
|||
case SOCK_CUSTOM:
|
||||
case SOCK_SHADER:
|
||||
case SOCK_GEOMETRY:
|
||||
case SOCK_FUNCTION:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
|
@ -2935,6 +2959,8 @@ static void *socket_value_storage(bNodeSocket &socket)
|
|||
return &socket.default_value_typed<bNodeSocketValueObject>()->value;
|
||||
case SOCK_MATERIAL:
|
||||
return &socket.default_value_typed<bNodeSocketValueMaterial>()->value;
|
||||
case SOCK_FUNCTION:
|
||||
return &socket.default_value_typed<bNodeSocketValueFunction>()->value;
|
||||
case SOCK_STRING:
|
||||
/* We don't want do this now! */
|
||||
return nullptr;
|
||||
|
@ -2992,7 +3018,8 @@ void node_socket_move_default_value(Main & /*bmain*/,
|
|||
SOCK_IMAGE,
|
||||
SOCK_MATERIAL,
|
||||
SOCK_TEXTURE,
|
||||
SOCK_OBJECT))
|
||||
SOCK_OBJECT,
|
||||
SOCK_FUNCTION))
|
||||
{
|
||||
src_type.value_initialize(src_value);
|
||||
}
|
||||
|
|
|
@ -915,7 +915,8 @@ void DepsgraphNodeBuilder::build_object_modifiers(Object *object)
|
|||
}
|
||||
if (modifier_node->flag & DEPSOP_FLAG_USER_MODIFIED) {
|
||||
if (nmd->simulation_cache &&
|
||||
nmd->simulation_cache->cache_state() == bke::sim::CacheState::Valid) {
|
||||
nmd->simulation_cache->cache_state() == bke::sim::CacheState::Valid)
|
||||
{
|
||||
nmd->simulation_cache->invalidate();
|
||||
}
|
||||
}
|
||||
|
@ -1767,6 +1768,9 @@ void DepsgraphNodeBuilder::build_nodetree_socket(bNodeSocket *socket)
|
|||
else if (socket->type == SOCK_MATERIAL) {
|
||||
build_id((ID *)((bNodeSocketValueMaterial *)socket->default_value)->value);
|
||||
}
|
||||
else if (socket->type == SOCK_FUNCTION) {
|
||||
build_id((ID *)((bNodeSocketValueFunction *)socket->default_value)->value);
|
||||
}
|
||||
}
|
||||
|
||||
void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
|
||||
|
|
|
@ -2647,6 +2647,12 @@ void DepsgraphRelationBuilder::build_nodetree_socket(bNodeSocket *socket)
|
|||
build_material(material);
|
||||
}
|
||||
}
|
||||
else if (socket->type == SOCK_FUNCTION) {
|
||||
bNodeTree *ntree = ((bNodeSocketValueFunction *)socket->default_value)->value;
|
||||
if (ntree != nullptr) {
|
||||
build_nodetree(ntree);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DepsgraphRelationBuilder::build_nodetree(bNodeTree *ntree)
|
||||
|
|
|
@ -1294,7 +1294,8 @@ static void std_node_socket_draw(
|
|||
}
|
||||
|
||||
if ((sock->in_out == SOCK_OUT) || (sock->flag & SOCK_IS_LINKED) ||
|
||||
(sock->flag & SOCK_HIDE_VALUE)) {
|
||||
(sock->flag & SOCK_HIDE_VALUE))
|
||||
{
|
||||
node_socket_button_label(C, layout, ptr, node_ptr, text);
|
||||
return;
|
||||
}
|
||||
|
@ -1416,6 +1417,10 @@ static void std_node_socket_draw(
|
|||
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
uiItemR(layout, ptr, "default_value", DEFAULT_FLAGS, text, 0);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
node_socket_button_label(C, layout, ptr, node_ptr, text);
|
||||
break;
|
||||
|
@ -1458,7 +1463,8 @@ static void std_node_socket_interface_draw(bContext * /*C*/, uiLayout *layout, P
|
|||
case SOCK_COLLECTION:
|
||||
case SOCK_IMAGE:
|
||||
case SOCK_TEXTURE:
|
||||
case SOCK_MATERIAL: {
|
||||
case SOCK_MATERIAL:
|
||||
case SOCK_FUNCTION: {
|
||||
uiItemR(col, ptr, "default_value", DEFAULT_FLAGS, IFACE_("Default"), 0);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -756,6 +756,10 @@ typedef struct bNodeSocketValueMaterial {
|
|||
struct Material *value;
|
||||
} bNodeSocketValueMaterial;
|
||||
|
||||
typedef struct bNodeSocketValueFunction {
|
||||
struct bNodeTree *value;
|
||||
} bNodeSocketValueFunction;
|
||||
|
||||
/* Data structs, for `node->storage`. */
|
||||
|
||||
typedef enum CMPNodeMaskType {
|
||||
|
|
|
@ -4865,6 +4865,20 @@ bool rna_NodeSocketMaterial_default_value_poll(PointerRNA *UNUSED(ptr), PointerR
|
|||
return ma->gp_style == NULL;
|
||||
}
|
||||
|
||||
bool rna_NodeSocketFunction_default_value_poll(PointerRNA *ptr, PointerRNA value)
|
||||
{
|
||||
bNodeTree *ntree = (bNodeTree *)ptr->owner_id;
|
||||
bNodeTree *ngroup = value.data;
|
||||
|
||||
/* only allow node trees of the same type as the group node's tree */
|
||||
if (ngroup->type != ntree->type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *disabled_hint = NULL;
|
||||
return nodeGroupPoll(ntree, ngroup, &disabled_hint);
|
||||
}
|
||||
|
||||
static int rna_NodeConvertColorSpace_from_color_space_get(struct PointerRNA *ptr)
|
||||
{
|
||||
bNode *node = (bNode *)ptr->data;
|
||||
|
@ -12666,14 +12680,40 @@ static void rna_def_node_socket_function(BlenderRNA *brna,
|
|||
const char *interface_idname)
|
||||
{
|
||||
StructRNA *srna;
|
||||
PropertyRNA *prop;
|
||||
|
||||
srna = RNA_def_struct(brna, identifier, "NodeSocketStandard");
|
||||
RNA_def_struct_ui_text(srna, "Function Node Socket", "Function socket of a node");
|
||||
RNA_def_struct_sdna(srna, "bNodeSocket");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocketValueMaterial", "default_value");
|
||||
|
||||
prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "value");
|
||||
RNA_def_property_struct_type(prop, "NodeTree");
|
||||
RNA_def_property_pointer_funcs(
|
||||
prop, NULL, NULL, NULL, "rna_NodeSocketFunction_default_value_poll");
|
||||
RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
|
||||
RNA_def_property_update(
|
||||
prop, NC_NODE | NA_EDITED, "rna_NodeSocketStandard_value_and_relation_update");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT | PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
|
||||
srna = RNA_def_struct(brna, interface_idname, "NodeSocketInterfaceStandard");
|
||||
RNA_def_struct_ui_text(srna, "Function Node Socket Interface", "Function socket of a node");
|
||||
RNA_def_struct_sdna(srna, "bNodeSocket");
|
||||
|
||||
RNA_def_struct_sdna_from(srna, "bNodeSocketValueMaterial", "default_value");
|
||||
|
||||
prop = RNA_def_property(srna, "default_value", PROP_POINTER, PROP_NONE);
|
||||
RNA_def_property_pointer_sdna(prop, NULL, "value");
|
||||
RNA_def_property_struct_type(prop, "NodeTree");
|
||||
RNA_def_property_pointer_funcs(
|
||||
prop, NULL, NULL, NULL, "rna_NodeSocketFunction_default_value_poll");
|
||||
RNA_def_property_ui_text(prop, "Default Value", "Input value used for unconnected socket");
|
||||
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_NodeSocketInterface_update");
|
||||
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT);
|
||||
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
|
||||
}
|
||||
|
||||
static void rna_def_node_socket_standard_types(BlenderRNA *brna)
|
||||
|
|
|
@ -85,6 +85,7 @@
|
|||
#include "ED_undo.h"
|
||||
#include "ED_viewer_path.hh"
|
||||
|
||||
#include "NOD_closure.hh"
|
||||
#include "NOD_geometry.h"
|
||||
#include "NOD_geometry_nodes_lazy_function.hh"
|
||||
#include "NOD_node_declaration.hh"
|
||||
|
@ -144,6 +145,12 @@ static void add_used_ids_from_sockets(const ListBase &sockets, Set<ID *> &ids)
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
if (bNodeTree *ntree = ((bNodeSocketValueFunction *)socket->default_value)->value) {
|
||||
ids.add(&ntree->id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -508,6 +515,11 @@ static std::unique_ptr<IDProperty, bke::idprop::IDPropertyDeleter> id_property_c
|
|||
socket.default_value);
|
||||
return bke::idprop::create(socket.identifier, reinterpret_cast<ID *>(value->value));
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
const bNodeSocketValueFunction *value = static_cast<const bNodeSocketValueFunction *>(
|
||||
socket.default_value);
|
||||
return bke::idprop::create(socket.identifier, reinterpret_cast<ID *>(value->value));
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -532,6 +544,7 @@ static bool id_property_type_matches_socket(const bNodeSocket &socket, const IDP
|
|||
case SOCK_TEXTURE:
|
||||
case SOCK_IMAGE:
|
||||
case SOCK_MATERIAL:
|
||||
case SOCK_FUNCTION:
|
||||
return property.type == IDP_ID;
|
||||
}
|
||||
BLI_assert_unreachable();
|
||||
|
@ -611,6 +624,14 @@ static void init_socket_cpp_value_from_property(const IDProperty &property,
|
|||
*(Material **)r_value = material;
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
using Closure = blender::nodes::Closure;
|
||||
|
||||
ID *id = IDP_Id(&property);
|
||||
bNodeTree *ntree = (id && GS(id->name) == ID_NT) ? (bNodeTree *)id : nullptr;
|
||||
new (r_value) Closure(Closure::make_from_node_tree(ntree));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
BLI_assert_unreachable();
|
||||
break;
|
||||
|
@ -1792,6 +1813,10 @@ static void draw_property_for_socket(const bContext &C,
|
|||
uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "images", socket.name, ICON_IMAGE);
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
uiItemPointerR(row, md_ptr, rna_path, bmain_ptr, "node_groups", socket.name, ICON_NODETREE);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (input_has_attribute_toggle(*nmd->node_group, socket_index)) {
|
||||
add_attribute_search_or_value_buttons(C, row, *nmd, md_ptr, socket);
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
* \ingroup nodes
|
||||
*/
|
||||
|
||||
#include "BLI_cpp_type.hh"
|
||||
#include "BLI_generic_pointer.hh"
|
||||
|
||||
struct bNodeTree;
|
||||
|
||||
namespace blender::nodes {
|
||||
|
||||
struct GeometryNodesLazyFunctionGraphInfo;
|
||||
|
@ -31,11 +32,11 @@ class Closure {
|
|||
std::shared_ptr<ClosureInputValues> bound_values_;
|
||||
|
||||
public:
|
||||
Closure() = default;
|
||||
Closure(const Closure &other) = default;
|
||||
Closure();
|
||||
Closure(const Closure &other);
|
||||
explicit Closure(const GeometryNodesLazyFunctionGraphInfo &lf_graph_info,
|
||||
MutableSpan<GMutablePointer> &&bound_values);
|
||||
~Closure();
|
||||
~Closure() = default;
|
||||
|
||||
Closure &operator=(const Closure &other) = default;
|
||||
|
||||
|
@ -43,6 +44,8 @@ class Closure {
|
|||
|
||||
Span<GMutablePointer> bound_values() const;
|
||||
MutableSpan<GMutablePointer> bound_values();
|
||||
|
||||
static Closure make_from_node_tree(const bNodeTree *node_tree);
|
||||
};
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
|
||||
#include "NOD_closure.hh"
|
||||
|
||||
#include "DNA_node_types.h"
|
||||
|
||||
#include "BKE_node_runtime.hh"
|
||||
|
||||
#include "NOD_geometry_nodes_lazy_function.hh"
|
||||
|
||||
namespace blender::nodes {
|
||||
|
@ -15,8 +19,10 @@ ClosureInputValues::ClosureInputValues(const Span<GMutablePointer> &values) : va
|
|||
ClosureInputValues::~ClosureInputValues()
|
||||
{
|
||||
for (GMutablePointer &ptr : values_) {
|
||||
ptr.destruct();
|
||||
MEM_freeN(ptr.get());
|
||||
if (ptr.get()) {
|
||||
ptr.destruct();
|
||||
MEM_freeN(ptr.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -30,6 +36,13 @@ MutableSpan<GMutablePointer> ClosureInputValues::values()
|
|||
return values_;
|
||||
}
|
||||
|
||||
Closure::Closure() : bound_values_(nullptr) {}
|
||||
|
||||
Closure::Closure(const Closure &other)
|
||||
: lf_graph_info_(other.lf_graph_info_), bound_values_(other.bound_values_)
|
||||
{
|
||||
}
|
||||
|
||||
Closure::Closure(const GeometryNodesLazyFunctionGraphInfo &lf_graph_info,
|
||||
MutableSpan<GMutablePointer> &&bound_values)
|
||||
: lf_graph_info_(&lf_graph_info),
|
||||
|
@ -37,8 +50,6 @@ Closure::Closure(const GeometryNodesLazyFunctionGraphInfo &lf_graph_info,
|
|||
{
|
||||
}
|
||||
|
||||
Closure::~Closure() {}
|
||||
|
||||
const GeometryNodesLazyFunctionGraphInfo *Closure::lf_graph_info() const
|
||||
{
|
||||
return lf_graph_info_;
|
||||
|
@ -54,4 +65,21 @@ MutableSpan<GMutablePointer> Closure::bound_values()
|
|||
return bound_values_->values();
|
||||
}
|
||||
|
||||
Closure Closure ::make_from_node_tree(const bNodeTree *node_tree)
|
||||
{
|
||||
if (node_tree == nullptr) {
|
||||
return Closure();
|
||||
}
|
||||
|
||||
BLI_assert(node_tree->runtime);
|
||||
const std::unique_ptr<blender::nodes::GeometryNodesLazyFunctionGraphInfo> &lf_graph_info_ptr =
|
||||
node_tree->runtime->geometry_nodes_lazy_function_graph_info;
|
||||
BLI_assert(lf_graph_info_ptr);
|
||||
|
||||
Array<GMutablePointer> bound_values(node_tree->interface_inputs().size());
|
||||
// TODO fill with default values of the tree
|
||||
|
||||
return Closure(*lf_graph_info_ptr.get(), bound_values);
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
|
|
@ -256,9 +256,12 @@ SocketDeclarationPtr declaration_for_interface_socket(const bNodeTree &ntree,
|
|||
dst = std::move(value);
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION:
|
||||
dst = std::make_unique<decl::Function>();
|
||||
case SOCK_FUNCTION: {
|
||||
auto value = std::make_unique<decl::Function>();
|
||||
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;
|
||||
|
@ -368,7 +371,8 @@ void node_function_signature_declare(const bNodeFunctionSignature &sig,
|
|||
r_declaration.inputs.append(std::move(decl));
|
||||
}
|
||||
for (const int socket_i : IndexRange(sig.outputs_num)) {
|
||||
SocketDeclarationPtr decl = declaration_for_signature_parameter(sig.outputs[socket_i], SOCK_OUT);
|
||||
SocketDeclarationPtr decl = declaration_for_signature_parameter(sig.outputs[socket_i],
|
||||
SOCK_OUT);
|
||||
if (field_interface) {
|
||||
decl->output_field_dependency = field_interface->outputs[socket_i];
|
||||
}
|
||||
|
@ -543,7 +547,8 @@ bool BKE_node_is_connected_to_output(const bNodeTree *ntree, const bNode *node)
|
|||
for (const bNodeSocket *socket : next_node->output_sockets()) {
|
||||
for (const bNodeLink *link : socket->directly_linked_links()) {
|
||||
if (link->tonode->typeinfo->nclass == NODE_CLASS_OUTPUT &&
|
||||
link->tonode->flag & NODE_DO_OUTPUT) {
|
||||
link->tonode->flag & NODE_DO_OUTPUT)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
nodes_to_check.push(link->tonode);
|
||||
|
|
|
@ -418,6 +418,14 @@ void node_socket_init_default_value(bNodeSocket *sock)
|
|||
"node socket value material");
|
||||
dval->value = nullptr;
|
||||
|
||||
sock->default_value = dval;
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
bNodeSocketValueFunction *dval = MEM_cnew<bNodeSocketValueFunction>(
|
||||
"node socket value function");
|
||||
dval->value = nullptr;
|
||||
|
||||
sock->default_value = dval;
|
||||
break;
|
||||
}
|
||||
|
@ -514,6 +522,13 @@ void node_socket_copy_default_value(bNodeSocket *to, const bNodeSocket *from)
|
|||
id_us_plus(&toval->value->id);
|
||||
break;
|
||||
}
|
||||
case SOCK_FUNCTION: {
|
||||
bNodeSocketValueFunction *toval = (bNodeSocketValueFunction *)to->default_value;
|
||||
bNodeSocketValueFunction *fromval = (bNodeSocketValueFunction *)from->default_value;
|
||||
*toval = *fromval;
|
||||
id_us_plus(&toval->value->id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
to->flag |= (from->flag & SOCK_HIDE_VALUE);
|
||||
|
@ -796,10 +811,13 @@ static bNodeSocketType *make_socket_type_material()
|
|||
|
||||
static bNodeSocketType *make_socket_type_function()
|
||||
{
|
||||
using Closure = blender::nodes::Closure;
|
||||
|
||||
bNodeSocketType *socktype = make_standard_socket_type(SOCK_FUNCTION, PROP_NONE);
|
||||
socktype->base_cpp_type = &blender::CPPType::get<blender::nodes::Closure>();
|
||||
socktype->get_base_cpp_value = [](const bNodeSocket &/*socket*/, void *r_value) {
|
||||
new (r_value) blender::nodes::Closure();
|
||||
socktype->base_cpp_type = &blender::CPPType::get<Closure>();
|
||||
socktype->get_base_cpp_value = [](const bNodeSocket &socket, void *r_value) {
|
||||
const bNodeTree *ntree = ((bNodeSocketValueFunction *)socket.default_value)->value;
|
||||
new (r_value) Closure(Closure::make_from_node_tree(ntree));
|
||||
};
|
||||
socktype->geometry_nodes_cpp_type = socktype->base_cpp_type;
|
||||
socktype->get_geometry_nodes_cpp_value = socktype->get_base_cpp_value;
|
||||
|
|
Loading…
Reference in New Issue