only import on demand
This commit is contained in:
parent
e23369df94
commit
25ef83878a
4 changed files with 722 additions and 107 deletions
215
butils.py
215
butils.py
|
@ -314,7 +314,6 @@ def find_font_face_object(font_obj, face_name):
|
|||
return None
|
||||
|
||||
def move_in_fontcollection(obj, fontcollection, allow_duplicates=False):
|
||||
|
||||
# parent nesting structure
|
||||
# the font object
|
||||
font_obj = find_font_object(fontcollection,
|
||||
|
@ -377,80 +376,104 @@ def move_in_fontcollection(obj, fontcollection, allow_duplicates=False):
|
|||
|
||||
return obj
|
||||
|
||||
def load_font_from_filepath(filepath):
|
||||
def register_font_from_filepath(filepath):
|
||||
from .bimport import get_font_faces_in_file
|
||||
|
||||
availables = get_font_faces_in_file(filepath)
|
||||
|
||||
fonts = {}
|
||||
for a in availables:
|
||||
font_name = a["font_name"]
|
||||
face_name = a["face_name"]
|
||||
glyph = a["glyph"]
|
||||
if not font_name in fonts:
|
||||
fonts[font_name] = {}
|
||||
if not face_name in fonts[font_name]:
|
||||
fonts[font_name][face_name] = []
|
||||
fonts[font_name][face_name].append(glyph)
|
||||
for font_name in fonts:
|
||||
for face_name in fonts[font_name]:
|
||||
Font.register_font(font_name,
|
||||
face_name,
|
||||
fonts[font_name][face_name],
|
||||
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")
|
||||
return False
|
||||
|
||||
abc3d_data = bpy.context.scene.abc3d_data
|
||||
allObjectsBefore = []
|
||||
for ob in bpy.data.objects:
|
||||
allObjectsBefore.append(ob.name)
|
||||
|
||||
bpy.ops.import_scene.gltf(filepath=filepath)
|
||||
marker_property = "font_import"
|
||||
bpy.ops.abc3d.import_font_gltf(filepath=filepath,
|
||||
glyphs=glyphs,
|
||||
marker_property=marker_property,
|
||||
font_name=font_name,
|
||||
face_name=face_name)
|
||||
|
||||
fontcollection = bpy.data.collections.get("ABC3D")
|
||||
if fontcollection is None:
|
||||
fontcollection = bpy.data.collections.new("ABC3D")
|
||||
|
||||
modified_font_faces = []
|
||||
all_glyph_os = []
|
||||
remove_list = []
|
||||
all_objects = []
|
||||
for o in bpy.data.objects:
|
||||
all_objects.append(o)
|
||||
for o in all_objects:
|
||||
o_exists = True
|
||||
try:
|
||||
o, o.name
|
||||
except ReferenceError as e:
|
||||
o_exists = False
|
||||
if o_exists and o.name not in allObjectsBefore:
|
||||
# must be new
|
||||
if ("glyph" in o.keys()
|
||||
and "face_name" in o.keys()
|
||||
and "font_name" in o.keys()
|
||||
and not ("type" in o.keys() and o["type"] == "metrics")
|
||||
and not is_metrics_object(o)
|
||||
):
|
||||
glyph_id = o["glyph"]
|
||||
font_name = o["font_name"]
|
||||
face_name = o["face_name"]
|
||||
# ShowMessageBox("Loading Font", "INFO", f"adding glyph {glyph_id} for {font_name} {face_name}")
|
||||
print(f"adding glyph {glyph_id} for {font_name} {face_name}")
|
||||
glyph_obj = move_in_fontcollection(
|
||||
o,
|
||||
fontcollection)
|
||||
Font.add_glyph(
|
||||
font_name,
|
||||
face_name,
|
||||
glyph_id,
|
||||
glyph_obj)
|
||||
for c in o.children:
|
||||
if is_metrics_object(c):
|
||||
add_metrics_obj_from_bound_box(glyph_obj,
|
||||
bound_box_as_array(c.bound_box))
|
||||
if glyph_obj != o:
|
||||
remove_list.append(o)
|
||||
|
||||
# found = False
|
||||
# for f in abc3d_data.available_fonts.values():
|
||||
# print(f"has in availables {f.font_name} {f.face_name}")
|
||||
# if f.font_name == font_name and f.face_name == face_name:
|
||||
# found = True
|
||||
# break
|
||||
# if not found:
|
||||
# f = abc3d_data.available_fonts.add()
|
||||
# f.font_name = font_name
|
||||
# f.face_name = face_name
|
||||
# print(f"{__name__} added {font_name} {face_name}")
|
||||
elif o_exists:
|
||||
for o in bpy.context.scene.objects:
|
||||
if marker_property in o:
|
||||
if "type" in o and o["type"] == "glyph":
|
||||
all_glyph_os.append(o)
|
||||
else:
|
||||
remove_list.append(o)
|
||||
for o in remove_list:
|
||||
try:
|
||||
bpy.data.objects.remove(o, do_unlink=True)
|
||||
except ReferenceError as e:
|
||||
print(f"{__name__} could not remove object, because it doesn't exist")
|
||||
print(f"{__name__}: loaded font from {filepath}")
|
||||
|
||||
for o in all_glyph_os:
|
||||
glyph_id = o["glyph"]
|
||||
font_name = o["font_name"]
|
||||
face_name = o["face_name"]
|
||||
del o[marker_property]
|
||||
|
||||
glyph_obj = move_in_fontcollection(
|
||||
o,
|
||||
fontcollection)
|
||||
Font.add_glyph(
|
||||
font_name,
|
||||
face_name,
|
||||
glyph_id,
|
||||
glyph_obj)
|
||||
for c in o.children:
|
||||
if is_metrics_object(c):
|
||||
add_metrics_obj_from_bound_box(glyph_obj,
|
||||
bound_box_as_array(c.bound_box))
|
||||
modified_font_faces.append({"font_name": font_name,
|
||||
"face_name": face_name})
|
||||
|
||||
if glyph_obj != o:
|
||||
remove_list.append(o)
|
||||
|
||||
for mff in modified_font_faces:
|
||||
glyphs = []
|
||||
face = Font.fonts[mff["font_name"]].faces[mff["face_name"]]
|
||||
# iterate glyphs
|
||||
for g in face.glyphs:
|
||||
# iterate alternates
|
||||
for glyph in face.glyphs[g]:
|
||||
glyphs.append(glyph)
|
||||
if len(glyphs) > 0:
|
||||
add_default_metrics_to_objects(glyphs)
|
||||
# calculate unit factor
|
||||
h = get_glyph_height(glyphs[0])
|
||||
if h != 0:
|
||||
face.unit_factor = 1 / h
|
||||
|
||||
update_available_fonts()
|
||||
remove_list = []
|
||||
for o in bpy.context.scene.collection.all_objects:
|
||||
if not o.name in fontcollection.all_objects:
|
||||
if marker_property in o and o[marker_property] == True:
|
||||
remove_list.append(o)
|
||||
|
||||
simply_delete_objects(remove_list)
|
||||
|
||||
# completely_delete_objects(remove_list)
|
||||
|
||||
def update_available_fonts():
|
||||
abc3d_data = bpy.context.scene.abc3d_data
|
||||
|
@ -491,11 +514,24 @@ def load_installed_fonts():
|
|||
if file.endswith(".glb") or file.endswith(".gltf"):
|
||||
font_path = os.path.join(font_dir, file)
|
||||
# ShowMessageBox("Loading Font", "INFO", f"loading font from {font_path}")
|
||||
print(f"loading font from {font_path}")
|
||||
for f in bpy.context.scene.abc3d_data.available_fonts.values():
|
||||
print(f"available font: {f.font_name} {f.face_name}")
|
||||
# print(f"loading font from {font_path}")
|
||||
# for f in bpy.context.scene.abc3d_data.available_fonts.values():
|
||||
# print(f"available font: {f.font_name} {f.face_name}")
|
||||
register_font_from_filepath(font_path)
|
||||
load_font_from_filepath(font_path)
|
||||
|
||||
def register_installed_fonts():
|
||||
preferences = getPreferences(bpy.context)
|
||||
font_dir = f"{preferences.assets_dir}/fonts"
|
||||
for file in os.listdir(font_dir):
|
||||
if file.endswith(".glb") or file.endswith(".gltf"):
|
||||
font_path = os.path.join(font_dir, file)
|
||||
# ShowMessageBox("Loading Font", "INFO", f"loading font from {font_path}")
|
||||
# print(f"loading font from {font_path}")
|
||||
# for f in bpy.context.scene.abc3d_data.available_fonts.values():
|
||||
# print(f"available font: {f.font_name} {f.face_name}")
|
||||
register_font_from_filepath(font_path)
|
||||
|
||||
def ShowMessageBox(title = "Message Box", icon = 'INFO', message=""):
|
||||
|
||||
"""Show a simple message box
|
||||
|
@ -531,12 +567,15 @@ def ShowMessageBox(title = "Message Box", icon = 'INFO', message=""):
|
|||
self.layout.label(text=n)
|
||||
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
|
||||
|
||||
def completely_delete_objects(objs):
|
||||
def simply_delete_objects(objs):
|
||||
context_override = bpy.context.copy()
|
||||
context_override["selected_objects"] = list(objs)
|
||||
with bpy.context.temp_override(**context_override):
|
||||
bpy.ops.object.delete()
|
||||
|
||||
def completely_delete_objects(objs):
|
||||
simply_delete_objects(objs)
|
||||
|
||||
# remove deleted objects
|
||||
# this is necessary
|
||||
for g in objs:
|
||||
|
@ -578,7 +617,23 @@ def get_glyph_advance(glyph_obj):
|
|||
return abs(c.bound_box[4][0] - c.bound_box[0][0])
|
||||
return abs(glyph_obj.bound_box[4][0] - glyph_obj.bound_box[0][0])
|
||||
|
||||
def set_text_on_curve(text_properties):
|
||||
def get_glyph_height(glyph_obj):
|
||||
for c in glyph_obj.children:
|
||||
if is_metrics_object(c):
|
||||
return abs(c.bound_box[0][1] - c.bound_box[3][1])
|
||||
return abs(glyph_obj.bound_box[0][1] - glyph_obj.bound_box[3][1])
|
||||
|
||||
def prepare_text(font_name, face_name, text):
|
||||
loaded, missing, loadable, files = Font.test_glyphs_availability(
|
||||
font_name,
|
||||
face_name,
|
||||
text)
|
||||
if len(loadable) > 0:
|
||||
for filepath in files:
|
||||
load_font_from_filepath(filepath, loadable, font_name, face_name)
|
||||
return True
|
||||
|
||||
def set_text_on_curve(text_properties, recursive=True):
|
||||
# starttime = time.perf_counter_ns()
|
||||
mom = text_properties.text_object
|
||||
if mom.type != "CURVE":
|
||||
|
@ -605,6 +660,22 @@ def set_text_on_curve(text_properties):
|
|||
|
||||
# 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)
|
||||
|
@ -696,7 +767,8 @@ def set_text_on_curve(text_properties):
|
|||
ob.rotation_quaternion = q
|
||||
# ob.rotation_quaternion = (mom.matrix_world @ q.to_matrix().to_4x4()).to_quaternion()
|
||||
|
||||
scalor = 0.001 * text_properties.font_size
|
||||
face = Font.fonts[text_properties.font_name].faces[text_properties.face_name]
|
||||
scalor = face.unit_factor * text_properties.font_size
|
||||
|
||||
glyph_advance = get_glyph_advance(glyph) * scalor + text_properties.letter_spacing
|
||||
|
||||
|
@ -929,6 +1001,13 @@ def get_metrics_bound_box(bb, bb_uebermetrics):
|
|||
metrics[7][0] = bb[7][0]
|
||||
return metrics
|
||||
|
||||
def get_metrics_object(o):
|
||||
if is_glyph(o):
|
||||
for c in o.children:
|
||||
if is_metrics_object(c):
|
||||
return c
|
||||
return None
|
||||
|
||||
def add_default_metrics_to_objects(objects=None, overwrite_existing=False):
|
||||
if type(objects) == type(None):
|
||||
objects=bpy.context.selected_objects
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue