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