mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Refactor: Geometry Nodes: add BundleKey type
Previously, a raw `UString` was used as bundle key. However, that did not capture all the constraints put on the key (some characters are forbidden). This patch adds a smaller `BundleKey` wrapper around `UString` that ensures these constraints during construction so that code using the type does not have to check it again. This might also become useful when we want `Bundle` to become a thinner wrapper around `Map` instead of duplicating large parts of its interface. Pull Request: https://projects.blender.org/blender/blender/pulls/159023
This commit is contained in:
parent
578ebff417
commit
761c881737
25 changed files with 285 additions and 189 deletions
|
|
@ -1494,8 +1494,8 @@ template<typename T>
|
|||
if (!io_item) {
|
||||
return false;
|
||||
}
|
||||
const std::optional<std::string> key = io_item->lookup_str("key");
|
||||
if (!key) {
|
||||
const std::optional<std::string> key_str = io_item->lookup_str("key");
|
||||
if (key_str) {
|
||||
return false;
|
||||
}
|
||||
const std::optional<StringRefNull> socket_idname = io_item->lookup_str("socket_idname");
|
||||
|
|
@ -1512,7 +1512,11 @@ template<typename T>
|
|||
if (!stype) {
|
||||
return false;
|
||||
}
|
||||
r_bundle.add(UString(*key), nodes::BundleItemSocketValue{stype, std::move(*value)});
|
||||
std::optional<nodes::BundleKey> key = nodes::BundleKey::from_str(*key_str);
|
||||
if (!key) {
|
||||
return false;
|
||||
}
|
||||
r_bundle.add(*key, nodes::BundleItemSocketValue{stype, std::move(*value)});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1525,7 +1529,7 @@ static void serialize_bundle_items(const nodes::Bundle &bundle,
|
|||
for (const auto &item : bundle.items()) {
|
||||
if (const auto *socket_value = std::get_if<nodes::BundleItemSocketValue>(&item.value.value)) {
|
||||
DictionaryValue &io_bundle_item = *r_io_items.append_dict();
|
||||
io_bundle_item.append_str("key", item.key.string());
|
||||
io_bundle_item.append_str("key", item.key.ustr().string());
|
||||
io_bundle_item.append_str("socket_idname", socket_value->type->idname.string());
|
||||
io::serialize::DictionaryValue &io_bundle_item_value = *io_bundle_item.append_dict("value");
|
||||
serialize_socket_value_variant(
|
||||
|
|
|
|||
|
|
@ -370,7 +370,7 @@ class RuntimeToBakeValue {
|
|||
|
||||
void runtime_to_bake__Bundle(nodes::Bundle &bundle)
|
||||
{
|
||||
Vector<UString> values_to_remove;
|
||||
Vector<nodes::BundleKey> values_to_remove;
|
||||
for (const auto &item : bundle.items()) {
|
||||
if (auto *socket_value = std::get_if<nodes::BundleItemSocketValue>(&item.value.value)) {
|
||||
if (!this->runtime_to_bake__SocketValueVariant(socket_value->value)) {
|
||||
|
|
@ -378,7 +378,7 @@ class RuntimeToBakeValue {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (const UString &value_to_remove : values_to_remove) {
|
||||
for (const nodes::BundleKey &value_to_remove : values_to_remove) {
|
||||
bundle.remove(value_to_remove);
|
||||
}
|
||||
}
|
||||
|
|
@ -580,7 +580,7 @@ class BakeToRuntimeValue {
|
|||
{
|
||||
for (auto &&item : bundle.items()) {
|
||||
if (auto *socket_value = std::get_if<nodes::BundleItemSocketValue>(&item.value.value)) {
|
||||
this->bake_to_runtime__SocketValueVariant(socket_value->value, item.key.ref());
|
||||
this->bake_to_runtime__SocketValueVariant(socket_value->value, item.key.ustr().ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ TEST_F(SocketValueVisitorTest, edit_in_nested_mesh)
|
|||
geometry_set_list.append(std::move(instance_geometry));
|
||||
nodes::GListPtr list_ptr = nodes::GList::from_container(std::move(geometry_set_list));
|
||||
nodes::BundlePtr bundle_ptr = nodes::Bundle::create();
|
||||
bundle_ptr.ensure_mutable_inplace().add("test"_ustr,
|
||||
bundle_ptr.ensure_mutable_inplace().add(*nodes::BundleKey::from_str("test"),
|
||||
SocketValueVariant::From(std::move(list_ptr)));
|
||||
SocketValueVariant value = SocketValueVariant::From(std::move(bundle_ptr));
|
||||
|
||||
|
|
|
|||
|
|
@ -1100,7 +1100,7 @@ static bool socket_needs_volume_grid_search(const bNode &node, const bNodeSocket
|
|||
static bool socket_needs_bundle_type_search(const bNode &node, const bNodeSocket &socket)
|
||||
{
|
||||
if (node.type_legacy == NODE_COMBINE_BUNDLE) {
|
||||
return socket.name == nodes::Bundle::type_item_name;
|
||||
return socket.name == nodes::Bundle::type_item_name.ustr();
|
||||
}
|
||||
if (node.is_type("NodeGetNestedBundlePaths"_ustr)) {
|
||||
return socket.name == StringRef("Bundle Type");
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ static void bundle_type_string_search_exec(bContext *C, void *data_v, void * /*i
|
|||
if (item.socket_type != SOCK_STRING) {
|
||||
return;
|
||||
}
|
||||
if (item.name != nodes::Bundle::type_item_name) {
|
||||
if (item.name != nodes::Bundle::type_item_name.ustr()) {
|
||||
return;
|
||||
}
|
||||
nodes::sync_node(*C, *node, nullptr);
|
||||
|
|
|
|||
|
|
@ -910,8 +910,8 @@ void BundleDataSource::collect_flat_items(const nodes::Bundle &bundle, const Str
|
|||
{
|
||||
for (const auto &item : bundle.items()) {
|
||||
const std::string path = parent_path.is_empty() ?
|
||||
item.key.string() :
|
||||
nodes::Bundle::combine_path({parent_path, item.key.ref()});
|
||||
item.key.ustr().string() :
|
||||
nodes::Bundle::combine_path({parent_path, item.key.ustr().ref()});
|
||||
flat_item_keys_.append(path);
|
||||
flat_items_.append(&item.value);
|
||||
if (const auto *value = std::get_if<nodes::BundleItemSocketValue>(&item.value.value)) {
|
||||
|
|
@ -1094,9 +1094,16 @@ static bke::SocketValueVariant lookup_bundle_path(const nodes::BundlePtr &bundle
|
|||
if (path.bundle_path_num == 0) {
|
||||
return bke::SocketValueVariant::From(bundle);
|
||||
}
|
||||
Vector<UString> keys;
|
||||
Vector<nodes::BundleKey> keys;
|
||||
for (const int i : IndexRange(path.bundle_path_num)) {
|
||||
keys.append(UString(path.bundle_path[i].identifier));
|
||||
if (const std::optional<nodes::BundleKey> key = nodes::BundleKey::from_str(
|
||||
path.bundle_path[i].identifier))
|
||||
{
|
||||
keys.append(*key);
|
||||
}
|
||||
else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return bundle->lookup_path<bke::SocketValueVariant>(keys).value_or(bke::SocketValueVariant{});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ struct GeometryDomainDataId {
|
|||
};
|
||||
|
||||
struct GeometryBundleItemId {
|
||||
Vector<UString> keys;
|
||||
Vector<nodes::BundleKey> keys;
|
||||
SpreadsheetClosureInputOutput closure_in_out = SPREADSHEET_CLOSURE_NONE;
|
||||
};
|
||||
|
||||
|
|
@ -69,7 +69,8 @@ struct GeometryDataIdentifier {
|
|||
{
|
||||
}
|
||||
|
||||
GeometryDataIdentifier(Vector<UString> bundle_keys, SpreadsheetClosureInputOutput closure_in_out)
|
||||
GeometryDataIdentifier(Vector<nodes::BundleKey> bundle_keys,
|
||||
SpreadsheetClosureInputOutput closure_in_out)
|
||||
: id(GeometryBundleItemId{std::move(bundle_keys), closure_in_out})
|
||||
{
|
||||
}
|
||||
|
|
@ -568,18 +569,18 @@ class GeometryBundleViewItem : public DataSetViewItem {
|
|||
|
||||
std::optional<GeometryDataIdentifier> get_geometry_data_id() const override
|
||||
{
|
||||
return GeometryDataIdentifier(Vector<UString>(), SPREADSHEET_CLOSURE_NONE);
|
||||
return GeometryDataIdentifier(Vector<nodes::BundleKey>(), SPREADSHEET_CLOSURE_NONE);
|
||||
}
|
||||
};
|
||||
|
||||
class GeometryBundleItemViewItem : public DataSetViewItem {
|
||||
private:
|
||||
UString key_;
|
||||
nodes::BundleKey key_;
|
||||
|
||||
public:
|
||||
GeometryBundleItemViewItem(const UString key) : key_(key)
|
||||
GeometryBundleItemViewItem(const nodes::BundleKey key) : key_(key)
|
||||
{
|
||||
label_ = key_.string();
|
||||
label_ = key_.ustr().ref();
|
||||
}
|
||||
|
||||
void build_row(ui::Layout &row) override
|
||||
|
|
@ -589,7 +590,7 @@ class GeometryBundleItemViewItem : public DataSetViewItem {
|
|||
|
||||
std::optional<GeometryDataIdentifier> get_geometry_data_id() const override
|
||||
{
|
||||
Vector<UString> keys;
|
||||
Vector<nodes::BundleKey> keys;
|
||||
keys.append(key_);
|
||||
this->foreach_parent([&](const AbstractTreeViewItem &parent) {
|
||||
if (const auto *bundle_item = dynamic_cast<const GeometryBundleItemViewItem *>(&parent)) {
|
||||
|
|
@ -896,7 +897,7 @@ void DataSetViewItem::on_activate(bContext &C)
|
|||
}
|
||||
else if (const auto *bundle_item_id = std::get_if<GeometryBundleItemId>(&data_id->id)) {
|
||||
sspreadsheet.geometry_id.geometry_item_type = SPREADSHEET_GEOMETRY_ITEM_TYPE_BUNDLE;
|
||||
Vector<UString> keys = bundle_item_id->keys.as_span();
|
||||
Vector<nodes::BundleKey> keys = bundle_item_id->keys.as_span();
|
||||
spreadsheet_bundle_path_init_from(
|
||||
keys, bundle_item_id->closure_in_out, sspreadsheet.geometry_id.geometry_bundle_path);
|
||||
RNA_property_update(&C, &ptr, RNA_struct_find_property(&ptr, "geometry_component_type"));
|
||||
|
|
@ -949,7 +950,7 @@ std::optional<bool> DataSetViewItem::should_be_active() const
|
|||
}
|
||||
for (const int i : IndexRange(bundle_item_id->keys.size())) {
|
||||
if (sspreadsheet.geometry_id.geometry_bundle_path.bundle_path[i].identifier !=
|
||||
bundle_item_id->keys[i])
|
||||
bundle_item_id->keys[i].ustr())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1218,7 +1219,7 @@ class ViewerDataTreeItem : public ui::AbstractTreeViewItem {
|
|||
|
||||
struct ViewerDataPath {
|
||||
int viewer_item;
|
||||
Vector<UString> bundles;
|
||||
Vector<nodes::BundleKey> bundles;
|
||||
SpreadsheetClosureInputOutput closure_input_output = SPREADSHEET_CLOSURE_NONE;
|
||||
|
||||
friend bool operator==(const ViewerDataPath &a, const ViewerDataPath &b) = default;
|
||||
|
|
@ -1230,7 +1231,11 @@ struct ViewerDataPath {
|
|||
for (const auto &elem : Span(table_id.viewer_item_bundle_path.bundle_path,
|
||||
table_id.viewer_item_bundle_path.bundle_path_num))
|
||||
{
|
||||
this->bundles.append(UString(elem.identifier));
|
||||
const std::optional<nodes::BundleKey> key = nodes::BundleKey::from_str(elem.identifier);
|
||||
if (!key) {
|
||||
continue;
|
||||
}
|
||||
this->bundles.append(*key);
|
||||
}
|
||||
this->closure_input_output = SpreadsheetClosureInputOutput(
|
||||
table_id.viewer_item_bundle_path.closure_input_output);
|
||||
|
|
@ -1268,9 +1273,9 @@ class BundleViewerTreeItem : public ViewerDataTreeItem {
|
|||
friend ViewerDataPath;
|
||||
|
||||
public:
|
||||
BundleViewerTreeItem(const UString key)
|
||||
BundleViewerTreeItem(const nodes::BundleKey key)
|
||||
{
|
||||
label_ = key.string();
|
||||
label_ = key.ustr().ref();
|
||||
}
|
||||
|
||||
void build_row(ui::Layout &row) override
|
||||
|
|
@ -1304,7 +1309,11 @@ ViewerDataPath::ViewerDataPath(const Span<const ViewerDataTreeItem *> tree_items
|
|||
this->viewer_item = viewer_node_item->item_.identifier;
|
||||
}
|
||||
else if (const auto *bundle_item = dynamic_cast<const BundleViewerTreeItem *>(item)) {
|
||||
this->bundles.append(UString(bundle_item->label_));
|
||||
if (const std::optional<nodes::BundleKey> key = nodes::BundleKey::from_str(
|
||||
bundle_item->label_))
|
||||
{
|
||||
this->bundles.append(*key);
|
||||
}
|
||||
}
|
||||
else if (const auto *bundle_item = dynamic_cast<const ClosureInOutViewerTreeItem *>(item)) {
|
||||
this->closure_input_output = bundle_item->in_out_;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "BLO_read_write.hh"
|
||||
|
||||
#include "NOD_geometry_nodes_bundle.hh"
|
||||
#include "spreadsheet_column.hh"
|
||||
#include "spreadsheet_table.hh"
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ void spreadsheet_bundle_path_clear(SpreadsheetBundleTreeViewPath &bundle_path)
|
|||
}
|
||||
|
||||
void spreadsheet_bundle_path_init_from(
|
||||
const Span<UString> keys,
|
||||
const Span<nodes::BundleKey> keys,
|
||||
const std::optional<SpreadsheetClosureInputOutput> closure_input_output,
|
||||
SpreadsheetBundleTreeViewPath &r_bundle_path)
|
||||
{
|
||||
|
|
@ -80,7 +81,7 @@ void spreadsheet_bundle_path_init_from(
|
|||
r_bundle_path.bundle_path = MEM_new_array<SpreadsheetBundlePathElem>(keys.size(), __func__);
|
||||
r_bundle_path.bundle_path_num = keys.size();
|
||||
for (const int i : keys.index_range()) {
|
||||
const StringRef key = keys[i].ref();
|
||||
const StringRef key = keys[i].ustr().ref();
|
||||
r_bundle_path.bundle_path[i].identifier = BLI_strdupn(key.data(), key.size());
|
||||
}
|
||||
r_bundle_path.closure_input_output = closure_input_output.value_or(SPREADSHEET_CLOSURE_NONE);
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@
|
|||
|
||||
#include "DNA_space_types.h"
|
||||
|
||||
#include "NOD_geometry_nodes_bundle.hh"
|
||||
|
||||
namespace blender::ed::spreadsheet {
|
||||
|
||||
SpreadsheetTableIDGeometry *spreadsheet_table_id_new_geometry();
|
||||
|
|
@ -28,7 +30,7 @@ void spreadsheet_table_id_foreach_id(SpreadsheetTableID &table_id, LibraryForeac
|
|||
|
||||
void spreadsheet_bundle_path_clear(SpreadsheetBundleTreeViewPath &bundle_path);
|
||||
void spreadsheet_bundle_path_init_from(
|
||||
Span<UString> keys,
|
||||
Span<nodes::BundleKey> keys,
|
||||
std::optional<SpreadsheetClosureInputOutput> closure_input_output,
|
||||
SpreadsheetBundleTreeViewPath &r_bundle_path);
|
||||
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ void RNA_api_text(StructRNA *srna)
|
|||
parm = RNA_def_string(func, "text", "Text", 0, "", "New text for this data-block");
|
||||
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
|
||||
|
||||
func = RNA_def_function(srna, "from_string", "rna_Text_from_string");
|
||||
func = RNA_def_function(srna, "from_str", "rna_Text_from_string");
|
||||
RNA_def_function_ui_description(func, "Replace text with this string.");
|
||||
parm = RNA_def_string(func, "text", "Text", 0, "", "");
|
||||
RNA_def_parameter_flags(parm, PropertyFlag(0), PARM_REQUIRED);
|
||||
|
|
|
|||
|
|
@ -56,6 +56,28 @@ struct BundleItemValue {
|
|||
template<typename T> const T *as_pointer() const;
|
||||
};
|
||||
|
||||
class BundleKey {
|
||||
private:
|
||||
UString key_;
|
||||
|
||||
BundleKey(UString key);
|
||||
|
||||
public:
|
||||
static std::optional<BundleKey> from_ustr(UString key);
|
||||
static std::optional<BundleKey> from_str(StringRef key);
|
||||
|
||||
uint64_t hash() const;
|
||||
bool operator==(const BundleKey &other) const = default;
|
||||
|
||||
UString ustr() const;
|
||||
|
||||
/* Disallow certain characters so that we can use them to e.g. build a bundle path or
|
||||
* expressions referencing multiple bundle items. We might not need all of them in the future,
|
||||
* but better reserve them now while we still can. */
|
||||
static constexpr StringRefNull forbidden_key_chars = "/*&|\"^~!,{}()+$#@[];:?<>.-%\\=";
|
||||
static bool is_valid_key(StringRef key);
|
||||
};
|
||||
|
||||
/**
|
||||
* A bundle is a map containing keys and their corresponding values.
|
||||
*
|
||||
|
|
@ -63,33 +85,33 @@ struct BundleItemValue {
|
|||
*/
|
||||
class Bundle : public ImplicitSharingMixin {
|
||||
public:
|
||||
using BundleItemMap = Map<UString, BundleItemValue>;
|
||||
using BundleItemMap = Map<BundleKey, BundleItemValue>;
|
||||
|
||||
private:
|
||||
BundleItemMap items_;
|
||||
|
||||
public:
|
||||
static inline UString type_item_name = "Type"_ustr;
|
||||
static inline BundleKey type_item_name = *BundleKey::from_str("Type");
|
||||
static BundlePtr create();
|
||||
|
||||
bool add(UString key, const BundleItemValue &value);
|
||||
bool add(UString key, BundleItemValue &&value);
|
||||
void add_new(UString key, const BundleItemValue &value);
|
||||
void add_new(UString key, BundleItemValue &&value);
|
||||
void add_override(UString key, const BundleItemValue &value);
|
||||
bool add(BundleKey key, const BundleItemValue &value);
|
||||
bool add(BundleKey key, BundleItemValue &&value);
|
||||
void add_new(BundleKey key, const BundleItemValue &value);
|
||||
void add_new(BundleKey key, BundleItemValue &&value);
|
||||
void add_override(BundleKey key, const BundleItemValue &value);
|
||||
bool add_path(StringRef path, const BundleItemValue &value);
|
||||
void add_path_new(StringRef path, const BundleItemValue &value);
|
||||
void add_path_override(StringRef path, const BundleItemValue &value);
|
||||
|
||||
template<typename T>
|
||||
requires(!std::is_same_v<std::decay_t<T>, BundleItemValue>)
|
||||
void add(UString key, T &&value);
|
||||
void add(BundleKey key, T &&value);
|
||||
template<typename T>
|
||||
requires(!std::is_same_v<std::decay_t<T>, BundleItemValue>)
|
||||
void add_new(UString key, T &&value);
|
||||
void add_new(BundleKey key, T &&value);
|
||||
template<typename T>
|
||||
requires(!std::is_same_v<std::decay_t<T>, BundleItemValue>)
|
||||
void add_override(UString key, T &&value);
|
||||
void add_override(BundleKey key, T &&value);
|
||||
template<typename T>
|
||||
requires(!std::is_same_v<std::decay_t<T>, BundleItemValue>)
|
||||
void add_path(StringRef path, T &&value);
|
||||
|
|
@ -97,28 +119,28 @@ class Bundle : public ImplicitSharingMixin {
|
|||
requires(!std::is_same_v<std::decay_t<T>, BundleItemValue>)
|
||||
void add_path_override(StringRef path, T &&value);
|
||||
|
||||
bool remove(UString key);
|
||||
bool remove(BundleKey key);
|
||||
bool remove_path(StringRef path);
|
||||
bool remove_path(Span<UString> path);
|
||||
bool contains(UString key) const;
|
||||
bool remove_path(Span<BundleKey> path);
|
||||
bool contains(BundleKey key) const;
|
||||
bool contains_path(StringRef path) const;
|
||||
bool contains_path(Span<UString> path) const;
|
||||
bool contains_path(Span<BundleKey> path) const;
|
||||
|
||||
const BundleItemValue *lookup(UString key) const;
|
||||
BundleItemValue *lookup(UString key);
|
||||
const BundleItemValue *lookup_path(Span<UString> path) const;
|
||||
const BundleItemValue *lookup(BundleKey key) const;
|
||||
BundleItemValue *lookup(BundleKey key);
|
||||
const BundleItemValue *lookup_path(Span<BundleKey> path) const;
|
||||
const BundleItemValue *lookup_path(StringRef path) const;
|
||||
BundleItemValue *lookup_path_for_write(Span<UString> path);
|
||||
BundleItemValue *lookup_path_for_write(Span<BundleKey> path);
|
||||
BundleItemValue *lookup_path_for_write(StringRef path);
|
||||
template<typename T> std::optional<T> lookup(UString key) const;
|
||||
template<typename T> std::optional<T> lookup_path(Span<UString> path) const;
|
||||
template<typename T> std::optional<T> lookup(BundleKey key) const;
|
||||
template<typename T> std::optional<T> lookup_path(Span<BundleKey> path) const;
|
||||
template<typename T> std::optional<T> lookup_path(StringRef path) const;
|
||||
template<typename T> T *lookup_ptr(UString key);
|
||||
template<typename T> const T *lookup_ptr(UString key) const;
|
||||
template<typename T> T *lookup_ptr(BundleKey key);
|
||||
template<typename T> const T *lookup_ptr(BundleKey key) const;
|
||||
template<typename T> const T *lookup_path_ptr(StringRef path) const;
|
||||
template<typename T> const T *lookup_path_ptr(Span<UString> path) const;
|
||||
template<typename T> const T *lookup_path_ptr(Span<BundleKey> path) const;
|
||||
template<typename T> T *lookup_path_for_write_ptr(StringRef path);
|
||||
template<typename T> T *lookup_path_for_write_ptr(Span<UString> path);
|
||||
template<typename T> T *lookup_path_for_write_ptr(Span<BundleKey> path);
|
||||
|
||||
Bundle &ensure_nested_bundle(StringRef path);
|
||||
|
||||
|
|
@ -149,15 +171,10 @@ class Bundle : public ImplicitSharingMixin {
|
|||
|
||||
/** Create the combined path by inserting '/' between each element. */
|
||||
static std::string combine_path(Span<StringRef> path);
|
||||
static std::string combine_path(Span<UString> path);
|
||||
static std::string combine_path(Span<BundleKey> path);
|
||||
|
||||
/* Disallow certain characters so that we can use them to e.g. build a bundle path or
|
||||
* expressions referencing multiple bundle items. We might not need all of them in the future,
|
||||
* but better reserve them now while we still can. */
|
||||
static constexpr StringRefNull forbidden_key_chars = "/*&|\"^~!,{}()+$#@[];:?<>.-%\\=";
|
||||
static bool is_valid_key(StringRef key);
|
||||
static bool is_valid_path(StringRef path);
|
||||
static std::optional<Vector<UString>> split_path(StringRef path);
|
||||
static std::optional<Vector<BundleKey>> split_path(StringRef path);
|
||||
};
|
||||
|
||||
enum class BundlePathsGatherFilterResult {
|
||||
|
|
@ -172,7 +189,8 @@ Vector<std::string> gather_bundle_paths_by_data_type(const Bundle &bundle,
|
|||
eNodeSocketDatatype data_type);
|
||||
|
||||
void foreach_nested_bundle_item(
|
||||
const Bundle &bundle, FunctionRef<void(Span<UString> path, const BundleItemValue &value)> fn);
|
||||
const Bundle &bundle,
|
||||
FunctionRef<void(Span<BundleKey> path, const BundleItemValue &value)> fn);
|
||||
|
||||
template<typename T>
|
||||
inline std::optional<T> BundleItemValue::as_socket_value(
|
||||
|
|
@ -277,7 +295,7 @@ template<typename T> inline std::optional<T> BundleItemValue::as() const
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
template<typename T> inline std::optional<T> Bundle::lookup(const UString key) const
|
||||
template<typename T> inline std::optional<T> Bundle::lookup(const BundleKey key) const
|
||||
{
|
||||
const BundleItemValue *item = this->lookup(key);
|
||||
if (!item) {
|
||||
|
|
@ -286,7 +304,7 @@ template<typename T> inline std::optional<T> Bundle::lookup(const UString key) c
|
|||
return item->as<T>();
|
||||
}
|
||||
|
||||
template<typename T> inline T *Bundle::lookup_ptr(const UString key)
|
||||
template<typename T> inline T *Bundle::lookup_ptr(const BundleKey key)
|
||||
{
|
||||
BundleItemValue *item = this->lookup(key);
|
||||
return item ? item->as_pointer<T>() : nullptr;
|
||||
|
|
@ -298,19 +316,19 @@ template<typename T> inline const T *Bundle::lookup_path_ptr(const StringRef pat
|
|||
return item ? item->as_pointer<T>() : nullptr;
|
||||
}
|
||||
|
||||
template<typename T> inline const T *Bundle::lookup_path_ptr(const Span<UString> path) const
|
||||
template<typename T> inline const T *Bundle::lookup_path_ptr(const Span<BundleKey> path) const
|
||||
{
|
||||
const BundleItemValue *item = this->lookup_path(path);
|
||||
return item ? item->as_pointer<T>() : nullptr;
|
||||
}
|
||||
|
||||
template<typename T> inline const T *Bundle::lookup_ptr(const UString key) const
|
||||
template<typename T> inline const T *Bundle::lookup_ptr(const BundleKey key) const
|
||||
{
|
||||
const BundleItemValue *item = this->lookup(key);
|
||||
return item ? item->as_pointer<T>() : nullptr;
|
||||
}
|
||||
|
||||
template<typename T> inline T *Bundle::lookup_path_for_write_ptr(const Span<UString> path)
|
||||
template<typename T> inline T *Bundle::lookup_path_for_write_ptr(const Span<BundleKey> path)
|
||||
{
|
||||
BundleItemValue *item = this->lookup_path_for_write(path);
|
||||
return item ? item->as_pointer<T>() : nullptr;
|
||||
|
|
@ -322,7 +340,7 @@ template<typename T> inline T *Bundle::lookup_path_for_write_ptr(const StringRef
|
|||
return item ? item->as_pointer<T>() : nullptr;
|
||||
}
|
||||
|
||||
template<typename T> inline std::optional<T> Bundle::lookup_path(const Span<UString> path) const
|
||||
template<typename T> inline std::optional<T> Bundle::lookup_path(const Span<BundleKey> path) const
|
||||
{
|
||||
const BundleItemValue *item = this->lookup_path(path);
|
||||
if (!item) {
|
||||
|
|
@ -376,7 +394,7 @@ template<typename T, typename Fn> inline void to_stored_type(T &&value, Fn &&fn)
|
|||
|
||||
template<typename T>
|
||||
requires(!std::is_same_v<std::decay_t<T>, BundleItemValue>)
|
||||
inline void Bundle::add(const UString key, T &&value)
|
||||
inline void Bundle::add(const BundleKey key, T &&value)
|
||||
{
|
||||
to_stored_type(std::forward<T>(value),
|
||||
[&]<typename U>(U &&item_value) { this->add(key, std::forward<U>(item_value)); });
|
||||
|
|
@ -384,7 +402,7 @@ inline void Bundle::add(const UString key, T &&value)
|
|||
|
||||
template<typename T>
|
||||
requires(!std::is_same_v<std::decay_t<T>, BundleItemValue>)
|
||||
inline void Bundle::add_new(const UString key, T &&value)
|
||||
inline void Bundle::add_new(const BundleKey key, T &&value)
|
||||
{
|
||||
to_stored_type(std::forward<T>(value), [&]<typename U>(U &&item_value) {
|
||||
this->add_new(key, std::forward<U>(item_value));
|
||||
|
|
@ -402,7 +420,7 @@ inline void Bundle::add_path(const StringRef path, T &&value)
|
|||
|
||||
template<typename T>
|
||||
requires(!std::is_same_v<std::decay_t<T>, BundleItemValue>)
|
||||
inline void Bundle::add_override(const UString key, T &&value)
|
||||
inline void Bundle::add_override(const BundleKey key, T &&value)
|
||||
{
|
||||
to_stored_type(std::forward<T>(value), [&]<typename U>(U &&item_value) {
|
||||
this->add_override(key, std::forward<U>(item_value));
|
||||
|
|
@ -438,4 +456,38 @@ inline int64_t Bundle::size() const
|
|||
return items_.size();
|
||||
}
|
||||
|
||||
inline BundleKey::BundleKey(const UString key) : key_(key) {}
|
||||
|
||||
inline uint64_t BundleKey::hash() const
|
||||
{
|
||||
return get_default_hash(key_);
|
||||
}
|
||||
|
||||
std::optional<BundleKey> inline BundleKey::from_ustr(const UString key)
|
||||
{
|
||||
if (is_valid_key(key.ref())) {
|
||||
return BundleKey(key);
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<BundleKey> inline BundleKey::from_str(const StringRef key)
|
||||
{
|
||||
/* Check validity before converting to UString. */
|
||||
if (is_valid_key(key)) {
|
||||
return BundleKey(UString(key));
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
inline UString BundleKey::ustr() const
|
||||
{
|
||||
return key_;
|
||||
}
|
||||
|
||||
inline std::string_view format_as(const BundleKey key)
|
||||
{
|
||||
return key.ustr().ref();
|
||||
}
|
||||
|
||||
} // namespace blender::nodes
|
||||
|
|
|
|||
|
|
@ -58,9 +58,9 @@ class StringPattern {
|
|||
* Create a new pattern. If the pattern is invalid, nullopt is returned and the error message is
|
||||
* set.
|
||||
*/
|
||||
static std::optional<StringPattern> from_string(StringPatternMode mode,
|
||||
StringRef pattern,
|
||||
std::string &r_error);
|
||||
static std::optional<StringPattern> from_str(StringPatternMode mode,
|
||||
StringRef pattern,
|
||||
std::string &r_error);
|
||||
|
||||
/** Returns true if the string matches the pattern. */
|
||||
bool match(StringRef query) const;
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ static void node_declare(NodeDeclarationBuilder &b)
|
|||
}
|
||||
}
|
||||
|
||||
if (i == 0 && socket_type == SOCK_STRING && name == Bundle::type_item_name) {
|
||||
if (i == 0 && socket_type == SOCK_STRING && name == Bundle::type_item_name.ustr()) {
|
||||
decl.optional_label();
|
||||
b.add_separator();
|
||||
}
|
||||
|
|
@ -156,12 +156,13 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
continue;
|
||||
}
|
||||
const StringRef name = item.name;
|
||||
if (!Bundle::is_valid_key(name)) {
|
||||
const std::optional<BundleKey> key = BundleKey::from_str(name);
|
||||
if (!key) {
|
||||
continue;
|
||||
}
|
||||
bke::SocketValueVariant value = params.extract_input<bke::SocketValueVariant>(
|
||||
node.input_socket(i).identifier_ustr());
|
||||
bundle.add(UString(name), BundleItemSocketValue{stype, std::move(value)});
|
||||
bundle.add(*key, BundleItemSocketValue{stype, std::move(value)});
|
||||
}
|
||||
|
||||
params.set_output("Bundle"_ustr, std::move(bundle_ptr));
|
||||
|
|
@ -252,7 +253,7 @@ std::string CombineBundleItemsAccessor::validate_name(const StringRef name)
|
|||
if (name.is_empty()) {
|
||||
return result;
|
||||
}
|
||||
const Span<char> forbidden_chars = Bundle::forbidden_key_chars;
|
||||
const Span<char> forbidden_chars = BundleKey::forbidden_key_chars;
|
||||
for (const char c : name) {
|
||||
if (forbidden_chars.contains(c)) {
|
||||
result += '_';
|
||||
|
|
@ -272,7 +273,7 @@ std::string CombineBundleItemsAccessor::validate_name(const StringRef name)
|
|||
result[last_index] = '_';
|
||||
}
|
||||
}
|
||||
BLI_assert(Bundle::is_valid_key(result));
|
||||
BLI_assert(BundleKey::is_valid_key(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -285,7 +286,7 @@ std::optional<StringRefNull> combine_bundle_node_type(const bNodeTree & /*tree*/
|
|||
if (socket.type != SOCK_STRING) {
|
||||
continue;
|
||||
}
|
||||
if (socket.name != Bundle::type_item_name) {
|
||||
if (socket.name != Bundle::type_item_name.ustr()) {
|
||||
continue;
|
||||
}
|
||||
return socket.default_value_typed<bNodeSocketValueString>()->value;
|
||||
|
|
|
|||
|
|
@ -71,10 +71,10 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
Vector<std::string> paths;
|
||||
switch (mode) {
|
||||
case Mode::All: {
|
||||
foreach_nested_bundle_item(bundle,
|
||||
[&](const Span<UString> path, const BundleItemValue & /*value*/) {
|
||||
paths.append(Bundle::combine_path(path));
|
||||
});
|
||||
foreach_nested_bundle_item(
|
||||
bundle, [&](const Span<BundleKey> path, const BundleItemValue & /*value*/) {
|
||||
paths.append(Bundle::combine_path(path));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case Mode::BundleType: {
|
||||
|
|
@ -82,7 +82,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
const StringPatternMode pattern_mode = params.extract_input<StringPatternMode>(
|
||||
"Pattern Mode"_ustr);
|
||||
std::string pattern_error;
|
||||
std::optional<StringPattern> pattern_fn = StringPattern::from_string(
|
||||
std::optional<StringPattern> pattern_fn = StringPattern::from_str(
|
||||
pattern_mode, type_pattern, pattern_error);
|
||||
if (!pattern_fn) {
|
||||
params.error_message_add(NodeWarningType::Error, pattern_error);
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
}
|
||||
Bundle &mutable_output_bundle = output_bundle.ensure_mutable_inplace();
|
||||
|
||||
VectorSet<UString> overridden_keys;
|
||||
VectorSet<BundleKey> overridden_keys;
|
||||
for (; bundle_i < bundles.values.size(); bundle_i++) {
|
||||
BundlePtr &bundle = bundles.values[bundle_i];
|
||||
if (!bundle) {
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
}
|
||||
|
||||
std::string pattern_error;
|
||||
std::optional<StringPattern> pattern_fn = StringPattern::from_string(
|
||||
std::optional<StringPattern> pattern_fn = StringPattern::from_str(
|
||||
params.get_input<StringPatternMode>("Pattern Mode"_ustr), pattern, pattern_error);
|
||||
if (!pattern_fn) {
|
||||
params.error_message_add(NodeWarningType::Error, pattern_error);
|
||||
|
|
|
|||
|
|
@ -139,14 +139,15 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
for (const int i : IndexRange(storage.items_num)) {
|
||||
const NodeSeparateBundleItem &item = storage.items[i];
|
||||
const StringRef name = item.name;
|
||||
if (!Bundle::is_valid_key(name)) {
|
||||
std::optional<BundleKey> key = BundleKey::from_str(name);
|
||||
if (!key) {
|
||||
continue;
|
||||
}
|
||||
const bke::bNodeSocketType *stype = bke::node_socket_type_find_static(item.socket_type);
|
||||
if (!stype || !stype->geometry_nodes_default_value) {
|
||||
continue;
|
||||
}
|
||||
const BundleItemValue *value = bundle->lookup(UString(name));
|
||||
const BundleItemValue *value = bundle->lookup(*key);
|
||||
if (!value) {
|
||||
params.error_message_add(
|
||||
NodeWarningType::Error,
|
||||
|
|
|
|||
|
|
@ -403,7 +403,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
if (attribute_patterns_list->cpp_type().is<std::string>()) {
|
||||
attribute_patterns_list.typed<std::string>()->foreach([&](const std::string &pattern) {
|
||||
std::string error;
|
||||
if (std::optional<StringPattern> pattern_fn = StringPattern::from_string(
|
||||
if (std::optional<StringPattern> pattern_fn = StringPattern::from_str(
|
||||
pattern_mode, pattern, error))
|
||||
{
|
||||
patterns.append(std::move(*pattern_fn));
|
||||
|
|
|
|||
|
|
@ -673,7 +673,7 @@ class XpbdSolverStep {
|
|||
void gather_nested_bundle_paths()
|
||||
{
|
||||
foreach_nested_bundle_item(world_,
|
||||
[&](const Span<UString> path, const BundleItemValue &value) {
|
||||
[&](const Span<BundleKey> path, const BundleItemValue &value) {
|
||||
const BundlePtr *bundle_ptr = value.as_pointer<BundlePtr>();
|
||||
if (!bundle_ptr || !*bundle_ptr) {
|
||||
return;
|
||||
|
|
@ -830,17 +830,23 @@ class XpbdSolverStep {
|
|||
}
|
||||
const Bundle &bundle = **bundle_ptr;
|
||||
const Bundle *previous_bundle = this->get_previous_bundle(bundle);
|
||||
const bke::GeometrySet *geometry = bundle.lookup_ptr<bke::GeometrySet>("geometry"_ustr);
|
||||
const float margin = bundle.lookup<float>("margin"_ustr).value_or(0.0f);
|
||||
const float friction = bundle.lookup<float>("friction"_ustr).value_or(0.0f);
|
||||
const float compliance = bundle.lookup<float>("compliance"_ustr).value_or(0.0f);
|
||||
const bool deforming = bundle.lookup<bool>("deforming"_ustr).value_or(false);
|
||||
const bool use_edge_contacts = bundle.lookup<bool>("use_edge_contacts"_ustr).value_or(false);
|
||||
const bool is_boundary = bundle.lookup<bool>("is_boundary"_ustr).value_or(false);
|
||||
const float error_threshold = bundle.lookup<float>("error_threshold"_ustr).value_or(1e-3f);
|
||||
const bke::GeometrySet *geometry = bundle.lookup_ptr<bke::GeometrySet>(
|
||||
*BundleKey::from_str("geometry"));
|
||||
const float margin = bundle.lookup<float>(*BundleKey::from_str("margin")).value_or(0.0f);
|
||||
const float friction = bundle.lookup<float>(*BundleKey::from_str("friction")).value_or(0.0f);
|
||||
const float compliance =
|
||||
bundle.lookup<float>(*BundleKey::from_str("compliance")).value_or(0.0f);
|
||||
const bool deforming =
|
||||
bundle.lookup<bool>(*BundleKey::from_str("deforming")).value_or(false);
|
||||
const bool use_edge_contacts =
|
||||
bundle.lookup<bool>(*BundleKey::from_str("use_edge_contacts")).value_or(false);
|
||||
const bool is_boundary =
|
||||
bundle.lookup<bool>(*BundleKey::from_str("is_boundary")).value_or(false);
|
||||
const float error_threshold =
|
||||
bundle.lookup<float>(*BundleKey::from_str("error_threshold")).value_or(1e-3f);
|
||||
const bke::GeometrySet *prev_geometry = previous_bundle ?
|
||||
previous_bundle->lookup_ptr<bke::GeometrySet>(
|
||||
"geometry"_ustr) :
|
||||
*BundleKey::from_str("geometry")) :
|
||||
nullptr;
|
||||
if (!geometry) {
|
||||
continue;
|
||||
|
|
@ -1603,11 +1609,16 @@ class XpbdSolverStep {
|
|||
const Bundle &bundle = **world_.lookup_path_ptr<BundlePtr>(path);
|
||||
RodStretchShearConstraint constraint;
|
||||
constraint.path = path;
|
||||
constraint.error_threshold = bundle.lookup<float>("error_threshold"_ustr).value_or(1e-3f);
|
||||
constraint.lambda_pos_attr =
|
||||
bundle.lookup<std::string>("lambda_position_attribute"_ustr).value_or("");
|
||||
constraint.lambda_rot_attr =
|
||||
bundle.lookup<std::string>("lambda_rotation_attribute"_ustr).value_or("");
|
||||
constraint.error_threshold =
|
||||
bundle.lookup<float>(*BundleKey::from_str("error_threshold")).value_or(1e-3f);
|
||||
constraint.lambda_pos_attr = bundle
|
||||
.lookup<std::string>(
|
||||
*BundleKey::from_str("lambda_position_attribute"))
|
||||
.value_or("");
|
||||
constraint.lambda_rot_attr = bundle
|
||||
.lookup<std::string>(
|
||||
*BundleKey::from_str("lambda_rotation_attribute"))
|
||||
.value_or("");
|
||||
|
||||
const int constraint_i = constraints_.rod_stretch_shear_constraints.append_and_get_index(
|
||||
std::move(constraint));
|
||||
|
|
@ -1729,7 +1740,8 @@ class XpbdSolverStep {
|
|||
|
||||
RodBendTwistConstraint constraint;
|
||||
constraint.path = path;
|
||||
constraint.error_threshold = bundle.lookup<float>("error_threshold"_ustr).value_or(1e-2f);
|
||||
constraint.error_threshold =
|
||||
bundle.lookup<float>(*BundleKey::from_str("error_threshold")).value_or(1e-2f);
|
||||
|
||||
const int constraint_i = constraints_.rod_bend_twist_constraints.append_and_get_index(
|
||||
std::move(constraint));
|
||||
|
|
@ -1805,7 +1817,8 @@ class XpbdSolverStep {
|
|||
for (const StringRef path : paths) {
|
||||
const Bundle &bundle = **world_.lookup_path_ptr<BundlePtr>(path);
|
||||
|
||||
const float error_threshold = bundle.lookup<float>("error_threshold"_ustr).value_or(1e-3f);
|
||||
const float error_threshold =
|
||||
bundle.lookup<float>(*BundleKey::from_str("error_threshold")).value_or(1e-3f);
|
||||
const int constraint_i = constraints_.edge_length_constraints.append_and_get_index(
|
||||
{path, error_threshold});
|
||||
|
||||
|
|
@ -1868,7 +1881,8 @@ class XpbdSolverStep {
|
|||
CrossEdgeLengthConstraintBundle::name);
|
||||
for (const StringRef path : paths) {
|
||||
const Bundle &bundle = **world_.lookup_path_ptr<BundlePtr>(path);
|
||||
const float error_threshold = bundle.lookup<float>("error_threshold"_ustr).value_or(1e-3f);
|
||||
const float error_threshold =
|
||||
bundle.lookup<float>(*BundleKey::from_str("error_threshold")).value_or(1e-3f);
|
||||
const int constraint_i = constraints_.cross_edge_length_constraints.append_and_get_index(
|
||||
{path, error_threshold});
|
||||
for (const int data_key_i : geometries_.data.index_range()) {
|
||||
|
|
@ -2092,8 +2106,10 @@ class XpbdSolverStep {
|
|||
const Bundle &bundle = **world_.lookup_path_ptr<BundlePtr>(path);
|
||||
PinPositionConstraint constraint;
|
||||
constraint.path = path;
|
||||
constraint.error_threshold = bundle.lookup<float>("error_threshold"_ustr).value_or(1e-3f);
|
||||
constraint.lambda_attr = bundle.lookup<std::string>("lambda_attribute"_ustr).value_or("");
|
||||
constraint.error_threshold =
|
||||
bundle.lookup<float>(*BundleKey::from_str("error_threshold")).value_or(1e-3f);
|
||||
constraint.lambda_attr =
|
||||
bundle.lookup<std::string>(*BundleKey::from_str("lambda_attribute")).value_or("");
|
||||
const int constraint_i = constraints_.pin_position_constraints.append_and_get_index(
|
||||
std::move(constraint));
|
||||
|
||||
|
|
@ -2248,7 +2264,8 @@ class XpbdSolverStep {
|
|||
|
||||
PinRotationConstraint constraint;
|
||||
constraint.path = path;
|
||||
constraint.error_threshold = bundle.lookup<float>("error_threshold"_ustr).value_or(1e-2f);
|
||||
constraint.error_threshold =
|
||||
bundle.lookup<float>(*BundleKey::from_str("error_threshold")).value_or(1e-2f);
|
||||
const int constraint_i = constraints_.pin_rotation_constraints.append_and_get_index(
|
||||
std::move(constraint));
|
||||
|
||||
|
|
@ -2929,7 +2946,8 @@ class XpbdSolverStep {
|
|||
|
||||
const Bundle *get_previous_bundle(const Bundle &bundle) const
|
||||
{
|
||||
const BundlePtr *previous_bundle_ptr = bundle.lookup_ptr<BundlePtr>("previous"_ustr);
|
||||
const BundlePtr *previous_bundle_ptr = bundle.lookup_ptr<BundlePtr>(
|
||||
*BundleKey::from_str("previous"));
|
||||
if (!previous_bundle_ptr || !*previous_bundle_ptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
|
@ -2944,7 +2962,8 @@ class XpbdSolverStep {
|
|||
const GeometrySetData &geo_set_data = geometries_.geometry_sets[data_key.geo_bundle_i];
|
||||
const StringRef geo_bundle_path = geo_set_data.path;
|
||||
|
||||
const bool filter_local = effector.lookup<bool>("filter_local"_ustr).value_or(false);
|
||||
const bool filter_local =
|
||||
effector.lookup<bool>(*BundleKey::from_str("filter_local")).value_or(false);
|
||||
if (filter_local) {
|
||||
const int pos = effector_path.rfind('/');
|
||||
if (pos == StringRef::not_found) {
|
||||
|
|
@ -2957,7 +2976,8 @@ class XpbdSolverStep {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
const std::string filter = effector.lookup<std::string>("filter"_ustr).value_or("");
|
||||
const std::string filter =
|
||||
effector.lookup<std::string>(*BundleKey::from_str("filter")).value_or("");
|
||||
const bool match = tag_filter_matches(filter, geo_set_data.tags);
|
||||
return match;
|
||||
}
|
||||
|
|
@ -3322,7 +3342,7 @@ static void node_geo_exec(GeoNodeExecParams params)
|
|||
if (!solver_path.empty()) {
|
||||
BundlePtr solver_data_ptr = Bundle::create();
|
||||
Bundle &solver_data = solver_data_ptr.ensure_mutable_inplace();
|
||||
solver_data.add_path(Bundle::type_item_name.string(), std::string(XPBDSolverDataBundle::name));
|
||||
solver_data.add(Bundle::type_item_name, std::string(XPBDSolverDataBundle::name));
|
||||
solver_data.add_path("residual_error", step.result().total_residual_error);
|
||||
world.add_path_override(solver_path, std::move(solver_data_ptr));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ FlatBundleTypePtr FlatBundleTypeBuilder::build()
|
|||
BundleSignature FlatBundleType::to_bundle_signature() const
|
||||
{
|
||||
BundleSignature signature;
|
||||
signature.add(Bundle::type_item_name.string(), SOCK_STRING);
|
||||
signature.add(Bundle::type_item_name.ustr().string(), SOCK_STRING);
|
||||
for (const Item &item : items_) {
|
||||
signature.add(item.name().ref(), item.decl->socket_type);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -370,12 +370,12 @@ void NodeTreeLogger::log_value(const bNode &node, const bNodeSocket &socket, con
|
|||
if (const BundleItemSocketValue *socket_value = std::get_if<BundleItemSocketValue>(
|
||||
&item.value.value))
|
||||
{
|
||||
items.append({item.key, {socket_value->type}});
|
||||
items.append({item.key.ustr(), {socket_value->type}});
|
||||
}
|
||||
if (const BundleItemInternalValue *internal_value = std::get_if<BundleItemInternalValue>(
|
||||
&item.value.value))
|
||||
{
|
||||
items.append({item.key, {internal_value->value->type_name()}});
|
||||
items.append({item.key.ustr(), {internal_value->value->type_name()}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,17 +32,18 @@ void BundleSignature::set_auto_structure_types()
|
|||
}
|
||||
}
|
||||
|
||||
bool Bundle::is_valid_key(const StringRef key)
|
||||
bool BundleKey::is_valid_key(const StringRef key)
|
||||
{
|
||||
if (key.is_empty()) {
|
||||
return false;
|
||||
}
|
||||
if (key != key.trim()) {
|
||||
/* Keys must not have leading or trailing white-space. This simplifies potentially using these
|
||||
/* Keys must not have leading or trailing white-space. This simplifies potentially using
|
||||
these
|
||||
* keys in expressions later on (or even just have a comma separated list of keys). */
|
||||
return false;
|
||||
}
|
||||
return key.find_first_of(Bundle::forbidden_key_chars) == StringRef::not_found;
|
||||
return key.find_first_of(BundleKey::forbidden_key_chars) == StringRef::not_found;
|
||||
}
|
||||
|
||||
bool Bundle::is_valid_path(const StringRef path)
|
||||
|
|
@ -50,29 +51,30 @@ bool Bundle::is_valid_path(const StringRef path)
|
|||
return split_path(path).has_value();
|
||||
}
|
||||
|
||||
std::optional<Vector<UString>> Bundle::split_path(const StringRef path)
|
||||
std::optional<Vector<BundleKey>> Bundle::split_path(const StringRef path)
|
||||
{
|
||||
if (path.is_empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
Vector<UString> path_elems;
|
||||
Vector<BundleKey> path_elems;
|
||||
StringRef remaining = path;
|
||||
while (!remaining.is_empty()) {
|
||||
const int sep = remaining.find_first_of('/');
|
||||
if (sep == StringRef::not_found) {
|
||||
const StringRef key = remaining;
|
||||
if (!is_valid_key(key)) {
|
||||
return std::nullopt;
|
||||
const StringRef key_str = remaining;
|
||||
if (const std::optional<BundleKey> key = BundleKey::from_str(key_str)) {
|
||||
path_elems.append(*key);
|
||||
}
|
||||
path_elems.append(UString(key));
|
||||
break;
|
||||
}
|
||||
const StringRef key = remaining.substr(0, sep);
|
||||
if (!is_valid_key(key)) {
|
||||
const StringRef key_str = remaining.substr(0, sep);
|
||||
if (const std::optional<BundleKey> key = BundleKey::from_str(key_str)) {
|
||||
path_elems.append(*key);
|
||||
remaining = remaining.substr(sep + 1);
|
||||
}
|
||||
else {
|
||||
return std::nullopt;
|
||||
}
|
||||
path_elems.append(UString(key));
|
||||
remaining = remaining.substr(sep + 1);
|
||||
}
|
||||
return path_elems;
|
||||
}
|
||||
|
|
@ -82,25 +84,23 @@ BundlePtr Bundle::create()
|
|||
return BundlePtr(MEM_new<Bundle>(__func__));
|
||||
}
|
||||
|
||||
void Bundle::add_new(const UString key, const BundleItemValue &value)
|
||||
void Bundle::add_new(const BundleKey key, const BundleItemValue &value)
|
||||
{
|
||||
BLI_assert(is_valid_key(key.ref()));
|
||||
items_.add_new_as(key, value);
|
||||
}
|
||||
|
||||
void Bundle::add_new(UString key, BundleItemValue &&value)
|
||||
void Bundle::add_new(BundleKey key, BundleItemValue &&value)
|
||||
{
|
||||
BLI_assert(is_valid_key(key.ref()));
|
||||
items_.add_new_as(key, std::move(value));
|
||||
}
|
||||
|
||||
void Bundle::add_override(const UString key, const BundleItemValue &value)
|
||||
void Bundle::add_override(const BundleKey key, const BundleItemValue &value)
|
||||
{
|
||||
this->remove(key);
|
||||
this->add_new(key, value);
|
||||
}
|
||||
|
||||
bool Bundle::add(const UString key, const BundleItemValue &value)
|
||||
bool Bundle::add(const BundleKey key, const BundleItemValue &value)
|
||||
{
|
||||
if (this->contains(key)) {
|
||||
return false;
|
||||
|
|
@ -109,7 +109,7 @@ bool Bundle::add(const UString key, const BundleItemValue &value)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Bundle::add(const UString key, BundleItemValue &&value)
|
||||
bool Bundle::add(const BundleKey key, BundleItemValue &&value)
|
||||
{
|
||||
if (this->contains(key)) {
|
||||
return false;
|
||||
|
|
@ -129,9 +129,9 @@ static BundleItemValue create_nested_bundle_item()
|
|||
void Bundle::add_path_override(const StringRef path, const BundleItemValue &value)
|
||||
{
|
||||
BLI_assert(is_valid_path(path));
|
||||
const Vector<UString> path_elems = *split_path(path);
|
||||
const Vector<BundleKey> path_elems = *split_path(path);
|
||||
Bundle *current = this;
|
||||
for (const UString path_elem : path_elems.as_span().drop_back(1)) {
|
||||
for (const BundleKey path_elem : path_elems.as_span().drop_back(1)) {
|
||||
BundleItemValue &item = current->items_.lookup_or_add_cb_as(
|
||||
path_elem, [&]() { return create_nested_bundle_item(); });
|
||||
BundlePtr *child_bundle_ptr = item.as_pointer<BundlePtr>();
|
||||
|
|
@ -172,22 +172,20 @@ Bundle &Bundle::ensure_nested_bundle(const StringRef path)
|
|||
return new_bundle_ref;
|
||||
}
|
||||
|
||||
const BundleItemValue *Bundle::lookup(const UString key) const
|
||||
const BundleItemValue *Bundle::lookup(const BundleKey key) const
|
||||
{
|
||||
BLI_assert(is_valid_key(key.ref()));
|
||||
return items_.lookup_ptr_as(key);
|
||||
}
|
||||
|
||||
BundleItemValue *Bundle::lookup(const UString key)
|
||||
BundleItemValue *Bundle::lookup(const BundleKey key)
|
||||
{
|
||||
BLI_assert(is_valid_key(key.ref()));
|
||||
return items_.lookup_ptr_as(key);
|
||||
}
|
||||
|
||||
const BundleItemValue *Bundle::lookup_path(const Span<UString> path) const
|
||||
const BundleItemValue *Bundle::lookup_path(const Span<BundleKey> path) const
|
||||
{
|
||||
BLI_assert(!path.is_empty());
|
||||
const UString first_elem = path[0];
|
||||
const BundleKey first_elem = path[0];
|
||||
const BundleItemValue *item = this->lookup(first_elem);
|
||||
if (!item) {
|
||||
return nullptr;
|
||||
|
|
@ -205,14 +203,14 @@ const BundleItemValue *Bundle::lookup_path(const Span<UString> path) const
|
|||
const BundleItemValue *Bundle::lookup_path(const StringRef path) const
|
||||
{
|
||||
BLI_assert(is_valid_path(path));
|
||||
const Vector<UString> path_elems = *split_path(path);
|
||||
const Vector<BundleKey> path_elems = *split_path(path);
|
||||
return this->lookup_path(path_elems);
|
||||
}
|
||||
|
||||
BundleItemValue *Bundle::lookup_path_for_write(Span<UString> path)
|
||||
BundleItemValue *Bundle::lookup_path_for_write(Span<BundleKey> path)
|
||||
{
|
||||
BLI_assert(!path.is_empty());
|
||||
const UString first_elem = path[0];
|
||||
const BundleKey first_elem = path[0];
|
||||
BundleItemValue *item = this->lookup(first_elem);
|
||||
if (!item) {
|
||||
return nullptr;
|
||||
|
|
@ -234,7 +232,7 @@ BundleItemValue *Bundle::lookup_path_for_write(Span<UString> path)
|
|||
BundleItemValue *Bundle::lookup_path_for_write(StringRef path)
|
||||
{
|
||||
BLI_assert(is_valid_path(path));
|
||||
const Vector<UString> path_elems = *split_path(path);
|
||||
const Vector<BundleKey> path_elems = *split_path(path);
|
||||
return this->lookup_path_for_write(path_elems);
|
||||
}
|
||||
|
||||
|
|
@ -281,20 +279,19 @@ BundlePtr Bundle::copy() const
|
|||
return copy_ptr;
|
||||
}
|
||||
|
||||
bool Bundle::remove(const UString key)
|
||||
bool Bundle::remove(const BundleKey key)
|
||||
{
|
||||
BLI_assert(is_valid_key(key.ref()));
|
||||
return items_.remove_as(key);
|
||||
}
|
||||
|
||||
bool Bundle::remove_path(const StringRef path)
|
||||
{
|
||||
BLI_assert(is_valid_path(path));
|
||||
const Vector<UString> path_elems = *split_path(path);
|
||||
const Vector<BundleKey> path_elems = *split_path(path);
|
||||
return this->remove_path(path_elems);
|
||||
}
|
||||
|
||||
bool Bundle::remove_path(const Span<UString> path)
|
||||
bool Bundle::remove_path(const Span<BundleKey> path)
|
||||
{
|
||||
BLI_assert(this->is_mutable());
|
||||
BLI_assert(!path.is_empty());
|
||||
|
|
@ -302,7 +299,7 @@ bool Bundle::remove_path(const Span<UString> path)
|
|||
return false;
|
||||
}
|
||||
Bundle *current = this;
|
||||
for (const UString path_elem : path.drop_back(1)) {
|
||||
for (const BundleKey path_elem : path.drop_back(1)) {
|
||||
BundleItemValue &item = current->items_.lookup_as(path_elem);
|
||||
BundlePtr *child_bundle_ptr = item.as_pointer<BundlePtr>();
|
||||
current = &child_bundle_ptr->ensure_mutable_inplace();
|
||||
|
|
@ -311,9 +308,8 @@ bool Bundle::remove_path(const Span<UString> path)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Bundle::contains(const UString key) const
|
||||
bool Bundle::contains(const BundleKey key) const
|
||||
{
|
||||
BLI_assert(is_valid_key(key.ref()));
|
||||
return items_.contains_as(key);
|
||||
}
|
||||
|
||||
|
|
@ -322,7 +318,7 @@ bool Bundle::contains_path(const StringRef path) const
|
|||
return this->lookup_path(path) != nullptr;
|
||||
}
|
||||
|
||||
bool Bundle::contains_path(const Span<UString> path) const
|
||||
bool Bundle::contains_path(const Span<BundleKey> path) const
|
||||
{
|
||||
return this->lookup_path(path) != nullptr;
|
||||
}
|
||||
|
|
@ -332,7 +328,7 @@ std::string Bundle::combine_path(const Span<StringRef> path)
|
|||
return fmt::format("{}", fmt::join(path, "/"));
|
||||
}
|
||||
|
||||
std::string Bundle::combine_path(const Span<UString> path)
|
||||
std::string Bundle::combine_path(const Span<BundleKey> path)
|
||||
{
|
||||
return fmt::format("{}", fmt::join(path, "/"));
|
||||
}
|
||||
|
|
@ -453,8 +449,8 @@ std::optional<BundleSignature> LinkedBundleSignatures::get_merged_signature() co
|
|||
|
||||
static void foreach_nested_bundle_item_recursive(
|
||||
const Bundle &bundle,
|
||||
const FunctionRef<void(Span<UString>, const BundleItemValue &value)> fn,
|
||||
Vector<UString> &r_path)
|
||||
const FunctionRef<void(Span<BundleKey>, const BundleItemValue &value)> fn,
|
||||
Vector<BundleKey> &r_path)
|
||||
{
|
||||
for (const auto &child_item : bundle.items()) {
|
||||
r_path.append(child_item.key);
|
||||
|
|
@ -474,9 +470,10 @@ static void foreach_nested_bundle_item_recursive(
|
|||
}
|
||||
|
||||
void foreach_nested_bundle_item(
|
||||
const Bundle &bundle, const FunctionRef<void(Span<UString>, const BundleItemValue &value)> fn)
|
||||
const Bundle &bundle,
|
||||
const FunctionRef<void(Span<BundleKey>, const BundleItemValue &value)> fn)
|
||||
{
|
||||
Vector<UString> path;
|
||||
Vector<BundleKey> path;
|
||||
foreach_nested_bundle_item_recursive(bundle, fn, path);
|
||||
}
|
||||
|
||||
|
|
@ -484,17 +481,18 @@ Vector<std::string> gather_bundle_paths_by_bundle_type(
|
|||
const Bundle &bundle, const FunctionRef<bool(StringRef type)> type_filter_fn)
|
||||
{
|
||||
Vector<std::string> paths;
|
||||
foreach_nested_bundle_item(bundle, [&](const Span<UString> path, const BundleItemValue &value) {
|
||||
if (const BundlePtr *child_bundle_ptr = value.as_pointer<BundlePtr>()) {
|
||||
if (*child_bundle_ptr) {
|
||||
if (const std::optional<StringRef> type = (*child_bundle_ptr)->type()) {
|
||||
if (type_filter_fn(*type)) {
|
||||
paths.append(Bundle::combine_path(path));
|
||||
foreach_nested_bundle_item(
|
||||
bundle, [&](const Span<BundleKey> path, const BundleItemValue &value) {
|
||||
if (const BundlePtr *child_bundle_ptr = value.as_pointer<BundlePtr>()) {
|
||||
if (*child_bundle_ptr) {
|
||||
if (const std::optional<StringRef> type = (*child_bundle_ptr)->type()) {
|
||||
if (type_filter_fn(*type)) {
|
||||
paths.append(Bundle::combine_path(path));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
|
@ -502,13 +500,14 @@ Vector<std::string> gather_bundle_paths_by_data_type(const Bundle &bundle,
|
|||
const eNodeSocketDatatype data_type)
|
||||
{
|
||||
Vector<std::string> paths;
|
||||
foreach_nested_bundle_item(bundle, [&](const Span<UString> path, const BundleItemValue &value) {
|
||||
if (const auto *socket_value = std::get_if<BundleItemSocketValue>(&value.value)) {
|
||||
if (socket_value->type->type == data_type) {
|
||||
paths.append(Bundle::combine_path(path));
|
||||
}
|
||||
}
|
||||
});
|
||||
foreach_nested_bundle_item(
|
||||
bundle, [&](const Span<BundleKey> path, const BundleItemValue &value) {
|
||||
if (const auto *socket_value = std::get_if<BundleItemSocketValue>(&value.value)) {
|
||||
if (socket_value->type->type == data_type) {
|
||||
paths.append(Bundle::combine_path(path));
|
||||
}
|
||||
}
|
||||
});
|
||||
return paths;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ TEST_F(BundleTest, AddItems)
|
|||
{
|
||||
BundlePtr bundle_ptr = Bundle::create();
|
||||
Bundle &bundle = const_cast<Bundle &>(*bundle_ptr);
|
||||
bundle.add("a"_ustr, 3);
|
||||
bundle.add(*BundleKey::from_str("a"), 3);
|
||||
EXPECT_EQ(bundle.size(), 1);
|
||||
EXPECT_TRUE(bundle.contains("a"_ustr));
|
||||
EXPECT_EQ(bundle.lookup<int>("a"_ustr), 3);
|
||||
EXPECT_TRUE(bundle.contains(*BundleKey::from_str("a")));
|
||||
EXPECT_EQ(bundle.lookup<int>(*BundleKey::from_str("a")), 3);
|
||||
}
|
||||
|
||||
TEST_F(BundleTest, AddLookupPath)
|
||||
|
|
@ -91,7 +91,7 @@ TEST_F(BundleTest, EnsureNestedBundle)
|
|||
BundlePtr bundle_ptr = Bundle::create();
|
||||
Bundle &bundle = bundle_ptr.ensure_mutable_inplace();
|
||||
Bundle &nested_bundle = bundle.ensure_nested_bundle("a/b/c");
|
||||
nested_bundle.add("test"_ustr, 4);
|
||||
nested_bundle.add(*BundleKey::from_str("test"), 4);
|
||||
const std::optional<int> value = bundle.lookup_path<int>("a/b/c/test");
|
||||
EXPECT_EQ(value, 4);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ const EnumPropertyItem string_pattern_mode_items[] = {
|
|||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
std::optional<StringPattern> StringPattern::from_string(StringPatternMode mode,
|
||||
StringRef pattern,
|
||||
std::string &r_error)
|
||||
std::optional<StringPattern> StringPattern::from_str(StringPatternMode mode,
|
||||
StringRef pattern,
|
||||
std::string &r_error)
|
||||
{
|
||||
switch (mode) {
|
||||
case StringPatternMode::Exact: {
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ def api_dump(use_properties=True, use_functions=True):
|
|||
sys.stderr.write("\n\nEOF\n")
|
||||
else:
|
||||
text = bpy.data.texts.new(name="api.py")
|
||||
text.from_string(data)
|
||||
text.from_str(data)
|
||||
|
||||
print("END")
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue