This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/functions/intern/multi_function_builder.cc
Jacques Lucke 4e78b89e48 Geometry Nodes: add field support for socket inspection
Since fields were committed to master, socket inspection did
not work correctly for all socket types anymore. Now the same
functionality as before is back. Furthermore, fields that depend
on some input will now show the inputs in the socket inspection.

I added support for evaluating constant fields more immediately.
This has the benefit that the same constant field is not evaluated
more than once. It also helps with making the field independent
of the multi-functions that it uses. We might still want to change
the ownership handling for the multi-functions of nodes a bit,
but that can be done separately.

Differential Revision: https://developer.blender.org/D12444
2021-09-11 13:05:20 +02:00

172 lines
5.5 KiB
C++

/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "FN_multi_function_builder.hh"
#include "BLI_hash.hh"
namespace blender::fn {
CustomMF_GenericConstant::CustomMF_GenericConstant(const CPPType &type,
const void *value,
bool make_value_copy)
: type_(type), owns_value_(make_value_copy)
{
if (make_value_copy) {
void *copied_value = MEM_mallocN_aligned(type.size(), type.alignment(), __func__);
type.copy_construct(value, copied_value);
value = copied_value;
}
value_ = value;
MFSignatureBuilder signature{"Constant " + type.name()};
std::stringstream ss;
type.print_or_default(value, ss, type.name());
signature.single_output(ss.str(), type);
signature_ = signature.build();
this->set_signature(&signature_);
}
CustomMF_GenericConstant::~CustomMF_GenericConstant()
{
if (owns_value_) {
signature_.param_types[0].data_type().single_type().destruct((void *)value_);
MEM_freeN((void *)value_);
}
}
void CustomMF_GenericConstant::call(IndexMask mask,
MFParams params,
MFContext UNUSED(context)) const
{
GMutableSpan output = params.uninitialized_single_output(0);
type_.fill_construct_indices(value_, output.data(), mask);
}
uint64_t CustomMF_GenericConstant::hash() const
{
return type_.hash_or_fallback(value_, (uintptr_t)this);
}
bool CustomMF_GenericConstant::equals(const MultiFunction &other) const
{
const CustomMF_GenericConstant *_other = dynamic_cast<const CustomMF_GenericConstant *>(&other);
if (_other == nullptr) {
return false;
}
if (type_ != _other->type_) {
return false;
}
return type_.is_equal(value_, _other->value_);
}
static std::string gspan_to_string(GSpan array)
{
const CPPType &type = array.type();
std::stringstream ss;
ss << "[";
const int64_t max_amount = 5;
for (int64_t i : IndexRange(std::min(max_amount, array.size()))) {
type.print_or_default(array[i], ss, type.name());
ss << ", ";
}
if (max_amount < array.size()) {
ss << "...";
}
ss << "]";
return ss.str();
}
CustomMF_GenericConstantArray::CustomMF_GenericConstantArray(GSpan array) : array_(array)
{
const CPPType &type = array.type();
MFSignatureBuilder signature{"Constant " + type.name() + " Vector"};
signature.vector_output(gspan_to_string(array), type);
signature_ = signature.build();
this->set_signature(&signature_);
}
void CustomMF_GenericConstantArray::call(IndexMask mask,
MFParams params,
MFContext UNUSED(context)) const
{
GVectorArray &vectors = params.vector_output(0);
for (int64_t i : mask) {
vectors.extend(i, array_);
}
}
CustomMF_DefaultOutput::CustomMF_DefaultOutput(StringRef name,
Span<MFDataType> input_types,
Span<MFDataType> output_types)
: output_amount_(output_types.size())
{
MFSignatureBuilder signature{name};
for (MFDataType data_type : input_types) {
signature.input("Input", data_type);
}
for (MFDataType data_type : output_types) {
signature.output("Output", data_type);
}
signature_ = signature.build();
this->set_signature(&signature_);
}
void CustomMF_DefaultOutput::call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const
{
for (int param_index : this->param_indices()) {
MFParamType param_type = this->param_type(param_index);
if (!param_type.is_output()) {
continue;
}
if (param_type.data_type().is_single()) {
GMutableSpan span = params.uninitialized_single_output(param_index);
const CPPType &type = span.type();
type.fill_construct_indices(type.default_value(), span.data(), mask);
}
}
}
CustomMF_GenericCopy::CustomMF_GenericCopy(StringRef name, MFDataType data_type)
{
MFSignatureBuilder signature{name};
signature.input("Input", data_type);
signature.output("Output", data_type);
signature_ = signature.build();
this->set_signature(&signature_);
}
void CustomMF_GenericCopy::call(IndexMask mask, MFParams params, MFContext UNUSED(context)) const
{
const MFDataType data_type = this->param_type(0).data_type();
switch (data_type.category()) {
case MFDataType::Single: {
const GVArray &inputs = params.readonly_single_input(0, "Input");
GMutableSpan outputs = params.uninitialized_single_output(1, "Output");
inputs.materialize_to_uninitialized(mask, outputs.data());
break;
}
case MFDataType::Vector: {
const GVVectorArray &inputs = params.readonly_vector_input(0, "Input");
GVectorArray &outputs = params.vector_output(1, "Output");
outputs.extend(mask, inputs);
break;
}
}
}
} // namespace blender::fn