Merge branch 'master' into sculpt-dev

This commit is contained in:
Pablo Dobarro 2021-03-04 20:06:27 +01:00
commit dd1c4c84c9
26 changed files with 250 additions and 74 deletions

View File

@ -223,7 +223,7 @@ struct GSet *BKE_main_gset_create(struct Main *bmain, struct GSet *gset);
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb) \
{ \
ListBase *_lbarray[MAX_LIBARRAY]; \
ListBase *_lbarray[INDEX_ID_MAX]; \
int _i = set_listbasepointers((_bmain), _lbarray); \
while (_i--) { \
(_lb) = _lbarray[_i];
@ -234,9 +234,13 @@ struct GSet *BKE_main_gset_create(struct Main *bmain, struct GSet *gset);
((void)0)
/**
* DO NOT use break statement with that macro,
* use #FOREACH_MAIN_LISTBASE and #FOREACH_MAIN_LISTBASE_ID instead
* if you need that kind of control flow. */
* Top level `foreach`-like macro allowing to loop over all IDs in a given #Main data-base.
*
* NOTE: Order tries to go from 'user IDs' to 'used IDs' (e.g. collections will be processed
* before objects, which will be processed before obdata types, etc.).
*
* WARNING: DO NOT use break statement with that macro, use #FOREACH_MAIN_LISTBASE and
* #FOREACH_MAIN_LISTBASE_ID instead if you need that kind of control flow. */
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id) \
{ \
ListBase *_lb; \
@ -259,8 +263,8 @@ const char *BKE_main_blendfile_path_from_global(void);
struct ListBase *which_libbase(struct Main *bmain, short type);
#define MAX_LIBARRAY 41
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
//#define INDEX_ID_MAX 41
int set_listbasepointers(struct Main *main, struct ListBase *lb[]);
#define MAIN_VERSION_ATLEAST(main, ver, subver) \
((main)->versionfile > (ver) || \

View File

@ -865,7 +865,7 @@ bool BKE_blendfile_write_partial(Main *bmain_src,
ReportList *reports)
{
Main *bmain_dst = MEM_callocN(sizeof(Main), "copybuffer");
ListBase *lbarray_dst[MAX_LIBARRAY], *lbarray_src[MAX_LIBARRAY];
ListBase *lbarray_dst[INDEX_ID_MAX], *lbarray_src[INDEX_ID_MAX];
int a, retval;
void *path_list_backup = NULL;

View File

@ -783,7 +783,7 @@ void BKE_bpath_traverse_main(Main *bmain,
const int flag,
void *bpath_user_data)
{
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int a = set_listbasepointers(bmain, lbarray);
while (a--) {
BKE_bpath_traverse_id_list(bmain, lbarray[a], visit_cb, flag, bpath_user_data);

View File

@ -63,7 +63,7 @@ bool BKE_idtype_cache_key_cmp(const void *key_a_v, const void *key_b_v)
(key_a->offset_in_ID != key_b->offset_in_ID) || (key_a->cache_v != key_b->cache_v);
}
static IDTypeInfo *id_types[MAX_LIBARRAY] = {NULL};
static IDTypeInfo *id_types[INDEX_ID_MAX] = {NULL};
static void id_type_init(void)
{

View File

@ -916,7 +916,7 @@ void BKE_main_id_tag_idcode(struct Main *mainvar,
*/
void BKE_main_id_tag_all(struct Main *mainvar, const int tag, const bool value)
{
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int a;
a = set_listbasepointers(mainvar, lbarray);
@ -949,7 +949,7 @@ void BKE_main_id_flag_listbase(ListBase *lb, const int flag, const bool value)
*/
void BKE_main_id_flag_all(Main *bmain, const int flag, const bool value)
{
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int a;
a = set_listbasepointers(bmain, lbarray);
while (a--) {
@ -1870,7 +1870,7 @@ void BKE_library_make_local(Main *bmain,
const bool untagged_only,
const bool set_fake)
{
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
LinkNode *todo_ids = NULL;
LinkNode *copied_ids = NULL;

View File

@ -240,7 +240,7 @@ void BKE_id_free_us(Main *bmain, void *idv) /* test users */
static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
{
const int tag = LIB_TAG_DOIT;
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
Link dummy_link = {0};
int base_count, i;

View File

@ -440,7 +440,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
typedef struct IDUsersIter {
ID *id;
ListBase *lb_array[MAX_LIBARRAY];
ListBase *lb_array[INDEX_ID_MAX];
int lb_idx;
ID *curr_id;
@ -514,7 +514,7 @@ int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
{
IDUsersIter iter;
ListBase *lb_array[MAX_LIBARRAY];
ListBase *lb_array[INDEX_ID_MAX];
ID *id = idv;
int i = set_listbasepointers(bmain, lb_array);
bool is_defined = false;
@ -567,7 +567,7 @@ bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv)
void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *is_used_local, bool *is_used_linked)
{
IDUsersIter iter;
ListBase *lb_array[MAX_LIBARRAY];
ListBase *lb_array[INDEX_ID_MAX];
ID *id = idv;
int i = set_listbasepointers(bmain, lb_array);
bool is_defined = false;
@ -805,7 +805,7 @@ void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
*/
void BKE_library_indirectly_used_data_tag_clear(Main *bmain)
{
ListBase *lb_array[MAX_LIBARRAY];
ListBase *lb_array[INDEX_ID_MAX];
bool do_loop = true;
while (do_loop) {

View File

@ -53,7 +53,7 @@ Main *BKE_main_new(void)
void BKE_main_free(Main *mainvar)
{
/* also call when reading a file, erase all, etc */
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int a;
/* Since we are removing whole main, no need to bother 'properly'
@ -532,18 +532,17 @@ ListBase *which_libbase(Main *bmain, short type)
}
/**
* puts into array *lb pointers to all the #ListBase structs in main,
* and returns the number of them as the function result. This is useful for
* generic traversal of all the blocks in a Main (by traversing all the
* lists in turn), without worrying about block types.
* Put the pointers to all the #ListBase structs in given `bmain` into the `*lb[INDEX_ID_MAX]`
* array, and return the number of those for convinience.
*
* \note #MAX_LIBARRAY define should match this code */
int set_listbasepointers(Main *bmain, ListBase **lb)
* This is useful for generic traversal of all the blocks in a #Main (by traversing all the lists
* in turn), without worrying about block types.
*
* \note The order of each ID type #ListBase in the array is determined by the `INDEX_ID_<IDTYPE>`
* enum definitions in `DNA_ID.h`. See also the #FOREACH_MAIN_ID_BEGIN macro in `BKE_main.h`
*/
int set_listbasepointers(Main *bmain, ListBase *lb[INDEX_ID_MAX])
{
/* BACKWARDS! also watch order of free-ing! (mesh<->mat), first items freed last.
* This is important because freeing data decreases user-counts of other data-blocks,
* if this data is its self freed it can crash. */
/* Libraries may be accessed from pretty much any other ID. */
lb[INDEX_ID_LI] = &(bmain->libraries);
@ -606,5 +605,5 @@ int set_listbasepointers(Main *bmain, ListBase **lb)
lb[INDEX_ID_NULL] = NULL;
return (MAX_LIBARRAY - 1);
return (INDEX_ID_MAX - 1);
}

View File

@ -66,7 +66,7 @@ struct IDNameLib_TypeMap {
* Opaque structure, external API users only see this.
*/
struct IDNameLib_Map {
struct IDNameLib_TypeMap type_maps[MAX_LIBARRAY];
struct IDNameLib_TypeMap type_maps[INDEX_ID_MAX];
struct GHash *uuid_map;
struct Main *bmain;
struct GSet *valid_id_pointers;
@ -77,7 +77,7 @@ static struct IDNameLib_TypeMap *main_idmap_from_idcode(struct IDNameLib_Map *id
short id_type)
{
if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) {
for (int i = 0; i < MAX_LIBARRAY; i++) {
for (int i = 0; i < INDEX_ID_MAX; i++) {
if (id_map->type_maps[i].id_type == id_type) {
return &id_map->type_maps[i];
}
@ -108,13 +108,13 @@ struct IDNameLib_Map *BKE_main_idmap_create(struct Main *bmain,
id_map->idmap_types = idmap_types;
int index = 0;
while (index < MAX_LIBARRAY) {
while (index < INDEX_ID_MAX) {
struct IDNameLib_TypeMap *type_map = &id_map->type_maps[index];
type_map->map = NULL;
type_map->id_type = BKE_idtype_idcode_iter_step(&index);
BLI_assert(type_map->id_type != 0);
}
BLI_assert(index == MAX_LIBARRAY);
BLI_assert(index == INDEX_ID_MAX);
if (idmap_types & MAIN_IDMAP_TYPE_UUID) {
ID *id;
@ -231,7 +231,7 @@ void BKE_main_idmap_destroy(struct IDNameLib_Map *id_map)
{
if (id_map->idmap_types & MAIN_IDMAP_TYPE_NAME) {
struct IDNameLib_TypeMap *type_map = id_map->type_maps;
for (int i = 0; i < MAX_LIBARRAY; i++, type_map++) {
for (int i = 0; i < INDEX_ID_MAX; i++, type_map++) {
if (type_map->map) {
BLI_ghash_free(type_map->map, NULL, NULL);
type_map->map = NULL;

View File

@ -103,6 +103,22 @@ template<typename Key, typename Value> class MultiValueMap {
return {};
}
/**
* Get a mutable span to all the values that are stored for the given key.
*/
MutableSpan<Value> lookup(const Key &key)
{
return this->lookup_as(key);
}
template<typename ForwardKey> MutableSpan<Value> lookup_as(const ForwardKey &key)
{
Vector<Value> *vector = map_.lookup_ptr_as(key);
if (vector != nullptr) {
return vector->as_mutable_span();
}
return {};
}
/**
* Note: This signature will change when the implementation changes.
*/

View File

@ -395,6 +395,7 @@ void extract_normalized_words(StringRef str,
struct SearchItem {
blender::Span<blender::StringRef> normalized_words;
int length;
void *user_data;
};
@ -416,8 +417,10 @@ void BLI_string_search_add(StringSearch *search, const char *str, void *user_dat
{
using namespace blender;
Vector<StringRef, 64> words;
string_search::extract_normalized_words(str, search->allocator, words);
search->items.append({search->allocator.construct_array_copy(words.as_span()), user_data});
StringRef str_ref{str};
string_search::extract_normalized_words(str_ref, search->allocator, words);
search->items.append(
{search->allocator.construct_array_copy(words.as_span()), (int)str_ref.size(), user_data});
}
/**
@ -453,7 +456,15 @@ int BLI_string_search_query(StringSearch *search, const char *query, void ***r_d
* score. Results with the same score are in the order they have been added to the search. */
Vector<int> sorted_result_indices;
for (const int score : found_scores) {
Span<int> indices = result_indices_by_score.lookup(score);
MutableSpan<int> indices = result_indices_by_score.lookup(score);
if (score == found_scores[0]) {
/* Sort items with best score by length. Shorter items are more likely the ones you are
* looking for. This also ensures that exact matches will be at the top, even if the query is
* a substring of another item. */
std::sort(indices.begin(), indices.end(), [&](int a, int b) {
return search->items[a].length < search->items[b].length;
});
}
sorted_result_indices.extend(indices);
}

View File

@ -29,6 +29,27 @@ TEST(multi_value_map, LookupExistant)
EXPECT_EQ(map.lookup(3)[0], 6);
}
TEST(multi_value_map, LookupMutable)
{
MultiValueMap<int, int> map;
map.add(1, 2);
map.add(4, 5);
map.add(4, 6);
map.add(6, 7);
MutableSpan<int> span = map.lookup(4);
EXPECT_EQ(span.size(), 2);
span[0] = 10;
span[1] = 20;
map.add(4, 5);
MutableSpan<int> new_span = map.lookup(4);
EXPECT_EQ(new_span.size(), 3);
EXPECT_EQ(new_span[0], 10);
EXPECT_EQ(new_span[1], 20);
EXPECT_EQ(new_span[2], 5);
}
TEST(multi_value_map, AddMultiple)
{
MultiValueMap<int, int> map;

View File

@ -60,7 +60,7 @@ bool BLO_main_validate_libraries(Main *bmain, ReportList *reports)
blo_split_main(&mainlist, bmain);
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int i = set_listbasepointers(bmain, lbarray);
while (i--) {
for (ID *id = lbarray[i]->first; id != NULL; id = id->next) {

View File

@ -449,7 +449,7 @@ static void oldnewmap_free(OldNewMap *onm)
static void add_main_to_main(Main *mainvar, Main *from)
{
ListBase *lbarray[MAX_LIBARRAY], *fromarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX], *fromarray[INDEX_ID_MAX];
int a;
set_listbasepointers(mainvar, lbarray);
@ -517,7 +517,7 @@ void blo_split_main(ListBase *mainlist, Main *main)
lib_main_array[i] = libmain;
}
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
i = set_listbasepointers(main, lbarray);
while (i--) {
ID *id = lbarray[i]->first;
@ -1965,7 +1965,7 @@ void blo_end_packed_pointer_map(FileData *fd, Main *oldmain)
/* undo file support: add all library pointers in lookup */
void blo_add_library_pointer_map(ListBase *old_mainlist, FileData *fd)
{
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
LISTBASE_FOREACH (Main *, ptr, old_mainlist) {
int i = set_listbasepointers(ptr, lbarray);
@ -4543,7 +4543,7 @@ void BLO_main_expander(BLOExpandDoitCallback expand_doit_func)
*/
void BLO_expand_main(void *fdhandle, Main *mainvar)
{
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
FileData *fd = fdhandle;
ID *id;
int a;
@ -4713,7 +4713,7 @@ static void add_loose_object_data_to_scene(Main *mainvar,
}
/* Loop over all ID types, instancing object-data for ID types that have support for it. */
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int i = set_listbasepointers(mainvar, lbarray);
while (i--) {
const short idcode = BKE_idtype_idcode_from_index(i);
@ -4979,7 +4979,7 @@ static bool library_link_idcode_needs_tag_check(const short idcode, const int fl
*/
static void library_link_clear_tag(Main *mainvar, const int flag)
{
for (int i = 0; i < MAX_LIBARRAY; i++) {
for (int i = 0; i < INDEX_ID_MAX; i++) {
const short idcode = BKE_idtype_idcode_from_index(i);
BLI_assert(idcode != -1);
if (library_link_idcode_needs_tag_check(idcode, flag)) {
@ -5068,8 +5068,8 @@ static void split_main_newid(Main *mainptr, Main *main_newid)
BLI_strncpy(main_newid->name, mainptr->name, sizeof(main_newid->name));
main_newid->curlib = mainptr->curlib;
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray_newid[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
ListBase *lbarray_newid[INDEX_ID_MAX];
int i = set_listbasepointers(mainptr, lbarray);
set_listbasepointers(main_newid, lbarray_newid);
while (i--) {
@ -5227,7 +5227,7 @@ void *BLO_library_read_struct(FileData *fd, BHead *bh, const char *blockname)
static int has_linked_ids_to_read(Main *mainvar)
{
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int a = set_listbasepointers(mainvar, lbarray);
while (a--) {
@ -5295,7 +5295,7 @@ static void read_library_linked_ids(FileData *basefd,
{
GHash *loaded_ids = BLI_ghash_str_new(__func__);
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int a = set_listbasepointers(mainvar, lbarray);
while (a--) {
@ -5344,7 +5344,7 @@ static void read_library_clear_weak_links(FileData *basefd, ListBase *mainlist,
{
/* Any remaining weak links at this point have been lost, silently drop
* those by setting them to NULL pointers. */
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int a = set_listbasepointers(mainvar, lbarray);
while (a--) {

View File

@ -1141,7 +1141,7 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *bmain)
}
}
if (!MAIN_VERSION_ATLEAST(bmain, 276, 5)) {
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int a;
/* Important to clear all non-persistent flags from older versions here,

View File

@ -768,7 +768,7 @@ static void write_userdef(BlendWriter *writer, const UserDef *userdef)
/* Keep it last of write_foodata functions. */
static void write_libraries(WriteData *wd, Main *main)
{
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
ID *id;
int a, tot;
bool found_one;
@ -954,7 +954,7 @@ static bool write_file_handle(Main *mainvar,
* if needed, without duplicating whole code. */
Main *bmain = mainvar;
do {
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int a = set_listbasepointers(bmain, lbarray);
while (a--) {
ID *id = lbarray[a]->first;

View File

@ -33,9 +33,7 @@
#include "MEM_guardedalloc.h"
#include "DNA_ID.h" /* for ID_Type */
#include "BKE_main.h" /* for MAX_LIBARRAY */
#include "DNA_ID.h" /* for ID_Type and INDEX_ID_MAX */
#include "BLI_threads.h" /* for SpinLock */
@ -111,10 +109,10 @@ struct Depsgraph {
bool need_update;
/* Indicates which ID types were updated. */
char id_type_updated[MAX_LIBARRAY];
char id_type_updated[INDEX_ID_MAX];
/* Indicates type of IDs present in the depsgraph. */
char id_type_exist[MAX_LIBARRAY];
char id_type_exist[INDEX_ID_MAX];
/* Quick-Access Temp Data ............. */

View File

@ -111,7 +111,7 @@ TreeElement *TreeDisplayLibraries::add_library_contents(Main &mainvar,
{
const short filter_id_type = id_filter_get();
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int tot;
if (filter_id_type) {
lbarray[0] = which_libbase(&mainvar, space_outliner_.filter_id_type);

View File

@ -42,7 +42,7 @@ TreeDisplayIDOrphans::TreeDisplayIDOrphans(SpaceOutliner &space_outliner)
ListBase TreeDisplayIDOrphans::buildTree(const TreeSourceData &source_data)
{
ListBase tree = {nullptr};
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
short filter_id_type = (space_outliner_.filter & SO_FILTER_ID_TYPE) ?
space_outliner_.filter_id_type :
0;

View File

@ -722,8 +722,36 @@ typedef enum IDRecalcFlag {
FILTER_ID_TE | FILTER_ID_TXT | FILTER_ID_VF | FILTER_ID_WO | FILTER_ID_CF | FILTER_ID_WS | \
FILTER_ID_LP | FILTER_ID_HA | FILTER_ID_PT | FILTER_ID_VO | FILTER_ID_SIM)
/* IMPORTANT: this enum matches the order currently use in set_listbasepointers,
* keep them in sync! */
/**
* This enum defines the index assigned to each type of IDs in the array returned by
* #set_listbasepointers, and by extension, controls the default order in which each ID type is
* processed during standard 'foreach' looping over all IDs of a #Main data-base.
*
* About Order:
* ------------
*
* This is (losely) defined with a relationship order in mind, from lowest level (ID types using,
* referencing almost no other ID types) to highest level (ID types potentially using many other ID
* types).
*
* So e.g. it ensures that this dependency chain is respected:
* #Material <- #Mesh <- #Object <- #Collection <- #Scene
*
* Default order of processing of IDs in 'foreach' macros (#FOREACH_MAIN_ID_BEGIN and the like),
* built on top of #set_listbasepointers, is actually reversed compared to the order defined here,
* since processing usually needs to happen on users before it happens on used IDs (when freeing
* e.g.).
*
* DO NOT rely on this order as being full-proofed dependency order, there are many cases were it
* can be violated (most obvious cases being custom properties and drivers, which can reference any
* other ID types).
*
* However, this order can be considered as an optimization heuristic, especially when processing
* relationships in a non-recursive pattern: in typical cases, a vast majority of those
* relationships can be processed fine in the first pass, and only few additional passes are
* required to address all remaining relationship cases.
* See e.g. how #BKE_library_unused_linked_data_set_tag is doing this.
*/
enum {
INDEX_ID_LI = 0,
INDEX_ID_IP,
@ -763,6 +791,8 @@ enum {
INDEX_ID_SCE,
INDEX_ID_WS,
INDEX_ID_WM,
/* TODO: This should probably be tweaked, #Mask and #Simulation are rather low-level types that
* should most likely be defined //before// #Object and geometry type indices? */
INDEX_ID_MSK,
INDEX_ID_SIM,
INDEX_ID_NULL,

View File

@ -174,8 +174,6 @@ class DParentNode : NonCopyable, NonMovable {
int id() const;
};
using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>;
class DerivedNodeTree : NonCopyable, NonMovable {
private:
LinearAllocator<> allocator_;

View File

@ -67,6 +67,7 @@ class OutputSocketRef;
class NodeRef;
class NodeTreeRef;
class LinkRef;
class InternalLinkRef;
class SocketRef : NonCopyable, NonMovable {
protected:
@ -106,16 +107,21 @@ class SocketRef : NonCopyable, NonMovable {
StringRefNull idname() const;
StringRefNull name() const;
StringRefNull identifier() const;
bNodeSocketType *typeinfo() const;
bNodeSocket *bsocket() const;
bNode *bnode() const;
bNodeTree *btree() const;
bool is_available() const;
};
class InputSocketRef final : public SocketRef {
public:
Span<const OutputSocketRef *> linked_sockets() const;
Span<const OutputSocketRef *> directly_linked_sockets() const;
bool is_multi_input_socket() const;
};
class OutputSocketRef final : public SocketRef {
@ -132,6 +138,7 @@ class NodeRef : NonCopyable, NonMovable {
int id_;
Vector<InputSocketRef *> inputs_;
Vector<OutputSocketRef *> outputs_;
Vector<InternalLinkRef *> internal_links_;
friend NodeTreeRef;
@ -140,6 +147,7 @@ class NodeRef : NonCopyable, NonMovable {
Span<const InputSocketRef *> inputs() const;
Span<const OutputSocketRef *> outputs() const;
Span<const InternalLinkRef *> internal_links() const;
const InputSocketRef &input(int index) const;
const OutputSocketRef &output(int index) const;
@ -150,6 +158,7 @@ class NodeRef : NonCopyable, NonMovable {
PointerRNA *rna() const;
StringRefNull idname() const;
StringRefNull name() const;
bNodeType *typeinfo() const;
int id() const;
@ -175,6 +184,21 @@ class LinkRef : NonCopyable, NonMovable {
bNodeLink *blink() const;
};
class InternalLinkRef : NonCopyable, NonMovable {
private:
InputSocketRef *from_;
OutputSocketRef *to_;
bNodeLink *blink_;
friend NodeTreeRef;
public:
const InputSocketRef &from() const;
const OutputSocketRef &to() const;
bNodeLink *blink() const;
};
class NodeTreeRef : NonCopyable, NonMovable {
private:
LinearAllocator<> allocator_;
@ -217,6 +241,19 @@ class NodeTreeRef : NonCopyable, NonMovable {
void find_targets_skipping_reroutes(OutputSocketRef &socket_ref, Vector<SocketRef *> &r_targets);
};
using NodeTreeRefMap = Map<bNodeTree *, std::unique_ptr<const NodeTreeRef>>;
const NodeTreeRef &get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree);
namespace node_tree_ref_types {
using nodes::InputSocketRef;
using nodes::NodeRef;
using nodes::NodeTreeRef;
using nodes::NodeTreeRefMap;
using nodes::OutputSocketRef;
using nodes::SocketRef;
} // namespace node_tree_ref_types
/* --------------------------------------------------------------------
* SocketRef inline methods.
*/
@ -308,6 +345,11 @@ inline StringRefNull SocketRef::identifier() const
return bsocket_->identifier;
}
inline bNodeSocketType *SocketRef::typeinfo() const
{
return bsocket_->typeinfo;
}
inline bNodeSocket *SocketRef::bsocket() const
{
return bsocket_;
@ -323,6 +365,11 @@ inline bNodeTree *SocketRef::btree() const
return node_->btree();
}
inline bool SocketRef::is_available() const
{
return (bsocket_->flag & SOCK_UNAVAIL) == 0;
}
/* --------------------------------------------------------------------
* InputSocketRef inline methods.
*/
@ -337,6 +384,11 @@ inline Span<const OutputSocketRef *> InputSocketRef::directly_linked_sockets() c
return directly_linked_sockets_.as_span().cast<const OutputSocketRef *>();
}
inline bool InputSocketRef::is_multi_input_socket() const
{
return bsocket_->flag & SOCK_MULTI_INPUT;
}
/* --------------------------------------------------------------------
* OutputSocketRef inline methods.
*/
@ -370,6 +422,11 @@ inline Span<const OutputSocketRef *> NodeRef::outputs() const
return outputs_;
}
inline Span<const InternalLinkRef *> NodeRef::internal_links() const
{
return internal_links_;
}
inline const InputSocketRef &NodeRef::input(int index) const
{
return *inputs_[index];
@ -405,6 +462,11 @@ inline StringRefNull NodeRef::name() const
return bnode_->name;
}
inline bNodeType *NodeRef::typeinfo() const
{
return bnode_->typeinfo;
}
inline int NodeRef::id() const
{
return id_;
@ -454,6 +516,25 @@ inline bNodeLink *LinkRef::blink() const
return blink_;
}
/* --------------------------------------------------------------------
* InternalLinkRef inline methods.
*/
inline const InputSocketRef &InternalLinkRef::from() const
{
return *from_;
}
inline const OutputSocketRef &InternalLinkRef::to() const
{
return *to_;
}
inline bNodeLink *InternalLinkRef::blink() const
{
return blink_;
}
/* --------------------------------------------------------------------
* NodeTreeRef inline methods.
*/

View File

@ -22,17 +22,11 @@
namespace blender::nodes {
static const NodeTreeRef &get_tree_ref(NodeTreeRefMap &node_tree_refs, bNodeTree *btree)
{
return *node_tree_refs.lookup_or_add_cb(btree,
[&]() { return std::make_unique<NodeTreeRef>(btree); });
}
DerivedNodeTree::DerivedNodeTree(bNodeTree *btree, NodeTreeRefMap &node_tree_refs) : btree_(btree)
{
BLI_assert(btree != nullptr);
const NodeTreeRef &main_tree_ref = get_tree_ref(node_tree_refs, btree);
const NodeTreeRef &main_tree_ref = get_tree_ref_from_map(node_tree_refs, *btree);
used_node_tree_refs_.add_new(&main_tree_ref);
Vector<DNode *> all_nodes;
@ -144,7 +138,7 @@ BLI_NOINLINE void DerivedNodeTree::expand_group_node(DNode &group_node,
return;
}
const NodeTreeRef &group_ref = get_tree_ref(node_tree_refs, btree);
const NodeTreeRef &group_ref = get_tree_ref_from_map(node_tree_refs, *btree);
used_node_tree_refs_.add(&group_ref);
DParentNode &parent = *allocator_.construct<DParentNode>();

View File

@ -52,6 +52,24 @@ NodeTreeRef::NodeTreeRef(bNodeTree *btree) : btree_(btree)
RNA_pointer_create(&btree->id, &RNA_NodeSocket, bsocket, &socket.rna_);
}
LISTBASE_FOREACH (bNodeLink *, blink, &bnode->internal_links) {
InternalLinkRef &internal_link = *allocator_.construct<InternalLinkRef>();
internal_link.blink_ = blink;
for (InputSocketRef *socket_ref : node.inputs_) {
if (socket_ref->bsocket_ == blink->fromsock) {
internal_link.from_ = socket_ref;
break;
}
}
for (OutputSocketRef *socket_ref : node.outputs_) {
if (socket_ref->bsocket_ == blink->tosock) {
internal_link.to_ = socket_ref;
break;
}
}
node.internal_links_.append(&internal_link);
}
input_sockets_.extend(node.inputs_.as_span());
output_sockets_.extend(node.outputs_.as_span());
@ -229,4 +247,10 @@ std::string NodeTreeRef::to_dot() const
return digraph.to_dot_string();
}
const NodeTreeRef &get_tree_ref_from_map(NodeTreeRefMap &node_tree_refs, bNodeTree &btree)
{
return *node_tree_refs.lookup_or_add_cb(&btree,
[&]() { return std::make_unique<NodeTreeRef>(&btree); });
}
} // namespace blender::nodes

View File

@ -217,7 +217,7 @@ static PyObject *bpy_lib_load(BPy_PropertyRNA *self, PyObject *args, PyObject *k
ret->flag = ((is_link ? FILE_LINK : 0) | (is_rel ? FILE_RELPATH : 0) |
(use_assets_only ? FILE_ASSETS_ONLY : 0));
ret->dict = _PyDict_NewPresized(MAX_LIBARRAY);
ret->dict = _PyDict_NewPresized(INDEX_ID_MAX);
return (PyObject *)ret;
}
@ -248,7 +248,7 @@ static PyObject *bpy_lib_enter(BPy_Library *self)
{
PyObject *ret;
BPy_Library *self_from;
PyObject *from_dict = _PyDict_NewPresized(MAX_LIBARRAY);
PyObject *from_dict = _PyDict_NewPresized(INDEX_ID_MAX);
ReportList reports;
BKE_reports_init(&reports, RPT_STORE);

View File

@ -804,7 +804,7 @@ static void lib_relocate_do(Main *bmain,
ReportList *reports,
const bool do_reload)
{
ListBase *lbarray[MAX_LIBARRAY];
ListBase *lbarray[INDEX_ID_MAX];
int lba_idx;
LinkNode *itemlink;