Cleanup: Move BKE_node.h to C++ #107790

Merged
Hans Goudey merged 16 commits from mod_moder/blender:tmp_move_node_on_cpp into main 2023-05-15 15:14:30 +02:00
17 changed files with 427 additions and 424 deletions
Showing only changes of commit e7a1f09481 - Show all commits

View File

@ -580,31 +580,12 @@ void ntreeBlendReadExpand(struct BlendExpander *expander, struct bNodeTree *ntre
/** \name Node Tree Interface
* \{ */
struct bNodeSocket *ntreeFindSocketInterface(struct bNodeTree *ntree,
eNodeSocketInOut in_out,
const char *identifier);
void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock);
struct bNodeSocket *ntreeAddSocketInterface(struct bNodeTree *ntree,
eNodeSocketInOut in_out,
const char *idname,
const char *name);
struct bNodeSocket *ntreeInsertSocketInterface(struct bNodeTree *ntree,
eNodeSocketInOut in_out,
const char *idname,
struct bNodeSocket *next_sock,
const char *name);
struct bNodeSocket *ntreeAddSocketInterfaceFromSocket(struct bNodeTree *ntree,
const struct bNode *from_node,
const struct bNodeSocket *from_sock);
struct bNodeSocket *ntreeAddSocketInterfaceFromSocketWithName(struct bNodeTree *ntree,
const struct bNode *from_node,
const struct bNodeSocket *from_sock,
const char *idname,
const char *name);
struct bNodeSocket *ntreeInsertSocketInterfaceFromSocket(struct bNodeTree *ntree,
struct bNodeSocket *next_sock,
const struct bNode *from_node,
const struct bNodeSocket *from_sock);
void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *sock);
/** \} */
@ -615,7 +596,6 @@ void ntreeRemoveSocketInterface(struct bNodeTree *ntree, struct bNodeSocket *soc
struct bNodeType *nodeTypeFind(const char *idname);
void nodeRegisterType(struct bNodeType *ntype);
void nodeUnregisterType(struct bNodeType *ntype);
bool nodeTypeUndefined(const struct bNode *node);
struct GHashIterator *nodeTypeGetIterator(void);
/* Helper macros for iterating over node types. */
@ -639,11 +619,9 @@ bool nodeSocketIsRegistered(const struct bNodeSocket *sock);
struct GHashIterator *nodeSocketTypeGetIterator(void);
const char *nodeSocketTypeLabel(const bNodeSocketType *stype);
bool nodeIsStaticSocketType(const struct bNodeSocketType *stype);
const char *nodeStaticSocketType(int type, int subtype);
const char *nodeStaticSocketInterfaceType(int type, int subtype);
const char *nodeStaticSocketLabel(int type, int subtype);
const char *nodeSocketSubTypeLabel(int subtype);
/* Helper macros for iterating over node types. */
#define NODE_SOCKET_TYPES_BEGIN(stype) \
@ -678,24 +656,13 @@ struct bNodeSocket *nodeAddStaticSocket(struct bNodeTree *ntree,
const char *identifier,
const char *name);
void nodeRemoveSocket(struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock);
void nodeRemoveSocketEx(struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocket *sock,
bool do_id_user);
void nodeRemoveAllSockets(struct bNodeTree *ntree, struct bNode *node);
void nodeModifySocketType(struct bNodeTree *ntree,
struct bNode *node,
struct bNodeSocket *sock,
const char *idname);
void nodeModifySocketTypeStatic(
struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *sock, int type, int subtype);
struct bNode *nodeAddNode(const struct bContext *C, struct bNodeTree *ntree, const char *idname);
struct bNode *nodeAddStaticNode(const struct bContext *C, struct bNodeTree *ntree, int type);
/**
* \note Goes over entire tree.
*/
void nodeUnlinkNode(struct bNodeTree *ntree, struct bNode *node);
/**
* Find the first available, non-duplicate name for a given node.
*/
@ -706,13 +673,6 @@ void nodeUniqueName(struct bNodeTree *ntree, struct bNode *node);
*/
void nodeUniqueID(struct bNodeTree *ntree, struct bNode *node);
/**
* Rebuild the `node_by_id` runtime vector set. Call after removing a node if not handled
* separately. This is important instead of just using `nodes_by_id.remove()` since it maintains
* the node order.
*/
void nodeRebuildIDVector(struct bNodeTree *node_tree);
/**
* Delete node, associated animation data and ID user count.
*/
@ -725,47 +685,6 @@ void nodeDimensionsGet(const struct bNode *node, float *r_width, float *r_height
void nodeTagUpdateID(struct bNode *node);
void nodeInternalLinks(struct bNode *node, struct bNodeLink **r_links, int *r_len);
#ifdef __cplusplus
namespace blender::bke {
/**
* \note keeps socket list order identical, for copying links.
* \param use_unique: If true, make sure the node's identifier and name are unique in the new
* tree. Must be *true* if the \a dst_tree had nodes that weren't in the source node's tree.
* Must be *false* when simply copying a node tree, so that identifiers don't change.
*/
bNode *node_copy_with_mapping(bNodeTree *dst_tree,
const bNode &node_src,
int flag,
bool use_unique,
Map<const bNodeSocket *, bNodeSocket *> &new_socket_map);
bNode *node_copy(bNodeTree *dst_tree, const bNode &src_node, int flag, bool use_unique);
/**
* 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.
*
* \note ID user reference-counting and changing the `nodes_by_id` vector are up to the caller.
*/
void node_free_node(bNodeTree *tree, bNode *node);
} // namespace blender::bke
#endif
/**
* Also used via RNA API, so we check for proper input output direction.
*/

View File

@ -24,34 +24,119 @@
namespace blender::bke {
/* -------------------------------------------------------------------- */
/** \name Node Tree Interface
* \{ */
bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree,
eNodeSocketInOut in_out,
const char *identifier);
}
bNodeSocket *ntreeInsertSocketInterface(bNodeTree *ntree,
eNodeSocketInOut in_out,
const char *idname,
bNodeSocket *next_sock,
const char *name);
bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree,
const bNode *from_node,
const bNodeSocket *from_sock);
bNodeSocket *ntreeAddSocketInterfaceFromSocketWithName(bNodeTree *ntree,
const bNode *from_node,
const bNodeSocket *from_sock,
const char *idname,
const char *name);
bNodeSocket *ntreeInsertSocketInterfaceFromSocket(bNodeTree *ntree,
bNodeSocket *next_sock,
const bNode *from_node,
const bNodeSocket *from_sock);
/** \} */
bool nodeTypeUndefined(const bNode *node);
bool nodeIsStaticSocketType(const bNodeSocketType *stype);
const char *nodeSocketSubTypeLabel(int subtype);
void nodeRemoveSocketEx(bNodeTree *ntree, bNode *node, bNodeSocket *sock, bool do_id_user);
void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node);
void nodeModifySocketType(bNodeTree *ntree, bNode *node, bNodeSocket *sock, const char *idname);
/**
* \note Goes over entire tree.
*/
void nodeUnlinkNode(bNodeTree *ntree, bNode *node);
/**
* Rebuild the `node_by_id` runtime vector set. Call after removing a node if not handled
* separately. This is important instead of just using `nodes_by_id.remove()` since it maintains
* the node order.
*/
void nodeRebuildIDVector(bNodeTree *node_tree);
/**
* \note keeps socket list order identical, for copying links.
* \param use_unique: If true, make sure the node's identifier and name are unique in the new
* tree. Must be *true* if the \a dst_tree had nodes that weren't in the source node's tree.
* Must be *false* when simply copying a node tree, so that identifiers don't change.
*/
bNode *node_copy_with_mapping(bNodeTree *dst_tree,
const bNode &node_src,
int flag,
bool use_unique,
Map<const bNodeSocket *, bNodeSocket *> &new_socket_map);
bNode *node_copy(bNodeTree *dst_tree, const bNode &src_node, int flag, bool use_unique);
/**
* 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.
*
* \note ID user reference-counting and changing the `nodes_by_id` vector are up to the caller.
*/
void node_free_node(bNodeTree *tree, bNode *node);
} // namespace blender::bke
namespace blender::bke {
/**
* Set the mute status of a single link.
*/
void nodeLinkSetMute( bNodeTree *ntree, bNodeLink *link, const bool muted);
bool nodeLinkIsSelected(const bNodeLink *link);
void nodeInternalRelink( bNodeTree *ntree, bNode *node);
void nodeLinkSetMute(bNodeTree *ntree, bNodeLink *link, const bool muted);
bool nodeLinkIsSelected(const bNodeLink *link);
void nodeInternalRelink(bNodeTree *ntree, bNode *node);
void nodeToView(const bNode *node, float x, float y, float *rx, float *ry);
void nodeFromView(const bNode *node, float x, float y, float *rx, float *ry);
void nodeToView(const bNode *node, float x, float y, float *rx, float *ry);
void nodeFromView(const bNode *node, float x, float y, float *rx, float *ry);
void nodePositionRelative( bNode *from_node,
const bNode *to_node,
const bNodeSocket *from_sock,
const bNodeSocket *to_sock);
void nodePositionRelative(bNode *from_node,
const bNode *to_node,
const bNodeSocket *from_sock,
const bNodeSocket *to_sock);
void nodePositionPropagate( bNode *node);
void nodePositionPropagate(bNode *node);
/**
* \note Recursive.
*/
bNode *nodeFindRootParent(bNode *node);
bNode *nodeFindRootParent(bNode *node);
/**
* Iterate over a chain of nodes, starting with \a node_start, executing
@ -102,7 +187,7 @@ struct bNodeLink *nodeFindLink(struct bNodeTree *ntree,
struct bNode *nodeGetActivePaintCanvas(struct bNodeTree *ntree);
}
} // namespace blender::bke
namespace blender::bke {
@ -133,7 +218,7 @@ bool nodeDeclarationEnsureOnOutdatedNode(struct bNodeTree *ntree, struct bNode *
*/
void nodeSocketDeclarationsUpdate(struct bNode *node);
}
} // namespace blender::bke
namespace blender::bke {
@ -144,7 +229,7 @@ BLI_INLINE bNodeInstanceHashIterator *node_instance_hash_iterator_new(bNodeInsta
return BLI_ghashIterator_new(hash->ghash);
}
BLI_INLINE void node_instance_hash_iterator_init(bNodeInstanceHashIterator *iter,
bNodeInstanceHash *hash)
bNodeInstanceHash *hash)
{
BLI_ghashIterator_init(iter, hash->ghash);
}
@ -174,22 +259,21 @@ BLI_INLINE bool node_instance_hash_iterator_done(bNodeInstanceHashIterator *iter
blender::bke::node_instance_hash_iterator_done(&iter_) == false; \
blender::bke::node_instance_hash_iterator_step(&iter_))
}
} // namespace blender::bke
namespace blender::bke {
/* Node Previews */
bool node_preview_used(const bNode *node);
bNodePreview *node_preview_verify(bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, bool create);
bNodePreview *node_preview_copy( bNodePreview *preview);
void node_preview_free( bNodePreview *preview);
bool node_preview_used(const bNode *node);
bNodePreview *node_preview_verify(
bNodeInstanceHash *previews, bNodeInstanceKey key, int xsize, int ysize, bool create);
bNodePreview *node_preview_copy(bNodePreview *preview);
void node_preview_free(bNodePreview *preview);
void node_preview_init_tree(bNodeTree *ntree, int xsize, int ysize);
void node_preview_remove_unused(bNodeTree *ntree);
void node_preview_clear(bNodePreview *preview);
void node_preview_merge_tree(bNodeTree *to_ntree,
bNodeTree *from_ntree,
bool remove_old);
void node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, bool remove_old);
/* -------------------------------------------------------------------- */
/** \name Node Type Access

View File

@ -204,7 +204,8 @@ static void ntree_copy_data(Main * /*bmain*/, ID *id_dst, const ID *id_src, cons
bNodeInstanceKey key = blender::bke::node_instance_hash_iterator_get_key(&iter);
bNodePreview *preview = static_cast<bNodePreview *>(
blender::bke::node_instance_hash_iterator_get_value(&iter));
BKE_node_instance_hash_insert(ntree_dst->previews, key, blender::bke::node_preview_copy(preview));
BKE_node_instance_hash_insert(
ntree_dst->previews, key, blender::bke::node_preview_copy(preview));
}
}
else {
@ -270,7 +271,8 @@ static void ntree_free_data(ID *id)
/* free preview hash */
if (ntree->previews) {
BKE_node_instance_hash_free(ntree->previews, (bNodeInstanceValueFP)blender::bke::node_preview_free);
BKE_node_instance_hash_free(ntree->previews,
(bNodeInstanceValueFP)blender::bke::node_preview_free);
}
if (ntree->id.tag & LIB_TAG_LOCALIZED) {
@ -1440,28 +1442,6 @@ void nodeUnregisterType(bNodeType *nt)
BLI_ghash_remove(nodetypes_hash, nt->idname, nullptr, node_free_type);
}
bool nodeTypeUndefined(const bNode *node)
{
if (node->typeinfo == &NodeTypeUndefined) {
return true;
}
if (node->is_group()) {
const ID *group_tree = node->id;
if (group_tree == nullptr) {
return false;
}
if (!ID_IS_LINKED(group_tree)) {
return false;
}
if ((group_tree->tag & LIB_TAG_MISSING) == 0) {
return false;
}
return true;
}
return false;
}
GHashIterator *nodeTypeGetIterator()
{
return BLI_ghashIterator_new(nodetypes_hash);
@ -1524,15 +1504,6 @@ const char *nodeSocketTypeLabel(const bNodeSocketType *stype)
return stype->label;
}
const char *nodeSocketSubTypeLabel(int subtype)
{
const char *name;
if (RNA_enum_name(rna_enum_property_subtype_items, subtype, &name)) {
return name;
}
return "";
}
bNodeSocket *nodeFindSocket(const bNode *node,
const eNodeSocketInOut in_out,
const char *identifier)
@ -1716,66 +1687,6 @@ static bool socket_id_user_decrement(bNodeSocket *sock)
return false;
}
void nodeModifySocketType(bNodeTree *ntree,
bNode * /*node*/,
bNodeSocket *sock,
const char *idname)
{
bNodeSocketType *socktype = nodeSocketTypeFind(idname);
if (!socktype) {
CLOG_ERROR(&LOG, "node socket type %s undefined", idname);
return;
}
if (sock->default_value) {
if (sock->type != socktype->type) {
/* Only reallocate the default value if the type changed so that UI data like min and max
* isn't removed. This assumes that the default value is stored in the same format for all
* socket types with the same #eNodeSocketDatatype. */
socket_id_user_decrement(sock);
MEM_freeN(sock->default_value);
sock->default_value = nullptr;
}
else {
/* Update the socket subtype when the storage isn't freed and recreated. */
switch (eNodeSocketDatatype(sock->type)) {
case SOCK_FLOAT: {
sock->default_value_typed<bNodeSocketValueFloat>()->subtype = socktype->subtype;
break;
}
case SOCK_VECTOR: {
sock->default_value_typed<bNodeSocketValueVector>()->subtype = socktype->subtype;
break;
}
case SOCK_INT: {
sock->default_value_typed<bNodeSocketValueInt>()->subtype = socktype->subtype;
break;
}
case SOCK_STRING: {
sock->default_value_typed<bNodeSocketValueString>()->subtype = socktype->subtype;
break;
}
case SOCK_RGBA:
case SOCK_SHADER:
case SOCK_BOOLEAN:
case SOCK_CUSTOM:
case __SOCK_MESH:
case SOCK_OBJECT:
case SOCK_IMAGE:
case SOCK_GEOMETRY:
case SOCK_COLLECTION:
case SOCK_TEXTURE:
case SOCK_MATERIAL:
break;
}
}
}
STRNCPY(sock->idname, idname);
node_socket_set_typeinfo(ntree, sock, socktype);
}
void nodeModifySocketTypeStatic(
bNodeTree *ntree, bNode *node, bNodeSocket *sock, const int type, const int subtype)
{
@ -1786,7 +1697,7 @@ void nodeModifySocketTypeStatic(
return;
}
nodeModifySocketType(ntree, node, sock, idname);
blender::bke::nodeModifySocketType(ntree, node, sock, idname);
}
bNodeSocket *nodeAddSocket(bNodeTree *ntree,
@ -1811,15 +1722,6 @@ bNodeSocket *nodeAddSocket(bNodeTree *ntree,
return sock;
}
bool nodeIsStaticSocketType(const bNodeSocketType *stype)
{
/*
* Cannot rely on type==SOCK_CUSTOM here, because type is 0 by default
* and can be changed on custom sockets.
*/
return RNA_struct_is_a(stype->ext_socket.srna, &RNA_NodeSocketStandard);
}
const char *nodeStaticSocketType(const int type, const int subtype)
{
switch (eNodeSocketDatatype(type)) {
@ -2054,59 +1956,7 @@ static void node_socket_free(bNodeSocket *sock, const bool do_id_user)
void nodeRemoveSocket(bNodeTree *ntree, bNode *node, bNodeSocket *sock)
{
nodeRemoveSocketEx(ntree, node, sock, true);
}
void nodeRemoveSocketEx(bNodeTree *ntree, bNode *node, bNodeSocket *sock, const bool do_id_user)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
if (link->fromsock == sock || link->tosock == sock) {
nodeRemLink(ntree, link);
}
}
for (const int64_t i : node->runtime->internal_links.index_range()) {
const bNodeLink &link = node->runtime->internal_links[i];
if (link.fromsock == sock || link.tosock == sock) {
node->runtime->internal_links.remove_and_reorder(i);
BKE_ntree_update_tag_node_internal_link(ntree, node);
break;
}
}
/* this is fast, this way we don't need an in_out argument */
BLI_remlink(&node->inputs, sock);
BLI_remlink(&node->outputs, sock);
node_socket_free(sock, do_id_user);
MEM_freeN(sock);
BKE_ntree_update_tag_socket_removed(ntree);
}
void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
if (link->fromnode == node || link->tonode == node) {
nodeRemLink(ntree, link);
}
}
node->runtime->internal_links.clear();
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->inputs) {
node_socket_free(sock, true);
MEM_freeN(sock);
}
BLI_listbase_clear(&node->inputs);
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->outputs) {
node_socket_free(sock, true);
MEM_freeN(sock);
}
BLI_listbase_clear(&node->outputs);
BKE_ntree_update_tag_socket_removed(ntree);
blender::bke::nodeRemoveSocketEx(ntree, node, sock, true);
}
bNode *nodeFindNodebyName(bNodeTree *ntree, const char *name)
@ -2660,10 +2510,10 @@ bool blender::bke::node_preview_used(const bNode *node)
}
bNodePreview *blender::bke::node_preview_verify(bNodeInstanceHash *previews,
bNodeInstanceKey key,
const int xsize,
const int ysize,
const bool create)
bNodeInstanceKey key,
const int xsize,
const int ysize,
const bool create)
{
bNodePreview *preview = static_cast<bNodePreview *>(
BKE_node_instance_hash_lookup(previews, key));
@ -2765,33 +2615,6 @@ void BKE_node_preview_clear_tree(bNodeTree *ntree)
}
}
void nodeUnlinkNode(bNodeTree *ntree, bNode *node)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
ListBase *lb = nullptr;
if (link->fromnode == node) {
lb = &node->outputs;
}
else if (link->tonode == node) {
lb = &node->inputs;
}
if (lb) {
/* Only bother adjusting if the socket is not on the node we're deleting. */
if (link->tonode != node && link->tosock->is_multi_input()) {
adjust_multi_input_indices_after_removed_link(
ntree, link->tosock, link->multi_input_socket_index);
}
LISTBASE_FOREACH (const bNodeSocket *, sock, lb) {
if (link->fromsock == sock || link->tosock == sock) {
nodeRemLink(ntree, link);
break;
}
}
}
}
}
static void node_unlink_attached(bNodeTree *ntree, const bNode *parent)
{
for (bNode *node : ntree->all_nodes()) {
@ -2801,17 +2624,6 @@ static void node_unlink_attached(bNodeTree *ntree, const bNode *parent)
}
}
void nodeRebuildIDVector(bNodeTree *node_tree)
{
/* Rebuild nodes #VectorSet which must have the same order as the list. */
node_tree->runtime->nodes_by_id.clear();
int i;
LISTBASE_FOREACH_INDEX (bNode *, node, &node_tree->nodes, i) {
node_tree->runtime->nodes_by_id.add_new(node);
node->runtime->index_in_tree = i;
}
}
namespace blender::bke {
void node_free_node(bNodeTree *ntree, bNode *node)
@ -2873,11 +2685,11 @@ void ntreeFreeLocalNode(bNodeTree *ntree, bNode *node)
/* These two lines assume the caller might want to free a single node and maintain
* a valid state in the node tree. */
nodeUnlinkNode(ntree, node);
blender::bke::nodeUnlinkNode(ntree, node);
node_unlink_attached(ntree, node);
blender::bke::node_free_node(ntree, node);
nodeRebuildIDVector(ntree);
blender::bke::nodeRebuildIDVector(ntree);
}
void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, const bool do_id_user)
@ -2935,12 +2747,12 @@ void nodeRemoveNode(Main *bmain, bNodeTree *ntree, bNode *node, const bool do_id
}
}
nodeUnlinkNode(ntree, node);
blender::bke::nodeUnlinkNode(ntree, node);
node_unlink_attached(ntree, node);
/* Free node itself. */
blender::bke::node_free_node(ntree, node);
nodeRebuildIDVector(ntree);
blender::bke::nodeRebuildIDVector(ntree);
}
static void node_socket_interface_free(bNodeTree * /*ntree*/,
@ -3160,6 +2972,18 @@ void ntreeLocalMerge(Main *bmain, bNodeTree *localtree, bNodeTree *ntree)
/* ************ NODE TREE INTERFACE *************** */
void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock)
{
/* this is fast, this way we don't need an in_out argument */
BLI_remlink(&ntree->inputs, sock);
BLI_remlink(&ntree->outputs, sock);
node_socket_interface_free(ntree, sock, true);
MEM_freeN(sock);
BKE_ntree_update_tag_interface(ntree);
}
static bNodeSocket *make_socket_interface(bNodeTree *ntree,
const eNodeSocketInOut in_out,
const char *idname,
@ -3196,19 +3020,6 @@ static bNodeSocket *make_socket_interface(bNodeTree *ntree,
return sock;
}
bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree,
const eNodeSocketInOut in_out,
const char *identifier)
{
ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs;
LISTBASE_FOREACH (bNodeSocket *, iosock, sockets) {
if (STREQ(iosock->identifier, identifier)) {
return iosock;
}
}
return nullptr;
}
bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree,
const eNodeSocketInOut in_out,
const char *idname,
@ -3225,75 +3036,6 @@ bNodeSocket *ntreeAddSocketInterface(bNodeTree *ntree,
return iosock;
}
bNodeSocket *ntreeInsertSocketInterface(bNodeTree *ntree,
const eNodeSocketInOut in_out,
const char *idname,
bNodeSocket *next_sock,
const char *name)
{
bNodeSocket *iosock = make_socket_interface(ntree, in_out, idname, name);
if (in_out == SOCK_IN) {
BLI_insertlinkbefore(&ntree->inputs, next_sock, iosock);
}
else if (in_out == SOCK_OUT) {
BLI_insertlinkbefore(&ntree->outputs, next_sock, iosock);
}
BKE_ntree_update_tag_interface(ntree);
return iosock;
}
bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree,
const bNode *from_node,
const bNodeSocket *from_sock)
{
return ntreeAddSocketInterfaceFromSocketWithName(
ntree, from_node, from_sock, from_sock->idname, from_sock->name);
}
bNodeSocket *ntreeAddSocketInterfaceFromSocketWithName(bNodeTree *ntree,
const bNode *from_node,
const bNodeSocket *from_sock,
const char *idname,
const char *name)
{
bNodeSocket *iosock = ntreeAddSocketInterface(
ntree, eNodeSocketInOut(from_sock->in_out), idname, DATA_(name));
if (iosock == nullptr) {
return nullptr;
}
if (iosock->typeinfo->interface_from_socket) {
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
}
return iosock;
}
bNodeSocket *ntreeInsertSocketInterfaceFromSocket(bNodeTree *ntree,
bNodeSocket *next_sock,
const bNode *from_node,
const bNodeSocket *from_sock)
{
bNodeSocket *iosock = ntreeInsertSocketInterface(
ntree, eNodeSocketInOut(from_sock->in_out), from_sock->idname, next_sock, from_sock->name);
if (iosock) {
if (iosock->typeinfo->interface_from_socket) {
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
}
}
return iosock;
}
void ntreeRemoveSocketInterface(bNodeTree *ntree, bNodeSocket *sock)
{
/* this is fast, this way we don't need an in_out argument */
BLI_remlink(&ntree->inputs, sock);
BLI_remlink(&ntree->outputs, sock);
node_socket_interface_free(ntree, sock, true);
MEM_freeN(sock);
BKE_ntree_update_tag_interface(ntree);
}
/* ************ find stuff *************** */
bNode *ntreeFindType(bNodeTree *ntree, const int type)
@ -3397,7 +3139,8 @@ void nodeClearActive(bNodeTree *ntree)
void nodeSetActive(bNodeTree *ntree, bNode *node)
{
const bool is_paint_canvas = blender::bke::nodeSupportsActiveFlag(node, NODE_ACTIVE_PAINT_CANVAS);
const bool is_paint_canvas = blender::bke::nodeSupportsActiveFlag(node,
NODE_ACTIVE_PAINT_CANVAS);
const bool is_texture_class = blender::bke::nodeSupportsActiveFlag(node, NODE_ACTIVE_TEXTURE);
int flags_to_set = NODE_ACTIVE;
SET_FLAG_FROM_TEST(flags_to_set, is_paint_canvas, NODE_ACTIVE_PAINT_CANVAS);
@ -3886,6 +3629,266 @@ void nodeFindNode(bNodeTree *ntree, bNodeSocket *sock, bNode **r_node, int *r_so
namespace blender::bke {
void nodeModifySocketType(bNodeTree *ntree,
bNode * /*node*/,
bNodeSocket *sock,
const char *idname)
{
bNodeSocketType *socktype = nodeSocketTypeFind(idname);
if (!socktype) {
CLOG_ERROR(&LOG, "node socket type %s undefined", idname);
return;
}
if (sock->default_value) {
if (sock->type != socktype->type) {
/* Only reallocate the default value if the type changed so that UI data like min and max
* isn't removed. This assumes that the default value is stored in the same format for all
* socket types with the same #eNodeSocketDatatype. */
socket_id_user_decrement(sock);
MEM_freeN(sock->default_value);
sock->default_value = nullptr;
}
else {
/* Update the socket subtype when the storage isn't freed and recreated. */
switch (eNodeSocketDatatype(sock->type)) {
case SOCK_FLOAT: {
sock->default_value_typed<bNodeSocketValueFloat>()->subtype = socktype->subtype;
break;
}
case SOCK_VECTOR: {
sock->default_value_typed<bNodeSocketValueVector>()->subtype = socktype->subtype;
break;
}
case SOCK_INT: {
sock->default_value_typed<bNodeSocketValueInt>()->subtype = socktype->subtype;
break;
}
case SOCK_STRING: {
sock->default_value_typed<bNodeSocketValueString>()->subtype = socktype->subtype;
break;
}
case SOCK_RGBA:
case SOCK_SHADER:
case SOCK_BOOLEAN:
case SOCK_CUSTOM:
case __SOCK_MESH:
case SOCK_OBJECT:
case SOCK_IMAGE:
case SOCK_GEOMETRY:
case SOCK_COLLECTION:
case SOCK_TEXTURE:
case SOCK_MATERIAL:
break;
}
}
}
STRNCPY(sock->idname, idname);
node_socket_set_typeinfo(ntree, sock, socktype);
}
void nodeRebuildIDVector(bNodeTree *node_tree)
{
/* Rebuild nodes #VectorSet which must have the same order as the list. */
node_tree->runtime->nodes_by_id.clear();
int i;
LISTBASE_FOREACH_INDEX (bNode *, node, &node_tree->nodes, i) {
node_tree->runtime->nodes_by_id.add_new(node);
node->runtime->index_in_tree = i;
}
}
void nodeUnlinkNode(bNodeTree *ntree, bNode *node)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
ListBase *lb = nullptr;
if (link->fromnode == node) {
lb = &node->outputs;
}
else if (link->tonode == node) {
lb = &node->inputs;
}
if (lb) {
/* Only bother adjusting if the socket is not on the node we're deleting. */
if (link->tonode != node && link->tosock->is_multi_input()) {
adjust_multi_input_indices_after_removed_link(
ntree, link->tosock, link->multi_input_socket_index);
}
LISTBASE_FOREACH (const bNodeSocket *, sock, lb) {
if (link->fromsock == sock || link->tosock == sock) {
nodeRemLink(ntree, link);
break;
}
}
}
}
}
void nodeRemoveAllSockets(bNodeTree *ntree, bNode *node)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
if (link->fromnode == node || link->tonode == node) {
nodeRemLink(ntree, link);
}
}
node->runtime->internal_links.clear();
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->inputs) {
node_socket_free(sock, true);
MEM_freeN(sock);
}
BLI_listbase_clear(&node->inputs);
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, sock, &node->outputs) {
node_socket_free(sock, true);
MEM_freeN(sock);
}
BLI_listbase_clear(&node->outputs);
BKE_ntree_update_tag_socket_removed(ntree);
}
void nodeRemoveSocketEx(bNodeTree *ntree, bNode *node, bNodeSocket *sock, const bool do_id_user)
{
LISTBASE_FOREACH_MUTABLE (bNodeLink *, link, &ntree->links) {
if (link->fromsock == sock || link->tosock == sock) {
nodeRemLink(ntree, link);
}
}
for (const int64_t i : node->runtime->internal_links.index_range()) {
const bNodeLink &link = node->runtime->internal_links[i];
if (link.fromsock == sock || link.tosock == sock) {
node->runtime->internal_links.remove_and_reorder(i);
BKE_ntree_update_tag_node_internal_link(ntree, node);
break;
}
}
/* this is fast, this way we don't need an in_out argument */
BLI_remlink(&node->inputs, sock);
BLI_remlink(&node->outputs, sock);
node_socket_free(sock, do_id_user);
MEM_freeN(sock);
BKE_ntree_update_tag_socket_removed(ntree);
}
const char *nodeSocketSubTypeLabel(int subtype)
{
const char *name;
if (RNA_enum_name(rna_enum_property_subtype_items, subtype, &name)) {
return name;
}
return "";
}
bool nodeIsStaticSocketType(const bNodeSocketType *stype)
{
/*
* Cannot rely on type==SOCK_CUSTOM here, because type is 0 by default
* and can be changed on custom sockets.
*/
return RNA_struct_is_a(stype->ext_socket.srna, &RNA_NodeSocketStandard);
}
bool nodeTypeUndefined(const bNode *node)
{
if (node->typeinfo == &NodeTypeUndefined) {
return true;
}
if (node->is_group()) {
const ID *group_tree = node->id;
if (group_tree == nullptr) {
return false;
}
if (!ID_IS_LINKED(group_tree)) {
return false;
}
if ((group_tree->tag & LIB_TAG_MISSING) == 0) {
return false;
}
return true;
}
return false;
}
bNodeSocket *ntreeInsertSocketInterfaceFromSocket(bNodeTree *ntree,
bNodeSocket *next_sock,
const bNode *from_node,
const bNodeSocket *from_sock)
{
bNodeSocket *iosock = blender::bke::ntreeInsertSocketInterface(
ntree, eNodeSocketInOut(from_sock->in_out), from_sock->idname, next_sock, from_sock->name);
if (iosock) {
if (iosock->typeinfo->interface_from_socket) {
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
}
}
return iosock;
}
bNodeSocket *ntreeAddSocketInterfaceFromSocketWithName(bNodeTree *ntree,
const bNode *from_node,
const bNodeSocket *from_sock,
const char *idname,
const char *name)
{
bNodeSocket *iosock = ntreeAddSocketInterface(
ntree, eNodeSocketInOut(from_sock->in_out), idname, DATA_(name));
if (iosock == nullptr) {
return nullptr;
}
if (iosock->typeinfo->interface_from_socket) {
iosock->typeinfo->interface_from_socket(ntree, iosock, from_node, from_sock);
}
return iosock;
}
bNodeSocket *ntreeAddSocketInterfaceFromSocket(bNodeTree *ntree,
const bNode *from_node,
const bNodeSocket *from_sock)
{
return ntreeAddSocketInterfaceFromSocketWithName(
ntree, from_node, from_sock, from_sock->idname, from_sock->name);
}
bNodeSocket *ntreeInsertSocketInterface(bNodeTree *ntree,
const eNodeSocketInOut in_out,
const char *idname,
bNodeSocket *next_sock,
const char *name)
{
bNodeSocket *iosock = make_socket_interface(ntree, in_out, idname, name);
if (in_out == SOCK_IN) {
BLI_insertlinkbefore(&ntree->inputs, next_sock, iosock);
}
else if (in_out == SOCK_OUT) {
BLI_insertlinkbefore(&ntree->outputs, next_sock, iosock);
}
BKE_ntree_update_tag_interface(ntree);
return iosock;
}
bNodeSocket *ntreeFindSocketInterface(bNodeTree *ntree,
const eNodeSocketInOut in_out,
const char *identifier)
{
ListBase *sockets = (in_out == SOCK_IN) ? &ntree->inputs : &ntree->outputs;
LISTBASE_FOREACH (bNodeSocket *, iosock, sockets) {
if (STREQ(iosock->identifier, identifier)) {
return iosock;
}
}
return nullptr;
}
void nodeLinkSetMute(bNodeTree *ntree, bNodeLink *link, const bool muted)
{
const bool was_muted = link->is_muted();
@ -4264,9 +4267,7 @@ void node_preview_merge_tree(bNodeTree *to_ntree, bNodeTree *from_ntree, bool re
/* replace existing previews */
BKE_node_instance_hash_remove(
to_ntree->previews,
key,
reinterpret_cast<bNodeInstanceValueFP>(node_preview_free));
to_ntree->previews, key, reinterpret_cast<bNodeInstanceValueFP>(node_preview_free));
BKE_node_instance_hash_insert(to_ntree->previews, key, preview);
}
@ -4446,4 +4447,4 @@ void node_type_size(bNodeType *ntype, const int width, const int minwidth, const
}
}
}
} // namespace blender::bke

View File

@ -940,7 +940,7 @@ static void version_geometry_nodes_primitive_uv_maps(bNodeTree &ntree)
BLI_addhead(&ntree.nodes, node);
}
if (!new_nodes.is_empty()) {
nodeRebuildIDVector(&ntree);
blender::bke::nodeRebuildIDVector(&ntree);
}
}
@ -1074,7 +1074,7 @@ static void version_geometry_nodes_extrude_smooth_propagation(bNodeTree &ntree)
BLI_addhead(&ntree.nodes, node);
}
if (!new_nodes.is_empty()) {
nodeRebuildIDVector(&ntree);
blender::bke::nodeRebuildIDVector(&ntree);
}
}

View File

@ -130,7 +130,7 @@ Node *COM_convert_bnode(bNode *b_node)
Node *node = nullptr;
/* ignore undefined nodes with missing or invalid node data */
if (nodeTypeUndefined(b_node)) {
if (blender::bke::nodeTypeUndefined(b_node)) {
return nullptr;
}

View File

@ -83,7 +83,7 @@ static void add_reroute_node_fn(nodes::LinkSearchOpParams &params)
static void add_group_input_node_fn(nodes::LinkSearchOpParams &params)
{
/* Add a group input based on the connected socket, and add a new group input node. */
bNodeSocket *interface_socket = ntreeAddSocketInterfaceFromSocket(
bNodeSocket *interface_socket = blender::bke::ntreeAddSocketInterfaceFromSocket(
&params.node_tree, &params.node, &params.socket);
const int group_input_index = BLI_findindex(&params.node_tree.inputs, interface_socket);

View File

@ -2351,7 +2351,7 @@ static void node_draw_basis(const bContext &C,
const float outline_width = 1.0f;
{
/* Use warning color to indicate undefined types. */
if (nodeTypeUndefined(&node)) {
if (blender::bke::nodeTypeUndefined(&node)) {
UI_GetThemeColorBlend4f(TH_REDALERT, TH_NODE, 0.4f, color);
}
/* Muted nodes get a mix of the background with the node color. */
@ -2424,7 +2424,7 @@ static void node_draw_basis(const bContext &C,
if (node.flag & SELECT) {
UI_GetThemeColor4fv((node.flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, color_outline);
}
else if (nodeTypeUndefined(&node)) {
else if (blender::bke::nodeTypeUndefined(&node)) {
UI_GetThemeColor4fv(TH_REDALERT, color_outline);
}
else if (ELEM(node.type, GEO_NODE_SIMULATION_INPUT, GEO_NODE_SIMULATION_OUTPUT)) {
@ -2493,7 +2493,7 @@ static void node_draw_hidden(const bContext &C,
/* Body. */
float color[4];
{
if (nodeTypeUndefined(&node)) {
if (blender::bke::nodeTypeUndefined(&node)) {
/* Use warning color to indicate undefined types. */
UI_GetThemeColorBlend4f(TH_REDALERT, TH_NODE, 0.4f, color);
}
@ -2590,7 +2590,7 @@ static void node_draw_hidden(const bContext &C,
if (node.flag & SELECT) {
UI_GetThemeColor4fv((node.flag & NODE_ACTIVE) ? TH_ACTIVE : TH_SELECT, color_outline);
}
else if (nodeTypeUndefined(&node)) {
else if (blender::bke::nodeTypeUndefined(&node)) {
UI_GetThemeColor4fv(TH_REDALERT, color_outline);
}
else {

View File

@ -2184,7 +2184,7 @@ static int ntree_socket_add_exec(bContext *C, wmOperator *op)
bNodeSocket *sock;
if (active_sock) {
/* Insert a copy of the active socket right after it. */
sock = ntreeInsertSocketInterface(
sock = blender::bke::ntreeInsertSocketInterface(
ntree, in_out, active_sock->idname, active_sock->next, active_sock->name);
/* XXX this only works for actual sockets, not interface templates! */
// nodeSocketCopyValue(sock, &ntree_ptr, active_sock, &ntree_ptr);
@ -2302,7 +2302,7 @@ static int ntree_socket_change_type_exec(bContext *C, wmOperator *op)
return OPERATOR_FINISHED;
}
nodeModifySocketType(ntree, nullptr, iosock, socket_type->idname);
blender::bke::nodeModifySocketType(ntree, nullptr, iosock, socket_type->idname);
/* Need the extra update here because the loop above does not check for valid links in the node
* group we're currently editing. */

View File

@ -529,7 +529,7 @@ static bool node_group_separate_selected(
}
}
if (!make_copy) {
nodeRebuildIDVector(&ngroup);
blender::bke::nodeRebuildIDVector(&ngroup);
}
/* add internal links to the ntree */
@ -844,7 +844,7 @@ static bNodeSocket *add_interface_from_socket(const bNodeTree &original_tree,
const bNodeSocket &socket_for_name = prefer_node_for_interface_name(socket.owner_node()) ?
socket :
socket_for_io;
return ntreeAddSocketInterfaceFromSocketWithName(&tree_for_interface,
return blender::bke::ntreeAddSocketInterfaceFromSocketWithName(&tree_for_interface,
&node_for_io,
&socket_for_io,
socket_for_io.idname,
@ -960,7 +960,7 @@ static void node_group_make_insert_selected(const bContext &C,
if (socket->is_directly_linked()) {
continue;
}
const bNodeSocket *io_socket = ntreeAddSocketInterfaceFromSocket(&group, node, socket);
const bNodeSocket *io_socket = blender::bke::ntreeAddSocketInterfaceFromSocket(&group, node, socket);
new_internal_links.append({node, socket, io_socket});
}
};
@ -1012,7 +1012,7 @@ static void node_group_make_insert_selected(const bContext &C,
BKE_ntree_update_tag_node_removed(&ntree);
BKE_ntree_update_tag_node_new(&group, node);
}
nodeRebuildIDVector(&ntree);
blender::bke::nodeRebuildIDVector(&ntree);
/* Update input and output node first, since the group node declaration can depend on them. */
nodes::update_node_declaration_and_sockets(group, *input_node);

View File

@ -142,7 +142,7 @@ static void composite_node_add_init(bNodeTree * /*bnodetree*/, bNode *bnode)
static bool composite_node_tree_socket_type_valid(bNodeTreeType * /*ntreetype*/,
bNodeSocketType *socket_type)
{
return nodeIsStaticSocketType(socket_type) &&
return blender::bke::nodeIsStaticSocketType(socket_type) &&
ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA);
}

View File

@ -53,7 +53,7 @@ static void cmp_node_switch_view_update(bNodeTree *ntree, bNode *node)
}
if (scene == nullptr) {
nodeRemoveAllSockets(ntree, node);
blender::bke::nodeRemoveAllSockets(ntree, node);
/* make sure there is always one socket */
cmp_node_switch_view_sanitycheck(ntree, node);
return;

View File

@ -91,7 +91,7 @@ static bool geometry_node_tree_validate_link(eNodeSocketDatatype type_a,
static bool geometry_node_tree_socket_type_valid(bNodeTreeType * /*treetype*/,
bNodeSocketType *socket_type)
{
return nodeIsStaticSocketType(socket_type) && ELEM(socket_type->type,
return blender::bke::nodeIsStaticSocketType(socket_type) && ELEM(socket_type->type,
SOCK_FLOAT,
SOCK_VECTOR,
SOCK_RGBA,

View File

@ -438,10 +438,10 @@ void ntree_update_reroute_nodes(bNodeTree *ntree)
bNodeSocket *output_socket = (bNodeSocket *)reroute_node->outputs.first;
if (input_socket->typeinfo != socket_type) {
nodeModifySocketType(ntree, reroute_node, input_socket, socket_type->idname);
blender::bke::nodeModifySocketType(ntree, reroute_node, input_socket, socket_type->idname);
}
if (output_socket->typeinfo != socket_type) {
nodeModifySocketType(ntree, reroute_node, output_socket, socket_type->idname);
blender::bke::nodeModifySocketType(ntree, reroute_node, output_socket, socket_type->idname);
}
}
}
@ -523,7 +523,7 @@ static bool group_input_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *li
/* Don't connect to other "extend" sockets. */
return false;
}
const bNodeSocket *io_socket = ntreeAddSocketInterfaceFromSocket(
const bNodeSocket *io_socket = blender::bke::ntreeAddSocketInterfaceFromSocket(
ntree, link->tonode, link->tosock);
if (!io_socket) {
return false;
@ -544,7 +544,7 @@ static bool group_output_insert_link(bNodeTree *ntree, bNode *node, bNodeLink *l
/* Don't connect to other "extend" sockets. */
return false;
}
const bNodeSocket *io_socket = ntreeAddSocketInterfaceFromSocket(
const bNodeSocket *io_socket = blender::bke::ntreeAddSocketInterfaceFromSocket(
ntree, link->fromnode, link->fromsock);
if (!io_socket) {
return false;

View File

@ -240,7 +240,7 @@ static void refresh_socket_list(bNodeTree &ntree,
}
LISTBASE_FOREACH_MUTABLE (bNodeSocket *, old_socket, &sockets) {
if (!new_sockets.contains(old_socket)) {
nodeRemoveSocketEx(&ntree, &node, old_socket, do_id_user);
blender::bke::nodeRemoveSocketEx(&ntree, &node, old_socket, do_id_user);
}
}
BLI_listbase_clear(&sockets);
@ -537,7 +537,7 @@ static bNodeSocketType *make_standard_socket_type(int type, int subtype)
const char *socket_idname = nodeStaticSocketType(type, subtype);
const char *interface_idname = nodeStaticSocketInterfaceType(type, subtype);
const char *socket_label = nodeStaticSocketLabel(type, subtype);
const char *socket_subtype_label = nodeSocketSubTypeLabel(subtype);
const char *socket_subtype_label = blender::bke::nodeSocketSubTypeLabel(subtype);
bNodeSocketType *stype;
StructRNA *srna;

View File

@ -154,7 +154,7 @@ static bool shader_validate_link(eNodeSocketDatatype from, eNodeSocketDatatype t
static bool shader_node_tree_socket_type_valid(bNodeTreeType * /*ntreetype*/,
bNodeSocketType *socket_type)
{
return nodeIsStaticSocketType(socket_type) &&
return blender::bke::nodeIsStaticSocketType(socket_type) &&
ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA, SOCK_SHADER);
}

View File

@ -131,7 +131,6 @@ void register_node_type_sh_volume_principled()
sh_node_type_base(&ntype, SH_NODE_VOLUME_PRINCIPLED, "Principled Volume", NODE_CLASS_SHADER);
ntype.declare = file_ns::node_declare;
blender::bke::node_type_size_preset(&ntype, NODE_SIZE_LARGE);
ntype.initfunc = file_ns::node_shader_init_volume_principled;
ntype.gpu_fn = file_ns::node_shader_gpu_volume_principled;
nodeRegisterType(&ntype);

View File

@ -124,7 +124,7 @@ static void update(bNodeTree *ntree)
static bool texture_node_tree_socket_type_valid(bNodeTreeType * /*ntreetype*/,
bNodeSocketType *socket_type)
{
return nodeIsStaticSocketType(socket_type) &&
return blender::bke::nodeIsStaticSocketType(socket_type) &&
ELEM(socket_type->type, SOCK_FLOAT, SOCK_VECTOR, SOCK_RGBA);
}