Refactor to get us closer to being able to remove `bNodeSocketType::geometry_nodes_cpp_type` which is always `SocketValueVariant` now. Pull Request: https://projects.blender.org/blender/blender/pulls/144419
131 lines
3.7 KiB
C++
131 lines
3.7 KiB
C++
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
#include "BKE_node_socket_value.hh"
|
|
|
|
#include "NOD_geometry_nodes_closure_fwd.hh"
|
|
#include "NOD_geometry_nodes_closure_location.hh"
|
|
#include "NOD_geometry_nodes_closure_signature.hh"
|
|
|
|
#include "BLI_resource_scope.hh"
|
|
|
|
#include "FN_lazy_function.hh"
|
|
|
|
namespace blender::nodes {
|
|
|
|
/**
|
|
* Describes the meaning of the various inputs and outputs of the lazy-function that's contained
|
|
* in the closure.
|
|
*/
|
|
struct ClosureFunctionIndices {
|
|
struct {
|
|
IndexRange main;
|
|
/** A boolean input for each output indicating whether that output is used. */
|
|
IndexRange output_usages;
|
|
/**
|
|
* A #GeometryNodesReferenceSet input for a subset of the outputs. This is used to tell the
|
|
* closure which attributes it has to propagate to the outputs.
|
|
*
|
|
* Main output index -> input `lf` socket index.
|
|
*/
|
|
Map<int, int> output_data_reference_sets;
|
|
} inputs;
|
|
struct {
|
|
IndexRange main;
|
|
/** A boolean output for each input indicating whether that input is used. */
|
|
IndexRange input_usages;
|
|
} outputs;
|
|
};
|
|
|
|
/**
|
|
* A closure is like a node group that is passed around as a value. It's typically evaluated using
|
|
* the Evaluate Closure node.
|
|
*
|
|
* Internally, a closure is a lazy-function. So the inputs that are passed to the closure are
|
|
* requested lazily. It's *not* yet supported to request the potentially captured values from the
|
|
* Closure Zone lazily.
|
|
*/
|
|
class Closure : public ImplicitSharingMixin {
|
|
private:
|
|
std::shared_ptr<ClosureSignature> signature_;
|
|
std::optional<ClosureSourceLocation> source_location_;
|
|
std::shared_ptr<ClosureEvalLog> eval_log_;
|
|
/**
|
|
* When building complex lazy-functions, e.g. from Geometry Nodes, one often has to allocate
|
|
* various additional resources (e.g. the lazy-functions for the individual nodes). Using
|
|
* #ResourceScope provides a simple way to pass ownership of all these additional resources to
|
|
* the Closure.
|
|
*/
|
|
std::unique_ptr<ResourceScope> scope_;
|
|
const fn::lazy_function::LazyFunction &function_;
|
|
ClosureFunctionIndices indices_;
|
|
Vector<bke::SocketValueVariant> default_input_values_;
|
|
|
|
public:
|
|
Closure(std::shared_ptr<ClosureSignature> signature,
|
|
std::unique_ptr<ResourceScope> scope,
|
|
const fn::lazy_function::LazyFunction &function,
|
|
ClosureFunctionIndices indices,
|
|
Vector<bke::SocketValueVariant> default_input_values,
|
|
std::optional<ClosureSourceLocation> source_location,
|
|
std::shared_ptr<ClosureEvalLog> eval_log)
|
|
: signature_(signature),
|
|
source_location_(source_location),
|
|
eval_log_(eval_log),
|
|
scope_(std::move(scope)),
|
|
function_(function),
|
|
indices_(indices),
|
|
default_input_values_(std::move(default_input_values))
|
|
{
|
|
}
|
|
|
|
const ClosureSignature &signature() const
|
|
{
|
|
return *signature_;
|
|
}
|
|
|
|
const ClosureFunctionIndices &indices() const
|
|
{
|
|
return indices_;
|
|
}
|
|
|
|
const fn::lazy_function::LazyFunction &function() const
|
|
{
|
|
return function_;
|
|
}
|
|
|
|
const std::optional<ClosureSourceLocation> &source_location() const
|
|
{
|
|
return source_location_;
|
|
}
|
|
|
|
const std::shared_ptr<ClosureEvalLog> &eval_log_ptr() const
|
|
{
|
|
return eval_log_;
|
|
}
|
|
|
|
const bke::SocketValueVariant &default_input_value(const int index) const
|
|
{
|
|
return default_input_values_[index];
|
|
}
|
|
|
|
void delete_self() override
|
|
{
|
|
MEM_delete(this);
|
|
}
|
|
|
|
void log_evaluation(const ClosureEvalLocation &location) const
|
|
{
|
|
if (!eval_log_) {
|
|
return;
|
|
}
|
|
std::lock_guard lock{eval_log_->mutex};
|
|
eval_log_->evaluations.append(location);
|
|
}
|
|
};
|
|
|
|
} // namespace blender::nodes
|