Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/node.cc
| Show First 20 Lines • Show All 319 Lines • ▼ Show 20 Lines | case SOCK_GEOMETRY: | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| static void node_foreach_id(ID *id, LibraryForeachIDData *data) | static void node_foreach_id(ID *id, LibraryForeachIDData *data) | ||||
| { | { | ||||
| bNodeTree *ntree = (bNodeTree *)id; | bNodeTree *ntree = (bNodeTree *)id; | ||||
| BKE_LIB_FOREACHID_PROCESS_ID(data, ntree->owner_id, IDWALK_CB_LOOPBACK); | |||||
| BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, ntree->gpd, IDWALK_CB_USER); | BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, ntree->gpd, IDWALK_CB_USER); | ||||
| LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { | LISTBASE_FOREACH (bNode *, node, &ntree->nodes) { | ||||
| BKE_LIB_FOREACHID_PROCESS_ID(data, node->id, IDWALK_CB_USER); | BKE_LIB_FOREACHID_PROCESS_ID(data, node->id, IDWALK_CB_USER); | ||||
| BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( | BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL( | ||||
| data, | data, | ||||
| IDP_foreach_property(node->prop, | IDP_foreach_property(node->prop, | ||||
| ▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | case NTREE_SHADER: { | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| default: | default: | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| static ID *node_owner_get(Main *bmain, ID *id, ID *owner_id_hint) | static ID *node_owner_get(Main *UNUSED(bmain), ID *id, ID *UNUSED(owner_id_hint)) | ||||
| { | { | ||||
| if ((id->flag & LIB_EMBEDDED_DATA) == 0) { | if ((id->flag & LIB_EMBEDDED_DATA) == 0) { | ||||
| return id; | return id; | ||||
| } | } | ||||
| /* TODO: Sort this NO_MAIN or not for embedded node trees. See T86119. */ | /* TODO: Sort this NO_MAIN or not for embedded node trees. See T86119. */ | ||||
| // BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0); | // BLI_assert((id->tag & LIB_TAG_NO_MAIN) == 0); | ||||
| bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id); | bNodeTree *ntree = reinterpret_cast<bNodeTree *>(id); | ||||
| BLI_assert(ntree->owner_id != NULL); | |||||
| BLI_assert(ntreeFromID(ntree->owner_id) == ntree); | |||||
| if (owner_id_hint != nullptr && ntreeFromID(owner_id_hint) == ntree) { | return ntree->owner_id; | ||||
brecht: Personally I would not these kinds of slow loops in debug builds, but rather:
```
BLI_assert… | |||||
Done Inline ActionsOn second thought, agree this full check is overkill here, your proposed assert seems indeed enough here. mont29: On second thought, agree this full check is overkill here, your proposed assert seems indeed… | |||||
| return owner_id_hint; | |||||
| } | |||||
| ListBase *lists[] = {&bmain->materials, | |||||
| &bmain->lights, | |||||
| &bmain->worlds, | |||||
| &bmain->textures, | |||||
| &bmain->scenes, | |||||
| &bmain->linestyles, | |||||
| &bmain->simulations, | |||||
| nullptr}; | |||||
| for (int i = 0; lists[i] != nullptr; i++) { | |||||
| LISTBASE_FOREACH (ID *, id_iter, lists[i]) { | |||||
| if (ntreeFromID(id_iter) == ntree) { | |||||
| return id_iter; | |||||
| } | |||||
| } | |||||
| } | |||||
| BLI_assert_msg(0, "Embedded node tree with no owner. Critical Main inconsistency."); | |||||
| return nullptr; | |||||
| } | } | ||||
| static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *sock) | static void write_node_socket_default_value(BlendWriter *writer, bNodeSocket *sock) | ||||
| { | { | ||||
| if (sock->default_value == nullptr) { | if (sock->default_value == nullptr) { | ||||
| return; | return; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock) | ||||
| BLO_read_data_address(reader, &sock->storage); | BLO_read_data_address(reader, &sock->storage); | ||||
| BLO_read_data_address(reader, &sock->default_value); | BLO_read_data_address(reader, &sock->default_value); | ||||
| BLO_read_data_address(reader, &sock->default_attribute_name); | BLO_read_data_address(reader, &sock->default_attribute_name); | ||||
| sock->total_inputs = 0; /* Clear runtime data set before drawing. */ | sock->total_inputs = 0; /* Clear runtime data set before drawing. */ | ||||
| sock->cache = nullptr; | sock->cache = nullptr; | ||||
| sock->runtime = MEM_new<bNodeSocketRuntime>(__func__); | sock->runtime = MEM_new<bNodeSocketRuntime>(__func__); | ||||
| } | } | ||||
| void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree) | void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree) | ||||
| { | { | ||||
| /* Special case for this pointer, do not rely on regular `lib_link` process here. Avoids needs | |||||
| * for do_versioning, and ensures coherence of data in any case. */ | |||||
| BLI_assert((ntree->id.flag & LIB_EMBEDDED_DATA) != 0 || owner_id == nullptr); | |||||
| ntree->owner_id = owner_id; | |||||
| /* NOTE: writing and reading goes in sync, for speed. */ | /* NOTE: writing and reading goes in sync, for speed. */ | ||||
| ntree->is_updating = false; | ntree->is_updating = false; | ||||
| ntree->typeinfo = nullptr; | ntree->typeinfo = nullptr; | ||||
| ntree->interface_type = nullptr; | ntree->interface_type = nullptr; | ||||
| ntree->progress = nullptr; | ntree->progress = nullptr; | ||||
| ntree->execdata = nullptr; | ntree->execdata = nullptr; | ||||
| ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__); | ntree->runtime = MEM_new<bNodeTreeRuntime>(__func__); | ||||
| ▲ Show 20 Lines • Show All 145 Lines • ▼ Show 20 Lines | void ntreeBlendReadData(BlendDataReader *reader, ID *owner_id, bNodeTree *ntree) | ||||
| BKE_previewimg_blend_read(reader, ntree->preview); | BKE_previewimg_blend_read(reader, ntree->preview); | ||||
| /* type verification is in lib-link */ | /* type verification is in lib-link */ | ||||
| } | } | ||||
| static void ntree_blend_read_data(BlendDataReader *reader, ID *id) | static void ntree_blend_read_data(BlendDataReader *reader, ID *id) | ||||
| { | { | ||||
| bNodeTree *ntree = (bNodeTree *)id; | bNodeTree *ntree = (bNodeTree *)id; | ||||
| ntreeBlendReadData(reader, ntree); | ntreeBlendReadData(reader, nullptr, ntree); | ||||
| } | } | ||||
| static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSocket *sock) | static void lib_link_node_socket(BlendLibReader *reader, Library *lib, bNodeSocket *sock) | ||||
| { | { | ||||
| IDP_BlendReadLib(reader, lib, sock->prop); | IDP_BlendReadLib(reader, lib, sock->prop); | ||||
| /* This can happen for all socket types when a file is saved in an older version of Blender than | /* This can happen for all socket types when a file is saved in an older version of Blender than | ||||
| * it was originally created in (T86298). Some socket types still require a default value. The | * it was originally created in (T86298). Some socket types still require a default value. The | ||||
| ▲ Show 20 Lines • Show All 1,728 Lines • ▼ Show 20 Lines | LISTBASE_FOREACH (bNodeSocket *, socket, &node->inputs) { | ||||
| if (socket->link != nullptr) { | if (socket->link != nullptr) { | ||||
| bNodeLink *link = socket->link; | bNodeLink *link = socket->link; | ||||
| nodePositionRelative(link->fromnode, link->tonode, link->fromsock, link->tosock); | nodePositionRelative(link->fromnode, link->tonode, link->fromsock, link->tosock); | ||||
| nodePositionPropagate(link->fromnode); | nodePositionPropagate(link->fromnode); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) | static bNodeTree *ntreeAddTree_do( | ||||
| Main *bmain, ID *owner_id, const bool is_embedded, const char *name, const char *idname) | |||||
| { | { | ||||
| /* trees are created as local trees for compositor, material or texture nodes, | /* trees are created as local trees for compositor, material or texture nodes, | ||||
| * node groups and other tree types are created as library data. | * node groups and other tree types are created as library data. | ||||
| */ | */ | ||||
| const bool is_embedded = (bmain == nullptr); | |||||
| int flag = 0; | int flag = 0; | ||||
| if (is_embedded) { | if (is_embedded) { | ||||
| flag |= LIB_ID_CREATE_NO_MAIN; | flag |= LIB_ID_CREATE_NO_MAIN; | ||||
| } | } | ||||
| bNodeTree *ntree = (bNodeTree *)BKE_libblock_alloc(bmain, ID_NT, name, flag); | bNodeTree *ntree = (bNodeTree *)BKE_libblock_alloc(bmain, ID_NT, name, flag); | ||||
| BKE_libblock_init_empty(&ntree->id); | BKE_libblock_init_empty(&ntree->id); | ||||
| if (is_embedded) { | if (is_embedded) { | ||||
| BLI_assert(owner_id != NULL); | |||||
| ntree->id.flag |= LIB_EMBEDDED_DATA; | ntree->id.flag |= LIB_EMBEDDED_DATA; | ||||
| ntree->owner_id = owner_id; | |||||
| bNodeTree **ntree_owner_ptr = BKE_ntree_ptr_from_id(owner_id); | |||||
| BLI_assert(ntree_owner_ptr != NULL); | |||||
| *ntree_owner_ptr = ntree; | |||||
| } | |||||
| else { | |||||
| BLI_assert(owner_id == NULL); | |||||
| } | } | ||||
| BLI_strncpy(ntree->idname, idname, sizeof(ntree->idname)); | BLI_strncpy(ntree->idname, idname, sizeof(ntree->idname)); | ||||
| ntree_set_typeinfo(ntree, ntreeTypeFind(idname)); | ntree_set_typeinfo(ntree, ntreeTypeFind(idname)); | ||||
| return ntree; | return ntree; | ||||
| } | } | ||||
| bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname) | |||||
| { | |||||
| return ntreeAddTree_do(bmain, nullptr, false, name, idname); | |||||
| } | |||||
| bNodeTree *ntreeAddTreeEmbedded(Main *UNUSED(bmain), | |||||
| ID *owner_id, | |||||
| const char *name, | |||||
| const char *idname) | |||||
| { | |||||
| return ntreeAddTree_do(nullptr, owner_id, true, name, idname); | |||||
| } | |||||
| bNodeTree *ntreeCopyTree_ex(const bNodeTree *ntree, Main *bmain, const bool do_id_user) | bNodeTree *ntreeCopyTree_ex(const bNodeTree *ntree, Main *bmain, const bool do_id_user) | ||||
| { | { | ||||
| const int flag = do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN; | const int flag = do_id_user ? 0 : LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_CREATE_NO_MAIN; | ||||
| bNodeTree *ntree_copy = (bNodeTree *)BKE_id_copy_ex(bmain, (ID *)ntree, nullptr, flag); | bNodeTree *ntree_copy = (bNodeTree *)BKE_id_copy_ex(bmain, (ID *)ntree, nullptr, flag); | ||||
| return ntree_copy; | return ntree_copy; | ||||
| } | } | ||||
| bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree) | bNodeTree *ntreeCopyTree(Main *bmain, const bNodeTree *ntree) | ||||
| ▲ Show 20 Lines • Show All 2,331 Lines • Show Last 20 Lines | |||||
Personally I would not these kinds of slow loops in debug builds, but rather: