[Bf-blender-cvs] [0e86c60c28b] master: Geometry Nodes: String to Curves Line/Pivot Point

Erik noreply at git.blender.org
Wed Jan 26 22:17:45 CET 2022


Commit: 0e86c60c28b62f4965aab94716e9545198d5f626
Author: Erik
Date:   Wed Jan 26 22:11:23 2022 +0100
Branches: master
https://developer.blender.org/rB0e86c60c28b62f4965aab94716e9545198d5f626

Geometry Nodes: String to Curves Line/Pivot Point

Adds two new attribute outputs:
"Line" outputs the line number of the character.
"Pivot Point" outputs the selected pivot point position per char.
Some refactoring of the text layout code.

Differential Revision: https://developer.blender.org/D13694

===================================================================

M	source/blender/makesdna/DNA_node_types.h
M	source/blender/makesrna/intern/rna_nodetree.c
M	source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc

===================================================================

diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h
index 099e41d7ff0..2bfd2e71eb7 100644
--- a/source/blender/makesdna/DNA_node_types.h
+++ b/source/blender/makesdna/DNA_node_types.h
@@ -1616,7 +1616,8 @@ typedef struct NodeGeometryStringToCurves {
   uint8_t align_x;
   /* GeometryNodeStringToCurvesAlignYMode */
   uint8_t align_y;
-  char _pad[1];
+  /* GeometryNodeStringToCurvesPivotMode */
+  uint8_t pivot_mode;
 } NodeGeometryStringToCurves;
 
 typedef struct NodeGeometryDeleteGeometry {
@@ -2344,6 +2345,16 @@ typedef enum GeometryNodeStringToCurvesAlignYMode {
   GEO_NODE_STRING_TO_CURVES_ALIGN_Y_BOTTOM = 4,
 } GeometryNodeStringToCurvesAlignYMode;
 
+typedef enum GeometryNodeStringToCurvesPivotMode {
+  GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_MIDPOINT = 0,
+  GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_LEFT = 1,
+  GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_CENTER = 2,
+  GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_RIGHT = 3,
+  GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_LEFT = 4,
+  GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_CENTER = 5,
+  GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_RIGHT = 6,
+} GeometryNodeStringToCurvesPivotMode;
+
 typedef enum GeometryNodeDeleteGeometryMode {
   GEO_NODE_DELETE_GEOMETRY_MODE_ALL = 0,
   GEO_NODE_DELETE_GEOMETRY_MODE_EDGE_FACE = 1,
diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c
index 536b2f7aa6e..38a447a9657 100644
--- a/source/blender/makesrna/intern/rna_nodetree.c
+++ b/source/blender/makesrna/intern/rna_nodetree.c
@@ -11378,6 +11378,33 @@ static void def_geo_string_to_curves(StructRNA *srna)
       {0, NULL, 0, NULL, NULL},
   };
 
+  static const EnumPropertyItem rna_node_geometry_string_to_curves_pivot_mode[] = {
+      {GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_MIDPOINT, "MIDPOINT", 0, "Midpoint", "Midpoint"},
+      {GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_LEFT, "TOP_LEFT", 0, "Top Left", "Top Left"},
+      {GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_CENTER,
+       "TOP_CENTER",
+       0,
+       "Top Center",
+       "Top Center"},
+      {GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_RIGHT, "TOP_RIGHT", 0, "Top Right", "Top Right"},
+      {GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_LEFT,
+       "BOTTOM_LEFT",
+       0,
+       "Bottom Left",
+       "Bottom Left"},
+      {GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_CENTER,
+       "BOTTOM_CENTER",
+       0,
+       "Bottom Center",
+       "Bottom Center"},
+      {GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_RIGHT,
+       "BOTTOM_RIGHT",
+       0,
+       "Bottom Right",
+       "Bottom Right"},
+      {0, NULL, 0, NULL, NULL},
+  };
+
   PropertyRNA *prop;
 
   prop = RNA_def_property(srna, "font", PROP_POINTER, PROP_NONE);
@@ -11410,6 +11437,13 @@ static void def_geo_string_to_curves(StructRNA *srna)
   RNA_def_property_enum_default(prop, GEO_NODE_STRING_TO_CURVES_ALIGN_Y_TOP_BASELINE);
   RNA_def_property_ui_text(prop, "Align Y", "");
   RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
+
+  prop = RNA_def_property(srna, "pivot_mode", PROP_ENUM, PROP_NONE);
+  RNA_def_property_enum_sdna(prop, NULL, "pivot_mode");
+  RNA_def_property_enum_items(prop, rna_node_geometry_string_to_curves_pivot_mode);
+  RNA_def_property_enum_default(prop, GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_LEFT);
+  RNA_def_property_ui_text(prop, "Pivot Point", "Pivot point position relative to character");
+  RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
 }
 
 static void def_geo_separate_geometry(StructRNA *srna)
diff --git a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
index 10c0d61ccb6..c4bd6c6157f 100644
--- a/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
+++ b/source/blender/nodes/geometry/nodes/node_geo_string_to_curves.cc
@@ -65,6 +65,8 @@ static void node_declare(NodeDeclarationBuilder &b)
   b.add_output<decl::String>(N_("Remainder")).make_available([](bNode &node) {
     node_storage(node).overflow = GEO_NODE_STRING_TO_CURVES_MODE_TRUNCATE;
   });
+  b.add_output<decl::Int>(N_("Line")).field_source();
+  b.add_output<decl::Vector>(N_("Pivot Point")).field_source();
 }
 
 static void node_layout(uiLayout *layout, struct bContext *C, PointerRNA *ptr)
@@ -84,6 +86,7 @@ static void node_layout(uiLayout *layout, struct bContext *C, PointerRNA *ptr)
   uiItemR(layout, ptr, "overflow", 0, "", ICON_NONE);
   uiItemR(layout, ptr, "align_x", 0, "", ICON_NONE);
   uiItemR(layout, ptr, "align_y", 0, "", ICON_NONE);
+  uiItemR(layout, ptr, "pivot_mode", 0, IFACE_("Pivot Point"), ICON_NONE);
 }
 
 static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
@@ -93,6 +96,7 @@ static void node_init(bNodeTree *UNUSED(ntree), bNode *node)
   data->overflow = GEO_NODE_STRING_TO_CURVES_MODE_OVERFLOW;
   data->align_x = GEO_NODE_STRING_TO_CURVES_ALIGN_X_LEFT;
   data->align_y = GEO_NODE_STRING_TO_CURVES_ALIGN_Y_TOP_BASELINE;
+  data->pivot_mode = GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_LEFT;
   node->storage = data;
   node->id = (ID *)BKE_vfont_builtin_get();
 }
@@ -115,10 +119,51 @@ static void node_update(bNodeTree *ntree, bNode *node)
                                                                         N_("Text Box Width"));
 }
 
+static float3 get_pivot_point(GeoNodeExecParams &params, CurveEval &curve)
+{
+  const NodeGeometryStringToCurves &storage = node_storage(params.node());
+  const GeometryNodeStringToCurvesPivotMode pivot_mode = (GeometryNodeStringToCurvesPivotMode)
+                                                             storage.pivot_mode;
+
+  float3 min(FLT_MAX), max(FLT_MIN);
+
+  /* Check if curve is empty. */
+  if (!curve.bounds_min_max(min, max, false)) {
+    return {0.0f, 0.0f, 0.0f};
+  }
+
+  switch (pivot_mode) {
+    case GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_MIDPOINT:
+      return (min + max) / 2;
+    case GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_LEFT:
+      return float3(min.x, min.y, 0.0f);
+    case GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_CENTER:
+      return float3((min.x + max.x) / 2, min.y, 0.0f);
+    case GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_RIGHT:
+      return float3(max.x, min.y, 0.0f);
+    case GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_LEFT:
+      return float3(min.x, max.y, 0.0f);
+    case GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_CENTER:
+      return float3((min.x + max.x) / 2, max.y, 0.0f);
+    case GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_RIGHT:
+      return float3(max.x, max.y, 0.0f);
+  }
+  return {0.0f, 0.0f, 0.0f};
+}
+
 struct TextLayout {
   /* Position of each character. */
   Vector<float2> positions;
 
+  /* Line number of each character. */
+  Array<int> line_numbers;
+
+  /* Map of Pivot point for each character code. */
+  Map<int, float3> pivot_points;
+
+  /* UTF-32 Character codes. */
+  Vector<char32_t> char_codes;
+
   /* The text that fit into the text box, with newline character sequences replaced. */
   std::string text;
 
@@ -212,6 +257,20 @@ static TextLayout get_text_layout(GeoNodeExecParams &params)
     }
   }
 
+  if (params.output_is_required("Line")) {
+    layout.line_numbers.reinitialize(layout.positions.size());
+    for (const int i : layout.positions.index_range()) {
+      CharTrans &ct = chartransdata[i];
+      layout.line_numbers[i] = ct.linenr;
+    }
+  }
+
+  /* Convert UTF-8 encoded string to UTF-32. */
+  len_chars = BLI_strlen_utf8_ex(layout.text.c_str(), &len_bytes);
+  layout.char_codes.resize(len_chars + 1);
+  BLI_str_utf8_as_utf32(layout.char_codes.data(), layout.text.c_str(), layout.char_codes.size());
+  layout.char_codes.remove_last();
+
   MEM_SAFE_FREE(chartransdata);
   MEM_SAFE_FREE(cu.str);
   MEM_SAFE_FREE(cu.strinfo);
@@ -222,15 +281,15 @@ static TextLayout get_text_layout(GeoNodeExecParams &params)
 
 /* Returns a mapping of UTF-32 character code to instance handle. */
 static Map<int, int> create_curve_instances(GeoNodeExecParams &params,
-                                            const float fontsize,
-                                            const Span<char32_t> charcodes,
+                                            TextLayout &layout,
                                             InstancesComponent &instance_component)
 {
   VFont *vfont = (VFont *)params.node().id;
   Map<int, int> handles;
+  bool pivot_required = params.output_is_required("Pivot Point");
 
-  for (int i : charcodes.index_range()) {
-    if (handles.contains(charcodes[i])) {
+  for (int i : layout.char_codes.index_range()) {
+    if (handles.contains(layout.char_codes[i])) {
       continue;
     }
     Curve cu = {{nullptr}};
@@ -240,36 +299,75 @@ static Map<int, int> create_curve_instances(GeoNodeExecParams &params,
     CharInfo charinfo = {0};
     charinfo.mat_nr = 1;
 
-    BKE_vfont_build_char(&cu, &cu.nurb, charcodes[i], &charinfo, 0, 0, 0, i, 1);
+    BKE_vfont_build_char(&cu, &cu.nurb, layout.char_codes[i], &charinfo, 0, 0, 0, i, 1);
     std::unique_ptr<CurveEval> curve_eval = curve_eval_from_dna_curve(cu);
     BKE_nurbList_free(&cu.nurb);
+
     float4x4 size_matrix = float4x4::identity();
-    size_matrix.apply_scale(fontsize);
+    size_matrix.apply_scale(layout.final_font_size);
     curve_eval->transform(size_matrix);
 
+    if (pivot_required) {
+      float3 pivot_point = get_pivot_point(params, *curve_eval);
+      layout.pivot_points.add_new(layout.char_codes[i], pivot_point);
+    }
+
     GeometrySet geometry_set_curve = GeometrySet::create_with_curve(curve_eval.release());
-    handles.add_new(charcodes[i], instance_component.add_reference(std::move(geometry_set_curve)));
+    handles.add_new(layout.char_codes[i],
+                    instance_component.add_reference(std::move(geometry_set_curve)));
   }
   return handles;
 }
 
 static void add_instances_from_handles(InstancesComponent &instances,
                                        const Map<int, int> &char_handles,
-                                       const Span<char32_t> charcodes,
-                                       const Span<float2> positions)
+                                       const TextLayout &layout)
 {
-  instances.re

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list