def create_convex_data(objects, convex_props={}, create_hull=False): """Creates a convex hull from selected objects...""" # SAVE ORIGINAL SELECTION original_selection = [] for obj in bpy.context.selected_objects: original_selection.append(obj) # MAKE A SELECTION FROM MESH OBJECTS make_objects_selected(objects) # IF MULTIPLE OBJECTS, CREATE JOINED MESH FROM ALL SELECTED MESHES bpy.ops.object.duplicate_move() original_active = None if bpy.context.active_object not in bpy.context.selected_objects: original_active = bpy.context.active_object bpy.context.scene.objects.active = bpy.context.selected_objects[0] if len(original_selection) > 1: bpy.ops.object.join() obj = object_to_delete = bpy.context.active_object for modifier in obj.modifiers: bpy.ops.object.modifier_apply(modifier=modifier.name) # if convex locator creation than decimate joined object to make sure # mesh is not to big for convex locator if not create_hull: modifier = obj.modifiers.new("triangulate", "TRIANGULATE") bpy.ops.object.modifier_apply(modifier=modifier.name) if len(obj.data.polygons ) > 256: # actually decimate if face count is to big initial_polycount = len(obj.data.polygons) modifier = obj.modifiers.new("decimate", "DECIMATE") while modifier.face_count > 256 or modifier.face_count < 200: # divide ratio by 2 until we get into desired count of faces diff = abs(modifier.ratio) / 2.0 if modifier.face_count > 256: diff *= -1.0 modifier.ratio += diff bpy.context.scene.update( ) # invoke scene update to get updated modifier bpy.ops.object.modifier_apply(modifier=modifier.name) lprint( "W Mesh used for convex locator was decimated because it had to many faces for convex locator.\n\t " + "Maximum triangles count is 256 but mesh had %s triangles.", (initial_polycount, )) # GET PROPERTIES FROM THE RESULTING OBJECT if not convex_props: convex_props = {'name': obj.name} convex_props = get_collider_props(obj, convex_props) # CREATE CONVEX HULL DATA geoms = {} mesh = obj.data bm = bmesh.new() bm.from_mesh(mesh) hull = None resulting_convex_object = None try: hull = bmesh.ops.convex_hull( bm, input=bm.verts, use_existing_faces=False, ) except RuntimeError: import traceback traceback.print_exc() # RETRIEVE CONVEX DATA # print(' > hull: %s' % str(hull)) if hull: for geom in ('geom', 'geom_unused', 'geom_holes', 'geom_interior'): geometry = hull[geom] # print('\n > geometry: %r' % geom) if geometry: verts = [] verts_index_correction = {} vert_i = 0 edges = [] faces = [] min_val = [None, None, None] max_val = [None, None, None] for item in geometry: # print(' > item[%i]: %s' % (item.index, str(item))) # print(' type: %s' % str(type(item))) # VERTICES if isinstance(item, bmesh.types.BMVert): vert_orig_index = item.index verts.append(item.co) # Bounding Box data evaluation min_val, max_val = _math.evaluate_minmax( item.co, min_val, max_val) verts_index_correction[vert_orig_index] = vert_i vert_i += 1 # EDGES # if isinstance(item, bmesh.types.BMEdge): # edges.append(item) # print(' > edge[%i]: %s' % (item.index, str(item.verts))) # FACES if isinstance(item, bmesh.types.BMFace): face_verts_correction = [] for vert in item.verts: face_verts_correction.append( verts_index_correction[vert.index]) # print(' > face[%i]: %s - %s' % (item.index, str(face_verts), str(face_verts_correction))) faces.append(face_verts_correction) # Bounding Box data creation bbox, bbcenter = _math.get_bb(min_val, max_val) geoms[geom] = (verts, faces, bbox, bbcenter) # CREATE CONVEX HULL MESH OBJECT if geom == 'geom' and create_hull: resulting_convex_object = make_mesh_from_verts_and_faces( verts, faces, convex_props) # make resulting object is on the same layers as joined object resulting_convex_object.layers = obj.layers bm.free() make_objects_selected((object_to_delete, )) bpy.ops.object.delete(use_global=True) # MAKE ORIGINAL ACTIVE OBJECT ACTIVE AGAIN if original_active: bpy.context.scene.objects.active = original_active if original_selection: make_objects_selected(original_selection) return geoms, convex_props, resulting_convex_object
def load(filepath): scs_globals = _get_scs_globals() print("\n************************************") print("** SCS PIC Importer **") print("** (c)2014 SCS Software **") print("************************************\n") ind = ' ' pic_container = _pix_container.get_data_from_file(filepath, ind) # TEST PRINTOUTS # ind = ' ' # for section in pic_container: # print('SEC.: "%s"' % section.type) # for prop in section.props: # print('%sProp: %s' % (ind, prop)) # for data in section.data: # print('%sdata: %s' % (ind, data)) # for sec in section.sections: # print_section(sec, ind) # print('\nTEST - Source: "%s"' % pic_container[0].props[1][1]) # print('') # TEST EXPORT # path, file = os.path.splitext(filepath) # export_filepath = str(path + '_reex' + file) # result = pix_write.write_data(pic_container, export_filepath, ind) # if result == {'FINISHED'}: # Print(dump_level, '\nI Test export succesful! The new file:\n "%s"', export_filepath) # else: # Print(dump_level, '\nE Test export failed! File:\n "%s"', export_filepath) # LOAD HEADER ''' NOTE: skipped for now as no data needs to be readed format_version, source, f_type, f_name, source_filename, author = _get_header(pic_container) ''' # LOAD GLOBALS ''' NOTE: skipped for now as no data needs to be readed vertex_count, triangle_count, material_count, piece_count, part_count, locator_count = _get_global(pic_container) ''' # LOAD MATERIALS if 0: # NOTE: NO MATERIALS USED FOR COLLIDERS AT A MOMENT! loaded_materials = [] for section in pic_container: if section.type == 'Material': material_alias, material_effect = _get_material(section) lprint('I Adding a Material Alias: "%s"', material_alias) loaded_materials.append(material_alias) # PRINT "MATERIAL SETTINGS" TO CONSOLE... if 0: import pprint pp = pprint.PrettyPrinter(indent=1) print("=== MATERIAL SETTINGS ==========================") pp.pprint(material_effect) print("==================================================") # LOAD PARTS parts = [] for section in pic_container: if section.type == "Part": (name, pieces, locators) = _get_part(section) parts.append({ "name": name, "pieces": pieces, "locators": locators }) # LOAD (CONVEX) PIECES pieces = [] for section in pic_container: if section.type == 'Piece': pieces.append(_get_piece(section)) # LOAD AND CREATE LOCATORS import_scale = scs_globals.import_scale locators = [] for section in pic_container: if section.type == 'Locator': (locator_name, locator_index, locator_position, locator_rotation, locator_alias, locator_weight, locator_type, locator_parameters, locator_convex_piece) = _get_locator(section) lprint('I Adding a Locator: "%s"', locator_name) locator = _object_utils.create_locator_empty( locator_name, locator_position, locator_rotation, (1, 1, 1), 1.0, 'Collision') locator.scs_props.scs_part = _get_locator_part( parts, locator_index) locator.scs_props.locator_collider_centered = True locator.scs_props.locator_collider_mass = locator_weight locator.scs_props.locator_collider_type = locator_type if locator_type == 'Box': locator.scs_props.locator_collider_box_x = locator_parameters[ 0] * import_scale locator.scs_props.locator_collider_box_y = locator_parameters[ 2] * import_scale locator.scs_props.locator_collider_box_z = locator_parameters[ 1] * import_scale elif locator_type in ('Sphere', 'Capsule', 'Cylinder'): locator.scs_props.locator_collider_dia = locator_parameters[ 0] * 2 * import_scale locator.scs_props.locator_collider_len = locator_parameters[ 1] * import_scale elif locator_type == 'Convex': piece_index, piece_material, verts, faces = pieces[ locator_convex_piece] if verts and faces: # BOUNDING BOX DATA CREATION AND SPACE CONVERSION min_val = [None, None, None] max_val = [None, None, None] scs_verts = [] for vert in verts: scs_vert = _convert_utils.change_to_scs_xyz_coordinates( vert, import_scale) scs_verts.append(scs_vert) min_val, max_val = _math_utils.evaluate_minmax( scs_vert, min_val, max_val) bbox, bbcenter = _math_utils.get_bb(min_val, max_val) # FACE FLIPPING flipped_faces = _mesh_utils.flip_faceverts(faces) # COLLIDER CREATION geom_data = (scs_verts, flipped_faces, bbox, bbcenter) _object_utils.add_collider_convex_locator( geom_data, {}, locator) locators.append(locator) # DATA BUILDING # WARNING PRINTOUTS # if piece_count < 0: Print(dump_level, '\nW More Pieces found than were declared!') # if piece_count > 0: Print(dump_level, '\nW Some Pieces not found, but were declared!') # if dump_level > 1: print('') print("************************************") return {'FINISHED'}, locators
def create_convex_data(objects, convex_props={}, create_hull=False): """Creates a convex hull from selected objects...""" # SAVE ORIGINAL SELECTION original_selection = [] for obj in bpy.context.selected_objects: original_selection.append(obj) # MAKE A SELECTION FROM MESH OBJECTS make_objects_selected(objects) # IF MULTIPLE OBJECTS, CREATE JOINED MESH FROM ALL SELECTED MESHES bpy.ops.object.duplicate_move() original_active = None if bpy.context.active_object not in bpy.context.selected_objects: original_active = bpy.context.active_object bpy.context.scene.objects.active = bpy.context.selected_objects[0] if len(original_selection) > 1: bpy.ops.object.join() obj = object_to_delete = bpy.context.active_object for modifier in obj.modifiers: bpy.ops.object.modifier_apply(modifier=modifier.name) # if convex locator creation than decimate joined object to make sure # mesh is not to big for convex locator if not create_hull: modifier = obj.modifiers.new("triangulate", "TRIANGULATE") bpy.ops.object.modifier_apply(modifier=modifier.name) if len(obj.data.polygons) > 256: # actually decimate if face count is to big initial_polycount = len(obj.data.polygons) modifier = obj.modifiers.new("decimate", "DECIMATE") while modifier.face_count > 256 or modifier.face_count < 200: # divide ratio by 2 until we get into desired count of faces diff = abs(modifier.ratio) / 2.0 if modifier.face_count > 256: diff *= -1.0 modifier.ratio += diff bpy.context.scene.update() # invoke scene update to get updated modifier bpy.ops.object.modifier_apply(modifier=modifier.name) lprint( "W Mesh used for convex locator was decimated because it had to many faces for convex locator.\n\t " + "Maximum triangles count is 256 but mesh had %s triangles.", (initial_polycount,), ) # GET PROPERTIES FROM THE RESULTING OBJECT if not convex_props: convex_props = {"name": obj.name} convex_props = get_collider_props(obj, convex_props) # CREATE CONVEX HULL DATA geoms = {} mesh = obj.data bm = bmesh.new() bm.from_mesh(mesh) hull = None resulting_convex_object = None try: hull = bmesh.ops.convex_hull(bm, input=bm.verts, use_existing_faces=False) except RuntimeError: import traceback traceback.print_exc() # RETRIEVE CONVEX DATA # print(' > hull: %s' % str(hull)) if hull: for geom in ("geom", "geom_unused", "geom_holes", "geom_interior"): geometry = hull[geom] # print('\n > geometry: %r' % geom) if geometry: verts = [] verts_index_correction = {} vert_i = 0 edges = [] faces = [] min_val = [None, None, None] max_val = [None, None, None] for item in geometry: # print(' > item[%i]: %s' % (item.index, str(item))) # print(' type: %s' % str(type(item))) # VERTICES if isinstance(item, bmesh.types.BMVert): vert_orig_index = item.index verts.append(item.co) # Bounding Box data evaluation min_val, max_val = _math.evaluate_minmax(item.co, min_val, max_val) verts_index_correction[vert_orig_index] = vert_i vert_i += 1 # EDGES # if isinstance(item, bmesh.types.BMEdge): # edges.append(item) # print(' > edge[%i]: %s' % (item.index, str(item.verts))) # FACES if isinstance(item, bmesh.types.BMFace): face_verts_correction = [] for vert in item.verts: face_verts_correction.append(verts_index_correction[vert.index]) # print(' > face[%i]: %s - %s' % (item.index, str(face_verts), str(face_verts_correction))) faces.append(face_verts_correction) # Bounding Box data creation bbox, bbcenter = _math.get_bb(min_val, max_val) geoms[geom] = (verts, faces, bbox, bbcenter) # CREATE CONVEX HULL MESH OBJECT if geom == "geom" and create_hull: resulting_convex_object = make_mesh_from_verts_and_faces(verts, faces, convex_props) # make resulting object is on the same layers as joined object resulting_convex_object.layers = obj.layers bm.free() make_objects_selected((object_to_delete,)) bpy.ops.object.delete(use_global=True) # MAKE ORIGINAL ACTIVE OBJECT ACTIVE AGAIN if original_active: bpy.context.scene.objects.active = original_active if original_selection: make_objects_selected(original_selection) return geoms, convex_props, resulting_convex_object
def create_convex_data(objects, convex_props={}, create_hull=False): """Creates a convex hull from selected objects...""" # SAVE ORIGINAL SELECTION original_selection = [] for obj in bpy.context.selected_objects: original_selection.append(obj) # MAKE A SELECTION FROM MESH OBJECTS make_objects_selected(objects) # IF MULTIPLE OBJECTS, CREATE JOINED MESH FROM ALL SELECTED MESHES bpy.ops.object.duplicate_move() # print(' selected: %i - active: %r' % (len(bpy.context.selected_objects), str(bpy.context.active_object))) original_active = None if bpy.context.active_object not in bpy.context.selected_objects: original_active = bpy.context.active_object bpy.context.scene.objects.active = bpy.context.selected_objects[0] bpy.ops.object.join() bpy.ops.object.transform_apply(location=False, rotation=False, scale=True) obj = object_to_delete = bpy.context.active_object # GET PROPERTIES FROM THE RESULTING OBJECT if not convex_props: convex_props = { 'name': _name.make_unique_name(obj, str(obj.name), sep=".") } convex_props = get_collider_props(obj, convex_props) # CREATE CONVEX HULL DATA geoms = {} mesh = obj.data bm = bmesh.new() bm.from_mesh(mesh) hull = None resulting_convex_object = None try: hull = bmesh.ops.convex_hull( bm, input=bm.verts, use_existing_faces=False, ) except RuntimeError: import traceback traceback.print_exc() # RETRIEVE CONVEX DATA # print(' > hull: %s' % str(hull)) if hull: for geom in ('geom', 'geom_unused', 'geom_holes', 'geom_interior'): geometry = hull[geom] # print('\n > geometry: %r' % geom) if geometry: verts = [] verts_index_correction = {} vert_i = 0 edges = [] faces = [] min_val = [None, None, None] max_val = [None, None, None] for item in geometry: # print(' > item[%i]: %s' % (item.index, str(item))) # print(' type: %s' % str(type(item))) # VERTICES if isinstance(item, bmesh.types.BMVert): vert_orig_index = item.index verts.append(item.co) # Bounding Box data evaluation min_val, max_val = _math.evaluate_minmax( item.co, min_val, max_val) verts_index_correction[vert_orig_index] = vert_i vert_i += 1 # EDGES # if isinstance(item, bmesh.types.BMEdge): # edges.append(item) # print(' > edge[%i]: %s' % (item.index, str(item.verts))) # FACES if isinstance(item, bmesh.types.BMFace): face_verts_correction = [] for vert in item.verts: face_verts_correction.append( verts_index_correction[vert.index]) # print(' > face[%i]: %s - %s' % (item.index, str(face_verts), str(face_verts_correction))) faces.append(face_verts_correction) # Bounding Box data creation bbox, bbcenter = _math.get_bb(min_val, max_val) geoms[geom] = (verts, faces, bbox, bbcenter) # CREATE CONVEX HULL MESH OBJECT if geom == 'geom' and create_hull: resulting_convex_object = make_mesh_from_verts_and_faces( verts, faces, convex_props) # else: # print(' < NO DATA (%r)' % geom) bm.free() make_objects_selected((object_to_delete, )) bpy.ops.object.delete(use_global=True) # MAKE ORIGINAL ACTIVE OBJECT ACTIVE AGAIN if original_active: bpy.context.scene.objects.active = original_active if original_selection: make_objects_selected(original_selection) return geoms, convex_props, resulting_convex_object
def create_convex_data(objects, convex_props={}, return_hull_object=False, max_face_count=256): """Creates a convex hull from selected objects... :param objects: list of blender objects to make convex hull from :type objects: list[bpy.types.Object] :param convex_props: existing convexr properties gotten with get_collider_props :type convex_props: dict :param return_hull_object: should convex data be as normal blender mesh object? :type return_hull_object: bool :param max_face_count: maximum number of faces that returned hull object can have, in interval (256, 6) :type max_face_count: int :return: tuple[(verts, faces, bb_size, bb_center), convex_props, returned_hull_object) :rtype: tuple[tuple, dict, bpy.types.Object] """ assert 6 <= max_face_count <= 256 # save original selection original_selection = [] for obj in bpy.context.selected_objects: original_selection.append(obj) # save original active original_active = bpy.context.active_object # make a selection from mesh objects make_objects_selected(objects) # if multiple objects, create joined mesh from all selected meshes bpy.ops.object.duplicate_move() if bpy.context.active_object not in bpy.context.selected_objects: bpy.context.view_layer.objects.active = bpy.context.selected_objects[0] if len(original_selection) > 1: bpy.ops.object.join() obj = object_to_delete = bpy.context.active_object for modifier in obj.modifiers: bpy.ops.object.modifier_apply(modifier=modifier.name) # get properties from the resulting object if not convex_props: convex_props = {'name': obj.name} convex_props = get_collider_props(obj, convex_props) # create convex hull data mesh = obj.data bm = bmesh.new() bm.from_mesh(mesh) bmesh.ops.remove_doubles(bm, verts=bm.verts, dist=0.01) # delete everything except verts, otherwise convex hull doesn't work as expected for face in bm.faces: bm.faces.remove(face) for edge in bm.edges: bm.edges.remove(edge) convex_hull_res = bmesh.ops.convex_hull(bm, input=bm.verts) # now again remove everything except real convex hull geometry for geom_type in ('geom_interior', 'geom_unused', 'geom_holes'): for item in convex_hull_res[geom_type]: try: if isinstance(item, bmesh.types.BMVert): bm.verts.remove(item) elif isinstance(item, bmesh.types.BMEdge): bm.edges.remove(item) elif isinstance(item, bmesh.types.BMFace): bm.faces.remove(item) except ReferenceError: continue # transform back to mesh bm.normal_update() bm.to_mesh(mesh) bm.free() # if convex locator creation then decimate convex hull even more to make sure mesh is not to big for convex locator if not return_hull_object and len(mesh.polygons) > max_face_count: initial_polycount = len(mesh.polygons) modifier = obj.modifiers.new("decimate", "DECIMATE") bpy.context.view_layer.update() while (modifier.face_count > max_face_count or modifier.face_count < max(max_face_count - 10, 10)) and modifier.ratio > 0.01: # divide ratio by 2 until we get into desired count of faces diff = abs(modifier.ratio) / 2.0 if modifier.face_count > max_face_count: diff *= -1.0 modifier.ratio += diff bpy.context.view_layer.update() # invoke depsgraph update to get updated modifier print("WHILE:", modifier.face_count, modifier.ratio) bpy.ops.object.modifier_apply(modifier=modifier.name) lprint("I Mesh used for convex locator was decimated because it had to many faces for convex locator.\n\t " + "Maximum triangles count is %i but mesh had %s triangles.", (max_face_count, initial_polycount)) # retrieve convex data verts = [] faces = [] min_val = [None, None, None] max_val = [None, None, None] for vert in mesh.vertices: verts.append(tuple(vert.co)) # Bounding Box data evaluation min_val, max_val = _math.evaluate_minmax(verts[-1], min_val, max_val) for poly in mesh.polygons: assert len(poly.vertices) == 3 faces.append(tuple(poly.vertices)) # bbox data creation bbox, bbcenter = _math.get_bb(min_val, max_val) geom = (verts, faces, bbox, bbcenter) # should have volume, if it doesn't it's not really a shape for axis_size in bbox: if axis_size == 0: geom = None # create convex hull object to return resulting_convex_object = None if return_hull_object and geom: resulting_convex_object = make_mesh_from_verts_and_faces(verts, faces, convex_props) # make sure resulting object is on the same collections as joined object for col in resulting_convex_object.users_collection: col.objects.unlink(resulting_convex_object) for col in obj.users_collection: col.objects.link(resulting_convex_object) make_objects_selected((object_to_delete,)) bpy.ops.object.delete(use_global=True) # make original active object active again if original_selection or original_active: make_objects_selected(original_selection, active_object=original_active) return geom, convex_props, resulting_convex_object
def load(filepath): scs_globals = _get_scs_globals() print("\n************************************") print("** SCS PIC Importer **") print("** (c)2014 SCS Software **") print("************************************\n") ind = ' ' pic_container = _pix_container.get_data_from_file(filepath, ind) # TEST PRINTOUTS # ind = ' ' # for section in pic_container: # print('SEC.: "%s"' % section.type) # for prop in section.props: # print('%sProp: %s' % (ind, prop)) # for data in section.data: # print('%sdata: %s' % (ind, data)) # for sec in section.sections: # print_section(sec, ind) # print('\nTEST - Source: "%s"' % pic_container[0].props[1][1]) # print('') # TEST EXPORT # path, file = os.path.splitext(filepath) # export_filepath = str(path + '_reex' + file) # result = pix_write.write_data(pic_container, export_filepath, ind) # if result == {'FINISHED'}: # Print(dump_level, '\nI Test export succesful! The new file:\n "%s"', export_filepath) # else: # Print(dump_level, '\nE Test export failed! File:\n "%s"', export_filepath) # LOAD HEADER ''' NOTE: skipped for now as no data needs to be readed format_version, source, f_type, f_name, source_filename, author = _get_header(pic_container) ''' # LOAD GLOBALS ''' NOTE: skipped for now as no data needs to be readed vertex_count, triangle_count, material_count, piece_count, part_count, locator_count = _get_global(pic_container) ''' # LOAD MATERIALS if 0: # NOTE: NO MATERIALS USED FOR COLLIDERS AT A MOMENT! loaded_materials = [] for section in pic_container: if section.type == 'Material': material_alias, material_effect = _get_material(section) lprint('I Adding a Material Alias: "%s"', material_alias) loaded_materials.append(material_alias) # PRINT "MATERIAL SETTINGS" TO CONSOLE... if 0: import pprint pp = pprint.PrettyPrinter(indent=1) print("=== MATERIAL SETTINGS ==========================") pp.pprint(material_effect) print("==================================================") # LOAD PARTS parts = [] for section in pic_container: if section.type == "Part": (name, pieces, locators) = _get_part(section) parts.append({"name": name, "pieces": pieces, "locators": locators}) # LOAD (CONVEX) PIECES pieces = [] for section in pic_container: if section.type == 'Piece': pieces.append(_get_piece(section)) # LOAD AND CREATE LOCATORS import_scale = scs_globals.import_scale locators = [] for section in pic_container: if section.type == 'Locator': (locator_name, locator_index, locator_position, locator_rotation, locator_alias, locator_weight, locator_type, locator_parameters, locator_convex_piece) = _get_locator(section) lprint('I Adding a Locator: "%s"', locator_name) locator = _object_utils.create_locator_empty(locator_name, locator_position, locator_rotation, (1, 1, 1), 1.0, 'Collision') locator.scs_props.scs_part = _get_locator_part(parts, locator_index) locator.scs_props.locator_collider_centered = True locator.scs_props.locator_collider_mass = locator_weight locator.scs_props.locator_collider_type = locator_type if locator_type == 'Box': locator.scs_props.locator_collider_box_x = locator_parameters[0] * import_scale locator.scs_props.locator_collider_box_y = locator_parameters[2] * import_scale locator.scs_props.locator_collider_box_z = locator_parameters[1] * import_scale elif locator_type in ('Sphere', 'Capsule', 'Cylinder'): locator.scs_props.locator_collider_dia = locator_parameters[0] * 2 * import_scale locator.scs_props.locator_collider_len = locator_parameters[1] * import_scale elif locator_type == 'Convex': piece_index, piece_material, verts, faces = pieces[locator_convex_piece] if verts and faces: # BOUNDING BOX DATA CREATION AND SPACE CONVERSION min_val = [None, None, None] max_val = [None, None, None] scs_verts = [] for vert in verts: scs_vert = _convert_utils.change_to_scs_xyz_coordinates(vert, import_scale) scs_verts.append(scs_vert) min_val, max_val = _math_utils.evaluate_minmax(scs_vert, min_val, max_val) bbox, bbcenter = _math_utils.get_bb(min_val, max_val) # FACE FLIPPING flipped_faces = _mesh_utils.flip_faceverts(faces) # COLLIDER CREATION geom_data = (scs_verts, flipped_faces, bbox, bbcenter) _object_utils.add_collider_convex_locator(geom_data, {}, locator) locators.append(locator) # DATA BUILDING # WARNING PRINTOUTS # if piece_count < 0: Print(dump_level, '\nW More Pieces found than were declared!') # if piece_count > 0: Print(dump_level, '\nW Some Pieces not found, but were declared!') # if dump_level > 1: print('') print("************************************") return {'FINISHED'}, locators