Nodes: avoid O(n^2) when looking up interface input indices
Previously, the code was O(n^2) because it iterated over all interface sockets, and for each it tried to find the corresponding index by iterating over all inputs again. Now, a `VectorSet` is used to make finding the index `O(1)`. The new utility function may also be useful elsewhere. Pull Request: https://projects.blender.org/blender/blender/pulls/132272
This commit is contained in:
@@ -611,7 +611,7 @@ inline blender::Span<bNodeTreeInterfaceSocket *> bNodeTree::interface_inputs()
|
||||
inline blender::Span<const bNodeTreeInterfaceSocket *> bNodeTree::interface_inputs() const
|
||||
{
|
||||
BLI_assert(this->tree_interface.items_cache_is_available());
|
||||
return this->tree_interface.runtime->inputs_;
|
||||
return this->tree_interface.runtime->inputs_.as_span();
|
||||
}
|
||||
|
||||
inline blender::Span<bNodeTreeInterfaceSocket *> bNodeTree::interface_outputs()
|
||||
@@ -623,7 +623,7 @@ inline blender::Span<bNodeTreeInterfaceSocket *> bNodeTree::interface_outputs()
|
||||
inline blender::Span<const bNodeTreeInterfaceSocket *> bNodeTree::interface_outputs() const
|
||||
{
|
||||
BLI_assert(this->tree_interface.items_cache_is_available());
|
||||
return this->tree_interface.runtime->outputs_;
|
||||
return this->tree_interface.runtime->outputs_.as_span();
|
||||
}
|
||||
|
||||
inline blender::Span<bNodeTreeInterfaceItem *> bNodeTree::interface_items()
|
||||
@@ -635,7 +635,25 @@ inline blender::Span<bNodeTreeInterfaceItem *> bNodeTree::interface_items()
|
||||
inline blender::Span<const bNodeTreeInterfaceItem *> bNodeTree::interface_items() const
|
||||
{
|
||||
BLI_assert(this->tree_interface.items_cache_is_available());
|
||||
return this->tree_interface.runtime->items_;
|
||||
return this->tree_interface.runtime->items_.as_span();
|
||||
}
|
||||
|
||||
inline int bNodeTree::interface_input_index(const bNodeTreeInterfaceSocket &io_socket) const
|
||||
{
|
||||
BLI_assert(this->tree_interface.items_cache_is_available());
|
||||
return this->tree_interface.runtime->inputs_.index_of_as(&io_socket);
|
||||
}
|
||||
|
||||
inline int bNodeTree::interface_output_index(const bNodeTreeInterfaceSocket &io_socket) const
|
||||
{
|
||||
BLI_assert(this->tree_interface.items_cache_is_available());
|
||||
return this->tree_interface.runtime->outputs_.index_of_as(&io_socket);
|
||||
}
|
||||
|
||||
inline int bNodeTree::interface_item_index(const bNodeTreeInterfaceItem &io_item) const
|
||||
{
|
||||
BLI_assert(this->tree_interface.items_cache_is_available());
|
||||
return this->tree_interface.runtime->items_.index_of_as(&io_item);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "BLI_cache_mutex.hh"
|
||||
#include "BLI_parameter_pack_utils.hh"
|
||||
#include "BLI_vector.hh"
|
||||
#include "BLI_vector_set.hh"
|
||||
|
||||
namespace blender::bke {
|
||||
|
||||
@@ -39,10 +40,10 @@ class bNodeTreeInterfaceRuntime {
|
||||
CacheMutex items_cache_mutex_;
|
||||
|
||||
/* Runtime topology cache for linear access to items. */
|
||||
Vector<bNodeTreeInterfaceItem *> items_;
|
||||
VectorSet<bNodeTreeInterfaceItem *> items_;
|
||||
/* Socket-only lists for input/output access by index. */
|
||||
Vector<bNodeTreeInterfaceSocket *> inputs_;
|
||||
Vector<bNodeTreeInterfaceSocket *> outputs_;
|
||||
VectorSet<bNodeTreeInterfaceSocket *> inputs_;
|
||||
VectorSet<bNodeTreeInterfaceSocket *> outputs_;
|
||||
};
|
||||
|
||||
namespace node_interface {
|
||||
|
||||
@@ -1423,13 +1423,13 @@ void bNodeTreeInterface::ensure_items_cache() const
|
||||
bNodeTreeInterface &mutable_self = const_cast<bNodeTreeInterface &>(*this);
|
||||
|
||||
mutable_self.foreach_item([&](bNodeTreeInterfaceItem &item) {
|
||||
runtime.items_.append(&item);
|
||||
runtime.items_.add_new(&item);
|
||||
if (bNodeTreeInterfaceSocket *socket = get_item_as<bNodeTreeInterfaceSocket>(&item)) {
|
||||
if (socket->flag & NODE_INTERFACE_SOCKET_INPUT) {
|
||||
runtime.inputs_.append(socket);
|
||||
runtime.inputs_.add_new(socket);
|
||||
}
|
||||
if (socket->flag & NODE_INTERFACE_SOCKET_OUTPUT) {
|
||||
runtime.outputs_.append(socket);
|
||||
runtime.outputs_.add_new(socket);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -16,9 +16,11 @@
|
||||
|
||||
/** Workaround to forward-declare C++ type in C header. */
|
||||
#ifdef __cplusplus
|
||||
# include <BLI_vector.hh>
|
||||
# include <string>
|
||||
|
||||
# include "BLI_vector.hh"
|
||||
# include "BLI_vector_set.hh"
|
||||
|
||||
namespace blender {
|
||||
template<typename T> class Span;
|
||||
template<typename T> class MutableSpan;
|
||||
@@ -847,6 +849,10 @@ typedef struct bNodeTree {
|
||||
blender::Span<const bNodeTreeInterfaceSocket *> interface_outputs() const;
|
||||
blender::Span<bNodeTreeInterfaceItem *> interface_items();
|
||||
blender::Span<const bNodeTreeInterfaceItem *> interface_items() const;
|
||||
|
||||
int interface_input_index(const bNodeTreeInterfaceSocket &io_socket) const;
|
||||
int interface_output_index(const bNodeTreeInterfaceSocket &io_socket) const;
|
||||
int interface_item_index(const bNodeTreeInterfaceItem &io_item) const;
|
||||
#endif
|
||||
} bNodeTree;
|
||||
|
||||
|
||||
@@ -2154,8 +2154,7 @@ static void draw_property_for_socket(DrawGroupInputsContext &ctx,
|
||||
uiLayout *row = uiLayoutRow(layout, true);
|
||||
uiLayoutSetPropDecorate(row, true);
|
||||
|
||||
const int input_index =
|
||||
const_cast<const bNodeTree *>(ctx.nmd.node_group)->interface_inputs().first_index(&socket);
|
||||
const int input_index = ctx.nmd.node_group->interface_input_index(socket);
|
||||
|
||||
/* Use #uiItemPointerR to draw pointer properties because #uiItemR would not have enough
|
||||
* information about what type of ID to select for editing the values. This is because
|
||||
|
||||
Reference in New Issue
Block a user