diff --git a/__init__.py b/__init__.py index c68b1f7..c8575d2 100644 --- a/__init__.py +++ b/__init__.py @@ -326,31 +326,32 @@ class ABC3D_PT_Panel(bpy.types.Panel): icon = 'ERROR' layout.row().label(text='no fonts loaded yet') + layout.operator(f"{__name__}.install_font", text='Install new font') layout.operator(f"{__name__}.load_installed_fonts", text="load installed fonts", icon=icon) layout.operator(f"{__name__}.open_asset_directory", text="open asset directory", icon='FILEBROWSER') -class ABC3D_PT_LoadFontPanel(bpy.types.Panel): - bl_label = "Install a new font" - bl_parent_id = "ABC3D_PT_Panel" - bl_category = "ABC3D" - bl_space_type = "VIEW_3D" - bl_region_type = "UI" +# class ABC3D_PT_LoadFontPanel(bpy.types.Panel): + # bl_label = "Install a new font" + # bl_parent_id = "ABC3D_PT_Panel" + # bl_category = "ABC3D" + # bl_space_type = "VIEW_3D" + # bl_region_type = "UI" - def draw(self, context): - layout = self.layout - wm = context.window_manager - scene = context.scene + # def draw(self, context): + # layout = self.layout + # wm = context.window_manager + # scene = context.scene - abc3d_data = scene.abc3d_data + # abc3d_data = scene.abc3d_data - box = layout.box() - box.row().label(text="1. Select fontfile") - box.row().prop(context.scene.abc3d_data, "font_path") - box.row().label(text="2. Install it:") - box.row().operator(f"{__name__}.install_font", text='Install new font') + # box = layout.box() + # box.row().label(text="1. Select fontfile") + # box.row().prop(context.scene.abc3d_data, "font_path") + # box.row().label(text="2. Install it:") + # box.row().operator(f"{__name__}.install_font", text='Install new font') class ABC3D_PT_FontList(bpy.types.Panel): @@ -666,7 +667,7 @@ class ABC3D_OT_InstallFont(bpy.types.Operator): description="Install a *.glb or *.gltf fontfile from disk", default="", maxlen=1024, - # update=font_path_update_callback, + update=font_path_update_callback, subtype="FILE_PATH") install_in_assets: bpy.props.BoolProperty( @@ -682,7 +683,7 @@ class ABC3D_OT_InstallFont(bpy.types.Operator): def draw(self, context): abc3d_data = context.scene.abc3d_data layout = self.layout - # layout.row().prop(self, "font_path") # crashes on Mac OS? + layout.row().prop(self, "font_path") # layout.row().prop(abc3d_data, "font_path") # closes the stupid panel on Mac OS.. layout.row().prop(self, "install_in_assets") if not self.install_in_assets and not self.load_into_memory: @@ -698,30 +699,30 @@ class ABC3D_OT_InstallFont(bpy.types.Operator): layout.label(text="load the font data on demand.") def invoke(self, context, event): - abc3d_data = context.scene.abc3d_data - self.font_path = abc3d_data.font_path - if not os.path.exists(self.font_path): - bpy.app.timers.register(lambda: butils.ShowMessageBox( - title=f"{__name__} Warning", - icon="ERROR", - message=[ - f"We believe the font path ({self.font_path}) does not exist.", - f"Did you select your fontfile in the field above the 'Install new font'-button?", - ], - ), first_interval=0.1) + # self.font_path = butils.bpy_to_abspath(self.font_path) + # if not os.path.exists(self.font_path): + # bpy.app.timers.register(lambda: butils.ShowMessageBox( + # title=f"{__name__} Warning", + # icon="ERROR", + # message=[ + # f"We believe the font path ({self.font_path}) does not exist.", + # f"Did you select your fontfile in the field above the 'Install new font'-button?", + # ], + # ), first_interval=0.1) return context.window_manager.invoke_props_dialog(self) def execute(self, context): scene = bpy.context.scene abc3d_data = context.scene.abc3d_data - if not os.path.exists(self.font_path): + font_path = butils.bpy_to_abspath(self.font_path) + if not os.path.exists(font_path): butils.ShowMessageBox( title=f"{__name__} Warning", icon="ERROR", message=[ f"Could not install font.", - f"We believe the font path ({self.font_path}) does not exist.", + f"We believe the font path ({font_path}) does not exist.", f"If this is an error, please let us know.", ], ) @@ -729,11 +730,11 @@ class ABC3D_OT_InstallFont(bpy.types.Operator): if self.install_in_assets: preferences = getPreferences(context) - filename = os.path.basename(self.font_path) + filename = os.path.basename(font_path) target = os.path.join(preferences.assets_dir, "fonts", filename) import shutil os.makedirs(os.path.dirname(target), exist_ok=True) - shutil.copyfile(self.font_path, target) + shutil.copyfile(font_path, target) # def register_load(target, load=False): # print(f"registering installed fonts") # bpy.app.timers.register(lambda: register_load(target, self.load_into_memory), first_interval=5) @@ -742,9 +743,9 @@ class ABC3D_OT_InstallFont(bpy.types.Operator): butils.load_font_from_filepath(target) butils.update_available_fonts() else: - butils.register_font_from_filepath(self.font_path) + butils.register_font_from_filepath(font_path) if self.load_into_memory: - butils.load_font_from_filepath(self.font_path) + butils.load_font_from_filepath(font_path) return {'FINISHED'} @@ -1507,7 +1508,7 @@ classes = ( ABC3D_UL_fonts, ABC3D_UL_texts, ABC3D_PT_Panel, - ABC3D_PT_LoadFontPanel, + # ABC3D_PT_LoadFontPanel, ABC3D_PT_FontList, ABC3D_PT_TextPlacement, ABC3D_PT_TextManagement, @@ -1585,7 +1586,7 @@ def load_used_glyphs(): [f"Font {t.font_name} is there,", f"but the FontFace {t.face_name} is missing,", "Do you have it installed?"]) - if len(a["maybe"]) > 0: + elif len(a["maybe"]) > 0: for fp in a["filepaths"]: butils.load_font_from_filepath(fp, a["maybe"]) @@ -1610,20 +1611,25 @@ def on_frame_changed(self, dummy): # TODO PERFORMANCE: only on demand butils.set_text_on_curve(t) - @persistent def on_depsgraph_update(scene, depsgraph): - for u in depsgraph.updates: - if f"{utils.prefix()}_linked_textobject" in u.id.keys() \ - and f"{utils.prefix()}_type" in u.id.keys() \ - and u.id[f"{utils.prefix()}_type"] == 'textobject': - linked_textobject = u.id[f"{utils.prefix()}_linked_textobject"] - if u.is_updated_geometry and len(scene.abc3d_data.available_texts) > linked_textobject and not "prevent_recursion" in u.id: - u.id["prevent_recursion"] = True - butils.set_text_on_curve( - scene.abc3d_data.available_texts[linked_textobject]) - elif "prevent_recursion" in u.id.keys(): - del u.id["prevent_recursion"] + if not bpy.context.mode.startswith("EDIT"): + for u in depsgraph.updates: + if f"{utils.prefix()}_linked_textobject" in u.id.keys() \ + and f"{utils.prefix()}_type" in u.id.keys() \ + and u.id[f"{utils.prefix()}_type"] == 'textobject': + linked_textobject = u.id[f"{utils.prefix()}_linked_textobject"] + if u.is_updated_geometry and len(scene.abc3d_data.available_texts) > linked_textobject: + def later(): + if not "lock_depsgraph_update_ntimes" in scene.abc3d_data \ + or scene.abc3d_data["lock_depsgraph_update_ntimes"] == 0: + print("******* not yet") + butils.set_text_on_curve( + scene.abc3d_data.available_texts[linked_textobject]) + elif scene.abc3d_data["lock_depsgraph_update_ntimes"] > 0: + scene.abc3d_data['lock_depsgraph_update_ntimes'] -= 1 + butils.run_in_main_thread(later) + def register(): diff --git a/bimport.py b/bimport.py index a1c88b7..2ec6f58 100644 --- a/bimport.py +++ b/bimport.py @@ -424,7 +424,13 @@ class ImportGLTF2(Operator, ConvertGLTF2_Base, ImportHelper): elapsed_s = "{:.2f}s".format(time.time() - start_time) print("font import gltf finished in " + elapsed_s) - gltf.log.removeHandler(gltf.log_handler) + # acrobatics to not break on MacOS + if hasattr(gltf, "log_handler"): + if hasattr(gltf.log, "removeHandler"): + gltf.log.removeHandler(gltf.log_handler) + elif hasattr(gltf.log, "logger"): + if hasattr(gltf.log.logger, "removeHandler"): + gltf.log.logger.removeHandler(gltf.log_handler) return {'FINISHED'} diff --git a/butils.py b/butils.py index af7617d..c6737be 100644 --- a/butils.py +++ b/butils.py @@ -392,6 +392,9 @@ def move_in_fontcollection(obj, fontcollection, allow_duplicates=False): return obj +def bpy_to_abspath(blender_path): + return os.path.realpath(bpy.path.abspath(blender_path)) + def register_font_from_filepath(filepath): from .bimport import get_font_faces_in_file @@ -857,6 +860,8 @@ def set_text_on_curve(text_properties, recursive=True): mom[f"{utils.prefix()}_translation"] = text_properties.translation bpy.context.view_layer.objects.active = mom bpy.ops.object.parent_set(type='OBJECT') + bpy.context.scene.abc3d_data["lock_depsgraph_update_ntimes"] = len(bpy.context.selected_objects) + mom["lock_depsgraph_update_ntimes"] = len(bpy.context.selected_objects) # endtime = time.perf_counter_ns() # elapsedtime = endtime - starttime diff --git a/common/utils.py b/common/utils.py index d45cd8c..e9757b4 100644 --- a/common/utils.py +++ b/common/utils.py @@ -68,6 +68,10 @@ def open_file_browser(directory): # xdg-open *should* be supported by recent Gnome, KDE, Xfce +def printerr(*args, **kwargs): + print(*args, file=sys.stderr, **kwargs) + + # # Evaluate a bezier curve for the parameter 0<=t<=1 along its length # def evaluateBezierPoint(p1, h1, h2, p2, t): # return ((1 - t)**3) * p1 + (3 * t * (1 - t)**2) * h1 + (3 * (t**2) * (1 - t)) * h2 + (t**3) * p2