From 3631ac8e49330eb10140065adb2cae8312f5b526 Mon Sep 17 00:00:00 2001 From: themancalledjakob Date: Fri, 23 Aug 2024 16:32:40 +0200 Subject: [PATCH] font path adventures with Mac OS --- __init__.py | 158 +++++++++++++++++++++++----------------------------- butils.py | 2 +- 2 files changed, 71 insertions(+), 89 deletions(-) diff --git a/__init__.py b/__init__.py index 70de638..3b86d86 100644 --- a/__init__.py +++ b/__init__.py @@ -93,60 +93,11 @@ class ABC3D_addonPreferences(bpy.types.AddonPreferences): layout.prop(self, "assets_dir") -class ABC3D_settings(bpy.types.PropertyGroup): - font_path: bpy.props.StringProperty( - name="Font path", - description="Load a *.glb or *.gltf fontfile from disk", - default="", - maxlen=1024, - subtype="FILE_PATH") - import_infix: bpy.props.StringProperty( - name="Font name import infix", - description="The infix which all font objects to import have. obj name: 'A_NM_Origin_Tender' -> infix: '_NM_Origin_Tender'", - default="_NM_", - maxlen=1024, - ) - text: bpy.props.StringProperty( - name="Text", - description="The text.", - default="HELLO", - maxlen=1024, - ) - target_object: bpy.props.PointerProperty( - name="The Target Object", - description="The target, which will be populated by character children of text.", - type=bpy.types.Object, - ) - letter_spacing: bpy.props.FloatProperty( - name="Letter Spacing", - description="Letter Spacing", - default=0.0, - ) - font_size: bpy.props.FloatProperty( - name="Font Size", - default=1.0, - subtype='NONE', - ) - translation: bpy.props.FloatVectorProperty( - name="Translation", - default=(0.0, 0.0, 0.0), - subtype='TRANSLATION', - ) - orientation: bpy.props.FloatVectorProperty( - name="Orientation", - default=(1.5707963267948966, 0.0, 0.0), # 90 degrees in radians - subtype='EULER', - ) - offset: bpy.props.FloatProperty( - name="Offset", - default=0.0, - subtype='NONE', - ) - class ABC3D_available_font(bpy.types.PropertyGroup): font_name: bpy.props.StringProperty(name="") face_name: bpy.props.StringProperty(name="") + class ABC3D_glyph_properties(bpy.types.PropertyGroup): glyph_id: bpy.props.StringProperty(maxlen=1) glyph_object: bpy.props.PointerProperty(type=bpy.types.Object) @@ -282,6 +233,20 @@ class ABC3D_data(bpy.types.PropertyGroup): active_text_index: bpy.props.IntProperty(update=active_text_index_update) + # def font_path_update_callback(self, context): + # butils.ShowMessageBox("Friendly Reminder", message="do not forget to click on 'Install new font'") + # bpy.ops.abc3d.install_font() + + # stupid hack for Mac OS + font_path: bpy.props.StringProperty( + name="Font path", + description="Install a *.glb or *.gltf fontfile from disk", + default="", + maxlen=1024, + # update=font_path_update_callback, + subtype="FILE_PATH") + + class ABC3D_UL_fonts(bpy.types.UIList): def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index): layout.label(text=f"{index}: {item.font_name} {item.face_name}") # avoids renaming the item by accident @@ -313,27 +278,25 @@ class ABC3D_PT_Panel(bpy.types.Panel): layout.row().label(text='no fonts loaded yet') layout.operator(f"{__name__}.load_installed_fonts", text="load installed fonts", icon=icon) + layout.row().prop(context.scene.abc3d_data, "font_path") + layout.row().operator(f"{__name__}.install_font", text='Install new font') -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" - bl_options = {"DEFAULT_CLOSED"} +# 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 = scene.abc3d - abc3d_data = scene.abc3d_data + # abc3d_data = scene.abc3d_data - layout.label(text="Install FontFile:") - layout.row().prop(abc3d, "font_path") - layout.row().operator(f"{__name__}.install_font", text='Install') + # layout.row().operator(f"{__name__}.install_font", text='Install new font') class ABC3D_PT_FontList(bpy.types.Panel): @@ -348,7 +311,6 @@ class ABC3D_PT_FontList(bpy.types.Panel): wm = context.window_manager scene = context.scene - abc3d = scene.abc3d abc3d_data = scene.abc3d_data layout.label(text="Available Fonts") @@ -403,7 +365,6 @@ class ABC3D_PT_TextPlacement(bpy.types.Panel): wm = context.window_manager scene = context.scene - abc3d = scene.abc3d abc3d_data = scene.abc3d_data placerow = layout.row() @@ -425,7 +386,6 @@ class ABC3D_PT_TextManagement(bpy.types.Panel): @classmethod def poll(self, context): scene = context.scene - abc3d = scene.abc3d abc3d_data = scene.abc3d_data # TODO: update available_texts def update(): @@ -495,7 +455,6 @@ class ABC3D_PT_TextManagement(bpy.types.Panel): wm = context.window_manager scene = context.scene - abc3d = scene.abc3d abc3d_data = scene.abc3d_data layout.label(text="Text Objects") @@ -515,7 +474,6 @@ class ABC3D_PT_FontCreation(bpy.types.Panel): wm = context.window_manager scene = context.scene - abc3d = scene.abc3d abc3d_data = scene.abc3d_data layout.row().operator(f"{__name__}.create_font_from_objects", text='Create/Extend Font') @@ -580,7 +538,6 @@ class ABC3D_PT_TextPropertiesPanel(bpy.types.Panel): layout = self.layout wm = context.window_manager scene = context.scene - abc3d = scene.abc3d abc3d_data = scene.abc3d_data props = self.get_active_text_properties() @@ -609,6 +566,20 @@ class ABC3D_OT_InstallFont(bpy.types.Operator): bl_label = "Load Font" bl_options = {'REGISTER', 'UNDO'} + def font_path_update_callback(self, context): + if os.path.exists(self.font_path): + print(f"{self.font_path} does exist") + else: + print(f"{self.font_path} does not exist") + + font_path: bpy.props.StringProperty( + name="Font path", + description="Install a *.glb or *.gltf fontfile from disk", + default="", + maxlen=1024, + # update=font_path_update_callback, + subtype="FILE_PATH") + install_in_assets: bpy.props.BoolProperty( name="install in assets", description="install the font in the assets directory of the addon", @@ -620,7 +591,9 @@ class ABC3D_OT_InstallFont(bpy.types.Operator): default=False) 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, "install_in_assets") if not self.install_in_assets and not self.load_into_memory: layout.label(text="If the fontfile is not installed,") @@ -634,27 +607,42 @@ 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) return context.window_manager.invoke_props_dialog(self) def execute(self, context): scene = bpy.context.scene - if not os.path.exists(scene.abc3d.font_path): + abc3d_data = context.scene.abc3d_data + if not os.path.exists(self.font_path): butils.ShowMessageBox( title=f"{__name__} Warning", icon="ERROR", - message=f"We believe the font path ({scene.abc3d.font_path}) does not exist.", + message=[ + f"Could not install font.", + f"We believe the font path ({self.font_path}) does not exist.", + f"If this is an error, please let us know.", + ], ) return {'CANCELLED'} if self.install_in_assets: preferences = getPreferences(context) - filename = os.path.basename(scene.abc3d.font_path) + filename = os.path.basename(self.font_path) target = os.path.join(preferences.assets_dir, "fonts", filename) - print(f"installing {scene.abc3d.font_path} -> {target}") import shutil os.makedirs(os.path.dirname(target), exist_ok=True) - shutil.copyfile(scene.abc3d.font_path, target) + shutil.copyfile(self.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) @@ -663,9 +651,9 @@ class ABC3D_OT_InstallFont(bpy.types.Operator): butils.load_font_from_filepath(target) butils.update_available_fonts() else: - butils.register_font_from_filepath(scene.abc3d.font_path) + butils.register_font_from_filepath(self.font_path) if self.load_into_memory: - butils.load_font_from_filepath(scene.abc3d.font_path) + butils.load_font_from_filepath(self.font_path) return {'FINISHED'} @@ -692,6 +680,7 @@ class ABC3D_OT_LoadInstalledFonts(bpy.types.Operator): return context.window_manager.invoke_props_dialog(self) def execute(self, context): + print("EXECUTE LOAD INSTALLED FONTS") scene = bpy.context.scene if self.load_into_memory: @@ -907,9 +896,6 @@ class ABC3D_OT_PlaceText(bpy.types.Operator): selected = bpy.context.view_layer.objects.active - # if abc3d.target_object: - # selected = abc3d.target_object - if selected: # font = abc3d_data.available_fonts[abc3d_data.active_font_index] # font_name = font.font_name @@ -1181,7 +1167,7 @@ class ABC3D_OT_CreateFontFromObjects(bpy.types.Operator): if fontcollection is None: fontcollection = bpy.data.collections.new("ABC3D") - ifxsplit = abc3d.import_infix.split('_') + ifxsplit = self.import_infix.split('_') # if len(ifxsplit) != 4: # font_name = f"{ifxsplit[1]}_{ifxsplit[2]}" @@ -1207,7 +1193,6 @@ class ABC3D_OT_CreateFontFromObjects(bpy.types.Operator): if butils.is_mesh(o) and not butils.is_metrics_object(o): uc = o.users_collection - # regex = f"{abc3d.import_infix}(.)*" if self.fix_common_misspellings: o.name = Font.fix_glyph_name_misspellings(o.name) # name = re.sub(regex, "", o.name) @@ -1332,11 +1317,10 @@ classes = ( ABC3D_glyph_properties, ABC3D_text_properties, ABC3D_data, - ABC3D_settings, ABC3D_UL_fonts, ABC3D_UL_texts, ABC3D_PT_Panel, - ABC3D_PT_LoadFontPanel, + # ABC3D_PT_LoadFontPanel, ABC3D_PT_FontList, ABC3D_PT_TextPlacement, ABC3D_PT_TextManagement, @@ -1378,7 +1362,6 @@ def on_frame_changed(self, dummy): def register(): for cls in classes: bpy.utils.register_class(cls) - bpy.types.Scene.abc3d = bpy.props.PointerProperty(type=ABC3D_settings) bpy.types.Scene.abc3d_data = bpy.props.PointerProperty(type=ABC3D_data) # bpy.types.Object.__del__ = lambda self: print(f"Bye {self.name}") print(f"REGISTER {bl_info['name']}") @@ -1413,7 +1396,6 @@ def unregister(): if on_frame_changed in bpy.app.handlers.frame_change_post: bpy.app.handlers.frame_change_post.remove(on_frame_changed) - del bpy.types.Scene.abc3d del bpy.types.Scene.abc3d_data print(f"UNREGISTER {bl_info['name']}") diff --git a/butils.py b/butils.py index 1c2be12..66a929a 100644 --- a/butils.py +++ b/butils.py @@ -416,7 +416,7 @@ def register_font_from_filepath(filepath): def load_font_from_filepath(filepath, glyphs="", font_name="", face_name=""): if not filepath.endswith(".glb") and not filepath.endswith(".gltf"): - ShowMessageBox(f"{bl_info['name']} Font loading error", 'ERROR', f"Filepath({filepath}) is not a *.glb or *.gltf file") + ShowMessageBox(f"Font loading error", 'ERROR', f"Filepath({filepath}) is not a *.glb or *.gltf file") return False marker_property = "font_import"