Files
test/source/blender/nodes/intern/geometry_nodes_bundle.cc
Jacques Lucke fbd29acaa2 Cleanup: Geometry Nodes: avoid unnecessary void pointer
All socket types use `SocketValueVariant` now, so using `void *` is not necessary anymore.

Pull Request: https://projects.blender.org/blender/blender/pulls/144415
2025-08-12 09:12:08 +02:00

244 lines
6.2 KiB
C++

/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include <fmt/format.h>
#include "BKE_node_socket_value.hh"
#include "BLI_cpp_type.hh"
#include "BKE_node_runtime.hh"
#include "NOD_geometry_nodes_bundle.hh"
#include "NOD_geometry_nodes_bundle_signature.hh"
namespace blender::nodes {
bool BundleSignature::matches_exactly(const BundleSignature &other) const
{
if (items.size() != other.items.size()) {
return false;
}
for (const Item &item : items) {
if (std::none_of(other.items.begin(), other.items.end(), [&](const Item &other_item) {
return item.key == other_item.key;
}))
{
return false;
}
}
return true;
}
bool BundleSignature::all_matching_exactly(const Span<BundleSignature> signatures)
{
if (signatures.is_empty()) {
return true;
}
for (const BundleSignature &signature : signatures.drop_front(1)) {
if (!signatures[0].matches_exactly(signature)) {
return false;
}
}
return true;
}
BundlePtr Bundle::create()
{
return BundlePtr(MEM_new<Bundle>(__func__));
}
[[maybe_unused]] static bool is_valid_key(const StringRef key)
{
return key.find('/') == StringRef::not_found;
}
void Bundle::add_new(const StringRef key, const BundleItemValue &value)
{
BLI_assert(is_valid_key(key));
items_.append(StoredItem{std::move(key), value});
}
void Bundle::add_override(const StringRef key, const BundleItemValue &value)
{
this->remove(key);
this->add_new(key, value);
}
bool Bundle::add(const StringRef key, const BundleItemValue &value)
{
if (this->contains(key)) {
return false;
}
this->add_new(key, value);
return true;
}
void Bundle::add_path_override(const StringRef path, const BundleItemValue &value)
{
BLI_assert(!path.is_empty());
BLI_assert(!path.endswith("/"));
BLI_assert(this->is_mutable());
const int sep = path.find_first_of('/');
if (sep == StringRef::not_found) {
const StringRef key = path;
this->remove(key);
this->add_new(key, value);
return;
}
const StringRef first_part = path.substr(0, sep);
BundlePtr child_bundle = this->lookup<BundlePtr>(first_part).value_or(nullptr);
if (!child_bundle) {
child_bundle = Bundle::create();
}
this->remove(first_part);
if (!child_bundle->is_mutable()) {
child_bundle = child_bundle->copy();
}
child_bundle->tag_ensured_mutable();
const_cast<Bundle &>(*child_bundle).add_path_override(path.substr(sep + 1), value);
bke::SocketValueVariant child_bundle_value = bke::SocketValueVariant::From(
std::move(child_bundle));
this->add(
first_part,
BundleItemSocketValue{bke::node_socket_type_find_static(SOCK_BUNDLE), child_bundle_value});
}
bool Bundle::add_path(StringRef path, const BundleItemValue &value)
{
if (this->contains_path(path)) {
return false;
}
this->add_path_new(path, value);
return true;
}
void Bundle::add_path_new(StringRef path, const BundleItemValue &value)
{
BLI_assert(!this->contains_path(path));
this->add_path_override(path, value);
}
const BundleItemValue *Bundle::lookup(const StringRef key) const
{
for (const StoredItem &item : items_) {
if (item.key == key) {
return &item.value;
}
}
return nullptr;
}
const BundleItemValue *Bundle::lookup_path(const Span<StringRef> path) const
{
BLI_assert(!path.is_empty());
const StringRef first_elem = path[0];
const BundleItemValue *item = this->lookup(first_elem);
if (!item) {
return nullptr;
}
if (path.size() == 1) {
return item;
}
const BundlePtr child_bundle = item->as<BundlePtr>().value_or(nullptr);
if (!child_bundle) {
return nullptr;
}
return child_bundle->lookup_path(path.drop_front(1));
}
static Vector<StringRef> split_path(const StringRef path)
{
Vector<StringRef> path_elems;
StringRef remaining = path;
while (!remaining.is_empty()) {
const int sep = remaining.find_first_of('/');
if (sep == StringRef::not_found) {
path_elems.append(remaining);
break;
}
path_elems.append(remaining.substr(0, sep));
remaining = remaining.substr(sep + 1);
}
return path_elems;
}
const BundleItemValue *Bundle::lookup_path(const StringRef path) const
{
const Vector<StringRef> path_elems = split_path(path);
return this->lookup_path(path_elems);
}
BundlePtr Bundle::copy() const
{
BundlePtr copy_ptr = Bundle::create();
Bundle &copy = const_cast<Bundle &>(*copy_ptr);
for (const StoredItem &item : items_) {
copy.add_new(item.key, item.value);
}
return copy_ptr;
}
bool Bundle::remove(const StringRef key)
{
BLI_assert(is_valid_key(key));
const int removed_num = items_.remove_if([&key](StoredItem &item) { return item.key == key; });
return removed_num >= 1;
}
bool Bundle::contains(const StringRef key) const
{
BLI_assert(is_valid_key(key));
for (const StoredItem &item : items_) {
if (item.key == key) {
return true;
}
}
return false;
}
bool Bundle::contains_path(const StringRef path) const
{
return this->lookup_path(path) != nullptr;
}
std::string Bundle::combine_path(const Span<StringRef> path)
{
return fmt::format("{}", fmt::join(path, "/"));
}
void Bundle::delete_self()
{
MEM_delete(this);
}
BundleSignature BundleSignature::from_combine_bundle_node(const bNode &node)
{
BLI_assert(node.is_type("NodeCombineBundle"));
const auto &storage = *static_cast<const NodeCombineBundle *>(node.storage);
BundleSignature signature;
for (const int i : IndexRange(storage.items_num)) {
const NodeCombineBundleItem &item = storage.items[i];
if (const bke::bNodeSocketType *stype = bke::node_socket_type_find_static(item.socket_type)) {
signature.items.add({item.name, stype});
}
}
return signature;
}
BundleSignature BundleSignature::from_separate_bundle_node(const bNode &node)
{
BLI_assert(node.is_type("NodeSeparateBundle"));
const auto &storage = *static_cast<const NodeSeparateBundle *>(node.storage);
BundleSignature signature;
for (const int i : IndexRange(storage.items_num)) {
const NodeSeparateBundleItem &item = storage.items[i];
if (const bke::bNodeSocketType *stype = bke::node_socket_type_find_static(item.socket_type)) {
signature.items.add({item.name, stype});
}
}
return signature;
}
} // namespace blender::nodes