stabilizing, user experience

use class for glyph availability
use isinstance instead of type
better user experience when export directory does not exist
This commit is contained in:
jrkb 2025-05-29 15:27:24 +02:00
parent 777644e509
commit 335ab1face
4 changed files with 279 additions and 129 deletions

View file

@ -35,7 +35,6 @@ if "Font" in locals():
importlib.reload(bimport)
importlib.reload(addon_updater_ops)
def getPreferences(context):
preferences = context.preferences
return preferences.addons[__name__].preferences
@ -398,51 +397,51 @@ class ABC3D_PT_FontList(bpy.types.Panel):
available_font = abc3d_data.available_fonts[abc3d_data.active_font_index]
font_name = available_font.font_name
face_name = available_font.face_name
available_glyphs = sorted(
Font.fonts[font_name].faces[face_name].glyphs_in_fontfile
)
loaded_glyphs = sorted(Font.fonts[font_name].faces[face_name].loaded_glyphs)
box = layout.box()
box.row().label(text=f"Font Name: {font_name}")
box.row().label(text=f"Face Name: {face_name}")
n = 16
n_rows = int(len(available_glyphs) / n)
box.row().label(text="Glyphs:")
subbox = box.box()
for i in range(0, n_rows + 1):
text = "".join(
[
f"{u}"
for ui, u in enumerate(available_glyphs)
if ui < (i + 1) * n and ui >= i * n
]
face : Font.FontFace = Font.get_font_face(font_name, face_name)
if face is not None:
available_glyphs = face.glyphs_in_fontfile
loaded_glyphs = sorted(face.loaded_glyphs)
box = layout.box()
box.row().label(text=f"Font Name: {font_name}")
box.row().label(text=f"Face Name: {face_name}")
n = 16
n_rows = int(len(available_glyphs) / n)
box.row().label(text="Glyphs:")
subbox = box.box()
for i in range(0, n_rows + 1):
text = "".join(
[
f"{u}"
for ui, u in enumerate(available_glyphs)
if ui < (i + 1) * n and ui >= i * n
]
)
scale_y = 0.5
row = subbox.row()
row.scale_y = scale_y
row.alignment = "CENTER"
row.label(text=text)
n_rows = int(len(loaded_glyphs) / n)
box.row().label(text="Loaded/Used Glyphs:")
subbox = box.box()
for i in range(0, n_rows + 1):
text = "".join(
[
f"{u}"
for ui, u in enumerate(loaded_glyphs)
if ui < (i + 1) * n and ui >= i * n
]
)
scale_y = 0.5
row = subbox.row()
row.scale_y = scale_y
row.label(text=text)
row = layout.row()
oper_lf = row.operator(
f"{__name__}.load_font", text="Load all glyphs in memory"
)
scale_y = 0.5
row = subbox.row()
row.scale_y = scale_y
row.alignment = "CENTER"
row.label(text=text)
n_rows = int(len(loaded_glyphs) / n)
box.row().label(text="Loaded/Used Glyphs:")
subbox = box.box()
for i in range(0, n_rows + 1):
text = "".join(
[
f"{u}"
for ui, u in enumerate(loaded_glyphs)
if ui < (i + 1) * n and ui >= i * n
]
)
scale_y = 0.5
row = subbox.row()
row.scale_y = scale_y
row.label(text=text)
row = layout.row()
oper_lf = row.operator(
f"{__name__}.load_font", text="Load all glyphs in memory"
)
oper_lf.font_name = font_name
oper_lf.face_name = face_name
oper_lf.font_name = font_name
oper_lf.face_name = face_name
class ABC3D_PT_TextPlacement(bpy.types.Panel):
@ -754,7 +753,6 @@ class ABC3D_PT_TextPropertiesPanel(bpy.types.Panel):
return t
return None
# NOTE: HERE
def get_active_glyph_properties(self):
a_o = bpy.context.active_object
if a_o is not None:
@ -1026,7 +1024,11 @@ class ABC3D_OT_LoadFont(bpy.types.Operator):
face_name: bpy.props.StringProperty()
def execute(self, context):
filepaths = Font.fonts[self.font_name].faces[self.face_name].filepaths
face : Font.FontFace = Font.get_font_face(self.font_name, self.face_name)
if face is None:
butils.ShowMessageBox(f"{utils.prefix()} Load Font", icon="ERROR", message=["Could not load font, sorry!", f"{self.font_name=} {self.face_name=}"])
return {"CANCELLED"}
filepaths = face.filepaths
for f in filepaths:
butils.load_font_from_filepath(f)
return {"FINISHED"}
@ -1402,6 +1404,9 @@ class ABC3D_OT_SaveFontToFile(bpy.types.Operator):
bl_label = "Save Font"
bl_options = {"REGISTER", "UNDO"}
can_execute : bpy.props.BoolProperty(default=True)
create_output_directory : bpy.props.BoolProperty(default=False)
def invoke(self, context, event):
wm = context.window_manager
preferences = getPreferences(context)
@ -1425,30 +1430,95 @@ class ABC3D_OT_SaveFontToFile(bpy.types.Operator):
available_font = abc3d_data.available_fonts[abc3d_data.active_font_index]
font_name = available_font.font_name
face_name = available_font.face_name
loaded_glyphs = sorted(Font.fonts[font_name].faces[face_name].loaded_glyphs)
n = 16
n_rows = int(len(loaded_glyphs) / n)
box = layout.box()
box.row().label(text="Glyphs to be exported:")
subbox = box.box()
for i in range(0, n_rows + 1):
text = "".join(
[
f"{u}"
for ui, u in enumerate(loaded_glyphs)
if ui < (i + 1) * n and ui >= i * n
]
)
scale_y = 0.5
row = subbox.row()
row.scale_y = scale_y
row.label(text=text)
layout.prop(abc3d_data, "export_dir")
face : Font.FontFace = Font.get_font_face(font_name, face_name)
if face is not None:
loaded_glyphs = sorted(face.loaded_glyphs)
n = 16
n_rows = int(len(loaded_glyphs) / n)
box = layout.box()
box.row().label(text="Glyphs to be exported:")
subbox = box.box()
for i in range(0, n_rows + 1):
text = "".join(
[
f"{u}"
for ui, u in enumerate(loaded_glyphs)
if ui < (i + 1) * n and ui >= i * n
]
)
scale_y = 0.5
row = subbox.row()
row.scale_y = scale_y
row.label(text=text)
row = layout.row()
export_dir = butils.bpy_to_abspath(abc3d_data.export_dir)
if os.access(export_dir, os.W_OK):
self.can_execute = True
elif os.path.exists(export_dir):
self.can_execute = False
row.alert = True
row.label(text="Export directory exists but is not writable")
row = layout.row()
row.alert = True
row.label(text="Please select another directory")
row = layout.row()
row.alert = True
elif not utils.can_create_path(export_dir): # does not exist and cannot be created
self.can_execute = False
row.alert = True
row.label(text="Directory does not exist and cannot be created")
row = layout.row()
row.alert = True
row.label(text="Please select another directory")
row = layout.row()
row.alert = True
elif utils.can_create_path(export_dir): # does not exist and can be created
self.can_execute = True
row.label(text="Directory does not exist")
row = layout.row()
row.label(text="But can and will be created on export")
row = layout.row()
else:
self.can_execute = False
row.alert = True
row.label(text="Please select another directory")
row = layout.row()
row.alert = True
row.prop(abc3d_data, "export_dir")
else:
print(f"{utils.prefix()}::save_font_to_file ERROR {face=} {font_name=} {face_name=}")
print(f"{utils.prefix()} {Font.fonts=}")
def execute(self, context):
global shared
scene = bpy.context.scene
abc3d_data = scene.abc3d_data
if not self.can_execute:
butils.ShowMessageBox(
"Cannot export font",
"ERROR",
[
f"export directory '{abc3d_data.export_dir}' does not exist or is not writable",
"try setting another path"
]
)
return {'CANCELLED'}
if not os.path.exists(butils.bpy_to_abspath(abc3d_data.export_dir)):
path = butils.bpy_to_abspath(abc3d_data.export_dir)
if utils.can_create_path(path):
os.makedirs(path, exist_ok=True)
else:
butils.ShowMessageBox(
"Cannot export font",
"ERROR",
[
f"export directory '{abc3d_data.export_dir}' does not exist and cannot be created",
"try setting another path"
]
)
return {'CANCELLED'}
fontcollection = bpy.data.collections.get("ABC3D")
@ -1528,7 +1598,10 @@ class ABC3D_OT_SaveFontToFile(bpy.types.Operator):
use_selection=True,
use_active_scene=True,
)
bpy.app.timers.register(lambda: bpy.ops.scene.delete(), first_interval=1)
def delete_scene():
bpy.ops.scene.delete()
return None
bpy.app.timers.register(lambda: delete_scene(), first_interval=1)
# bpy.ops.scene.delete()
# restore()
@ -1669,9 +1742,6 @@ class ABC3D_OT_CreateFontFromObjects(bpy.types.Operator):
font_name = self.font_name
face_name = self.face_name
# TODO: do not clear
# abc3d_data.available_fonts.clear()
# Font.fonts = {}
currentObjects = []
for o in context.selected_objects:
if o.name not in currentObjects:
@ -1842,7 +1912,7 @@ def load_used_glyphs():
abc3d_data = scene.abc3d_data
for t in abc3d_data.available_texts:
a = Font.test_availability(t.font_name, t.face_name, t.text)
if type(a) == type(int()):
if isinstance(a, int):
if a == Font.MISSING_FONT:
butils.ShowMessageBox(
"Missing Font",
@ -1859,9 +1929,9 @@ def load_used_glyphs():
"Do you have it installed?",
],
)
elif len(a["maybe"]) > 0:
for fp in a["filepaths"]:
butils.load_font_from_filepath(fp, a["maybe"])
elif len(a.unloaded) > 0:
for fp in a.filepaths:
butils.load_font_from_filepath(fp, a.unloaded)
@persistent