font path adventures with Mac OS

This commit is contained in:
themancalledjakob 2024-08-23 16:32:40 +02:00
parent edb2c8cb8b
commit 3631ac8e49
2 changed files with 71 additions and 89 deletions

View file

@ -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']}")

View file

@ -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"