Page MenuHome
Paste P2423

String to curve cleanup
ActivePublic

Authored by Hans Goudey (HooglyBoogly) on Sep 23 2021, 6:14 AM.
diff --git a/source/blender/blenlib/BLI_float4x4.hh b/source/blender/blenlib/BLI_float4x4.hh
index 347ce2caa34..14e61d53845 100644
--- a/source/blender/blenlib/BLI_float4x4.hh
+++ b/source/blender/blenlib/BLI_float4x4.hh
@@ -45,6 +45,13 @@ struct float4x4 {
return mat;
}
+ static float4x4 from_location(const float3 location)
+ {
+ float4x4 mat = float4x4::identity();
+ copy_v3_v3(mat.values[3], location);
+ return mat;
+ }
+
static float4x4 from_normalized_axis_data(const float3 location,
const float3 forward,
const float3 up)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_to_curve.cc b/source/blender/nodes/geometry/nodes/node_geo_string_to_curve.cc
index 0f08fd4cc3a..dd6276d7dd8 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_string_to_curve.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_string_to_curve.cc
@@ -98,8 +98,6 @@ static void string_replace(std::string &haystack,
const std::string &needle,
const std::string &other)
{
- if (haystack.empty() || needle.empty())
- return;
size_t i = 0, index;
while ((index = haystack.find(needle, i)) != std::string::npos) {
haystack.replace(index, needle.length(), other);
@@ -109,27 +107,32 @@ static void string_replace(std::string &haystack,
struct TextLayout {
/* Position of each character. */
- Vector<float3> positions;
+ Vector<float2> positions;
- /* Text could be truncated if in 'Truncate'-mode. */
+ /* The text that fit into the text box, with newline character sequences replaced. */
std::string text;
+ /* The text that didn't fit into the text box in 'Truncate' mode. May be empty. */
+ std::string truncated_text;
+
/* Font size could be modified if in 'Scale to fit'-mode. */
- float fontsize;
+ float final_font_size;
};
-static std::unique_ptr<TextLayout> get_text_layout(GeoNodeExecParams &params)
+static TextLayout get_text_layout(GeoNodeExecParams &params)
{
- std::unique_ptr<TextLayout> layout = std::make_unique<TextLayout>();
- layout->text = params.extract_input<std::string>("String");
- layout->fontsize = params.extract_input<float>("Size");
-
- if (layout->text.empty() || layout->fontsize <= 0.0f) {
- return layout;
+ TextLayout layout;
+ layout.text = params.extract_input<std::string>("String");
+ if (layout.text.empty()) {
+ return {};
}
/* Convert string input '\n' into newline characters. */
- string_replace(layout->text, "\\n", "\n");
+ string_replace(layout.text, "\\n", "\n");
+
+ if (layout.text.empty()) {
+ return {};
+ }
const NodeGeometryStringToCurve &storage =
*(const NodeGeometryStringToCurve *)params.node().storage;
@@ -140,6 +143,7 @@ static std::unique_ptr<TextLayout> get_text_layout(GeoNodeExecParams &params)
const GeometryNodeStringToCurveAlignYMode align_y = (GeometryNodeStringToCurveAlignYMode)
storage.align_y;
+ const float font_size = std::max(params.extract_input<float>("Size"), 0.0f);
const float char_spacing = params.extract_input<float>("Character Spacing");
const float word_spacing = params.extract_input<float>("Word Spacing");
const float line_spacing = params.extract_input<float>("Line Spacing");
@@ -156,7 +160,7 @@ static std::unique_ptr<TextLayout> get_text_layout(GeoNodeExecParams &params)
/* Set values from inputs */
cu.spacemode = align_x;
cu.align_y = align_y;
- cu.fsize = layout->fontsize;
+ cu.fsize = font_size;
cu.spacing = char_spacing;
cu.wordspace = word_spacing;
cu.linedist = line_spacing;
@@ -167,13 +171,13 @@ static std::unique_ptr<TextLayout> get_text_layout(GeoNodeExecParams &params)
cu.tb->h = textbox_h;
cu.totbox = 1;
size_t len_bytes;
- size_t len_chars = BLI_strlen_utf8_ex(layout->text.c_str(), &len_bytes);
+ size_t len_chars = BLI_strlen_utf8_ex(layout.text.c_str(), &len_bytes);
cu.len_char32 = len_chars;
cu.len = len_bytes;
cu.pos = len_chars;
cu.str = (char *)MEM_mallocN(len_bytes + sizeof(char32_t), "str");
cu.strinfo = (CharInfo *)MEM_callocN((len_chars + 4) * sizeof(CharInfo), "strinfo");
- BLI_strncpy(cu.str, layout->text.c_str(), len_bytes + 1);
+ BLI_strncpy(cu.str, layout.text.c_str(), len_bytes + 1);
struct CharTrans *chartransdata = nullptr;
int text_len;
@@ -187,30 +191,25 @@ static std::unique_ptr<TextLayout> get_text_layout(GeoNodeExecParams &params)
MEM_freeN((void *)r_text);
}
- struct CharInfo *info = cu.strinfo;
- layout->fontsize = cu.fsize_realtime;
- std::string truncated;
- layout->positions.reserve(text_len);
+ Span<CharInfo> info{cu.strinfo, text_len};
+ layout.final_font_size = cu.fsize_realtime;
+ layout.positions.reserve(text_len);
for (const int i : IndexRange(text_len)) {
- if (layout->text[i] == '\n') {
+ if (layout.text[i] == '\n') {
continue;
}
CharTrans &ct = chartransdata[i];
- layout->positions.append({ct.xof * layout->fontsize, ct.yof * layout->fontsize, 0});
+ layout.positions.append(float2(ct.xof, ct.yof) * layout.final_font_size);
if ((info[i].flag & CU_CHINFO_OVERFLOW) && (cu.overflow == CU_OVERFLOW_TRUNCATE)) {
- truncated = layout->text.substr(BLI_str_utf8_offset_from_index(layout->text.c_str(), i + 1));
- layout->text = layout->text.substr(
- 0, BLI_str_utf8_offset_from_index(layout->text.c_str(), i + 1));
+ const int offset = BLI_str_utf8_offset_from_index(layout.text.c_str(), i + 1);
+ layout.truncated_text = layout.text.substr(offset);
+ layout.text = layout.text.substr(0, offset);
break;
}
}
- if (overflow == GEO_NODE_STRING_TO_CURVE_OVERFLOW_TRUNCATE) {
- params.set_output("Truncated String", std::move(truncated));
- }
-
MEM_SAFE_FREE(chartransdata);
MEM_SAFE_FREE(cu.str);
MEM_SAFE_FREE(cu.strinfo);
@@ -242,8 +241,8 @@ static Map<int, int> create_curve_instances(GeoNodeExecParams &params,
BKE_vfont_build_char(&cu, &cu.nurb, charcodes[i], &charinfo, 0, 0, 0, i, 1);
std::unique_ptr<CurveEval> curve_eval = curve_eval_from_dna_curve(cu);
BKE_nurbList_free(&cu.nurb);
- const float4x4 size_matrix = float4x4::from_loc_eul_scale(
- float3(0), float3(0), float3(fontsize));
+ float4x4 size_matrix = float4x4::identity();
+ size_matrix.apply_scale(fontsize);
curve_eval->transform(size_matrix);
GeometrySet geometry_set_curve = GeometrySet::create_with_curve(curve_eval.release());
@@ -255,7 +254,7 @@ static Map<int, int> create_curve_instances(GeoNodeExecParams &params,
static void add_instances_from_handles(InstancesComponent &instances,
const Map<int, int> &char_handles,
const std::u32string &charcodes,
- const Span<float3> &positions)
+ const Span<float2> positions)
{
instances.resize(positions.size());
MutableSpan<int> handles = instances.instance_reference_handles();
@@ -265,7 +264,7 @@ static void add_instances_from_handles(InstancesComponent &instances,
threading::parallel_for(IndexRange(positions.size()), 256, [&](IndexRange range) {
for (const int i : range) {
handles[i] = char_handles.lookup(charcodes[i]);
- transforms[i] = float4x4::from_loc_eul_scale(positions[i], float3(0), float3(1));
+ transforms[i] = float4x4::from_location({positions[i].x, positions[i].y, 0});
instance_ids[i] = i;
}
});
@@ -273,23 +272,29 @@ static void add_instances_from_handles(InstancesComponent &instances,
static void geo_node_string_to_curve_exec(GeoNodeExecParams params)
{
- std::unique_ptr<TextLayout> layout = get_text_layout(params);
+ TextLayout layout = get_text_layout(params);
- if (layout->positions.size() == 0) {
+ const NodeGeometryStringToCurve &storage =
+ *(const NodeGeometryStringToCurve *)params.node().storage;
+ if (storage.overflow == GEO_NODE_STRING_TO_CURVE_OVERFLOW_TRUNCATE) {
+ params.set_output("Truncated String", std::move(layout.truncated_text));
+ }
+
+ if (layout.positions.size() == 0) {
params.set_output("Curve", GeometrySet());
return;
}
/* Convert UTF-8 encoded string to UTF-32. */
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
- std::u32string utf32_text = converter.from_bytes(layout->text);
+ std::u32string utf32_text = converter.from_bytes(layout.text);
/* Create and add instances. */
GeometrySet geometry_set_out;
InstancesComponent &instances = geometry_set_out.get_component_for_write<InstancesComponent>();
Map<int, int> char_handles = create_curve_instances(
- params, layout->fontsize, utf32_text, instances);
- add_instances_from_handles(instances, char_handles, utf32_text, layout->positions);
+ params, layout.final_font_size, utf32_text, instances);
+ add_instances_from_handles(instances, char_handles, utf32_text, layout.positions);
params.set_output("Curve", std::move(geometry_set_out));
}
@@ -301,13 +306,13 @@ void register_node_type_geo_string_to_curve()
static bNodeType ntype;
geo_node_type_base(&ntype, GEO_NODE_STRING_TO_CURVE, "String to Curve", NODE_CLASS_GEOMETRY, 0);
- node_type_size(&ntype, 190, 120, 700);
+ ntype.declare = blender::nodes::geo_node_string_to_curve_declare;
+ ntype.geometry_node_execute = blender::nodes::geo_node_string_to_curve_exec;
node_type_init(&ntype, blender::nodes::geo_node_string_to_curve_init);
node_type_update(&ntype, blender::nodes::geo_node_string_to_curve_update);
+ node_type_size(&ntype, 190, 120, 700);
node_type_storage(
&ntype, "NodeGeometryStringToCurve", node_free_standard_storage, node_copy_standard_storage);
- ntype.declare = blender::nodes::geo_node_string_to_curve_declare;
- ntype.geometry_node_execute = blender::nodes::geo_node_string_to_curve_exec;
ntype.draw_buttons = blender::nodes::geo_node_string_to_curve_layout;
nodeRegisterType(&ntype);
}

Event Timeline

Hans Goudey (HooglyBoogly) changed the title of this paste from Command-Line Input to String to curve cleanup.Sep 23 2021, 6:30 AM
Hans Goudey (HooglyBoogly) edited the content of this paste. (Show Details)