metrics io
add functions for metrics saving and loading we need to add and remove faces. if they don't have faces, blender gltf loader will ignore the meshes. but we want them in the end only with vertices and edges.
This commit is contained in:
parent
65605aa2c0
commit
5c4ee030d3
1 changed files with 116 additions and 33 deletions
149
butils.py
149
butils.py
|
@ -510,6 +510,37 @@ def completely_delete_objects(objs):
|
||||||
# not important
|
# not important
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def is_mesh(o):
|
||||||
|
return type(o.data) == bpy.types.Mesh
|
||||||
|
|
||||||
|
def is_metrics_object(o):
|
||||||
|
return (re.match("[\w]*_metrics$", o.name) != None or re.match("[\w]*_metrics.[\d]{3}$", o.name) != None) and is_mesh(o)
|
||||||
|
|
||||||
|
def is_glyph(o):
|
||||||
|
try:
|
||||||
|
return type(o.parent) is not type(None) \
|
||||||
|
and "glyphs" in o.parent.name \
|
||||||
|
and is_mesh(o) \
|
||||||
|
and not is_metrics_object(o)
|
||||||
|
except ReferenceError as e:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# blender bound_box vertices
|
||||||
|
#
|
||||||
|
# 3------7.
|
||||||
|
# |`. | `. +y
|
||||||
|
# | `2------6 |
|
||||||
|
# | | | | |
|
||||||
|
# 0---|--4. | +--- +x
|
||||||
|
# `. | `.| `.
|
||||||
|
# `1------5 `+z
|
||||||
|
|
||||||
|
def get_glyph_advance(glyph_obj):
|
||||||
|
for c in glyph_obj.children:
|
||||||
|
if is_metrics_object(c):
|
||||||
|
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 set_text_on_curve(text_properties):
|
||||||
# starttime = time.perf_counter_ns()
|
# starttime = time.perf_counter_ns()
|
||||||
mom = text_properties.text_object
|
mom = text_properties.text_object
|
||||||
|
@ -601,35 +632,45 @@ def set_text_on_curve(text_properties):
|
||||||
elif distribution_type == 'CALCULATE':
|
elif distribution_type == 'CALCULATE':
|
||||||
location, tangent = calc_point_on_bezier_curve(mom, advance, True)
|
location, tangent = calc_point_on_bezier_curve(mom, advance, True)
|
||||||
ob.location = mom.matrix_world @ (location + text_properties.translation)
|
ob.location = mom.matrix_world @ (location + text_properties.translation)
|
||||||
mask = [0]
|
if not text_properties.ignore_orientation:
|
||||||
input_rotations = [mathutils.Vector((0.0, 0.0, 0.0))]
|
mask = [0]
|
||||||
vectors = [tangent]
|
input_rotations = [mathutils.Vector((0.0, 0.0, 0.0))]
|
||||||
factors = [1.0]
|
vectors = [tangent]
|
||||||
local_main_axis = mathutils.Vector((1.0, 0.0, 0.0))
|
factors = [1.0]
|
||||||
motor = align_rotations_auto_pivot(mask,
|
local_main_axis = mathutils.Vector((1.0, 0.0, 0.0))
|
||||||
input_rotations,
|
motor = align_rotations_auto_pivot(mask,
|
||||||
vectors,
|
input_rotations,
|
||||||
factors,
|
vectors,
|
||||||
local_main_axis)
|
factors,
|
||||||
if ob.rotation_mode != 'QUATERNION':
|
local_main_axis)
|
||||||
ob.rotation_mode = 'QUATERNION'
|
if ob.rotation_mode != 'QUATERNION':
|
||||||
q = mathutils.Quaternion()
|
ob.rotation_mode = 'QUATERNION'
|
||||||
q.rotate(text_properties.orientation)
|
q = mathutils.Quaternion()
|
||||||
ob.rotation_quaternion = (mom.matrix_world @ motor[0] @ q.to_matrix().to_4x4()).to_quaternion()
|
q.rotate(text_properties.orientation)
|
||||||
|
ob.rotation_quaternion = (mom.matrix_world @ motor[0] @ q.to_matrix().to_4x4()).to_quaternion()
|
||||||
|
else:
|
||||||
|
q = mathutils.Quaternion()
|
||||||
|
q.rotate(text_properties.orientation)
|
||||||
|
ob.rotation_quaternion = q
|
||||||
|
# ob.rotation_quaternion = (mom.matrix_world @ q.to_matrix().to_4x4()).to_quaternion()
|
||||||
|
|
||||||
scalor = 0.001 * text_properties.font_size
|
scalor = 0.001 * text_properties.font_size
|
||||||
|
|
||||||
glyph_advance = (-1 * glyph.bound_box[0][0] + glyph.bound_box[4][0]) * scalor + text_properties.letter_spacing
|
glyph_advance = get_glyph_advance(glyph) * scalor + text_properties.letter_spacing
|
||||||
|
|
||||||
# now we need to compensate for curvature
|
# now we need to compensate for curvature
|
||||||
# otherwise letters will be closer together the curvier the bezier is
|
# otherwise letters will be closer together the curvier the bezier is
|
||||||
# this could be done more efficiently, but whatever
|
# this could be done more efficiently, but whatever
|
||||||
curve_compensation = 0
|
curve_compensation = 0
|
||||||
previous_location = calc_point_on_bezier_curve(mom, advance, False)
|
if text_properties.compensate_curvature:
|
||||||
new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance, False)
|
previous_location = calc_point_on_bezier_curve(mom, advance, False)
|
||||||
while (previous_location - new_location).length < glyph_advance:
|
new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance, False)
|
||||||
curve_compensation = curve_compensation + glyph_advance * 0.01
|
while (previous_location - new_location).length > glyph_advance:
|
||||||
new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance + curve_compensation, False)
|
curve_compensation = curve_compensation - glyph_advance * 0.01
|
||||||
|
new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance + curve_compensation, False)
|
||||||
|
while (previous_location - new_location).length < glyph_advance:
|
||||||
|
curve_compensation = curve_compensation + glyph_advance * 0.01
|
||||||
|
new_location = calc_point_on_bezier_curve(mom, advance + glyph_advance + curve_compensation, False)
|
||||||
|
|
||||||
ob.scale = (scalor, scalor, scalor)
|
ob.scale = (scalor, scalor, scalor)
|
||||||
|
|
||||||
|
@ -695,20 +736,62 @@ def add_metrics_obj_from_bound_box(glyph, bound_box=None):
|
||||||
|
|
||||||
mesh.from_pydata(verts, edges, faces)
|
mesh.from_pydata(verts, edges, faces)
|
||||||
|
|
||||||
def is_mesh(o):
|
def add_faces_to_metrics(obj):
|
||||||
return type(o.data) == bpy.types.Mesh
|
mesh = bpy.data.meshes.new(f"{obj.name}") # add the new mesh
|
||||||
|
bound_box = bound_box_as_array(obj.bound_box)
|
||||||
|
verts = [bound_box[0],
|
||||||
|
bound_box[1],
|
||||||
|
bound_box[2],
|
||||||
|
bound_box[3],
|
||||||
|
bound_box[4],
|
||||||
|
bound_box[5],
|
||||||
|
bound_box[6],
|
||||||
|
bound_box[7],
|
||||||
|
]
|
||||||
|
edges = [[0,1],[1,2],[2,3],[3,0],
|
||||||
|
[0,4],[1,5],[2,6],[3,7],
|
||||||
|
[4,5],[5,6],[6,7],[7,4],
|
||||||
|
]
|
||||||
|
faces = [
|
||||||
|
[0,1,2], [2,3,0],
|
||||||
|
[2,6,7], [7,3,2],
|
||||||
|
[6,5,4], [4,7,6],
|
||||||
|
[4,5,1], [0,4,1],
|
||||||
|
[1,5,6], [1,6,2],
|
||||||
|
[4,0,7], [7,0,3],
|
||||||
|
]
|
||||||
|
|
||||||
def is_metrics_object(o):
|
mesh.from_pydata(verts, edges, faces)
|
||||||
return (re.match("[\w]*_metrics$", o.name) != None or re.match("[\w]*_metrics.[\d]{3}$", o.name) != None) and is_mesh(o)
|
|
||||||
|
old_mesh = obj.data
|
||||||
|
obj.data = mesh
|
||||||
|
bpy.data.meshes.remove(old_mesh)
|
||||||
|
|
||||||
|
def remove_faces_from_metrics(obj):
|
||||||
|
mesh = bpy.data.meshes.new(f"{obj.name}") # add the new mesh
|
||||||
|
bound_box = bound_box_as_array(obj.bound_box)
|
||||||
|
verts = [bound_box[0],
|
||||||
|
bound_box[1],
|
||||||
|
bound_box[2],
|
||||||
|
bound_box[3],
|
||||||
|
bound_box[4],
|
||||||
|
bound_box[5],
|
||||||
|
bound_box[6],
|
||||||
|
bound_box[7],
|
||||||
|
]
|
||||||
|
edges = [[0,1],[1,2],[2,3],[3,0],
|
||||||
|
[0,4],[1,5],[2,6],[3,7],
|
||||||
|
[4,5],[5,6],[6,7],[7,4],
|
||||||
|
]
|
||||||
|
faces = [
|
||||||
|
]
|
||||||
|
|
||||||
|
mesh.from_pydata(verts, edges, faces)
|
||||||
|
|
||||||
|
old_mesh = obj.data
|
||||||
|
obj.data = mesh
|
||||||
|
bpy.data.meshes.remove(old_mesh)
|
||||||
|
|
||||||
def is_glyph(o):
|
|
||||||
try:
|
|
||||||
return type(o.parent) is not type(None) \
|
|
||||||
and "glyphs" in o.parent.name \
|
|
||||||
and is_mesh(o) \
|
|
||||||
and not is_metrics_object(o)
|
|
||||||
except ReferenceError as e:
|
|
||||||
return False
|
|
||||||
# duplicate
|
# duplicate
|
||||||
# def remove_metrics_from_selection():
|
# def remove_metrics_from_selection():
|
||||||
# for o in bpy.context.selected_objects:
|
# for o in bpy.context.selected_objects:
|
||||||
|
|
Loading…
Reference in a new issue