metrics
add metrics functions in butils
This commit is contained in:
parent
1bcce247e0
commit
b0dc8c8e71
1 changed files with 250 additions and 0 deletions
250
butils.py
250
butils.py
|
@ -3,6 +3,7 @@ import mathutils
|
|||
import queue
|
||||
import importlib
|
||||
import os
|
||||
import re
|
||||
# import time # for debugging performance
|
||||
|
||||
# then import dependencies for our addon
|
||||
|
@ -559,6 +560,7 @@ def set_text_on_curve(text_properties):
|
|||
if advance == next_line_advance:
|
||||
# self.report({'INFO'}, f"would like to add new line for {text_properties.text} please")
|
||||
print(f"would like to add new line for {text_properties.text} please")
|
||||
# TODO: add a new line
|
||||
advance = next_line_advance
|
||||
continue
|
||||
is_command = False
|
||||
|
@ -643,3 +645,251 @@ def set_text_on_curve(text_properties):
|
|||
# elapsedtime = endtime - starttime
|
||||
|
||||
return True
|
||||
|
||||
# blender bound_box vertices
|
||||
#
|
||||
# 3------7.
|
||||
# |`. | `. +y
|
||||
# | `2------6 -z |
|
||||
# | | | | `. |
|
||||
# 0---|--4. | `+--- +x
|
||||
# `. | `.|
|
||||
# `1------5
|
||||
|
||||
def add_metrics_obj_from_bound_box(glyph, bound_box=None):
|
||||
mesh = bpy.data.meshes.new(f"{glyph.name}_metrics") # add the new mesh
|
||||
obj = bpy.data.objects.new(mesh.name, mesh)
|
||||
col = glyph.users_collection[0]
|
||||
col.objects.link(obj)
|
||||
# bpy.context.view_layer.objects.active = obj
|
||||
obj.parent = glyph
|
||||
|
||||
if type(bound_box) == type(None):
|
||||
bound_box = glyph.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)
|
||||
|
||||
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
|
||||
# duplicate
|
||||
# def remove_metrics_from_selection():
|
||||
# for o in bpy.context.selected_objects:
|
||||
# is_possibly_glyph = is_mesh(o)
|
||||
# if is_possibly_glyph:
|
||||
# metrics = []
|
||||
# for c in o.children:
|
||||
# if is_metrics_object(c):
|
||||
# metrics.append(c)
|
||||
# completely_delete_objs(metrics)
|
||||
|
||||
def get_max_bound_box(bb_1, bb_2 = None):
|
||||
if type(bb_2) == type(None):
|
||||
bb_2 = bb_1
|
||||
x_max = max(bb_1[4][0], bb_2[4][0])
|
||||
x_min = min(bb_1[0][0], bb_2[0][0])
|
||||
y_max = max(bb_1[3][1], bb_2[3][1])
|
||||
y_min = min(bb_1[0][1], bb_2[0][1])
|
||||
z_max = max(bb_1[1][2], bb_2[1][2])
|
||||
z_min = min(bb_1[0][2], bb_2[0][2])
|
||||
return [
|
||||
mathutils.Vector((x_min, y_min, z_min)),
|
||||
mathutils.Vector((x_min, y_min, z_max)),
|
||||
mathutils.Vector((x_min, y_max, z_max)),
|
||||
mathutils.Vector((x_min, y_max, z_min)),
|
||||
|
||||
mathutils.Vector((x_max, y_min, z_min)),
|
||||
mathutils.Vector((x_max, y_min, z_max)),
|
||||
mathutils.Vector((x_max, y_max, z_max)),
|
||||
mathutils.Vector((x_max, y_max, z_min)),
|
||||
]
|
||||
|
||||
# blender bound_box vertices
|
||||
#
|
||||
# 3------7.
|
||||
# |`. | `. +y
|
||||
# | `2------6 |
|
||||
# | | | | |
|
||||
# 0---|--4. | +--- +x
|
||||
# `. | `.| `.
|
||||
# `1------5 `+z
|
||||
|
||||
# why not [ [0] * 3 ] * 8
|
||||
# https://stackoverflow.com/questions/2397141/how-to-initialize-a-two-dimensional-array-list-of-lists-if-not-using-numpy-in
|
||||
def bound_box_as_array(bound_box):
|
||||
array = [ [0] * 3 for i in range(8) ]
|
||||
for i in range(0, len(bound_box)):
|
||||
for j in range(0, len(bound_box[i])):
|
||||
array[i][j] = bound_box[i][j]
|
||||
return array
|
||||
|
||||
##
|
||||
# @brief get_metrics_bound_box
|
||||
# generates a metrics bounding box
|
||||
# where x-width comes from bb
|
||||
# and y-height + z-depth from bb_uebermetrics
|
||||
#
|
||||
# @param bb
|
||||
# @param bb_uebermetrics
|
||||
#
|
||||
# @return metrics
|
||||
def get_metrics_bound_box(bb, bb_uebermetrics):
|
||||
metrics = [[0] * 3] * 8
|
||||
# hurrays
|
||||
if type(bb_uebermetrics) == bpy.types.bpy_prop_array:
|
||||
metrics = bound_box_as_array(bb_uebermetrics)
|
||||
else:
|
||||
metrics = bb_uebermetrics.copy()
|
||||
metrics[0][0] = bb[0][0]
|
||||
metrics[1][0] = bb[1][0]
|
||||
metrics[2][0] = bb[2][0]
|
||||
metrics[3][0] = bb[3][0]
|
||||
metrics[4][0] = bb[4][0]
|
||||
metrics[5][0] = bb[5][0]
|
||||
metrics[6][0] = bb[6][0]
|
||||
metrics[7][0] = bb[7][0]
|
||||
return metrics
|
||||
|
||||
def add_default_metrics_to_objects(objects=None, overwrite_existing=False):
|
||||
if type(objects) == type(None):
|
||||
objects=bpy.context.selected_objects
|
||||
targets = []
|
||||
reference_bound_box = None
|
||||
for o in objects:
|
||||
is_possibly_glyph = is_glyph(o)
|
||||
if is_possibly_glyph:
|
||||
metrics = []
|
||||
for c in o.children:
|
||||
if is_metrics_object(c):
|
||||
metrics.append(c)
|
||||
|
||||
if len(metrics) == 0:
|
||||
targets.append(o)
|
||||
reference_bound_box = get_max_bound_box(o.bound_box, reference_bound_box)
|
||||
elif len(metrics) >= 0 and overwrite_existing:
|
||||
completely_delete_objs(metrics)
|
||||
targets.append(o)
|
||||
reference_bound_box = get_max_bound_box(o.bound_box, reference_bound_box)
|
||||
else:
|
||||
for m in metrics:
|
||||
reference_bound_box = get_max_bound_box(m.bound_box, reference_bound_box)
|
||||
for t in targets:
|
||||
bound_box = get_metrics_bound_box(t.bound_box, reference_bound_box)
|
||||
add_metrics_obj_from_bound_box(t, bound_box)
|
||||
|
||||
def remove_metrics_from_objects(objects=None):
|
||||
if type(objects) == type(None):
|
||||
objects=bpy.context.selected_objects
|
||||
metrics = []
|
||||
for o in objects:
|
||||
for c in o.children:
|
||||
if is_metrics_object(c):
|
||||
metrics.append(c)
|
||||
completely_delete_objs(metrics)
|
||||
|
||||
def align_metrics_of_objects_to_active_object(objects=None):
|
||||
if type(objects) == type(None):
|
||||
objects=bpy.context.selected_objects
|
||||
if len(objects) == 0:
|
||||
return "no objects selected"
|
||||
|
||||
# define the reference_bound_box
|
||||
reference_bound_box = None
|
||||
if type(bpy.context.active_object) == type(None):
|
||||
return "no active_object, but align_to_active_object is True"
|
||||
for c in bpy.context.active_object.children:
|
||||
if is_metrics_object(c):
|
||||
reference_bound_box = bound_box_as_array(c.bound_box)
|
||||
break
|
||||
if type(reference_bound_box) == type(None):
|
||||
if not is_mesh(bpy.context.active_object):
|
||||
return "active_object is not a mesh and does not have a metrics child"
|
||||
reference_bound_box = bound_box_as_array(bpy.context.active_object.bound_box)
|
||||
|
||||
# do it
|
||||
for o in objects:
|
||||
is_possibly_glyph = is_glyph(o)
|
||||
if is_possibly_glyph:
|
||||
metrics = []
|
||||
for c in o.children:
|
||||
if is_metrics_object(c):
|
||||
metrics.append(c)
|
||||
|
||||
bb = None
|
||||
if len(metrics) == 0:
|
||||
bb = get_metrics_bound_box(o.bound_box,
|
||||
reference_bound_box)
|
||||
else:
|
||||
bb = get_metrics_bound_box(metrics[0].bound_box,
|
||||
reference_bound_box)
|
||||
if len(metrics) > 0:
|
||||
completely_delete_objs(metrics)
|
||||
|
||||
add_metrics_obj_from_bound_box(o, bb)
|
||||
return ""
|
||||
|
||||
def align_metrics_of_objects(objects=None):
|
||||
if type(objects) == type(None):
|
||||
objects=bpy.context.selected_objects
|
||||
if len(objects) == 0:
|
||||
return "no objects selected"
|
||||
|
||||
targets = []
|
||||
reference_bound_box = None
|
||||
for o in objects:
|
||||
is_possibly_glyph = is_glyph(o)
|
||||
if is_possibly_glyph:
|
||||
metrics = []
|
||||
for c in o.children:
|
||||
if is_metrics_object(c):
|
||||
metrics.append(c)
|
||||
|
||||
if len(metrics) == 0:
|
||||
reference_bound_box = get_max_bound_box(o.bound_box,
|
||||
reference_bound_box)
|
||||
elif len(metrics) > 0:
|
||||
reference_bound_box = get_max_bound_box(metrics[0].bound_box,
|
||||
reference_bound_box)
|
||||
targets.append(o)
|
||||
for t in targets:
|
||||
metrics = []
|
||||
for c in t.children:
|
||||
if is_metrics_object(c):
|
||||
metrics.append(c)
|
||||
bound_box = None
|
||||
if len(metrics) == 0:
|
||||
bound_box = get_metrics_bound_box(t.bound_box,
|
||||
reference_bound_box)
|
||||
else:
|
||||
bound_box = get_metrics_bound_box(metrics[0].bound_box,
|
||||
reference_bound_box)
|
||||
completely_delete_objs(metrics)
|
||||
|
||||
add_metrics_obj_from_bound_box(t, bound_box)
|
||||
return ""
|
||||
|
|
Loading…
Reference in a new issue