Example #1
0
 def __init__(self, parent=None):
     QtGui.QDialog.__init__(self, parent)
     self.ui = Ui_movie_dialog()
     self.ui.setupUi(self)
     self.setAcceptDrops(True)
     self.movie = movie_maker.V3dMovie()
     iconPath = os.path.join(os.path.dirname(movie_maker.__file__), 'icons')
     self.playIcon = QtGui.QIcon(os.path.join(iconPath, "play.png"))
     self.recordIcon = QtGui.QIcon(os.path.join(iconPath, "record.png"))
     self.pauseIcon = QtGui.QIcon(os.path.join(iconPath, "pause.png"))
     self.reelIcon = QtGui.QIcon(os.path.join(iconPath, "film_reel.png"))
     self.skipBackIcon = QtGui.QIcon(os.path.join(iconPath, "skip_backward.png"))
     self.skipAheadIcon = QtGui.QIcon(os.path.join(iconPath, "skip_ahead.png"))
     self.setWindowIcon(self.reelIcon)
     self.ui.frameCartoonLabel.hide() # its' just a placeholder
     self.configure_buttons()
     self.previous_save_dir = ""
     self._updateFrameCount()
     # Frame interval
     interval_validator = QtGui.QDoubleValidator(0.00, 10000.0, 2, 
             self.ui.frameIntervalSelector)
     self.ui.frameIntervalSelector.setValidator(interval_validator)
     self.connect(self.ui.frameIntervalSelector, QtCore.SIGNAL('textChanged(QString)'),
                  self.update_frame_interval)
     self.frame_interval = 2.5
     ix = self.ui.frameIntervalSelector.findText("2.50")
     self.ui.frameIntervalSelector.setCurrentIndex(ix)
     self._enter_state('ready')
Example #2
0
class MovieGui(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
        self.ui = Ui_movie_dialog()
        self.ui.setupUi(self)
        self.setAcceptDrops(True)
        self.movie = movie_maker.V3dMovie()
        iconPath = os.path.join(os.path.dirname(movie_maker.__file__), 'icons')
        self.playIcon = QtGui.QIcon(os.path.join(iconPath, "play.png"))
        self.recordIcon = QtGui.QIcon(os.path.join(iconPath, "record.png"))
        self.pauseIcon = QtGui.QIcon(os.path.join(iconPath, "pause.png"))
        self.reelIcon = QtGui.QIcon(os.path.join(iconPath, "film_reel.png"))
        self.skipBackIcon = QtGui.QIcon(os.path.join(iconPath, "skip_backward.png"))
        self.skipAheadIcon = QtGui.QIcon(os.path.join(iconPath, "skip_ahead.png"))
        self.setWindowIcon(self.reelIcon)
        self.ui.frameCartoonLabel.hide() # its' just a placeholder
        self.configure_buttons()
        self.previous_save_dir = ""
        self._updateFrameCount()
        # Frame interval
        interval_validator = QtGui.QDoubleValidator(0.00, 10000.0, 2, 
                self.ui.frameIntervalSelector)
        self.ui.frameIntervalSelector.setValidator(interval_validator)
        self.connect(self.ui.frameIntervalSelector, QtCore.SIGNAL('textChanged(QString)'),
                     self.update_frame_interval)
        self.frame_interval = 2.5
        ix = self.ui.frameIntervalSelector.findText("2.50")
        self.ui.frameIntervalSelector.setCurrentIndex(ix)
        self._enter_state('ready')
        
    def configure_buttons(self):
        self.connect(self.ui.addCurrentViewButton, QtCore.SIGNAL('clicked()'), 
               self.append_view)
        self.beginningButton = self.ui.playButtonBox.button(QtGui.QDialogButtonBox.Reset)
        self.beginningButton.setText('First')
        self.beginningButton.setToolTip("Go to the first key frame of your movie")
        # self.beginningButton = self.ui.buttonBox.addButton('Beginning', QtGui.QDialogButtonBox.ActionRole)
        self.beginningButton.setIcon(self.skipBackIcon)
        self.beginningButton.setEnabled(False)
        self.connect(self.beginningButton, QtCore.SIGNAL('clicked()'),
                     self.on_beginning_pressed)
        # self.playButton = self.ui.buttonBox.button(QtGui.QDialogButtonBox.Apply)
        # self.ui.buttonBox.button(QtGui.QDialogButtonBox.Apply).hide()
        self.playButton = self.ui.playButtonBox.addButton('Play', QtGui.QDialogButtonBox.ActionRole)
        self.playButton.setText("Play")
        self.playButton.setToolTip("Preview your movie")
        self.playButton.setIcon(self.playIcon)
        self.playButton.setMinimumWidth(100)
        self.connect(self.playButton, QtCore.SIGNAL('clicked()'),
               self.on_play_pause_pressed)
        self.endButton = self.ui.playButtonBox.addButton('Last', QtGui.QDialogButtonBox.ActionRole)
        self.endButton.setToolTip("Go to the final frame of your movie")
        self.endButton.setIcon(self.skipAheadIcon)
        self.endButton.setEnabled(False)
        self.connect(self.endButton, QtCore.SIGNAL('clicked()'),
                     self.on_end_pressed)
        self.saveImagesButton = self.ui.buttonBox.button(QtGui.QDialogButtonBox.Save)
        self.saveImagesButton.setText("Save images...")
        self.connect(self.saveImagesButton, QtCore.SIGNAL('clicked()'),
               self.save_images)
        # self.saveParametersButton = self.ui.buttonBox.addButton('Save', QtGui.QDialogButtonBox.ApplyRole)
        self.saveParametersButton = self.ui.buttonBox.button(QtGui.QDialogButtonBox.SaveAll)
        self.saveParametersButton.setText("Save...")
        self.saveParametersButton.setToolTip("Save your movie key frame parameters to a text file (.vmv format)")
        self.connect(self.saveParametersButton, QtCore.SIGNAL('clicked()'),
               self.save_parameters)
        # deleteAllButton used to be a generic button
        self.ui.deleteAllButton = self.ui.buttonBox.button(QtGui.QDialogButtonBox.Reset)
        self.ui.deleteAllButton.setText('Clear')
        self.ui.deleteAllButton.setToolTip("Delete all frames to start an empty movie")
        self.connect(self.ui.deleteAllButton, QtCore.SIGNAL('clicked()'),
               self.delete_all)
        self.loadButton = self.ui.buttonBox.button(QtGui.QDialogButtonBox.Open)
        self.loadButton.setToolTip("Load movie key frame parameters from a .vmv file")
        self.connect(self.loadButton, QtCore.SIGNAL('clicked()'),
                     self.load_parameters)
        self.helpButton = self.ui.playButtonBox.button(QtGui.QDialogButtonBox.Help)
        self.connect(self.helpButton, QtCore.SIGNAL('clicked()'),
                     self.help)
        self.ui.buttonBox.button(QtGui.QDialogButtonBox.Close).setToolTip(
                    "Close the movie maker window")
        self.ui.buttonBox.button(QtGui.QDialogButtonBox.Save).setToolTip(
                    "Write movie frame images to disk, so you can make a video file from them")

    def help(self):
        QtGui.QMessageBox.information(self, 
                "About V3D movie maker", 
                """
First adjust the V3D 3D window to the view you want to begin your movie with.  Next press "Add current view".  
Continue alternately changing the view and pressing "Add current view".

Press "Play" to preview your movie.

Press "Save images..." to save the movie frames to disk.
                """)
        
    def update_frame_interval(self, value_text):
        self.frame_interval = float(value_text)
        
    def show_frame(self, frame):
        self.movie.set_current_v3d_camera(frame.camera_position)
        self.movie.image_window.update() # The obviates need to print to get window update

    def delete_frame_cartoon(self, frame_cartoon):
        self.movie.key_frames.remove(frame_cartoon.frame)
        # TODO - remove label
        layout = self.ui.keyLabelFrame.layout()
        # Always remove any arrow label to the left of the frame label
        if frame_cartoon.arrow_label:
            layout.removeWidget(frame_cartoon.arrow_label)
        # TODO - if it's the first label, we should remove next one's arrow
        if layout.indexOf(frame_cartoon) == 1:
            if layout.count() >= 4:
                next_frame = layout.itemAt(3)
                next_frame.arrow_label = None
                print "deleting second frame arrow"
                layout.removeItem(layout.itemAt(2))
        layout.removeWidget(frame_cartoon)
        self._updateFrameCount()
        self._enter_state('ready')
        
    def replace_frame_cartoon(self, frame_cartoon):
        # print "replaced"
        frame_cartoon.frame.camera_position = self.movie.get_current_v3d_camera()
        
    def append_view(self):
        "Add a new key frame based on the current view in the V3D 3D viewer"
        # Perhaps there was no 3D viewer when the MovieGui was launched
        try:
            self.movie.append_current_view(interval=self.frame_interval)
        except ValueError:
            self.movie = movie_maker.V3dMovie()
            try:
                self.movie.append_current_view(interval=self.frame_interval)
            except:
                QtGui.QMessageBox.information(self,
                        "Movie maker cannot find a V3D 3D window.",
                        "Movie maker cannot find a V3D 3D window.  Perhaps you need to open one")
                return
        frame = self.movie.key_frames[-1]
        self.append_cartoon_frame(frame)
        self._updateFrameCount()
        self._enter_state('ready') # stop current animation

    def append_cartoon_frame(self, frame):
        "Add one frame cartoon to the cartoon panel"
        layout = self.ui.keyLabelFrame.layout()
        frame_cartoon = SingleKeyFrameLabel(self, frame)
        frame_cartoon.arrow_label = None
        if 1 < layout.count():
            # arrow
            arrow = FrameTransitionLabel(self, frame)
            layout.addWidget(arrow)
            frame_cartoon.arrow_label = arrow # so we can delete it at the same time
        frame_cartoon.go_to_frame.connect(self.show_frame)
        frame_cartoon.delete_frame.connect(self.delete_frame_cartoon)
        frame_cartoon.replace_frame.connect(self.replace_frame_cartoon)
        layout.addWidget(frame_cartoon)
        
    # There are three states - ready, playing, and paused
    def _enter_state(self, state):
        "Transition movie maker GUI to a new state, such as 'ready', 'playing', etc."
        # Ready to play from start
        self.play_state = state
        if 'ready' == state:
            self.play_generator = None
            self.playButton.setText('Play')
            self.playButton.setIcon(self.playIcon)
            self._updateFrameCount() # enable play button?
            self.ui.playbackLabel.setText('  (idle)  ')
        elif 'playing' == state:
            if None == self.play_generator:
                self.play_generator = self.movie.generate_play_frames()
            self.playButton.setText('Pause')
            self.playButton.setIcon(self.pauseIcon)
            self.endButton.setEnabled(True)
            self.beginningButton.setEnabled(True)
        elif 'paused' == state:
            assert None != self.play_generator
            self.playButton.setText('Play')
            self.playButton.setIcon(self.playIcon)
            self.endButton.setEnabled(True)
            self.beginningButton.setEnabled(True)
        else:
            assert(False)
        
    def on_play_pause_pressed(self):
        if ('ready' == self.play_state) or ('paused' == self.play_state): # play
            self._enter_state('playing')
            for elapsed_time in self.play_generator:
                self.update_play_time(elapsed_time)
                QtGui.QApplication.processEvents()
                if 'playing' != self.play_state:
                    return
            self._enter_state('ready')
        elif 'playing' == self.play_state:
            self._enter_state('paused')
        else: # stop
            assert(False)

    def update_play_time(self, elapsed_time):
        minutes = int(elapsed_time / 60.0)
        seconds = int(elapsed_time - minutes * 60)
        hundredths = int((elapsed_time - seconds - minutes * 60) * 100)
        time_string = "%02dm:%02d.%02ds" % (minutes, seconds, hundredths)
        self.ui.playbackLabel.setText(time_string)
        
    def on_beginning_pressed(self):
        self.movie.generate_play_frames().next()
        self._enter_state('ready')
        
    def on_end_pressed(self):
        self.movie.generate_final_frame_view()
        self._enter_state('ready')

    def save_images(self):
        dir = QtGui.QFileDialog.getExistingDirectory(
                    self,
                    "Choose directory to save frame files in",
                    self.previous_save_dir)
        if os.path.exists(dir):
            self.previous_save_dir = dir
            for n in self.movie.generate_write_frames(directory=str(dir)):
                QtGui.QApplication.processEvents()
            answer = QtGui.QMessageBox.information(self, "Frames saved", 
                 "Finished writing movie frames")
        self.show() # why does window get hidden in this method?

    def save_parameters(self):
        fname = QtGui.QFileDialog.getSaveFileName(
                    self,
                    "Choose file to save frame parameters in",
                    self.previous_save_dir,
                    "V3D movie files (*.vmv)")[0]
        if None == fname: return
        if len(fname) < 1: return
        fname = str(fname)
        # Note: Qt dialog already asks for confirmation.
        dir = os.path.dirname(fname)
        self.previous_save_dir = dir
        file_object = open(fname, 'w')
        self.movie.save_parameter_file(file_object)
        file_object.close()
        answer = QtGui.QMessageBox.information(self, "Parameters saved", 
             "Finished saving movie parameters file")
        self.show() # why does window get hidden in this method?

    def load_parameters(self):
        result = QtGui.QFileDialog.getOpenFileName(
                        self,
                        "Open V3D movie parameters file",
                        self.previous_save_dir,
                        "V3D movie files (*.vmv)")
        self.show() # why does window get hidden in this method?
        if None == result: return
        if 2 > len(result): return
        fname = result[0]
        if None == fname: return
        if len(fname) < 1: return
        if not os.path.exists(fname): 
            QtGui.QMessageBox.information(this, "No such file", "No such file")
            return
        file_object = open(fname, 'r')
        self.movie.load_parameter_file(file_object)
        self.clear_cartoon_panel()
        for frame in self.movie.key_frames:
            self.append_cartoon_frame(frame)
        self._updateFrameCount()
        self.show() # why does window get hidden in this method?
        
    def clear_cartoon_panel(self):
        # Remove the cartoons
        cartoon = self.ui.keyLabelFrame.layout().takeAt(0)
        while None != cartoon:
            cartoon = self.ui.keyLabelFrame.layout().takeAt(0)
        
    def delete_all(self):
        answer = QtGui.QMessageBox.question(self, "Confirm clear movie", 
                 "Really erase all key-frames?", 
                 QtGui.QMessageBox.Yes | QtGui.QMessageBox.No, 
                 QtGui.QMessageBox.No)
        if answer == QtGui.QMessageBox.Yes:
            self.movie.key_frames = []
            self.clear_cartoon_panel()
            self._updateFrameCount()
            self._enter_state('ready')

    def _updateFrameCount(self):
        nframes = len(self.movie.key_frames)
        if nframes == 0:
            self.ui.keyFrameLabel.setText("No key frames added")
            self.playButton.setEnabled(False)
            self.beginningButton.setEnabled(False)
            self.endButton.setEnabled(False)
            self.saveImagesButton.setEnabled(False)
            self.saveParametersButton.setEnabled(False)
            self.ui.deleteAllButton.setEnabled(False)
            self.ui.frameIntervalSelector.setEnabled(False)
        elif nframes == 1:
            self.ui.keyFrameLabel.setText("One key frame added")
            self.playButton.setEnabled(False)
            self.beginningButton.setEnabled(True)
            self.endButton.setEnabled(True)
            self.saveImagesButton.setEnabled(False)
            self.saveParametersButton.setEnabled(True)
            self.ui.deleteAllButton.setEnabled(True)
            self.ui.frameIntervalSelector.setEnabled(True)
        else:
            self.ui.keyFrameLabel.setText("%d key frames added" % nframes)
            self.playButton.setEnabled(True)
            self.beginningButton.setEnabled(True)
            self.endButton.setEnabled(True)
            self.saveImagesButton.setEnabled(True)
            self.saveParametersButton.setEnabled(True)
            self.ui.deleteAllButton.setEnabled(True)
            self.ui.frameIntervalSelector.setEnabled(True)