save font file
This commit is contained in:
parent
a99215df54
commit
c27b53b012
3 changed files with 513 additions and 94 deletions
223
butils.py
223
butils.py
|
@ -1,5 +1,20 @@
|
|||
import bpy
|
||||
import mathutils
|
||||
import importlib
|
||||
|
||||
# then import dependencies for our addon
|
||||
if "Font" in locals():
|
||||
importlib.reload(Font)
|
||||
else:
|
||||
from .common import Font
|
||||
|
||||
def apply_all_transforms(obj):
|
||||
mb = obj.matrix_basis
|
||||
if hasattr(obj.data, "transform"):
|
||||
obj.data.transform(mb)
|
||||
for c in obj.children:
|
||||
c.matrix_local = mb @ c.matrix_local
|
||||
obj.matrix_basis.identity()
|
||||
|
||||
def get_parent_collection_names(collection, parent_names):
|
||||
for parent_collection in bpy.data.collections:
|
||||
|
@ -8,29 +23,127 @@ def get_parent_collection_names(collection, parent_names):
|
|||
get_parent_collection_names(parent_collection, parent_names)
|
||||
return
|
||||
|
||||
# Ensure it's a curve object
|
||||
# TODO: no raising, please
|
||||
def get_curve_length(obj, num_samples = 100):
|
||||
total_length = 0
|
||||
|
||||
if obj.type != 'CURVE':
|
||||
raise TypeError("The selected object is not a curve")
|
||||
|
||||
curve = obj.data
|
||||
|
||||
# Loop through all splines in the curve
|
||||
for spline in curve.splines:
|
||||
total_length = total_length + spline.calc_length()
|
||||
|
||||
return total_length
|
||||
|
||||
# def get_objects_by_name(name, startswith="", endswith=""):
|
||||
# return [obj for obj in bpy.context.scene.objects if obj.name.startswith(startswith) and if obj.name.endswith(endswith)]
|
||||
|
||||
def find_objects_by_name(
|
||||
objects,
|
||||
equals="",
|
||||
contains="",
|
||||
startswith="",
|
||||
endswith=""):
|
||||
# handle equals
|
||||
if equals != "":
|
||||
index = objects.find(equals)
|
||||
if index >= 0:
|
||||
return [objects[index]]
|
||||
return []
|
||||
# handle others is more permissive
|
||||
return [obj for obj in objects if obj.name.startswith(startswith) and obj.name.endswith(endswith) and obj.name.find(contains) >= 0]
|
||||
|
||||
def find_objects_by_custom_property(
|
||||
objects,
|
||||
property_name="",
|
||||
property_value=""):
|
||||
return [obj for obj in objects if property_name in obj and obj[property_name] == property_value]
|
||||
|
||||
def turn_collection_hierarchy_into_path(obj):
|
||||
parent_collection = obj.users_collection[0]
|
||||
parent_names = []
|
||||
parent_names.append(parent_collection.name)
|
||||
get_parent_collection_names(parent_collection, parent_names)
|
||||
parent_names.reverse()
|
||||
return '\\'.join(parent_names)
|
||||
parent_collection = obj.users_collection[0]
|
||||
parent_names = []
|
||||
parent_names.append(parent_collection.name)
|
||||
get_parent_collection_names(parent_collection, parent_names)
|
||||
parent_names.reverse()
|
||||
return '\\'.join(parent_names)
|
||||
|
||||
def move_in_fontcollection(obj, fontcollection, scene):
|
||||
def find_font_object(fontcollection, font_name):
|
||||
fonts = find_objects_by_custom_property(fontcollection.objects,
|
||||
"is_font",
|
||||
True)
|
||||
for font in fonts:
|
||||
if font["font_name"] == font_name and font.parent == None:
|
||||
return font
|
||||
return None
|
||||
|
||||
def find_font_face_object(font_obj, face_name):
|
||||
faces = find_objects_by_custom_property(font_obj.children,
|
||||
"is_face",
|
||||
True)
|
||||
for face in faces:
|
||||
if face["face_name"] == face_name:
|
||||
return face
|
||||
return None
|
||||
|
||||
def move_in_fontcollection(obj, fontcollection):
|
||||
# print(turn_collection_hierarchy_into_path(obj))
|
||||
if scene.collection.objects.find(obj.name) >= 0:
|
||||
scene.collection.objects.unlink(obj)
|
||||
# if scene.collection.objects.find(obj.name) >= 0:
|
||||
# scene.collection.objects.unlink(obj)
|
||||
for c in obj.users_collection:
|
||||
c.objects.unlink(obj)
|
||||
if fontcollection.objects.find(obj.name) < 0:
|
||||
fontcollection.objects.link(obj)
|
||||
# TODO: move in glyphs
|
||||
# if fontcollection.objects.find("glyphs") < 0:
|
||||
# empty = bpy.data.objects.new("glyphs", None)
|
||||
# empty.empty_display_type = 'PLAIN_AXES'
|
||||
# fontcollection.objects.link(empty)
|
||||
# glyphs = fontcollection.objects.get("glyphs")
|
||||
# if obj.parent != glyphs:
|
||||
# obj.parent = glyphs
|
||||
|
||||
# parent nesting structure
|
||||
# the font object
|
||||
font_obj = find_font_object(fontcollection,
|
||||
obj["font_name"])
|
||||
if font_obj == None:
|
||||
font_obj = bpy.data.objects.new(obj["font_name"], None)
|
||||
font_obj.empty_display_type = 'PLAIN_AXES'
|
||||
fontcollection.objects.link(font_obj)
|
||||
|
||||
# ensure custom properties are set
|
||||
font_obj["font_name"] = obj["font_name"]
|
||||
font_obj["is_font"] = True
|
||||
|
||||
# the face object as a child of font object
|
||||
face_obj = find_font_face_object(font_obj,
|
||||
obj["face_name"])
|
||||
if face_obj == None:
|
||||
face_obj = bpy.data.objects.new(obj["face_name"], None)
|
||||
face_obj.empty_display_type = 'PLAIN_AXES'
|
||||
face_obj["is_face"] = True
|
||||
fontcollection.objects.link(face_obj)
|
||||
# ensure custom properties are set
|
||||
face_obj["face_name"] = obj["face_name"]
|
||||
face_obj["font_name"] = obj["font_name"]
|
||||
|
||||
if face_obj.parent != font_obj:
|
||||
face_obj.parent = font_obj
|
||||
|
||||
# create glyphs if it does not exist
|
||||
glyphs_objs = find_objects_by_name(face_obj.children, startswith="glyphs")
|
||||
if len(glyphs_objs) <= 0:
|
||||
glyphs_obj = bpy.data.objects.new("glyphs", None)
|
||||
glyphs_obj.empty_display_type = 'PLAIN_AXES'
|
||||
fontcollection.objects.link(glyphs_obj)
|
||||
glyphs_obj.parent = face_obj
|
||||
elif len(glyphs_objs) > 1:
|
||||
print(f"found more glyphs objects than expected")
|
||||
|
||||
# now it must exist
|
||||
glyphs_obj = find_objects_by_name(face_obj.children, startswith="glyphs")[0]
|
||||
glyphs_obj["face_name"] = obj["face_name"]
|
||||
glyphs_obj["font_name"] = obj["font_name"]
|
||||
|
||||
# and now parent it!
|
||||
if obj.parent != glyphs_obj:
|
||||
obj.parent = glyphs_obj
|
||||
|
||||
def ShowMessageBox(title = "Message Box", icon = 'INFO', message=""):
|
||||
|
||||
|
@ -66,3 +179,79 @@ def ShowMessageBox(title = "Message Box", icon = 'INFO', message=""):
|
|||
for n in myLines:
|
||||
self.layout.label(text=n)
|
||||
bpy.context.window_manager.popup_menu(draw, title = title, icon = icon)
|
||||
|
||||
def set_text_on_curve(text_properties):
|
||||
mom = text_properties.text_object
|
||||
if mom.type != "CURVE":
|
||||
return False
|
||||
|
||||
glyph_objects = []
|
||||
for g in text_properties.glyphs:
|
||||
glyph_objects.append(g.glyph_object)
|
||||
|
||||
context_override = bpy.context.copy()
|
||||
context_override["selected_objects"] = list(glyph_objects)
|
||||
with bpy.context.temp_override(**context_override):
|
||||
bpy.ops.object.delete()
|
||||
# bpy.ops.object.delete({"selected_objects": glyph_objects})
|
||||
text_properties.glyphs.clear()
|
||||
|
||||
#TODO: fix selection with context_override
|
||||
previous_selection = bpy.context.selected_objects
|
||||
bpy.ops.object.select_all(action='DESELECT')
|
||||
selected_objects = []
|
||||
|
||||
curve_length = get_curve_length(mom)
|
||||
advance = 0
|
||||
for i, c in enumerate(text_properties.text):
|
||||
glyph_id = c
|
||||
glyph = Font.get_glyph(text_properties.font_name,
|
||||
text_properties.font_face,
|
||||
glyph_id)
|
||||
|
||||
if glyph == None:
|
||||
self.report({'ERROR'}, f"Glyph not found for {font_name} {font_face} {glyph_id}")
|
||||
continue
|
||||
|
||||
ob = bpy.data.objects.new(f"{glyph_id}", glyph.data)
|
||||
|
||||
ob.constraints.new(type='FOLLOW_PATH')
|
||||
ob.constraints["Follow Path"].target = mom
|
||||
ob.constraints["Follow Path"].use_fixed_location = True
|
||||
ob.constraints["Follow Path"].offset_factor = advance / curve_length
|
||||
ob.constraints["Follow Path"].use_curve_follow = True
|
||||
ob.constraints["Follow Path"].forward_axis = "FORWARD_X"
|
||||
ob.constraints["Follow Path"].up_axis = "UP_Y"
|
||||
|
||||
scalor = 0.001
|
||||
|
||||
glyph_advance = (-1 * glyph.bound_box[0][0] + glyph.bound_box[4][0]) * scalor + text_properties.letter_spacing
|
||||
|
||||
ob.scale = (scalor, scalor, scalor)
|
||||
mom.users_collection[0].objects.link(ob)
|
||||
|
||||
advance = advance + glyph_advance
|
||||
|
||||
glyph_data = text_properties.glyphs.add()
|
||||
glyph_data.glyph_id = glyph_id
|
||||
glyph_data.glyph_object = ob
|
||||
glyph_data.letter_spacing = 0
|
||||
ob.select_set(True)
|
||||
# selected_objects.append(ob)
|
||||
# selected_objects.append(mom)
|
||||
|
||||
mom.select_set(True)
|
||||
bpy.context.view_layer.objects.active = mom
|
||||
bpy.ops.object.parent_set(type='OBJECT')
|
||||
# bpy.ops.object.select_all(action='DESELECT')
|
||||
# for o in previous_selection:
|
||||
# o.select_set(True)
|
||||
|
||||
# context_override = bpy.context.copy()
|
||||
# context_override["selected_objects"] = selected_objects
|
||||
# context_override["active_object"] = mom
|
||||
# with bpy.context.temp_override(**context_override):
|
||||
# bpy.ops.object.parent_set(type='OBJECT')
|
||||
|
||||
|
||||
return True
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue