Geometry Nodes: Character at Index node #120954

Open
Hans Goudey wants to merge 3 commits from HooglyBoogly/blender:geometry-nodes-character-at-index into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
5 changed files with 89 additions and 0 deletions

View File

@ -507,6 +507,7 @@ class NODE_MT_category_GEO_TEXT(Menu):
def draw(self, _context):
layout = self.layout
node_add_menu.add_node_type(layout, "FunctionNodeCharacterAtIndex")
node_add_menu.add_node_type(layout, "GeometryNodeStringJoin")
node_add_menu.add_node_type(layout, "FunctionNodeReplaceString")
node_add_menu.add_node_type(layout, "FunctionNodeSliceString")

View File

@ -1319,6 +1319,7 @@ void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, int layer_index
#define FN_NODE_SEPARATE_TRANSFORM 1236
#define FN_NODE_INVERT_MATRIX 1237
#define FN_NODE_TRANSPOSE_MATRIX 1238
#define FN_NODE_CHARACTER_AT_INDEX 1239
/** \} */

View File

@ -265,6 +265,7 @@ DefNode(TextureNode, TEX_NODE_PROC+TEX_DISTNOISE, 0, "TEX_DI
DefNode(FunctionNode, FN_NODE_ALIGN_EULER_TO_VECTOR, 0, "ALIGN_EULER_TO_VECTOR", AlignEulerToVector, "Align Euler to Vector", "")
DefNode(FunctionNode, FN_NODE_AXIS_ANGLE_TO_ROTATION, 0, "AXIS_ANGLE_TO_ROTATION", AxisAngleToRotation, "Axis Angle to Rotation", "")
DefNode(FunctionNode, FN_NODE_BOOLEAN_MATH, 0, "BOOLEAN_MATH", BooleanMath, "Boolean Math", "")
DefNode(FunctionNode, FN_NODE_CHARACTER_AT_INDEX, 0, "CHARACTER_AT_INDEX", CharacterAtIndex, "Character at Index", "Retrieve a specific Unicode character from a string")
DefNode(FunctionNode, FN_NODE_COMBINE_COLOR, 0, "COMBINE_COLOR", CombineColor, "Combine Color", "")
DefNode(FunctionNode, FN_NODE_QUATERNION_TO_ROTATION, 0, "QUATERNION_TO_ROTATION", QuaternionToRotation, "Quaternion to Rotation", "")
DefNode(FunctionNode, FN_NODE_COMBINE_TRANSFORM, 0, "COMBINE_TRANSFORM", CombineTransform, "Combine Transform", "")

View File

@ -21,6 +21,7 @@ set(SRC
nodes/node_fn_align_euler_to_vector.cc
nodes/node_fn_axis_angle_to_rotation.cc
nodes/node_fn_boolean_math.cc
nodes/node_fn_character_at_index.cc
nodes/node_fn_combine_color.cc
nodes/node_fn_combine_transform.cc
nodes/node_fn_compare.cc

View File

@ -0,0 +1,85 @@
/* SPDX-FileCopyrightText: 2024 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_string_utf8.h"
#include "node_function_util.hh"
namespace blender::nodes::node_fn_character_at_index_cc {
static void node_declare(NodeDeclarationBuilder &b)
{
b.is_function_node();
b.add_input<decl::String>("String");
b.add_input<decl::Int>("Index");
b.add_output<decl::String>("Character");
b.add_output<decl::Int>("Unicode");
}
class CharacterAtIndexFunction : public mf::MultiFunction {
public:
CharacterAtIndexFunction()
{
static mf::Signature signature_;
mf::SignatureBuilder builder{"Character at Index", signature_};
builder.single_input<std::string>("String");
builder.single_input<int>("Index");
builder.single_output<std::string>("Character");
builder.single_output<int>("Unicode");
this->set_signature(&signature_);
}
void call(const IndexMask &mask, mf::Params params, mf::Context /*context*/) const override
{
const VArray<std::string> strings = params.readonly_single_input<std::string>(0, "String");
const VArray<int> indices = params.readonly_single_input<int>(1, "Index");
MutableSpan<std::string> characters = params.uninitialized_single_output<std::string>(
2, "Character");
MutableSpan<int> unicodes = params.uninitialized_single_output<int>(3, "Unicode");
Vector<char32_t> char_codes;
mask.foreach_index([&](const int64_t i) {
const std::string string = strings[i];
const int index = indices[i];
size_t len_bytes;
const size_t len_chars = BLI_strlen_utf8_ex(string.c_str(), &len_bytes);
char_codes.resize(len_chars + 1);
BLI_str_utf8_as_utf32(char_codes.data(), string.c_str(), char_codes.size());
if (!char_codes.index_range().contains(index)) {
unicodes[i] = -1;
new (&characters[i]) std::string();
return;
}
char ch_utf8[BLI_UTF8_MAX + 1];
const size_t ch_utf8_len = BLI_str_utf8_from_unicode(
char_codes[index], ch_utf8, sizeof(ch_utf8) - 1);
unicodes[i] = char_codes[index];
new (&characters[i]) std::string(ch_utf8, ch_utf8_len);
});
}
};
static void node_build_multi_function(NodeMultiFunctionBuilder &builder)
{
static CharacterAtIndexFunction slice_fn;
builder.set_matching_fn(&slice_fn);
}
static void node_register()
{
static bNodeType ntype;
fn_node_type_base(
&ntype, FN_NODE_CHARACTER_AT_INDEX, "Character at Index", NODE_CLASS_CONVERTER);
ntype.declare = node_declare;
ntype.build_multi_function = node_build_multi_function;
nodeRegisterType(&ntype);
}
NOD_REGISTER_NODE(node_register)
} // namespace blender::nodes::node_fn_character_at_index_cc