diff --git a/__init__.py b/__init__.py index fbcc235..b98d237 100644 --- a/__init__.py +++ b/__init__.py @@ -479,6 +479,7 @@ class ABC3D_PT_TextManagement(bpy.types.Panel): layout.label(text="Text Objects") layout.template_list("ABC3D_UL_texts", "", abc3d_data, "available_texts", abc3d_data, "active_text_index") + layout.row().operator(f"{__name__}.remove_text", text="Remove Textobject") class ABC3D_PT_FontCreation(bpy.types.Panel): bl_label = "Font Creation" @@ -754,6 +755,55 @@ class ABC3D_OT_TemporaryHelper(bpy.types.Operator): return {'FINISHED'} +class ABC3D_OT_RemoveText(bpy.types.Operator): + """Remove Text 3D""" + bl_idname = f"{__name__}.remove_text" + bl_label = "Remove Text" + bl_options = {'REGISTER', 'UNDO'} + + remove_objects: bpy.props.BoolProperty( + name="Remove Objects", + description="Remove both ABC3D text functionality and the objects/meshes", + default=True) + + def invoke(self, context, event): + wm = context.window_manager + return wm.invoke_props_dialog(self) + + def execute(self, context): + abc3d_data = context.scene.abc3d_data + if abc3d_data.active_text_index < 0: + butils.ShowMessageBox( + title="No text selected", + message=("Please select a text."), + icon='GHOST_ENABLED') + return {'CANCELLED'} + + i = abc3d_data.active_text_index + if type(abc3d_data.available_texts[i].text_object) != type(None): + mom = abc3d_data.available_texts[i].text_object + def delif(o, p): + if p in o: + del o[p] + delif(mom,f"{utils.prefix()}_linked_textobject") + delif(mom,f"{utils.prefix()}_font_name") + delif(mom,f"{utils.prefix()}_face_name") + delif(mom,f"{utils.prefix()}_font_size") + delif(mom,f"{utils.prefix()}_letter_spacing") + delif(mom,f"{utils.prefix()}_orientation") + delif(mom,f"{utils.prefix()}_translation") + if self.remove_objects: + remove_list = [] + for g in abc3d_data.available_texts[i].glyphs: + if type(g) != type(None): + remove_list.append(g.glyph_object) + butils.simply_delete_objects(remove_list) + + abc3d_data.available_texts.remove(i) + + return {'FINISHED'} + + class ABC3D_OT_PlaceText(bpy.types.Operator): """Place Text 3D on active object""" bl_idname = f"{__name__}.placetext" @@ -1261,6 +1311,7 @@ classes = ( ABC3D_OT_AlignMetricsToActiveObject, ABC3D_OT_AlignMetrics, ABC3D_OT_TemporaryHelper, + ABC3D_OT_RemoveText, ABC3D_OT_PlaceText, ABC3D_OT_InstallFont, ABC3D_OT_ToggleABC3DCollection, diff --git a/butils.py b/butils.py index 3d66e91..b93a5ea 100644 --- a/butils.py +++ b/butils.py @@ -633,6 +633,11 @@ def prepare_text(font_name, face_name, text): load_font_from_filepath(filepath, loadable, font_name, face_name) return True +def is_bezier(curve): + if len(curve.data.splines) < 1: + return False + return curve.data.splines[0].type == 'BEZIER' + def set_text_on_curve(text_properties, recursive=True): # starttime = time.perf_counter_ns() mom = text_properties.text_object @@ -660,33 +665,7 @@ def set_text_on_curve(text_properties, recursive=True): # if we regenerate.... delete objects if regenerate: - # loaded, missing, maybe, files = Font.test_glyphs_availability( - # text_properties.font_name, - # text_properties.face_name, - # text_properties.text) - # if len(maybe) > 0 and recursive: - # print(f"doing the thing {len(files)} times") - # for filepath in files: - # def loader(): - # set_text_on_curve(text_properties, False) - # print(f"loading font from filepath {filepath} {maybe}") - # load_font_from_filepath(filepath, maybe) - # print(f"font: {text_properties.font_name} face: {text_properties.face_name}") - # print("text",text_properties.text) - # text_properties.font_size = text_properties.font_size - # # run_in_main_thread(loader) - # return completely_delete_objects(glyph_objects) - # context_override = bpy.context.copy() - # context_override["selected_objects"] = list(glyph_objects) - # with bpy.context.temp_override(**context_override): - # bpy.ops.object.delete() - - # # remove deleted objects - # # this is necessary - # for g in glyph_objects: - # if type(g) != type(None): - # bpy.data.objects.remove(g, do_unlink=True) text_properties.glyphs.clear() @@ -733,7 +712,7 @@ def set_text_on_curve(text_properties, recursive=True): else: ob = text_properties.glyphs[i].glyph_object - distribution_type = 'CALCULATE' + distribution_type = 'CALCULATE' if is_bezier(mom) else 'FOLLOW_PATH' if distribution_type == 'FOLLOW_PATH': ob.constraints.new(type='FOLLOW_PATH') ob.constraints["Follow Path"].target = mom @@ -776,15 +755,16 @@ def set_text_on_curve(text_properties, recursive=True): # otherwise letters will be closer together the curvier the bezier is # this could be done more efficiently, but whatever curve_compensation = 0 - if text_properties.compensate_curvature and glyph_advance > 0: - previous_location = calc_point_on_bezier_curve(mom, advance, False) - new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance, False) - while (previous_location - new_location).length > glyph_advance: - curve_compensation = curve_compensation - glyph_advance * 0.01 - new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance + curve_compensation, False) - while (previous_location - new_location).length < glyph_advance: - curve_compensation = curve_compensation + glyph_advance * 0.01 - new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance + curve_compensation, False) + if distribution_type == 'CALCULATE': + if text_properties.compensate_curvature and glyph_advance > 0: + previous_location = calc_point_on_bezier_curve(mom, advance, False) + new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance, False) + while (previous_location - new_location).length > glyph_advance: + curve_compensation = curve_compensation - glyph_advance * 0.01 + new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance + curve_compensation, False) + while (previous_location - new_location).length < glyph_advance: + curve_compensation = curve_compensation + glyph_advance * 0.01 + new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance + curve_compensation, False) ob.scale = (scalor, scalor, scalor)