182 lines
4.8 KiB
Python
182 lines
4.8 KiB
Python
import bpy
|
|
import bmesh
|
|
from mathutils import Vector, Matrix
|
|
from bpy_extras import mesh_utils
|
|
from .geometry_utils import bound_box_center
|
|
from .addon_utils import get_object_color
|
|
|
|
|
|
def border_over_shape(border, verts, loops):
|
|
for loop in loops:
|
|
for i, p in enumerate(loop):
|
|
a = Vector(verts[loop[i - 1]])
|
|
b = Vector(verts[p])
|
|
|
|
for j in range(0, 4):
|
|
c = border[j - 1]
|
|
d = border[j]
|
|
if intersect_line_line_2d(a, b, c, d):
|
|
return True
|
|
|
|
for point in verts:
|
|
if point_inside_rect(point, border):
|
|
return True
|
|
|
|
for point in border:
|
|
if point_over_shape(point, verts, loops):
|
|
return True
|
|
|
|
|
|
def border_loop(vert, loop):
|
|
border_edge = [e for e in vert.link_edges if e.is_rectary]
|
|
|
|
if border_edge:
|
|
for edge in border_edge:
|
|
other_vert = edge.other_vert(vert)
|
|
|
|
if not other_vert in loop:
|
|
loop.append(other_vert)
|
|
border_loop(other_vert, loop)
|
|
|
|
return loop
|
|
else:
|
|
return [vert]
|
|
|
|
|
|
def contour_loops(bm, vert_index=0, loops=None, vert_indices=None):
|
|
loops = loops or []
|
|
vert_indices = vert_indices or [v.index for v in bm.verts]
|
|
|
|
bm.verts.ensure_lookup_table()
|
|
|
|
loop = border_loop(bm.verts[vert_index], [bm.verts[vert_index]])
|
|
if len(loop) > 1:
|
|
loops.append(loop)
|
|
|
|
for v in loop:
|
|
vert_indices.remove(v.index)
|
|
|
|
if len(vert_indices):
|
|
contour_loops(bm, vert_indices[0], loops, vert_indices)
|
|
|
|
return loops
|
|
|
|
|
|
def get_shape_data(ob, matrix=None, depsgraph=None):
|
|
if not matrix:
|
|
matrix = Matrix()
|
|
if not depsgraph:
|
|
depsgraph = bpy.context.evaluated_depsgraph_get()
|
|
|
|
gamma = 1 / 2.2
|
|
eval_ob = ob.evaluated_get(depsgraph)
|
|
mesh = eval_ob.to_mesh()
|
|
|
|
bm = bmesh.new()
|
|
bm.from_mesh(mesh)
|
|
|
|
bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.002)
|
|
bmesh.ops.dissolve_limit(bm, angle_limit=0.001745, verts=bm.verts, edges=bm.edges)
|
|
|
|
bmesh.ops.connect_verts_concave(bm, faces=bm.faces)
|
|
bmesh.ops.triangulate(bm, faces=bm.faces)
|
|
|
|
edges = [[v.index for v in e.verts] for e in bm.edges if len(e.link_faces) <= 1]
|
|
bm.to_mesh(mesh)
|
|
mesh.update()
|
|
bm.clear()
|
|
|
|
points = []
|
|
polygons = []
|
|
depths = []
|
|
|
|
for vert in mesh.vertices:
|
|
co = matrix @ (ob.matrix_world @ Vector(vert.co))
|
|
points.append([round(co[0], 1), round(co[1], 1)])
|
|
|
|
depths += [co[2]]
|
|
|
|
if depths:
|
|
depth = max(depths)
|
|
else:
|
|
print(f"{ob.name} has no vertices")
|
|
depth = 0
|
|
|
|
for face in mesh.polygons:
|
|
polygons.append([v for v in face.vertices])
|
|
|
|
color = get_object_color(ob)
|
|
if color:
|
|
color = [round(pow(c, gamma), 4) for c in color]
|
|
else:
|
|
color = [0.5, 0.5, 0.5]
|
|
|
|
shape = {
|
|
"source_name": ob.name,
|
|
"tooltip": ob.rig_picker.name,
|
|
"depth": depth,
|
|
"points": points,
|
|
"polygons": polygons,
|
|
"edges": edges,
|
|
"color": color,
|
|
"type": ob.rig_picker.shape_type,
|
|
}
|
|
|
|
if shape["type"] == "OPERATOR":
|
|
shape["operator"] = ob.rig_picker.operator
|
|
shape["shortcut"] = ob.rig_picker.shortcut
|
|
|
|
elif shape["type"] == "BONE":
|
|
shape["bone"] = ob.rig_picker.name
|
|
|
|
eval_ob.to_mesh_clear()
|
|
|
|
return shape
|
|
|
|
|
|
def get_picker_data(collection):
|
|
picker_data = []
|
|
|
|
depsgraph = bpy.context.evaluated_depsgraph_get()
|
|
canvas = collection.rig_picker.canvas
|
|
|
|
if canvas.type == "CURVE":
|
|
canvas_points = canvas.data.splines[0].points
|
|
else:
|
|
canvas_points = canvas.data.vertices
|
|
|
|
canvas_coords = [canvas.matrix_world @ Vector((p.co)) for p in canvas_points]
|
|
|
|
height = abs(max(co.y for co in canvas_coords) - min(co.y for co in canvas_coords))
|
|
width = abs(max(co.x for co in canvas_coords) - min(co.x for co in canvas_coords))
|
|
|
|
center = sum(canvas_coords, Vector()) / len(canvas_coords)
|
|
scale = 2048 / max(height, width) # Reference height for the canvas
|
|
|
|
matrix = Matrix.Translation(-center)
|
|
matrix = Matrix.Scale(scale, 4) @ matrix
|
|
|
|
# sorted by their z axes
|
|
for ob in collection.all_objects:
|
|
if ob.instance_collection:
|
|
for shape in ob.instance_collection.all_objects:
|
|
picker_data.append(
|
|
get_shape_data(
|
|
shape, matrix=matrix @ ob.matrix_world, depsgraph=depsgraph
|
|
)
|
|
)
|
|
|
|
elif ob.type in ("MESH", "CURVE", "FONT"):
|
|
picker_data.append(get_shape_data(ob, matrix=matrix, depsgraph=depsgraph))
|
|
|
|
else:
|
|
# print(f'{ob.name} of type {ob.type} not supported')
|
|
continue
|
|
|
|
picker_data.sort(key=lambda x: x["depth"])
|
|
|
|
# print(picker_datas)
|
|
|
|
return picker_data
|
|
# rig.data.rig_picker['shapes'] = picker_datas
|