diff --git a/__init__.py b/__init__.py index 2a71c8f..ef361dc 100644 --- a/__init__.py +++ b/__init__.py @@ -242,6 +242,18 @@ class ABC3D_text_properties(bpy.types.PropertyGroup): name="Ignore Curve Orientation", default=False, ) + loop_in: bpy.props.BoolProperty( + update=update_callback, + name="Loop In", + description="Loop letter on curve if negative offset would place it in front of it.", + default=False, + ) + loop_out: bpy.props.BoolProperty( + update=update_callback, + name="Loop Out", + description="Loop letter on curve if a large offset would place it behind it.", + default=False, + ) distribution_type: bpy.props.StringProperty() glyphs: bpy.props.CollectionProperty(type=ABC3D_glyph_properties) @@ -724,7 +736,7 @@ class ABC3D_PT_TextPropertiesPanel(bpy.types.Panel): if f"{utils.prefix()}_linked_textobject" in a_o: text_index = a_o[f"{utils.prefix()}_linked_textobject"] return bpy.context.scene.abc3d_data.available_texts[text_index] - elif f"{utils.prefix()}_linked_textobject" in a_o.parent: + elif a_o.parent is not None and f"{utils.prefix()}_linked_textobject" in a_o.parent: text_index = a_o.parent[f"{utils.prefix()}_linked_textobject"] return bpy.context.scene.abc3d_data.available_texts[text_index] else: @@ -809,6 +821,8 @@ class ABC3D_PT_TextPropertiesPanel(bpy.types.Panel): layout.row().prop(props, "offset") layout.row().prop(props, "compensate_curvature") layout.row().prop(props, "ignore_orientation") + layout.row().prop(props, "loop_in") + layout.row().prop(props, "loop_out") layout.column().prop(props, "translation") layout.column().prop(props, "orientation") diff --git a/butils.py b/butils.py index 94ed804..eec7106 100644 --- a/butils.py +++ b/butils.py @@ -820,11 +820,12 @@ def update_matrices(obj): def is_or_has_parent(o, parent, if_is_parent=True, max_depth=10): if o == parent and if_is_parent: return True + oo = o for i in range(0, max_depth): - o = o.parent - if o == parent: + oo = oo.parent + if oo == parent: return True - if o is None: + if oo is None: return False return False @@ -1013,11 +1014,21 @@ def set_text_on_curve(text_properties, reset_timeout_s=0.1, reset_depsgraph_n=4) glyph_pre_advance, glyph_post_advance = get_glyph_prepost_advances(glyph) advance += glyph_pre_advance * scalor + # check if we want to loop + applied_advance = advance + if text_properties.loop_in: + if applied_advance < 0: + applied_advance %= curve_length + + if text_properties.loop_out: + if applied_advance > curve_length: + applied_advance %= curve_length + if distribution_type == "FOLLOW_PATH": outer_node.constraints.new(type="FOLLOW_PATH") outer_node.constraints["Follow Path"].target = mom outer_node.constraints["Follow Path"].use_fixed_location = True - outer_node.constraints["Follow Path"].offset_factor = advance / curve_length + outer_node.constraints["Follow Path"].offset_factor = applied_advance / curve_length outer_node.constraints["Follow Path"].use_curve_follow = True outer_node.constraints["Follow Path"].forward_axis = "FORWARD_X" outer_node.constraints["Follow Path"].up_axis = "UP_Y" @@ -1033,7 +1044,7 @@ def set_text_on_curve(text_properties, reset_timeout_s=0.1, reset_depsgraph_n=4) previous_inner_node_rotation_mode = inner_node.rotation_mode # get info from bezier - location, tangent, spline_index = calc_point_on_bezier_curve(mom, advance, True, True) + location, tangent, spline_index = calc_point_on_bezier_curve(mom, applied_advance, True, True) # check if we are on a new line if spline_index != previous_spline_index: @@ -1073,7 +1084,6 @@ def set_text_on_curve(text_properties, reset_timeout_s=0.1, reset_depsgraph_n=4) ############### PREPARE FOR THE NEXT - print(f"{glyph_id}: {glyph_properties.letter_spacing=}") glyph_advance = ( glyph_post_advance * scalor + text_properties.letter_spacing + glyph_properties.letter_spacing )