Exemplo n.º 1
0
def createMenu(parentMenu, parentName, view):
    for menuItem in ButtleDataSingleton().get(
    ).getQObjectPluginsIdentifiersByParentPath(parentName):
        """
            TODO : Need to be documented.
        """
        # menuItem is a tuple : see getPluginsIdentifiersAsDictionary() is data/tuttleTools.py
        pluginParent, pluginId = menuItem  # if the item is not a plugin, pluginId = ""

        isAPlugin = ButtleDataSingleton().get().isAPlugin(pluginId) is True
        noPluginFound = pluginId is False

        if noPluginFound:
            action = QAction(pluginParent, parentMenu)
            action.setData(None)
            parentMenu.addAction(action)
        # If it is a plugin, we add it to the menu
        elif isAPlugin:
            action = QAction(pluginParent, parentMenu)
            action.setData(pluginId)
            parentMenu.addAction(action)
        # Else we create a new menu
        else:
            submenu = QMenu(view)
            submenu.setTitle(pluginParent)
            parentMenu.addMenu(submenu)
            createMenu(submenu, parentName + pluginParent + "/", view)
Exemplo n.º 2
0
    def canConnectTmpNodes(self, dataTmpClip, clip, clipIndex):
        """
            Returns True if the connection between the nodes is possible, else False.
            This function is called by Clip.qml on the event onDragEnter, to display in real time if the nodes can be connected (during a creation of a connection).
            It simulates a connection and calls the function self.canConnect(clip1, clip2).
        """
        buttleData = ButtleDataSingleton().get()

        # we split the data of the tmpClip (from mimeData) to find needed informations about this clip.
        infosTmpClip = dataTmpClip.split("/")

        if infosTmpClip[0] != "clip" or len(infosTmpClip) != 4:
            return False
        else:
            tmpClipNodeName, tmpClipName, tmpClipIndex = infosTmpClip[
                1], infosTmpClip[2], int(infosTmpClip[3])

        # we find the position of this tmpClip to be able to create a IdClip object.
        positionTmpClip = buttleData.getGraphWrapper().getPositionClip(
            tmpClipNodeName, tmpClipName, tmpClipIndex)
        tmpClip = IdClip(tmpClipNodeName, tmpClipName, clipIndex,
                         positionTmpClip)

        if tmpClip:
            # idem, for the "dropped" clip = newClip
            positionNewClip = buttleData.getGraphWrapper().getPositionClip(
                clip.getNodeName(), clip.getClipName(), clipIndex)
            newClip = IdClip(clip.getNodeName(), clip.getClipName(), clipIndex,
                             positionNewClip)

            # finally we return if the clips can be connected
            return self.canConnect(tmpClip, newClip)

        else:
            return False
Exemplo n.º 3
0
    def canConnect(self, clip1, clip2):
        """
            Returns True if the connection between the nodes is possible, else False.
            A connection is possible if the clip isn't already taken, and if the clips are from 2 different nodes, not already connected.
        """
        buttleData = ButtleDataSingleton().get()
        graph = buttleData.getGraph()

        # if the clips are from the same node : False
        if (clip1.getNodeName() == clip2.getNodeName()):
            return False

        # if the clips are 2 inputs or 2 outputs : False
        if (clip1.getClipName() == "Output" and clip2.getClipName()
                == "Output") or (clip1.getClipName() != "Output"
                                 and clip2.getClipName() != "Output"):
            return False

        # if the input clip is already taken : False
        if (clip1.getClipName() != "Output"
                and graph.contains(clip1)) or (clip2.getClipName() != "Output"
                                               and graph.contains(clip2)):
            return False

        # if the nodes containing the clips are already connected : False
        if (graph.nodesConnected(clip2, clip1)):
            return False

        return True
Exemplo n.º 4
0
 def getNbFrames(self):
     """
         Returns the number of frames of this node.
     """
     #import which needs to be changed in the future
     from buttleofx.data import ButtleDataSingleton
     buttleData = ButtleDataSingleton().get()
     graph = buttleData.getGraph().getGraphTuttle()
     node = self._node.getTuttleNode().asImageEffectNode()
     try:
         self.setFrameError("")
         graph.setup()
     except Exception as e:
         logging.debug("can't get nbFrames of the node" +
                       self._node.getName())
         self.setFrameError(str(e))
         return 0
         raise
     timeDomain = node.getTimeDomain(
     )  #getTimeDomain() returns first frame and last one
     nbFrames = timeDomain.max - timeDomain.min
     #not very elegant but allow to avoid a problem because an image returns a number of frames very high
     if nbFrames > 100000000 or nbFrames < 0:
         nbFrames = 1
     #print "nbFrames: ", nbFrames
     return nbFrames
Exemplo n.º 5
0
    def retrieveImage(self, frame, frameChanged):
        """
            Computes the node at the frame indicated if the frame has changed (if the time has changed).
        """
        buttleData = ButtleDataSingleton().get()
        #Get the name of the currentNode of the viewer
        node = buttleData.getCurrentViewerNodeName()
        #Get the gloabl hashCode of the node
        if node is not None:
            hashMap = tuttle.NodeHashContainer()
            buttleData.getGraph().getGraphTuttle().computeGlobalHashAtTime(hashMap, frame)
            node_hashCode = hashMap.getHash(node, frame)
        #Get the map
        mapNodeToImage = buttleData.getMapNodeNameToComputedImage()

        try:
            self.setNodeError("")
            for key in mapNodeToImage.keys():
                #If the image is already calculated
                if node_hashCode == key and frameChanged is False:
                    #print "**************************Image already calculated**********************"
                    return mapNodeToImage.get(node_hashCode)
            #If it is not
            #print "**************************Image is not already calculated**********************"
            return self.computeNode(node, frame)
        except Exception as e:
            logging.debug("Can't display node : " + node)
            self.setNodeError(str(e))
            raise
Exemplo n.º 6
0
    def nodeMoved(self, nodeName, newX, newY):
        """
            This function pushes a cmdMoved in the CommandManager.
        """

        from buttleofx.data import ButtleDataSingleton
        buttleData = ButtleDataSingleton().get()
        node = buttleData.getGraph().getNode(nodeName)

        # What is the value of the movement (compared to the old position) ?
        oldX, oldY = node.getOldCoord()
        xMovement = newX - oldX
        yMovement = newY - oldY

        # if the node did'nt really move, nothing is done
        if (xMovement, xMovement) == (0, 0):
            return

        commands = []

        # we create a GroupUndoableCommands of CmdSetCoord for each selected node
        for selectedNodeWrapper in buttleData.getCurrentSelectedNodeWrappers():
            # we get the needed informations for this node
            selectedNode = selectedNodeWrapper.getNode()
            selectedNodeName = selectedNode.getName()
            oldX, oldY = selectedNode.getOldCoord()

            # we set the new coordinates of the node (each selected node is doing the same movement)
            cmdMoved = CmdSetCoord(self, selectedNodeName, (oldX + xMovement, oldY + yMovement))
            commands.append(cmdMoved)

        # then we push the group of commands
        CommandManager().push(GroupUndoableCommands(commands))
Exemplo n.º 7
0
    def nodeMoved(self, nodeName, newX, newY):
        """
            This function pushes a cmdMoved in the CommandManager.
        """

        from buttleofx.data import ButtleDataSingleton
        buttleData = ButtleDataSingleton().get()
        node = buttleData.getGraph().getNode(nodeName)

        # What is the value of the movement (compared to the old position) ?
        oldX, oldY = node.getOldCoord()
        xMovement = newX - oldX
        yMovement = newY - oldY

        # if the node did'nt really move, nothing is done
        if (xMovement, xMovement) == (0, 0):
            return

        commands = []

        # we create a GroupUndoableCommands of CmdSetCoord for each selected node
        for selectedNodeWrapper in buttleData.getCurrentSelectedNodeWrappers():
            # we get the needed informations for this node
            selectedNode = selectedNodeWrapper.getNode()
            selectedNodeName = selectedNode.getName()
            oldX, oldY = selectedNode.getOldCoord()

            # we set the new coordinates of the node (each selected node is doing the same movement)
            cmdMoved = CmdSetCoord(self, selectedNodeName,
                                   (oldX + xMovement, oldY + yMovement))
            commands.append(cmdMoved)

        # then we push the group of commands
        CommandManager().push(GroupUndoableCommands(commands))
Exemplo n.º 8
0
    def canConnect(self, clip1, clip2):
        """
            Returns True if the connection between the nodes is possible, else False.
            A connection is possible if the clip isn't already taken, and if the clips are from 2 different nodes, not already connected.
        """
        buttleData = ButtleDataSingleton().get()
        graph = buttleData.getGraph()

        # if the clips are from the same node : False
        if (clip1.getNodeName() == clip2.getNodeName()):
            return False

        # if the clips are 2 inputs or 2 outputs : False
        if (clip1.getClipName() == "Output" and clip2.getClipName() == "Output") or (clip1.getClipName() != "Output" and clip2.getClipName() != "Output"):
            return False

        # if the input clip is already taken : False
        if (clip1.getClipName() != "Output" and graph.contains(clip1)) or (clip2.getClipName() != "Output" and graph.contains(clip2)):
            return False

        # if the nodes containing the clips are already connected : False
        if(graph.nodesConnected(clip2, clip1)):
            return False

        return True
Exemplo n.º 9
0
 def disconnect(self, connectionWrapper):
     """
         Removes a connection between 2 clips.
     """
     buttleData = ButtleDataSingleton().get()
     buttleData.getGraph().deleteConnection(
         connectionWrapper.getConnection())
Exemplo n.º 10
0
    def canConnectTmpNodes(self, dataTmpClip, clip, clipIndex):
        """
            Returns True if the connection between the nodes is possible, else False.
            This function is called by Clip.qml on the event onDragEnter, to display in real time if the nodes can be connected (during a creation of a connection).
            It simulates a connection and calls the function self.canConnect(clip1, clip2).
        """
        buttleData = ButtleDataSingleton().get()

        # we split the data of the tmpClip (from mimeData) to find needed informations about this clip.
        infosTmpClip = dataTmpClip.split("/")

        if infosTmpClip[0] != "clip" or len(infosTmpClip) != 4:
            return False
        else:
            tmpClipNodeName, tmpClipName, tmpClipIndex = infosTmpClip[1], infosTmpClip[2], int(infosTmpClip[3])

        # we find the position of this tmpClip to be able to create a IdClip object.
        positionTmpClip = buttleData.getGraphWrapper().getPositionClip(tmpClipNodeName, tmpClipName, tmpClipIndex)
        tmpClip = IdClip(tmpClipNodeName, tmpClipName, clipIndex, positionTmpClip)

        if tmpClip:
            # idem, for the "dropped" clip = newClip
            positionNewClip = buttleData.getGraphWrapper().getPositionClip(clip.getNodeName(), clip.getClipName(), clipIndex)
            newClip = IdClip(clip.getNodeName(), clip.getClipName(), clipIndex, positionNewClip)

            # finally we return if the clips can be connected
            return self.canConnect(tmpClip, newClip)

        else:
            return False
Exemplo n.º 11
0
    def creationNode(self, nodeType, x=20, y=20):
        """
            Creates a node.
        """
        buttleData = ButtleDataSingleton().get()
        buttleData.getGraph().createNode(nodeType, x, y)

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 12
0
    def nodeMoved(self, nodeName, x, y):
        """
            This function pushes a cmdMoved in the CommandManager.
        """
        buttleData = ButtleDataSingleton().get()
        buttleData.getGraph().nodeMoved(nodeName, x, y)

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 13
0
    def creationNode(self, nodeType, x=20, y=20):
        """
            Creates a node.
        """
        buttleData = ButtleDataSingleton().get()
        buttleData.getGraph().createNode(nodeType, x, y)

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 14
0
    def nodeMoved(self, nodeName, x, y):
        """
            This function pushes a cmdMoved in the CommandManager.
        """
        buttleData = ButtleDataSingleton().get()
        buttleData.getGraph().nodeMoved(nodeName, x, y)

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 15
0
 def pause(self):
     logging.debug("--------------pause-------------")
     self._timer.stop()
     buttleData = ButtleDataSingleton().get()
     if buttleData.getVideoIsPlaying():
         buttleData.setVideoIsPlaying(False)
         # close processGraph and delete it
         buttleData.getProcessGraph().endSequence()
         buttleData.setProcessGraph(None)
     self.framePlayerChanged.emit()
Exemplo n.º 16
0
    def emitNodeContentChanged(self):
        """
            If necessary, call emitOneParamChangedSignal, to warn buttleEvent that a param just changed (to update the viewer)
            Also emit nodeContentChanged signal, to warn the node wrapper that a param just changed (for property si secret of other params for example !)
        """
        from buttleofx.data import ButtleDataSingleton
        buttleData = ButtleDataSingleton().get()
        if (self._name == buttleData.getCurrentViewerNodeName()):
            # to buttleEvent
            buttleEvent = ButtleEventSingleton().get()
            buttleEvent.emitOneParamChangedSignal()

        # to the node wrapper
        self.nodeContentChanged()
Exemplo n.º 17
0
    def emitNodeContentChanged(self):
        """
            If necessary, call emitOneParamChangedSignal, to warn buttleEvent that a param just changed (to update the viewer)
            Also emit nodeContentChanged signal, to warn the node wrapper that a param just changed (for property si secret of other params for example !)
        """
        from buttleofx.data import ButtleDataSingleton
        buttleData = ButtleDataSingleton().get()
        if (self._name == buttleData.getCurrentViewerNodeName()):
            # to buttleEvent
            buttleEvent = ButtleEventSingleton().get()
            buttleEvent.emitOneParamChangedSignal()

        # to the node wrapper
        self.nodeContentChanged()
Exemplo n.º 18
0
 def deleteSelection(self):
     buttleData = ButtleDataSingleton().get()
     if (buttleData.currentConnectionWrapper):
         self._connectionManager.disconnect(
             buttleData.currentConnectionWrapper)
     else:
         self._nodeManager.destructionNodes()
Exemplo n.º 19
0
    def dropFile(self, url, x, y):
        """
            Drops a file on the graph.
            - Image or video : creates a reader node.
            - Json : load a graph (if the format allows it)
        """
        buttleData = ButtleDataSingleton().get()

        extension = url.split(".")[-1].lower()
        if extension == 'bofx':
            buttleData.loadData(url)  # also need to verify the json format
        else:
            buttleData.getGraph().createReaderNode(url, x, y)

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 20
0
 def graphHadChanged(self):
     """
         Indicates to ButtleData that a command just had been done.
         This function will update the property graphCanBeSaved of ButtleData and will change the display of the "save graph" icon.
     """
     from buttleofx.data import ButtleDataSingleton
     ButtleDataSingleton().get().setGraphCanBeSaved(self.savedGraphIndex != self.index)
Exemplo n.º 21
0
    def connectionDropEvent(self, dataTmpClip, clip, clipIndex):
        """
            Creates or deletes a connection between 2 clips ('tmpClip', the "dragged" clip, and 'newClip', the "dropped" clip)
            Arguments :
            - dataTmpClip : the string from mimeData, identifying the tmpClip (the "dragged" clip).
            - clip : the ClipWrapper of the "dropped" clip.
            - clipIndex : the index of the "dropped" clip.
        """
        buttleData = ButtleDataSingleton().get()

        # we split the data of the tmpClip (from mimeData) to find needed informations about this clip.
        infosTmpClip = dataTmpClip.split("/")

        if infosTmpClip[0] != "clip" or len(infosTmpClip) != 4:
            return  # use exception !
        else:
            tmpClipNodeName, tmpClipName, tmpClipIndex = infosTmpClip[1], infosTmpClip[2], int(infosTmpClip[3])

        # we find the position of this tmpClip to be able to create a IdClip object.
        positionTmpClip = buttleData.getGraphWrapper().getPositionClip(tmpClipNodeName, tmpClipName, tmpClipIndex)
        tmpClip = IdClip(tmpClipNodeName, tmpClipName, clipIndex, positionTmpClip)

        if tmpClip:
            # idem, for the "dropped" clip = newClip
            positionNewClip = buttleData.getGraphWrapper().getPositionClip(clip.getNodeName(), clip.getClipName(), clipIndex)
            newClip = IdClip(clip.getNodeName(), clip.getClipName(), clipIndex, positionNewClip)

            # a connection must be created from the ouput clip to the input clip (the order of the arguments is important !)
            if tmpClip.getClipName() == "Output":
                clipOut, clipIn = tmpClip, newClip
            else:
                clipOut, clipIn = newClip, tmpClip

            # if the clips can be connected, we connect them
            if self.canConnect(clipOut, clipIn):
                self.connect(clipOut, clipIn)
                return

            # else if they can't be connected, we check if they are already connected, and disconnect them if it is the case.
            else:
                connection = buttleData.getGraph().getConnectionByClips(clipOut, clipIn)
                if connection:
                    self.disconnect(buttleData.getGraphWrapper().getConnectionWrapper(connection.getId()))
                    return

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 22
0
 def stop(self):
     logging.debug("--------------stop-------------")
     self._timer.stop()
     buttleData = ButtleDataSingleton().get()
     # if a video is reading, we need to close the processGraph
     if buttleData.getVideoIsPlaying():
         buttleData.setVideoIsPlaying(False)
         # close processGraph and delete it
         buttleData.getProcessGraph().endSequence()
         buttleData.setProcessGraph(None)
         # return to the beginning of the video
     self._frame = 0
     self.framePlayerChanged.emit()
Exemplo n.º 23
0
    def pasteNode(self):
        """
            Pasts the current node(s).
        """
        buttleData = ButtleDataSingleton().get()
        # If nodes have been copied previously
        if buttleData.getCurrentCopiedNodesInfo():
            # Create a copy for each node copied
            for node in buttleData.getCurrentCopiedNodesInfo():
                buttleData.getGraph().createNode(buttleData.getCurrentCopiedNodesInfo()[node]["nodeType"], 20, 20)
                newNode = buttleData.getGraph().getNodes()[-1]
                newNode.setColor(buttleData.getCurrentCopiedNodesInfo()[node]["color"])
                newNode.setNameUser(buttleData.getCurrentCopiedNodesInfo()[node]["nameUser"] + buttleData.getCurrentCopiedNodesInfo()[node]["mode"])
                newNode.getTuttleNode().getParamSet().copyParamsValues(buttleData.getCurrentCopiedNodesInfo()[node]["params"])

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 24
0
 def pause(self):
     logging.debug("--------------pause-------------")
     self._timer.stop()
     buttleData = ButtleDataSingleton().get()
     if buttleData.getVideoIsPlaying():
         buttleData.setVideoIsPlaying(False)
         # close processGraph and delete it
         buttleData.getProcessGraph().endSequence()
         buttleData.setProcessGraph(None)
     self.framePlayerChanged.emit()
Exemplo n.º 25
0
    def duplicationNode(self):
        """
            Duplicates the current node(s).
        """
        buttleData = ButtleDataSingleton().get()
        if buttleData.getCurrentSelectedNodeWrappers() != []:
            for node in buttleData.getCurrentSelectedNodeWrappers():
                # Create a node giving the current selected node's type, x and y
                nodeType = node.getNode().getType()
                coord = node.getNode().getCoord()
                buttleData.getGraph().createNode(nodeType, coord[0], coord[1])
                newNode = buttleData.getGraph().getNodes()[-1]

                # Get the current selected node's properties
                nameUser = node.getNameUser() + "_duplicate"
                oldCoord = node.getNode().getOldCoord()
                color = node.getNode().getColor()

                # Use the current selected node's properties to set the duplicated node's properties
                newNode.setNameUser(nameUser)
                newNode.setOldCoord(oldCoord[0], oldCoord[1])
                newNode.setColor(color)
                newNode.getTuttleNode().getParamSet().copyParamsValues(
                    node.getNode().getTuttleNode().getParamSet())

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 26
0
    def computeNode(self, node, frame):
        """
            Computes the node (displayed in the viewer) at the frame indicated.
        """
        buttleData = ButtleDataSingleton().get()
        graphTuttle = buttleData.getGraph().getGraphTuttle()

        #Get the output where we save the result
        self._tuttleImageCache = tuttle.MemoryCache()

        if buttleData.getVideoIsPlaying():  # if a video is playing
            processGraph = buttleData.getProcessGraph()
            processGraph.setupAtTime(frame)
            processGraph.processAtTime(self._tuttleImageCache, frame)
        else:  # if it's an image only
            processOptions = tuttle.ComputeOptions(int(frame))
            processGraph = tuttle.ProcessGraph(processOptions, graphTuttle,
                                               [node])
            processGraph.setup()
            timeRange = tuttle.TimeRange(frame, frame,
                                         1)  # buttleData.getTimeRange()
            processGraph.beginSequence(timeRange)
            processGraph.setupAtTime(frame)
            processGraph.processAtTime(self._tuttleImageCache, frame)
            processGraph.endSequence()

        self._computedImage = self._tuttleImageCache.get(0)

        #Add the computedImage to the map
        hashMap = tuttle.NodeHashContainer()
        graphTuttle.computeGlobalHashAtTime(hashMap, frame)
        hasCode = hashMap.getHash(node, frame)
        #Max 15 computedImages saved in memory
        if hasCode not in buttleData._mapNodeNameToComputedImage.keys(
        ) and len(buttleData._mapNodeNameToComputedImage) < 15:
            buttleData._mapNodeNameToComputedImage.update(
                {hasCode: self._computedImage})
        elif hasCode not in buttleData._mapNodeNameToComputedImage.keys(
        ) and len(buttleData._mapNodeNameToComputedImage) >= 15:
            #Delete a computed image from the memory (random)
            buttleData._mapNodeNameToComputedImage.popitem()
            buttleData._mapNodeNameToComputedImage.update(
                {hasCode: self._computedImage})

        return self._computedImage
Exemplo n.º 27
0
 def getFPS(self):
     """
         Returns the FPS of this node.
     """
     #import which needs to be changed in the future
     from buttleofx.data import ButtleDataSingleton
     buttleData = ButtleDataSingleton().get()
     graph = buttleData.getGraph().getGraphTuttle()
     node = self._node.getTuttleNode().asImageEffectNode()
     try:
         self.setFpsError("")
         graph.setup()
     except Exception as e:
         logging.debug("can't get fps of the node" + self._node.getName())
         self.setFpsError(str(e))
         return 1
         raise
     framerate = node.getOutputFrameRate()
     #print "framerate: ", framerate
     return framerate
Exemplo n.º 28
0
 def getFPS(self):
     """
         Returns the FPS of this node.
     """
     #import which needs to be changed in the future
     from buttleofx.data import ButtleDataSingleton
     buttleData = ButtleDataSingleton().get()
     graph = buttleData.getGraph().getGraphTuttle()
     node = self._node.getTuttleNode().asImageEffectNode()
     try:
         self.setFpsError("")
         graph.setup()
     except Exception as e:
         logging.debug("can't get fps of the node" + self._node.getName())
         self.setFpsError(str(e))
         return 1
         raise
     framerate = node.getOutputFrameRate()
     #print "framerate: ", framerate
     return framerate
Exemplo n.º 29
0
    def nodeIsMoving(self, nodeName, newX, newY):
        """
            This function updates the position of the selected nodes and the connections, when one or several nodes are moving.
        """
        buttleData = ButtleDataSingleton().get()
        node = buttleData.getGraph().getNode(nodeName)

        # What is the value of the movement (compared to the old position) ?
        oldX, oldY = node.getCoord()
        xMovement = newX - oldX
        yMovement = newY - oldY

        # for each selected node, we update the position considering the value of the movement
        for selectedNodeWrapper in buttleData.getCurrentSelectedNodeWrappers():
            selectedNode = selectedNodeWrapper.getNode()
            currentX, currentY = selectedNode.getCoord()
            selectedNode.setCoord(currentX + xMovement, currentY + yMovement)

            # we update also the position of all the connections
            buttleData.getGraph().connectionsCoordChanged(selectedNode)
Exemplo n.º 30
0
 def stop(self):
     logging.debug("--------------stop-------------")
     self._timer.stop()
     buttleData = ButtleDataSingleton().get()
     # if a video is reading, we need to close the processGraph
     if buttleData.getVideoIsPlaying():
         buttleData.setVideoIsPlaying(False)
         # close processGraph and delete it
         buttleData.getProcessGraph().endSequence()
         buttleData.setProcessGraph(None)
         # return to the beginning of the video
     self._frame = 0
     self.framePlayerChanged.emit()
Exemplo n.º 31
0
    def duplicationNode(self):
        """
            Duplicates the current node(s).
        """
        buttleData = ButtleDataSingleton().get()
        if buttleData.getCurrentSelectedNodeWrappers() != []:
            for node in buttleData.getCurrentSelectedNodeWrappers():
                # Create a node giving the current selected node's type, x and y
                nodeType = node.getNode().getType()
                coord = node.getNode().getCoord()
                buttleData.getGraph().createNode(nodeType, coord[0], coord[1])
                newNode = buttleData.getGraph().getNodes()[-1]

                # Get the current selected node's properties
                nameUser = node.getNameUser() + "_duplicate"
                oldCoord = node.getNode().getOldCoord()
                color = node.getNode().getColor()

                # Use the current selected node's properties to set the duplicated node's properties
                newNode.setNameUser(nameUser)
                newNode.setOldCoord(oldCoord[0], oldCoord[1])
                newNode.setColor(color)
                newNode.getTuttleNode().getParamSet().copyParamsValues(node.getNode().getTuttleNode().getParamSet())

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 32
0
    def retrieveImage(self, frame, frameChanged):
        """
            Computes the node at the frame indicated if the frame has changed (if the time has changed).
        """
        buttleData = ButtleDataSingleton().get()
        #Get the name of the currentNode of the viewer
        node = buttleData.getCurrentViewerNodeName()
        #Get the gloabl hashCode of the node
        if node is not None:
            hashMap = tuttle.NodeHashContainer()
            buttleData.getGraph().getGraphTuttle().computeGlobalHashAtTime(
                hashMap, frame)
            node_hashCode = hashMap.getHash(node, frame)
        #Get the map
        mapNodeToImage = buttleData.getMapNodeNameToComputedImage()

        try:
            self.setNodeError("")
            for key in mapNodeToImage.keys():
                #If the image is already calculated
                if node_hashCode == key and frameChanged is False:
                    #print "**************************Image already calculated**********************"
                    return mapNodeToImage.get(node_hashCode)
            #If it is not
            #print "**************************Image is not already calculated**********************"
            return self.computeNode(node, frame)
        except Exception as e:
            logging.debug("Can't display node : " + node)
            self.setNodeError(str(e))
            raise
Exemplo n.º 33
0
    def computeNode(self, node, frame):
        """
            Computes the node (displayed in the viewer) at the frame indicated.
        """
        buttleData = ButtleDataSingleton().get()
        graphTuttle = buttleData.getGraph().getGraphTuttle()

        #Get the output where we save the result
        self._tuttleImageCache = tuttle.MemoryCache()

        if buttleData.getVideoIsPlaying():  # if a video is playing
            processGraph = buttleData.getProcessGraph()
            processGraph.setupAtTime(frame)
            processGraph.processAtTime(self._tuttleImageCache, frame)
        else:  # if it's an image only
            processOptions = tuttle.ComputeOptions(int(frame))
            processGraph = tuttle.ProcessGraph(processOptions, graphTuttle, [node])
            processGraph.setup()
            timeRange = tuttle.TimeRange(frame, frame, 1)  # buttleData.getTimeRange()
            processGraph.beginSequence(timeRange)
            processGraph.setupAtTime(frame)
            processGraph.processAtTime(self._tuttleImageCache, frame)
            processGraph.endSequence()

        self._computedImage = self._tuttleImageCache.get(0)

        #Add the computedImage to the map
        hashMap = tuttle.NodeHashContainer()
        graphTuttle.computeGlobalHashAtTime(hashMap, frame)
        hasCode = hashMap.getHash(node, frame)
        #Max 15 computedImages saved in memory
        if hasCode not in buttleData._mapNodeNameToComputedImage.keys() and len(buttleData._mapNodeNameToComputedImage) < 15:
            buttleData._mapNodeNameToComputedImage.update({hasCode: self._computedImage})
        elif hasCode not in buttleData._mapNodeNameToComputedImage.keys() and len(buttleData._mapNodeNameToComputedImage) >= 15:
            #Delete a computed image from the memory (random)
            buttleData._mapNodeNameToComputedImage.popitem()
            buttleData._mapNodeNameToComputedImage.update({hasCode: self._computedImage})

        return self._computedImage
Exemplo n.º 34
0
    def redo(self):
        """
            Calls the cmdManager to redo the last command.
        """
        cmdManager = CommandManager()
        cmdManager.redo()

        # emit undo/redo display
        self.emitUndoRedoChanged()

        # if we need to update params or viewer
        buttleData = ButtleDataSingleton().get()
        buttleData.currentParamNodeChanged.emit()
        buttleData.currentViewerNodeChanged.emit()
Exemplo n.º 35
0
 def getNbFrames(self):
     """
         Returns the number of frames of this node.
     """
     #import which needs to be changed in the future
     from buttleofx.data import ButtleDataSingleton
     buttleData = ButtleDataSingleton().get()
     graph = buttleData.getGraph().getGraphTuttle()
     node = self._node.getTuttleNode().asImageEffectNode()
     try:
         self.setFrameError("")
         graph.setup()
     except Exception as e:
         logging.debug("can't get nbFrames of the node" + self._node.getName())
         self.setFrameError(str(e))
         return 0
         raise
     timeDomain = node.getTimeDomain() #getTimeDomain() returns first frame and last one
     nbFrames = timeDomain.max - timeDomain.min
     #not very elegant but allow to avoid a problem because an image returns a number of frames very high
     if nbFrames > 100000000 or nbFrames < 0:
         nbFrames = 1
     #print "nbFrames: ", nbFrames
     return nbFrames
Exemplo n.º 36
0
    def connectionDropEvent(self, dataTmpClip, clip, clipIndex):
        """
            Creates or deletes a connection between 2 clips ('tmpClip', the "dragged" clip, and 'newClip', the "dropped" clip)
            Arguments :
            - dataTmpClip : the string from mimeData, identifying the tmpClip (the "dragged" clip).
            - clip : the ClipWrapper of the "dropped" clip.
            - clipIndex : the index of the "dropped" clip.
        """
        buttleData = ButtleDataSingleton().get()

        # we split the data of the tmpClip (from mimeData) to find needed informations about this clip.
        infosTmpClip = dataTmpClip.split("/")

        if infosTmpClip[0] != "clip" or len(infosTmpClip) != 4:
            return  # use exception !
        else:
            tmpClipNodeName, tmpClipName, tmpClipIndex = infosTmpClip[
                1], infosTmpClip[2], int(infosTmpClip[3])

        # we find the position of this tmpClip to be able to create a IdClip object.
        positionTmpClip = buttleData.getGraphWrapper().getPositionClip(
            tmpClipNodeName, tmpClipName, tmpClipIndex)
        tmpClip = IdClip(tmpClipNodeName, tmpClipName, clipIndex,
                         positionTmpClip)

        if tmpClip:
            # idem, for the "dropped" clip = newClip
            positionNewClip = buttleData.getGraphWrapper().getPositionClip(
                clip.getNodeName(), clip.getClipName(), clipIndex)
            newClip = IdClip(clip.getNodeName(), clip.getClipName(), clipIndex,
                             positionNewClip)

            # a connection must be created from the ouput clip to the input clip (the order of the arguments is important !)
            if tmpClip.getClipName() == "Output":
                clipOut, clipIn = tmpClip, newClip
            else:
                clipOut, clipIn = newClip, tmpClip

            # if the clips can be connected, we connect them
            if self.canConnect(clipOut, clipIn):
                self.connect(clipOut, clipIn)
                return

            # else if they can't be connected, we check if they are already connected, and disconnect them if it is the case.
            else:
                connection = buttleData.getGraph().getConnectionByClips(
                    clipOut, clipIn)
                if connection:
                    self.disconnect(
                        buttleData.getGraphWrapper().getConnectionWrapper(
                            connection.getId()))
                    return

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 37
0
    def launchProcessGraph(self):
        buttleData = ButtleDataSingleton().get()
        #Get the name of the currentNode of the viewer
        node = buttleData.getCurrentViewerNodeName()
        # initialization of the process graph
        graph = buttleData.getGraph().getGraphTuttle()

        # timeRange between the frames of beginning and end (first frame, last frame, step)
        timeRange = tuttle.TimeRange(self._frame, self._nbFrames, 1)
        self._processOptions = tuttle.ComputeOptions(self._frame,
                                                     self._nbFrames, 1)
        processGraph = tuttle.ProcessGraph(self._processOptions, graph, [node])
        processGraph.setup()
        processGraph.beginSequence(timeRange)
        # communicate processGraph to buttleData
        buttleData.setProcessGraph(processGraph)

        buttleData.setVideoIsPlaying(True)
Exemplo n.º 38
0
    def launchProcessGraph(self):
        buttleData = ButtleDataSingleton().get()
        #Get the name of the currentNode of the viewer
        node = buttleData.getCurrentViewerNodeName()
        # initialization of the process graph
        graph = buttleData.getGraph().getGraphTuttle()

        # timeRange between the frames of beginning and end (first frame, last frame, step)
        timeRange = tuttle.TimeRange(self._frame, self._nbFrames, 1)
        self._processOptions = tuttle.ComputeOptions(self._frame, self._nbFrames, 1)
        processGraph = tuttle.ProcessGraph(self._processOptions, graph, [node])
        processGraph.setup()
        processGraph.beginSequence(timeRange)
        # communicate processGraph to buttleData
        buttleData.setProcessGraph(processGraph)
        
        buttleData.setVideoIsPlaying(True)
Exemplo n.º 39
0
    def mosquitoDragEvent(self):
        """
            Function called when the viewer's mosquito is dragged.
            The function sends the mimeData and launches a drag event.
        """

        widget = QtGui.QWidget()
        drag = QtGui.QDrag(widget)
        mimeData = QtCore.QMimeData()

        # set data (here it's just a text)
        mimeData.setText("mosquito_of_the_dead")
        drag.setMimeData(mimeData)

        # sets the image of the mosquito in the pixmap
        filePath = ButtleDataSingleton().get().getButtlePath()
        imgPath = filePath + "/gui/img/mosquito/mosquito.png"
        drag.setPixmap(QtGui.QPixmap(imgPath))

        # starts the drag
        drag.exec_(QtCore.Qt.MoveAction)
Exemplo n.º 40
0
    def dropFile(self, url, x, y):
        """
            Drops a file on the graph.
            - Image or video : creates a reader node.
            - Json : load a graph (if the format allows it)
        """
        buttleData = ButtleDataSingleton().get()

        extension = url.split(".")[-1].lower()
        if extension == 'bofx':
            buttleData.loadData(url)  # also need to verify the json format
        else:
            buttleData.getGraph().createReaderNode(url, x, y)

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 41
0
 def copyNode(self):
     """
         Copies the current node(s).
     """
     buttleData = ButtleDataSingleton().get()
     # Clear the info saved in currentCopiedNodesInfo
     buttleData.clearCurrentCopiedNodesInfo()
     # Save new data in currentCopiedNodesInfo for each selected node
     if buttleData.getCurrentSelectedNodeWrappers() != []:
         for node in buttleData.getCurrentSelectedNodeWrappers():
             copyNode = {}
             copyNode.update({"nodeType": node.getNode().getType()})
             copyNode.update({"nameUser": node.getNode().getNameUser()})
             copyNode.update({"color": node.getNode().getColor()})
             copyNode.update(
                 {"params": node.getNode().getTuttleNode().getParamSet()})
             copyNode.update({"mode": "_copy"})
             buttleData.getCurrentCopiedNodesInfo()[
                 node.getName()] = copyNode
             # Emit the change for the toolbar
             buttleData.pastePossibilityChanged.emit()
Exemplo n.º 42
0
 def copyNode(self):
     """
         Copies the current node(s).
     """
     buttleData = ButtleDataSingleton().get()
     # Clear the info saved in currentCopiedNodesInfo
     buttleData.clearCurrentCopiedNodesInfo()
     # Save new data in currentCopiedNodesInfo for each selected node
     if buttleData.getCurrentSelectedNodeWrappers() != []:
         for node in buttleData.getCurrentSelectedNodeWrappers():
             copyNode = {}
             copyNode.update({"nodeType": node.getNode().getType()})
             copyNode.update({"nameUser": node.getNode().getNameUser()})
             copyNode.update({"color": node.getNode().getColor()})
             copyNode.update({"params": node.getNode().getTuttleNode().getParamSet()})
             copyNode.update({"mode": "_copy"})
             buttleData.getCurrentCopiedNodesInfo()[node.getName()] = copyNode
             # Emit the change for the toolbar
             buttleData.pastePossibilityChanged.emit()
Exemplo n.º 43
0
    def nodeIsMoving(self, nodeName, newX, newY):
        """
            This function updates the position of the selected nodes and the connections, when one or several nodes are moving.
        """
        buttleData = ButtleDataSingleton().get()
        node = buttleData.getGraph().getNode(nodeName)

        # What is the value of the movement (compared to the old position) ?
        oldX, oldY = node.getCoord()
        xMovement = newX - oldX
        yMovement = newY - oldY

        # for each selected node, we update the position considering the value of the movement
        for selectedNodeWrapper in buttleData.getCurrentSelectedNodeWrappers():
            selectedNode = selectedNodeWrapper.getNode()
            currentX, currentY = selectedNode.getCoord()
            selectedNode.setCoord(currentX + xMovement, currentY + yMovement)

            # we update also the position of all the connections
            buttleData.getGraph().connectionsCoordChanged(selectedNode)
Exemplo n.º 44
0
 def disconnect(self, connectionWrapper):
     """
         Removes a connection between 2 clips.
     """
     buttleData = ButtleDataSingleton().get()
     buttleData.getGraph().deleteConnection(connectionWrapper.getConnection())
Exemplo n.º 45
0
 def connect(self, clipOut, clipIn):
     """
         Adds a connection between 2 clips.
     """
     buttleData = ButtleDataSingleton().get()
     buttleData.getGraph().createConnection(clipOut, clipIn)
Exemplo n.º 46
0
 def clearMapOfImageAlreadyCalculated(self):
     buttleData = ButtleDataSingleton().get()
     buttleData._mapNodeNameToComputedImage.clear()
Exemplo n.º 47
0
    def destructionNodes(self):
        """
            Deletes the current node(s).
        """
        buttleData = ButtleDataSingleton().get()

        # if the params of the current node deleted are display
        if buttleData.getCurrentParamNodeName(
        ) in buttleData.getCurrentSelectedNodeNames():
            buttleData.setCurrentParamNodeName(None)

        # if the viewer of the current node deleted is display
        if buttleData.getCurrentViewerNodeName(
        ) in buttleData.getCurrentSelectedNodeNames():
            buttleData.setCurrentViewerNodeName(None)
        # if the viewer display a node affected by the destruction
        # need something from Tuttle

        # if at least one node in the graph
        if len(buttleData.getGraphWrapper().getNodeWrappers()) > 0 and len(
                buttleData.getGraph().getNodes()) > 0:
            # if a node is selected
            if buttleData.getCurrentSelectedNodeNames() != []:
                buttleData.getGraph().deleteNodes([
                    nodeWrapper.getNode() for nodeWrapper in
                    buttleData.getCurrentSelectedNodeWrappers()
                ])
                buttleData.clearCurrentSelectedNodeNames()

        # emit signals
        buttleData.currentParamNodeChanged.emit()
        buttleData.currentViewerNodeChanged.emit()
        buttleData.currentSelectedNodesChanged.emit()

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 48
0
 def cutNode(self):
     """
         Cuts the current node(s).
     """
     # Call the copyNode function to save the data of the selected nodes
     self.copyNode()
     buttleData = ButtleDataSingleton().get()
     # If we are sure that at least one node is selected
     if buttleData.getCurrentSelectedNodeWrappers() != []:
         for node in buttleData.getCurrentSelectedNodeWrappers():
             # We precise that we want to cut the node and not only copy it
             buttleData.getCurrentCopiedNodesInfo()[node.getName()].update(
                 {"mode": ""})
             # And we delete it
             self.destructionNodes()
             # And update the view if necessary
             if buttleData.getCurrentViewerNodeName(
             ) in buttleData.getCurrentSelectedNodeNames():
                 buttleData.setCurrentViewerNodeName(None)
             if buttleData.getCurrentParamNodeName(
             ) in buttleData.getCurrentSelectedNodeNames():
                 buttleData.setCurrentParamNodeName(None)
             # Emit the change for the toolbar
             buttleData.pastePossibilityChanged.emit()
Exemplo n.º 49
0
 def connect(self, clipOut, clipIn):
     """
         Adds a connection between 2 clips.
     """
     buttleData = ButtleDataSingleton().get()
     buttleData.getGraph().createConnection(clipOut, clipIn)
Exemplo n.º 50
0
def main(argv):

    #preload Tuttle
    tuttle.core().preload()

    # give to QML acces to TimerPlayer defined in buttleofx/gui/viewer
    QtDeclarative.qmlRegisterType(TimerPlayer, "TimerPlayer", 1, 0, "TimerPlayer")
    # add new QML type
    QtDeclarative.qmlRegisterType(Finder, "FolderListViewItem", 1, 0, "FolderListView")
    if tuttleofx_installed:
        QtDeclarative.qmlRegisterType(GLViewport_tuttleofx, "Viewport", 1, 0, "GLViewport")
    else:
        QtDeclarative.qmlRegisterType(GLViewport_pil, "Viewport", 1, 0, "GLViewport")

    # init undo_redo contexts
    cmdManager = CommandManager()
    cmdManager.setActive()
    cmdManager.clean()

    # create QApplication
    app = ButtleApp(argv)

    # create the declarative view
    view = QtDeclarative.QDeclarativeView()
    view.setViewport(QtOpenGL.QGLWidget())
    view.setViewportUpdateMode(QtDeclarative.QDeclarativeView.FullViewportUpdate)

    # data
    buttleData = ButtleDataSingleton().get().init(view, currentFilePath)
    # manager
    buttleManager = ButtleManagerSingleton().get().init()
    # event
    buttleEvent = ButtleEventSingleton().get()
    # Menus
    fileMenu = MenuWrapper("file", 0, view, app)
    editMenu = MenuWrapper("edit", 0, view, app)
    addMenu = MenuWrapper("buttle/", 1, view, app)

    # expose data to QML
    rc = view.rootContext()
    rc.setContextProperty("_buttleApp", app)
    rc.setContextProperty("_buttleData", buttleData)
    rc.setContextProperty("_buttleManager", buttleManager)
    rc.setContextProperty("_buttleEvent", buttleEvent)
    rc.setContextProperty("_fileMenu", fileMenu)
    rc.setContextProperty("_editMenu", editMenu)
    rc.setContextProperty("_addMenu", addMenu)

    # set the view
    view.setSource(os.path.join(currentFilePath, "MainWindow.qml"))
    view.setResizeMode(QtDeclarative.QDeclarativeView.SizeRootObjectToView)
    view.setWindowTitle("ButtleOFX")
    view.setWindowIcon(QtGui.QIcon("blackMosquito.png"))
    view.setWindowIconText("ButtleOFX")
    view.setVisible(True)

    # Declare we are using instant coding tool on this view
    qic = QmlInstantCoding(view, verbose=True)

    # Add any source file (.qml and .js by default) in current working directory
    qic.addFilesFromDirectory(os.getcwd(), recursive=True)

    #add._menu.popup(view.mapToGlobal(QtCore.QPoint(0, 0)))

    view.show()
    app.exec_()
Exemplo n.º 51
0
    def pasteNode(self):
        """
            Pasts the current node(s).
        """
        buttleData = ButtleDataSingleton().get()
        # If nodes have been copied previously
        if buttleData.getCurrentCopiedNodesInfo():
            # Create a copy for each node copied
            for node in buttleData.getCurrentCopiedNodesInfo():
                buttleData.getGraph().createNode(
                    buttleData.getCurrentCopiedNodesInfo()[node]["nodeType"],
                    20, 20)
                newNode = buttleData.getGraph().getNodes()[-1]
                newNode.setColor(
                    buttleData.getCurrentCopiedNodesInfo()[node]["color"])
                newNode.setNameUser(
                    buttleData.getCurrentCopiedNodesInfo()[node]["nameUser"] +
                    buttleData.getCurrentCopiedNodesInfo()[node]["mode"])
                newNode.getTuttleNode().getParamSet().copyParamsValues(
                    buttleData.getCurrentCopiedNodesInfo()[node]["params"])

        # update undo/redo display
        self.undoRedoChanged()
Exemplo n.º 52
0
 def cutNode(self):
     """
         Cuts the current node(s).
     """
     # Call the copyNode function to save the data of the selected nodes
     self.copyNode()
     buttleData = ButtleDataSingleton().get()
     # If we are sure that at least one node is selected
     if buttleData.getCurrentSelectedNodeWrappers() != []:
         for node in buttleData.getCurrentSelectedNodeWrappers():
             # We precise that we want to cut the node and not only copy it
             buttleData.getCurrentCopiedNodesInfo()[node.getName()].update({"mode": ""})
             # And we delete it
             self.destructionNodes()
             # And update the view if necessary
             if buttleData.getCurrentViewerNodeName() in buttleData.getCurrentSelectedNodeNames():
                 buttleData.setCurrentViewerNodeName(None)
             if buttleData.getCurrentParamNodeName() in buttleData.getCurrentSelectedNodeNames():
                 buttleData.setCurrentParamNodeName(None)
             # Emit the change for the toolbar
             buttleData.pastePossibilityChanged.emit()
Exemplo n.º 53
0
    def destructionNodes(self):
        """
            Deletes the current node(s).
        """
        buttleData = ButtleDataSingleton().get()

        # if the params of the current node deleted are display
        if buttleData.getCurrentParamNodeName() in buttleData.getCurrentSelectedNodeNames():
            buttleData.setCurrentParamNodeName(None)

        # if the viewer of the current node deleted is display
        if buttleData.getCurrentViewerNodeName() in buttleData.getCurrentSelectedNodeNames():
            buttleData.setCurrentViewerNodeName(None)
        # if the viewer display a node affected by the destruction
        # need something from Tuttle

        # if at least one node in the graph
        if len(buttleData.getGraphWrapper().getNodeWrappers()) > 0 and len(buttleData.getGraph().getNodes()) > 0:
            # if a node is selected
            if buttleData.getCurrentSelectedNodeNames() != []:
                buttleData.getGraph().deleteNodes([nodeWrapper.getNode() for nodeWrapper in buttleData.getCurrentSelectedNodeWrappers()])
                buttleData.clearCurrentSelectedNodeNames()

        # emit signals
        buttleData.currentParamNodeChanged.emit()
        buttleData.currentViewerNodeChanged.emit()
        buttleData.currentSelectedNodesChanged.emit()

        # update undo/redo display
        self.undoRedoChanged()