38 auto &height =
b.add_input<
decl::Float>(
"Text Box Height")
42 .make_available([](
bNode &node) {
52 const bNode *node =
b.node_or_null();
53 if (node !=
nullptr) {
67 uiTemplateID(layout,
C,
ptr,
"font",
nullptr,
"FONT_OT_open",
"FONT_OT_unlink");
96 return {0.0f, 0.0f, 0.0f};
101 switch (pivot_mode) {
117 return {0.0f, 0.0f, 0.0f};
152 layout.
text =
params.extract_input<std::string>(
"String");
153 if (layout.
text.empty()) {
165 const float font_size = std::max(
params.extract_input<
float>(
"Size"), 0.0f);
166 const float char_spacing =
params.extract_input<
float>(
"Character Spacing");
167 const float word_spacing =
params.extract_input<
float>(
"Word Spacing");
168 const float line_spacing =
params.extract_input<
float>(
"Line Spacing");
169 const float textbox_w =
params.extract_input<
float>(
"Text Box Width");
172 params.extract_input<
float>(
"Text Box Height");
174 Curve cu = dna::shallow_zero_initialize();
178 cu.smallcaps_scale = 0.75f;
181 cu.spacemode = align_x;
182 cu.align_y = align_y;
183 cu.fsize = font_size;
184 cu.spacing = char_spacing;
185 cu.wordspace = word_spacing;
186 cu.linedist = line_spacing;
188 cu.overflow = overflow;
190 cu.tb->w = textbox_w;
191 cu.tb->h = textbox_h;
195 cu.len_char32 = len_chars;
200 memcpy(cu.str, layout.
text.c_str(), len_bytes + 1);
206 const char32_t *r_text =
nullptr;
207 float final_font_size = 0.0f;
233 layout.
text.c_str(), layout.
text.size(),
i + 1);
235 layout.
text = layout.
text.substr(0, offset);
240 if (
params.anonymous_attribute_output_is_required(
"Line")) {
242 for (
const int i : layout.
positions.index_range()) {
269 bool pivot_required =
params.anonymous_attribute_output_is_required(
"Pivot Point");
275 Curve cu = dna::shallow_zero_initialize();
282 const float2 char_offset = {0, 0};
284 cu, &cu.
nurb, layout.
char_codes[
i], &charinfo,
false, char_offset, 0,
i, 1);
286 if (curves_id ==
nullptr) {
287 if (pivot_required) {
302 if (pivot_required) {
310 const char32_t char_code[2] = {layout.
char_codes[
i], 0};
311 char inserted_utf8[8] = {0};
313 geometry_set.
name = std::string(inserted_utf8,
len);
330 for (const int i : range) {
331 handles[i] = char_handles.lookup(layout.char_codes[i]);
332 transforms[i] = math::from_location<float4x4>(
333 {layout.positions[i].x, layout.positions[i].y, 0});
344 if (std::optional<std::string> line_id =
params.get_output_anonymous_attribute_id_if_needed(
348 *line_id, AttrDomain::Instance);
353 if (std::optional<std::string> pivot_id =
params.get_output_anonymous_attribute_id_if_needed(
371 params.set_default_remaining_outputs();
378 params.set_output(
"Remainder", std::move(layout->truncated_text));
381 if (layout->positions.is_empty()) {
383 params.set_default_remaining_outputs();
388 std::unique_ptr<bke::Instances> instances = std::make_unique<bke::Instances>();
401 ntype.
ui_name =
"String to Curves";
403 "Generate a paragraph of text with a specific font, using a curve instance to store each "
void BKE_nurbList_free(ListBase *lb)
Low-level operations for curves.
#define NODE_STORAGE_FUNCS(StorageT)
#define NODE_CLASS_GEOMETRY
#define GEO_NODE_STRING_TO_CURVES
VFont * BKE_vfont_builtin_ensure()
void BKE_vfont_char_build(const Curve &cu, ListBase *nubase, unsigned int charcode, const CharInfo *info, bool is_smallcaps, const blender::float2 &offset, float rotate, int charidx, float fsize)
bool BKE_vfont_to_curve_ex(Object *ob, const Curve &cu, eEditFontMode mode, ListBase *r_nubase, const char32_t **r_text, int *r_text_len, bool *r_text_free, CharTrans **r_chartransdata, float *r_font_size_eval)
int BLI_str_utf8_offset_from_index(const char *str, size_t str_len, int index_target) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
size_t size_t BLI_str_utf32_as_utf8(char *__restrict dst, const char32_t *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t BLI_str_utf8_as_utf32(char32_t *__restrict dst_w, const char *__restrict src_c, size_t dst_w_maxncpy) ATTR_NONNULL(1
size_t BLI_strlen_utf8_ex(const char *strc, size_t *r_len_bytes) ATTR_NONNULL(1
#define BLT_I18NCONTEXT_ID_TEXT
GeometryNodeStringToCurvesAlignXMode
@ GEO_NODE_STRING_TO_CURVES_ALIGN_X_LEFT
GeometryNodeStringToCurvesPivotMode
@ GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_MIDPOINT
@ GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_RIGHT
@ GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_CENTER
@ GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_LEFT
@ GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_CENTER
@ GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_TOP_RIGHT
@ GEO_NODE_STRING_TO_CURVES_PIVOT_MODE_BOTTOM_LEFT
GeometryNodeStringToCurvesAlignYMode
@ GEO_NODE_STRING_TO_CURVES_ALIGN_Y_TOP_BASELINE
GeometryNodeStringToCurvesOverflowMode
@ GEO_NODE_STRING_TO_CURVES_MODE_TRUNCATE
@ GEO_NODE_STRING_TO_CURVES_MODE_SCALE_TO_FIT
@ GEO_NODE_STRING_TO_CURVES_MODE_OVERFLOW
#define NOD_REGISTER_NODE(REGISTER_FUNC)
void uiTemplateID(uiLayout *layout, const bContext *C, PointerRNA *ptr, blender::StringRefNull propname, const char *newop, const char *openop, const char *unlinkop, int filter=UI_TEMPLATE_ID_FILTER_ALL, bool live_icon=false, std::optional< blender::StringRef > text=std::nullopt)
BMesh const char void * data
void reinitialize(const int64_t new_size)
IndexRange index_range() const
void resize(const int64_t new_size)
Span< float3 > positions() const
void transform(const float4x4 &matrix)
MutableSpan< int > reference_handles_for_write()
int add_reference(const InstanceReference &reference)
void resize(int capacity)
bke::MutableAttributeAccessor attributes_for_write()
MutableSpan< float4x4 > transforms_for_write()
GSpanAttributeWriter lookup_or_add_for_write_only_span(StringRef attribute_id, AttrDomain domain, AttrType data_type)
void make_available(bNode &node) const
void * MEM_calloc_arrayN(size_t len, size_t size, const char *str)
void * MEM_callocN(size_t len, const char *str)
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
void MEM_freeN(void *vmemh)
Curves * curve_legacy_to_curves(const Curve &curve_legacy)
void node_type_size(bNodeType &ntype, int width, int minwidth, int maxwidth)
void node_register_type(bNodeType &ntype)
void node_type_storage(bNodeType &ntype, std::optional< StringRefNull > storagename, void(*freefunc)(bNode *node), void(*copyfunc)(bNodeTree *dest_ntree, bNode *dest_node, const bNode *src_node))
std::optional< Bounds< T > > min_max(const std::optional< Bounds< T > > &a, const T &b)
void debug_randomize_curve_order(bke::CurvesGeometry *curves)
MatT from_scale(const VecBase< typename MatT::base_type, ScaleDim > &scale)
static Map< int, int > create_curve_instances(GeoNodeExecParams ¶ms, TextLayout &layout, bke::Instances &instances)
static void add_instances_from_handles(bke::Instances &instances, const Map< int, int > &char_handles, const TextLayout &layout)
static void create_attributes(GeoNodeExecParams ¶ms, const TextLayout &layout, bke::Instances &instances)
static void node_init(bNodeTree *, bNode *node)
static float3 get_pivot_point(GeoNodeExecParams ¶ms, bke::CurvesGeometry &curves)
static void node_layout(uiLayout *layout, bContext *C, PointerRNA *ptr)
static std::optional< TextLayout > get_text_layout(GeoNodeExecParams ¶ms)
static void node_geo_exec(GeoNodeExecParams params)
static void node_declare(NodeDeclarationBuilder &b)
static void node_register()
void parallel_for(const IndexRange range, const int64_t grain_size, const Function &function, const TaskSizeHints &size_hints=detail::TaskSizeHints_Static(1))
MatBase< float, 4, 4 > float4x4
VecBase< float, 2 > float2
VecBase< float, 3 > float3
void geo_node_type_base(blender::bke::bNodeType *ntype, std::string idname, const std::optional< int16_t > legacy_type)
void node_free_standard_storage(bNode *node)
void node_copy_standard_storage(bNodeTree *, bNode *dest_node, const bNode *src_node)
static void text_free(SpaceLink *sl)
MutableVArraySpan< T > span
std::string ui_description
void(* initfunc)(bNodeTree *ntree, bNode *node)
NodeGeometryExecFunction geometry_node_execute
const char * enum_name_legacy
void(* draw_buttons)(uiLayout *, bContext *C, PointerRNA *ptr)
NodeDeclareFunction declare
static GeometrySet from_instances(Instances *instances, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
static GeometrySet from_curves(Curves *curves, GeometryOwnershipType ownership=GeometryOwnershipType::Owned)
Vector< char32_t > char_codes
std::string truncated_text
Array< int > line_numbers
Map< int, float3 > pivot_points
Vector< float2 > positions
void use_property_decorate_set(bool is_sep)
void use_property_split_set(bool value)
void prop(PointerRNA *ptr, PropertyRNA *prop, int index, int value, eUI_Item_Flag flag, std::optional< blender::StringRef > name_opt, int icon, std::optional< blender::StringRef > placeholder=std::nullopt)