Esempio n. 1
0
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
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
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
Esempio n. 5
0
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
Esempio n. 6
0
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