def main():
    camera = tde4.getCurrentCamera()
    point_group = tde4.getCurrentPGroup()
    if camera is None or point_group is None:
        msg = 'There is no current Point Group or Camera.'
        tde4.postQuestionRequester(TITLE, msg, 'Ok')
        return

    # check if context menu has been used, and retrieve point...
    point = tde4.getContextMenuObject()
    if point is not None:
        # retrieve point's parent pgroup (not necessarily being the current one!)...
        point_group = tde4.getContextMenuParentObject()
        points = tde4.getPointList(point_group, 1)
    else:
        # otherwise use regular selection...
        points = tde4.getPointList(point_group, 1)
    if len(points) == 0:
        msg = 'There are no selected points.'
        tde4.postQuestionRequester(TITLE, msg, 'Ok')
        return

    # widget default values
    start_frame = 1
    # Backwards compatibility with 3DE4 Release 2.
    if uvtrack_format.SUPPORT_CAMERA_FRAME_OFFSET is True:
        start_frame = tde4.getCameraFrameOffset(camera)
    pattern = '*' + EXT
    # Undistortion default is 'On'.
    undistort = 1

    # GUI
    req = tde4.createCustomRequester()
    tde4.addFileWidget(req, 'file_browser_widget', 'Filename...', pattern)
    tde4.addTextFieldWidget(req, 'start_frame_widget', 'Start Frame', str(start_frame))
    tde4.addToggleWidget(req, 'undistort_widget', 'Apply Undistortion', undistort)
    ret = tde4.postCustomRequester(req, TITLE, 500, 0, 'Ok', 'Cancel')
    if ret == 1:
        # Query GUI Widgets
        path = tde4.getWidgetValue(req, 'file_browser_widget')
        start_frame = tde4.getWidgetValue(req, 'start_frame_widget')
        start_frame = int(start_frame)
        undistort = tde4.getWidgetValue(req, 'undistort_widget')
        undistort = bool(undistort)

        # Generate file contents
        data_str = uvtrack_format.generate(
            point_group, camera, points,
            start_frame=start_frame,
            undistort=undistort
        )

        # Write file.
        if path.find(EXT, len(path)-3) == -1:
            # Ensure the file path ends with the extension, if not add it.
            path += EXT
        f = open(path, 'w')
        if f.closed:
            msg = "Error, couldn't open file.\n"
            msg += repr(path)
            tde4.postQuestionRequester(TITLE, msg, 'Ok')
            return
        f.write(data_str)
        f.close()
    return
def main():
    camera = tde4.getCurrentCamera()
    point_group = tde4.getCurrentPGroup()
    if camera is None or point_group is None:
        msg = 'There is no current Point Group or Camera.'
        tde4.postQuestionRequester(TITLE, msg, 'Ok')
        return

    # check if context menu has been used, and retrieve point...
    point = tde4.getContextMenuObject()
    if point is not None:
        # retrieve point's parent pgroup (not necessarily being the current
        # one!)...
        point_group = tde4.getContextMenuParentObject()
        points = tde4.getPointList(point_group, 1)
    else:
        # otherwise use regular selection...
        points = tde4.getPointList(point_group, 1)
    if len(points) == 0:
        msg = 'There are no selected points.'
        tde4.postQuestionRequester(TITLE, msg, 'Ok')
        return

    # widget default values
    start, end, step = tde4.getCameraSequenceAttr(camera)
    start_frame = start
    # Backwards compatibility with 3DE4 Release 2.
    if uvtrack_format.SUPPORT_CAMERA_FRAME_OFFSET is True:
        start_frame = tde4.getCameraFrameOffset(camera)
    pattern = '*' + EXT

    rs_enabled = False
    rs_distance = None
    # Backwards compatibility with 3DE4 Release 1.
    if uvtrack_format.SUPPORT_RS_ENABLED is True:
        rs_enabled = bool(tde4.getCameraRollingShutterEnabledFlag(camera))

    # GUI
    req = tde4.createCustomRequester()
    tde4.addFileWidget(req, 'file_browser_widget', 'Filename...', pattern)
    tde4.addTextFieldWidget(req, 'start_frame_widget', 'Start Frame',
                            str(start_frame))
    if rs_enabled is True:
        rs_distance = uvtrack_format.get_rs_distance(camera)
        tde4.addTextFieldWidget(req, 'rs_distance_widget',
                                'Rolling Shutter Content Distance [cm]',
                                str(rs_distance))
    ret = tde4.postCustomRequester(req, TITLE, 900, 0, 'Ok', 'Cancel')
    if ret == 1:
        # Query GUI Widgets
        path = tde4.getWidgetValue(req, 'file_browser_widget')
        start_frame = tde4.getWidgetValue(req, 'start_frame_widget')
        start_frame = int(start_frame)
        if rs_enabled is True:
            rs_distance = tde4.getWidgetValue(req, 'rs_distance_widget')
            rs_distance = float(rs_distance)
            uvtrack_format.set_rs_distance(camera, rs_distance)

        # Generate file contents
        data_str = uvtrack_format.generate(
            point_group,
            camera,
            points,
            start_frame=start_frame,
            rs_distance=rs_distance,
            fmt=uvtrack_format.UV_TRACK_FORMAT_VERSION_PREFERRED,
        )

        # Write file.
        if path.find(EXT, len(path) - 3) == -1:
            # Ensure the file path ends with the extension, if not add it.
            path += EXT
        f = open(path, 'w')
        if f.closed:
            msg = "Error, couldn't open file.\n"
            msg += repr(path)
            tde4.postQuestionRequester(TITLE, msg, 'Ok')
            return
        f.write(data_str)
        f.close()
    return
def main():
    camera = tde4.getCurrentCamera()
    point_group = tde4.getCurrentPGroup()
    if camera is None or point_group is None:
        msg = 'There is no current Point Group or Camera.'
        tde4.postQuestionRequester(TITLE, msg, 'Ok')
        return

    # check if context menu has been used, and retrieve point...
    point = tde4.getContextMenuObject()
    if point is not None:
        # retrieve point's parent pgroup (not necessarily being the current
        # one!)...
        point_group = tde4.getContextMenuParentObject()
        points = tde4.getPointList(point_group, 1)
    else:
        # otherwise use regular selection...
        points = tde4.getPointList(point_group, 1)
    if len(points) == 0:
        msg = 'There are no selected points.'
        tde4.postQuestionRequester(TITLE, msg, 'Ok')
        return

    start, end, step = tde4.getCameraSequenceAttr(camera)
    start_frame = start
    # Backwards compatibility with 3DE4 Release 2.
    if uvtrack_format.SUPPORT_CAMERA_FRAME_OFFSET is True:
        start_frame = tde4.getCameraFrameOffset(camera)

    rs_enabled = False
    rs_distance = None
    # Backwards compatibility with 3DE4 Release 1.
    if uvtrack_format.SUPPORT_RS_ENABLED is True:
        rs_enabled = bool(tde4.getCameraRollingShutterEnabledFlag(camera))
    if rs_enabled is True:
        rs_distance = uvtrack_format.get_rs_distance(camera)
        if (uvtrack_format.SUPPORT_PROJECT_NOTES is True
                and uvtrack_format.SUPPORT_RS_DISTANCE is False):
            uvtrack_format.set_rs_distance_into_project_notes(rs_distance)

    # Generate file contents
    data_str = uvtrack_format.generate(
        point_group,
        camera,
        points,
        start_frame=start_frame,
        rs_distance=rs_distance,
        fmt=uvtrack_format.UV_TRACK_FORMAT_VERSION_PREFERRED)

    # Write file.
    file_ext = EXT
    # Prefix with the current time 'YYYY-MM-DD_HH_MM', for example
    # '2020-12-04_14_26'.
    now_str = time.strftime('%Y-%m-%d_%H_%M')
    prefix = 'tmp_{0}_'.format(now_str)
    f = tempfile.NamedTemporaryFile(mode='w',
                                    prefix=prefix,
                                    suffix=file_ext,
                                    delete=False)
    if f.closed:
        msg = "Error: Couldn't open file.\n%r"
        msg = msg % f.name
        tde4.postQuestionRequester(TITLE, msg, 'Ok')
        return
    f.write(data_str)
    f.close()

    # Override the user's clipboard with the temporary file path.
    if uvtrack_format.SUPPORT_CLIPBOARD is True:
        tde4.setClipboardString(f.name)
    else:
        # Cannot set the clipboard, so we'll print to the Python Console
        # and the user can copy it. Pretty bad workaround.
        print(f.name)
    return