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]), round(co[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(canvas_coords).y - min(canvas_coords).y) width = abs(max(canvas_coords).x - min(canvas_coords).x) 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