def readLocalFile(self, file):
        if not file.isValid():
            return

        job = ReadMeshJob(file.toLocalFile())
        job.finished.connect(self._readMeshFinished)
        job.start()
Beispiel #2
0
    def _reloadNodes(self, nodes: List["SceneNode"], message: str,
                     action: str) -> None:
        """Reloads a list of nodes after the user pressed the "Reload" button.

        :param nodes: The list of nodes that needs to be reloaded.
        :param message: The message that triggered the action to reload them.
        :param action: The button that triggered the action to reload them.
        """

        if action != "reload":
            return
        if self._reload_message is not None:
            self._reload_message.hide()
        for node in nodes:
            meshdata = node.getMeshData()
            if meshdata:
                filename = meshdata.getFileName()
                if not filename or not os.path.isfile(
                        filename):  # File doesn't exist any more.
                    continue
                job = ReadMeshJob(filename)
                reload_finished_callback = functools.partial(
                    self._reloadJobFinished, node)

                # Store it so it won't get garbage collected. This is a memory leak, but just one partial per reload so
                # it's not much.
                self._callbacks.add(reload_finished_callback)

                job.finished.connect(reload_finished_callback)
                job.start()
Beispiel #3
0
 def _reloadNodes(self, nodes: List["SceneNode"], message: str, action: str) -> None:
     if action != "reload":
         return
     for node in nodes:
         if not os.path.isfile(node.getMeshData().getFileName()): #File doesn't exist any more.
             continue
         job = ReadMeshJob(node.getMeshData().getFileName())
         job.finished.connect(functools.partialmethod(self._reloadJobFinished, node))
         job.start()
Beispiel #4
0
 def _readLocalFile(self, file):
     # We need to prevent circular dependency, so do some just in time importing.
     from UM.Mesh.ReadMeshJob import ReadMeshJob
     filename = file.toLocalFile()
     job = ReadMeshJob(
         filename,
         add_to_recent_files=self.getAddToRecentFilesHint(filename))
     job.finished.connect(self._readMeshFinished)
     job.start()
Beispiel #5
0
 def _readLocalFile(self,
                    file: QUrl,
                    add_to_recent_files_hint: bool = True):
     # We need to prevent circular dependency, so do some just in time importing.
     from UM.Mesh.ReadMeshJob import ReadMeshJob
     filename = file.toLocalFile()
     job = ReadMeshJob(filename,
                       add_to_recent_files=add_to_recent_files_hint)
     job.finished.connect(self._readMeshFinished)
     job.start()
Beispiel #6
0
 def _reloadNodes(self, nodes: List["SceneNode"], message: str, action: str) -> None:
     if action != "reload":
         return
     self._reload_message.hide()
     for node in nodes:
         meshdata = node.getMeshData()
         if meshdata:
             filename = meshdata.getFileName()
             if not filename or not os.path.isfile(filename): #File doesn't exist any more.
                 continue
             job = ReadMeshJob(filename)
             self._reload_finished_callback = functools.partial(self._reloadJobFinished, node)
             job.finished.connect(self._reload_finished_callback)
             job.start()
Beispiel #7
0
 def _reloadNodes(self, nodes: List["SceneNode"], message: str, action: str) -> None:
     if action != "reload":
         return
     if self._reload_message is not None:
         self._reload_message.hide()
     for node in nodes:
         meshdata = node.getMeshData()
         if meshdata:
             filename = meshdata.getFileName()
             if not filename or not os.path.isfile(filename):  # File doesn't exist any more.
                 continue
             job = ReadMeshJob(filename)
             self._reload_finished_callback = functools.partial(self._reloadJobFinished, node)
             job.finished.connect(self._reload_finished_callback)
             job.start()
Beispiel #8
0
 def _reloadNodes(self, nodes: List["SceneNode"], message: str, action: str) -> None:
     if action != "reload":
         return
     if self._reload_message is not None:
         self._reload_message.hide()
     for node in nodes:
         meshdata = node.getMeshData()
         if meshdata:
             filename = meshdata.getFileName()
             if not filename or not os.path.isfile(filename):  # File doesn't exist any more.
                 continue
             job = ReadMeshJob(filename)
             reload_finished_callback = functools.partial(self._reloadJobFinished, node)
             self._callbacks.add(reload_finished_callback) #Store it so it won't get garbage collected. This is a memory leak, but just one partial per reload so it's not much.
             job.finished.connect(reload_finished_callback)
             job.start()
Beispiel #9
0
 def _reloadJobFinished(self, replaced_node: SceneNode, job: ReadMeshJob) -> None:
     for node in job.getResult():
         mesh_data = node.getMeshData()
         if mesh_data:
             replaced_node.setMeshData(mesh_data)
         else:
             Logger.log("w", "Could not find a mesh in reloaded node.")
Beispiel #10
0
 def _reloadJobFinished(self, job: ReadMeshJob) -> None:
     for node in job.getResult():
         mesh_data = node.getMeshData()
         if mesh_data:
             job._node.setMeshData(mesh_data)
         else:
             Logger.log("w", "Could not find a mesh in reloaded node.")
Beispiel #11
0
    def _foreignFileChanged(self, path):
        """On file changed connection. Rereads the changed file and updates it.
        
        This happens automatically and can be set on/off in the settings.
        Explicit for foreign file types (stl, obj, x3d, ply).

        :param path: The path to the changed foreign file.
        """

        export_path = '{}.{}'.format(path[:-6], self._foreign_file_extension)
        execute_list = "bpy.ops.export_mesh.{}(filepath = '{}', check_existing = False)".format(
            self._foreign_file_extension, export_path)

        command = '"{}" "{}" --background --python-expr "import bpy; import sys; exec(sys.argv[-1])" -- "{}"'.format(
            self._blender_path, path, execute_list)
        subprocess.run(command, shell=True)

        if self._preferences.getValue(
                'cura_blender/live_reload') and os.path.isfile(export_path):
            job = ReadMeshJob(export_path)
            job.finished.connect(self._readMeshFinished)
            job.start()
            # Give process time while waiting for the job to finish.
            while not job.isFinished():
                job.yieldThread()
            # Remove temporary export file. Original foreign file, was not overwritten and the node still got it's reference in case of an undo.
            os.remove(export_path)

        if os.path.isfile(path + '1'):
            # Instead of overwriting files, blender saves the old one with .blend1 extension. We don't want this file at all, but need the original one for the file watcher.
            os.remove(path + '1')

        # Adds new filewatcher reference, because cura removes filewatcher automatically for other file types after reading.
        self._foreign_file_watcher.addPath(path)
Beispiel #12
0
    def reloadAll(self):
        nodes = []
        for node in DepthFirstIterator(self.getController().getScene().getRoot()):
            if type(node) is not SceneNode or not node.getMeshData():
                continue

            nodes.append(node)

        if not nodes:
            return

        for node in nodes:
            if not node.getMeshData():
                continue

            file_name = node.getMeshData().getFileName()
            if file_name:
                job = ReadMeshJob(file_name)
                job.finished.connect(lambda j: node.setMeshData(j.getResult()))
                job.start()
Beispiel #13
0
    def reloadAll(self):
        Logger.log("i", "Reloading all loaded mesh data.")
        nodes = []
        for node in DepthFirstIterator(self.getController().getScene().getRoot()):
            if type(node) is not SceneNode or not node.getMeshData():
                continue

            nodes.append(node)

        if not nodes:
            return

        for node in nodes:
            file_name = node.getMeshData().getFileName()
            if file_name:
                job = ReadMeshJob(file_name)
                job._node = node
                job.finished.connect(self._reloadMeshFinished)
                job.start()
            else:
                Logger.log("w", "Unable to reload data because we don't have a filename.")
Beispiel #14
0
    def reloadAll(self):
        Logger.log("i", "Reloading all loaded mesh data.")
        nodes = []
        for node in DepthFirstIterator(self.getController().getScene().getRoot()):
            if type(node) is not SceneNode or not node.getMeshData():
                continue

            nodes.append(node)

        if not nodes:
            return

        for node in nodes:
            file_name = node.getMeshData().getFileName()
            if file_name:
                job = ReadMeshJob(file_name)
                job._node = node
                job.finished.connect(self._reloadMeshFinished)
                job.start()
            else:
                Logger.log("w", "Unable to reload data because we don't have a filename.")
Beispiel #15
0
    def _reloadJobFinished(self, replaced_node: SceneNode, job: ReadMeshJob) -> None:
        """Triggered when reloading has finished.

        This then puts the resulting mesh data in the node.
        """

        for node in job.getResult():
            mesh_data = node.getMeshData()
            if mesh_data:
                replaced_node.setMeshData(mesh_data)
            else:
                Logger.log("w", "Could not find a mesh in reloaded node.")
Beispiel #16
0
    def reloadMesh(self) -> None:
        self._node_queue = self._getSelectedNodes(force_single=True)
        if not self._node_queue:
            return

        mesh_data = self._node_queue[0].getMeshData()
        if not mesh_data:
            self._message.setText(catalog.i18nc("@info:status", "Reloading a group is not supported"))
            self._message.show()
            self._node_queue = [] #type: List[SceneNode]
            return

        file_name = mesh_data.getFileName()
        if not file_name:
            self._message.setText(catalog.i18nc("@info:status", "No link to the original file was found"))
            self._message.show()
            self._node_queue = [] #type: List[SceneNode]
            return

        job = ReadMeshJob(file_name)
        job.finished.connect(self._readMeshFinished)
        job.start()
Beispiel #17
0
    def _fileChanged(self, path):
        """On file changed connection. Rereads the changed file and updates it.
        
        This happens automatically and can be set on/off in the settings.

        :param path: The path to the changed blender file.
        """

        # Checks auto reload flag in settings file.
        if self._preferences.getValue('cura_blender/live_reload'):
            job = ReadMeshJob(path)
            job.finished.connect(self._readMeshFinished)
            job.start()
        # Refreshes file in file watcher in case the auto reload flag gets changed during runtime.
        else:
            time.sleep(1)
            fs_watcher.removePath(path)
            fs_watcher.addPath(path)

        if os.path.isfile(path + '1'):
            # Instead of overwriting files, blender saves the old one with .blend1 extension. We don't want this file at all, but need the original one for the file watcher.
            os.remove(path + '1')
Beispiel #18
0
    def replaceMeshes(self) -> None:
        self._node_queue = self._getSelectedNodes()
        if not self._node_queue:
            return

        for node in self._node_queue:
            mesh_data = node.getMeshData()
            if not mesh_data:
                self._message.setText(catalog.i18nc("@info:status", "Replacing a group is not supported"))
                self._message.show()
                self._node_queue = [] #type: List[SceneNode]
                return

        options = QFileDialog.Options()
        if sys.platform == "linux" and "KDE_FULL_SESSION" in os.environ:
            options |= QFileDialog.DontUseNativeDialog
        filter_types = ";;".join(self._application.getMeshFileHandler().supportedReadFileTypes)

        directory = None  # type: Optional[str]
        mesh_data = self._node_queue[0].getMeshData()
        if mesh_data:
            directory = mesh_data.getFileName()
        if not directory:
            directory = self._application.getDefaultPath("dialog_load_path").toLocalFile()

        file_name, _ = QFileDialog.getOpenFileName(
            parent=None,
            caption=catalog.i18nc("@title:window", "Select Replacement Mesh File"),
            directory=directory, options=options, filter=filter_types
        )
        if not file_name:
            self._node_queue = [] #type: List[SceneNode]
            return

        job = ReadMeshJob(file_name)
        job.finished.connect(self._readMeshFinished)
        job.start()
Beispiel #19
0
 def _readLocalFile(self, file):
     # We need to prevent circular dependency, so do some just in time importing.
     from UM.Mesh.ReadMeshJob import ReadMeshJob
     job = ReadMeshJob(file.toLocalFile())
     job.finished.connect(self._readMeshFinished)
     job.start()
Beispiel #20
0
 def _openFile(self, file):
     job = ReadMeshJob(os.path.abspath(file))
     job.finished.connect(self._onFileLoaded)
     job.start()
Beispiel #21
0
 def _openFile(self, file):
     job = ReadMeshJob(os.path.abspath(file))
     job.finished.connect(self._onFileLoaded)
     job.start()
Beispiel #22
0
    def run(self):
        self._i18n_catalog = i18nCatalog("cura");

        self.addOutputDevice("local_file", {
            "id": "local_file",
            "function": self._writeToLocalFile,
            "description": self._i18n_catalog.i18nc("Save button tooltip", "Save to Disk"),
            "shortDescription": self._i18n_catalog.i18nc("Save button tooltip", "Save to Disk"),
            "icon": "save",
            "priority": 0
        })

        self.showSplashMessage(self._i18n_catalog.i18nc("Splash screen message", "Setting up scene..."))

        controller = self.getController()

        controller.setActiveView("MeshView")
        controller.setCameraTool("CameraTool")
        controller.setSelectionTool("SelectionTool")

        t = controller.getTool("TranslateTool")
        if t:
            t.setEnabledAxis([ToolHandle.XAxis, ToolHandle.ZAxis])

        Selection.selectionChanged.connect(self.onSelectionChanged)

        root = controller.getScene().getRoot()
        self._platform = Platform(root)

        self._volume = BuildVolume.BuildVolume(root)

        self.getRenderer().setLightPosition(Vector(0, 150, 0))
        self.getRenderer().setBackgroundColor(QColor(245, 245, 245))

        self._physics = PlatformPhysics.PlatformPhysics(controller, self._volume)

        camera = Camera("3d", root)
        camera.setPosition(Vector(-150, 150, 300))
        camera.setPerspective(True)
        camera.lookAt(Vector(0, 0, 0))

        self._camera_animation = CameraAnimation.CameraAnimation()
        self._camera_animation.setCameraTool(self.getController().getTool("CameraTool"))

        controller.getScene().setActiveCamera("3d")

        self.showSplashMessage(self._i18n_catalog.i18nc("Splash screen message", "Loading interface..."))

        self.setMainQml(Resources.getPath(Resources.QmlFilesLocation, "Cura.qml"))
        self.initializeEngine()

        self.getStorageDevice("LocalFileStorage").removableDrivesChanged.connect(self._removableDrivesChanged)

        if self.getMachines():
            active_machine_pref = Preferences.getInstance().getValue("cura/active_machine")
            if active_machine_pref:
                for machine in self.getMachines():
                    if machine.getName() == active_machine_pref:
                        self.setActiveMachine(machine)

            if not self.getActiveMachine():
                self.setActiveMachine(self.getMachines()[0])
        else:
            self.requestAddPrinter.emit()

        self._removableDrivesChanged()
        if self._engine.rootObjects:
            self.closeSplash()

            for file in self.getCommandLineOption("file", []):
                job = ReadMeshJob(os.path.abspath(file))
                job.finished.connect(self._onFileLoaded)
                job.start()

            self.exec_()
Beispiel #23
0
 def readLocalFile(self, file):
     if not file.isValid():
         return
     job = ReadMeshJob(file.toLocalFile())
     job.finished.connect(self._readMeshFinished)
     job.start()
Beispiel #24
0
 def _readLocalFile(self, file):
     # We need to prevent circular dependency, so do some just in time importing.
     from UM.Mesh.ReadMeshJob import ReadMeshJob
     job = ReadMeshJob(file.toLocalFile())
     job.finished.connect(self._readMeshFinished)
     job.start()
Beispiel #25
0
    def run(self):
        self._i18n_catalog = i18nCatalog("cura");

        self.addOutputDevice("local_file", {
            "id": "local_file",
            "function": self._writeToLocalFile,
            "description": self._i18n_catalog.i18nc("Save button tooltip", "Save to Disk"),
            "icon": "save",
            "priority": 0
        })

        self.showSplashMessage(self._i18n_catalog.i18nc("Splash screen message", "Setting up scene..."))

        controller = self.getController()

        controller.setActiveView("MeshView")
        controller.setCameraTool("CameraTool")
        controller.setSelectionTool("SelectionTool")

        t = controller.getTool("TranslateTool")
        if t:
            t.setEnabledAxis([ToolHandle.XAxis, ToolHandle.ZAxis])

        Selection.selectionChanged.connect(self.onSelectionChanged)

        root = controller.getScene().getRoot()
        self._platform = Platform(root)

        self._volume = BuildVolume.BuildVolume(root)

        self.getRenderer().setLightPosition(Vector(0, 150, 0))
        self.getRenderer().setBackgroundColor(QColor(245, 245, 245))

        self._physics = PlatformPhysics.PlatformPhysics(controller, self._volume)

        camera = Camera("3d", root)
        camera.setPosition(Vector(-150, 150, 300))
        camera.setPerspective(True)
        camera.lookAt(Vector(0, 0, 0))

        self._camera_animation = CameraAnimation.CameraAnimation()
        self._camera_animation.setCameraTool(self.getController().getTool("CameraTool"))

        controller.getScene().setActiveCamera("3d")

        self.showSplashMessage(self._i18n_catalog.i18nc("Splash screen message", "Loading interface..."))

        self.setMainQml(Resources.getPath(Resources.QmlFilesLocation, "Cura.qml"))
        self.initializeEngine()

        self.getStorageDevice("LocalFileStorage").removableDrivesChanged.connect(self._removableDrivesChanged)

        if self.getMachines():
            active_machine_pref = Preferences.getInstance().getValue("cura/active_machine")
            if active_machine_pref:
                for machine in self.getMachines():
                    if machine.getName() == active_machine_pref:
                        self.setActiveMachine(machine)

            if not self.getActiveMachine():
                self.setActiveMachine(self.getMachines()[0])
        else:
            self.requestAddPrinter.emit()

        self._removableDrivesChanged()
        if self._engine.rootObjects:
            self.closeSplash()

            for file in self.getCommandLineOption("file", []):
                job = ReadMeshJob(os.path.abspath(file))
                job.finished.connect(self._onFileLoaded)
                job.start()

            self.exec_()