Meshroom/meshroom/ui/reconstruction.py

125 lines
4 KiB
Python
Executable file

import os
from threading import Thread
from PySide2.QtCore import QObject, Slot, Property, Signal, QJsonValue, QUrl
from meshroom import multiview
from meshroom.core import graph, defaultCacheFolder, cacheFolderName
from meshroom.ui import commands
class Reconstruction(QObject):
def __init__(self, graphFilepath="", parent=None):
super(Reconstruction, self).__init__(parent)
self._graph = None
self._undoStack = commands.UndoStack(self)
self._computeThread = Thread()
self._filepath = graphFilepath
if self._filepath:
self.load(self._filepath)
else:
self.new()
@Slot()
def new(self):
self.clear()
self._graph = multiview.photogrammetryPipeline()
self._graph.cacheDir = defaultCacheFolder
self.graphChanged.emit()
def clear(self):
if self._graph:
self._graph.deleteLater()
self._graph = None
self.setFilepath("")
self._undoStack.clear()
def setFilepath(self, path):
if self._filepath == path:
return
self._filepath = path
self.filepathChanged.emit()
@Slot(str)
def addNode(self, nodeType):
self._undoStack.tryAndPush(commands.AddNodeCommand(self._graph, nodeType))
@Slot(graph.Node)
def removeNode(self, node):
self._undoStack.tryAndPush(commands.RemoveNodeCommand(self._graph, node))
@Slot(graph.Attribute, graph.Attribute)
def addEdge(self, src, dst):
self._undoStack.tryAndPush(commands.AddEdgeCommand(self._graph, src, dst))
@Slot(graph.Edge)
def removeEdge(self, edge):
self._undoStack.tryAndPush(commands.RemoveEdgeCommand(self._graph, edge))
@Slot(graph.Attribute, "QVariant")
def setAttribute(self, attribute, value):
self._undoStack.tryAndPush(commands.SetAttributeCommand(self._graph, attribute, value))
@Slot(graph.Attribute, QJsonValue)
def appendAttribute(self, attribute, value):
if value.isArray():
pyValue = value.toArray().toVariantList()
else:
pyValue = None if value.isNull() else value.toObject()
self._undoStack.tryAndPush(commands.ListAttributeAppendCommand(self._graph, attribute, pyValue))
@Slot(graph.Attribute)
def removeAttribute(self, attribute):
self._undoStack.tryAndPush(commands.ListAttributeRemoveCommand(self._graph, attribute))
def load(self, filepath):
self.clear()
self._graph = graph.Graph("")
self._graph.load(filepath)
self.setFilepath(filepath)
self.graphChanged.emit()
@Slot(QUrl)
def loadUrl(self, url):
self.load(url.toLocalFile())
@Slot(QUrl)
def saveAs(self, url):
self.setFilepath(url.toLocalFile())
self.save()
@Slot()
def save(self):
self._graph.save(self._filepath)
self._graph.cacheDir = os.path.join(os.path.dirname(self._filepath), cacheFolderName)
self._undoStack.setClean()
@Slot(graph.Node)
def execute(self, node=None):
if self.computing:
return
nodes = [node] if node else self._graph.getLeaves()
self._computeThread = Thread(target=self._execute, args=(nodes,))
self._computeThread.start()
def _execute(self, nodes):
self.computingChanged.emit()
graph.execute(self._graph, nodes)
self.computingChanged.emit()
@Slot()
def stopExecution(self):
if not self.computing:
return
self._graph.stopExecution()
self._computeThread.join()
self.computingChanged.emit()
undoStack = Property(QObject, lambda self: self._undoStack, constant=True)
graphChanged = Signal()
graph = Property(graph.Graph, lambda self: self._graph, notify=graphChanged)
computingChanged = Signal()
computing = Property(bool, lambda self: self._computeThread.is_alive(), notify=computingChanged)
filepathChanged = Signal()
filepath = Property(str, lambda self: self._filepath, notify=filepathChanged)