def container_registry(application):
    MimeTypeDatabase.addMimeType(
        MimeType(
            name = "application/x-uranium-definitioncontainer",
            comment = "Uranium Definition Container",
            suffixes = ["def.json"]
        )
    )

    MimeTypeDatabase.addMimeType(
        MimeType(
            name = "application/x-uranium-instancecontainer",
            comment = "Uranium Instance Container",
            suffixes = [ "inst.cfg" ]
        )
    )

    MimeTypeDatabase.addMimeType(
        MimeType(
            name = "application/x-uranium-containerstack",
            comment = "Uranium Container Stack",
            suffixes = [ "stack.cfg" ]
        )
    )

    Resources.addSearchPath(os.path.realpath(os.path.join(os.path.dirname(__file__), "..", "..", "Settings")))
    ContainerRegistry._ContainerRegistry__instance = None # Reset the private instance variable every time
    PluginRegistry.getInstance().removeType("settings_container")

    ContainerRegistry.getInstance().load()

    return ContainerRegistry.getInstance()
Beispiel #2
0
    def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode):
        archive = VirtualFile()
        archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly)

        #Store the g-code from the scene.
        archive.addContentType(extension = "gcode", mime_type = "text/x-gcode")
        gcode_textio = StringIO() #We have to convert the g-code into bytes.
        PluginRegistry.getInstance().getPluginObject("GCodeWriter").write(gcode_textio, None)
        gcode = archive.getStream("/3D/model.gcode")
        gcode.write(gcode_textio.getvalue().encode("UTF-8"))
        archive.addRelation(virtual_path = "/3D/model.gcode", relation_type = "http://schemas.ultimaker.org/package/2018/relationships/gcode")

        #Store the thumbnail.
        if self._snapshot:
            archive.addContentType(extension = "png", mime_type = "image/png")
            thumbnail = archive.getStream("/Metadata/thumbnail.png")

            thumbnail_buffer = QBuffer()
            thumbnail_buffer.open(QBuffer.ReadWrite)
            thumbnail_image = self._snapshot
            thumbnail_image.save(thumbnail_buffer, "PNG")

            thumbnail.write(thumbnail_buffer.data())
            archive.addRelation(virtual_path = "/Metadata/thumbnail.png", relation_type = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail", origin = "/3D/model.gcode")
        else:
            Logger.log("d", "Thumbnail not created, cannot save it")

        archive.close()
        return True
 def _createMonitorViewFromQML(self) -> None:
     if self._monitor_view_qml_path is None and PluginRegistry.getInstance() is not None:
         self._monitor_view_qml_path = os.path.join(
             PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
             "resources", "qml", "MonitorStage.qml"
         )
     super()._createMonitorViewFromQML()
Beispiel #4
0
    def _read(self, file_name):
        with open(file_name, "rb") as file:
            file_data = file.read()
        uncompressed_gcode = gzip.decompress(file_data).decode("utf-8")
        PluginRegistry.getInstance().getPluginObject("GCodeReader").preReadFromStream(uncompressed_gcode)
        result = PluginRegistry.getInstance().getPluginObject("GCodeReader").readFromStream(uncompressed_gcode)

        return result
 def _spawnPrinterSelectionDialog(self):
     if self._printer_selection_dialog is None:
         if PluginRegistry.getInstance() is not None:
             path = os.path.join(
                 PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
                 "resources", "qml", "PrintWindow.qml"
             )
             self._printer_selection_dialog = self._application.createQmlComponent(path, {"OutputDevice": self})
     if self._printer_selection_dialog is not None:
         self._printer_selection_dialog.show()
Beispiel #6
0
    def activeToolPanel(self):
        if not self._active_tool:
            return QUrl()

        try:
            panel_file = PluginRegistry.getInstance().getMetaData(self._active_tool.getPluginId())["tool"]["tool_panel"]
        except KeyError:
            return QUrl()

        return QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self._active_tool.getPluginId()), panel_file))
    def _createView(self):
        ## Load all scripts in the scripts folder
        self.loadAllScripts(os.path.join(PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), "scripts"))
        
        path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), "PostProcessingPlugin.qml"))
        self._component = QQmlComponent(Application.getInstance()._engine, path)

        self._context = QQmlContext(Application.getInstance()._engine.rootContext())
        self._context.setContextProperty("manager", self)
        self._view = self._component.create(self._context)
    def __init__(self, device_id, address, properties, parent = None) -> None:
        super().__init__(device_id = device_id, address = address, properties=properties, connection_type = ConnectionType.NetworkConnection, parent = parent)
        self._api_prefix = "/cluster-api/v1/"

        self._application = CuraApplication.getInstance()

        self._number_of_extruders = 2

        self._dummy_lambdas = (
            "", {}, io.BytesIO()
        )  # type: Tuple[Optional[str], Dict[str, Union[str, int, bool]], Union[io.StringIO, io.BytesIO]]

        self._print_jobs = [] # type: List[UM3PrintJobOutputModel]
        self._received_print_jobs = False # type: bool

        if PluginRegistry.getInstance() is not None:
            plugin_path = PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting")
            if plugin_path is None:
                Logger.log("e", "Cloud not find plugin path for plugin UM3NetworkPrnting")
                raise RuntimeError("Cloud not find plugin path for plugin UM3NetworkPrnting")
            self._monitor_view_qml_path = os.path.join(plugin_path, "resources", "qml", "MonitorStage.qml")

        # Trigger the printersChanged signal when the private signal is triggered
        self.printersChanged.connect(self._clusterPrintersChanged)

        self._accepts_commands = True  # type: bool

        # Cluster does not have authentication, so default to authenticated
        self._authentication_state = AuthState.Authenticated

        self._error_message = None  # type: Optional[Message]
        self._write_job_progress_message = None  # type: Optional[Message]
        self._progress_message = None  # type: Optional[Message]

        self._active_printer = None  # type: Optional[PrinterOutputModel]

        self._printer_selection_dialog = None  # type: QObject

        self.setPriority(3)  # Make sure the output device gets selected above local file output
        self.setName(self._id)
        self.setShortDescription(i18n_catalog.i18nc("@action:button Preceded by 'Ready to'.", "Print over network"))
        self.setDescription(i18n_catalog.i18nc("@properties:tooltip", "Print over network"))

        self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network"))

        self._printer_uuid_to_unique_name_mapping = {}  # type: Dict[str, str]

        self._finished_jobs = []  # type: List[UM3PrintJobOutputModel]

        self._cluster_size = int(properties.get(b"cluster_size", 0))  # type: int

        self._latest_reply_handler = None  # type: Optional[QNetworkReply]
        self._sending_job = None

        self._active_camera_url = QUrl()  # type: QUrl
Beispiel #9
0
    def __init__(self, api_client: CloudApiClient, cluster: CloudClusterResponse, parent: QObject = None) -> None:

        # The following properties are expected on each networked output device.
        # Because the cloud connection does not off all of these, we manually construct this version here.
        # An example of why this is needed is the selection of the compatible file type when exporting the tool path.
        properties = {
            b"address": b"",
            b"name": cluster.host_name.encode() if cluster.host_name else b"",
            b"firmware_version": cluster.host_version.encode() if cluster.host_version else b"",
            b"printer_type": b""
        }

        super().__init__(device_id = cluster.cluster_id, address = "",
                         connection_type = ConnectionType.CloudConnection, properties = properties, parent = parent)
        self._api = api_client
        self._cluster = cluster

        self._setInterfaceElements()

        self._account = api_client.account

        # We use the Cura Connect monitor tab to get most functionality right away.
        if PluginRegistry.getInstance() is not None:
            self._monitor_view_qml_path = os.path.join(
                PluginRegistry.getInstance().getPluginPath("UM3NetworkPrinting"),
                "resources", "qml", "MonitorStage.qml"
            )

        # Trigger the printersChanged signal when the private signal is triggered.
        self.printersChanged.connect(self._clusterPrintersChanged)

        # We keep track of which printer is visible in the monitor page.
        self._active_printer = None  # type: Optional[PrinterOutputModel]

        # Properties to populate later on with received cloud data.
        self._print_jobs = []  # type: List[UM3PrintJobOutputModel]
        self._number_of_extruders = 2  # All networked printers are dual-extrusion Ultimaker machines.

        # We only allow a single upload at a time.
        self._progress = CloudProgressMessage()

        # Keep server string of the last generated time to avoid updating models more than once for the same response
        self._received_printers = None  # type: Optional[List[CloudClusterPrinterStatus]]
        self._received_print_jobs = None  # type: Optional[List[CloudClusterPrintJobStatus]]

        # A set of the user's job IDs that have finished
        self._finished_jobs = set()  # type: Set[str]

        # Reference to the uploaded print job / mesh
        self._tool_path = None  # type: Optional[bytes]
        self._uploaded_print_job = None  # type: Optional[CloudPrintJobResponse]
Beispiel #10
0
    def _onToolsChanged(self):
        items = []

        tools = self._controller.getAllTools()
        for name in tools:
            toolMetaData = PluginRegistry.getInstance().getMetaData(name).get("tool", {})

            # Skip tools that are marked as not visible
            if "visible" in toolMetaData and not toolMetaData["visible"]:
                continue

            # Optional metadata elements
            description = toolMetaData.get("description", "")
            iconName = toolMetaData.get("icon", "default.png")
            weight = toolMetaData.get("weight", 0)

            enabled = self._controller.getTool(name).getEnabled()

            items.append({
                "id": name,
                "name": toolMetaData.get("name", name),
                "icon": iconName,
                "active": False,
                "enabled": enabled,
                "description": description,
                "weight": weight
            })

        items.sort(key = lambda t: t["weight"])
        self.setItems(items)
Beispiel #11
0
 def loadChangeLogs(self):
     self._change_logs = collections.OrderedDict()
     with open(
         os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.txt"),
         "r",
         -1,
         "utf-8",
     ) as f:
         open_version = None
         open_header = ""  # Initialise to an empty header in case there is no "*" in the first line of the changelog
         for line in f:
             line = line.replace("\n", "")
             if "[" in line and "]" in line:
                 line = line.replace("[", "")
                 line = line.replace("]", "")
                 open_version = Version(line)
                 open_header = ""
                 self._change_logs[open_version] = collections.OrderedDict()
             elif line.startswith("*"):
                 open_header = line.replace("*", "")
                 self._change_logs[open_version][open_header] = []
             elif line != "":
                 if open_header not in self._change_logs[open_version]:
                     self._change_logs[open_version][open_header] = []
                 self._change_logs[open_version][open_header].append(line)
Beispiel #12
0
 def qmlPath(self) -> "QUrl":
     plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
     if plugin_path is None:
         Logger.log("e", "Cannot create QML view: cannot find plugin path for plugin [%s]", self.getPluginId())
         return QUrl("")
     path = os.path.join(plugin_path, self._qml_url)
     return QUrl.fromLocalFile(path)
Beispiel #13
0
    def createChangelogWindow(self):
        path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "ChangeLog.qml"))

        component = QQmlComponent(Application.getInstance()._engine, path)
        self._changelog_context = QQmlContext(Application.getInstance()._engine.rootContext())
        self._changelog_context.setContextProperty("manager", self)
        self._changelog_window = component.create(self._changelog_context)
Beispiel #14
0
    def importProfile(self, file_name):
        if not file_name:
            return { "status": "error", "message": catalog.i18nc("@info:status", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, "Invalid path")}

        plugin_registry = PluginRegistry.getInstance()
        for plugin_id, meta_data in self._getIOPlugins("profile_reader"):
            profile_reader = plugin_registry.getPluginObject(plugin_id)
            try:
                profile_or_list = profile_reader.read(file_name) # Try to open the file with the profile reader.
            except Exception as e:
                #Note that this will fail quickly. That is, if any profile reader throws an exception, it will stop reading. It will only continue reading if the reader returned None.
                Logger.log("e", "Failed to import profile from %s: %s", file_name, str(e))
                return { "status": "error", "message": catalog.i18nc("@info:status", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, str(e))}
            if profile_or_list: # Success!
                name_seed = os.path.splitext(os.path.basename(file_name))[0]
                if type(profile_or_list) is not list:
                    profile = profile_or_list
                    self._configureProfile(profile, name_seed)
                    return { "status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profile {0}", profile.getName()) }
                else:
                    for profile in profile_or_list:
                        self._configureProfile(profile, name_seed)

                    if len(profile_or_list) == 1:
                        return {"status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profile {0}", profile_or_list[0].getName())}
                    else:
                        profile_names = ", ".join([profile.getName() for profile in profile_or_list])
                        return { "status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profiles {0}", profile_names) }

        #If it hasn't returned by now, none of the plugins loaded the profile successfully.
        return { "status": "error", "message": catalog.i18nc("@info:status", "Profile {0} has an unknown file type.", file_name)}
Beispiel #15
0
    def _update(self) -> None:
        items = []
        views = self._controller.getAllViews()
        current_view = self._controller.getActiveView()
        if current_view is None:
            return

        for view_id in views:
            view_meta_data = PluginRegistry.getInstance().getMetaData(view_id).get("view", {})

            # Skip view modes that are marked as not visible
            if "visible" in view_meta_data and not view_meta_data["visible"]:
                continue

            # Metadata elements
            name = view_meta_data.get("name", view_id)
            description = view_meta_data.get("description", "")
            icon_name = view_meta_data.get("icon", "")
            weight = view_meta_data.get("weight", 0)

            items.append({
                "id": view_id,
                "name": name,
                "active": view_id == current_view.getPluginId(),
                "description": description,
                "icon": icon_name,
                "weight": weight
            })

        items.sort(key = lambda t: t["weight"])
        self.setItems(items)
Beispiel #16
0
 def _onEngineCreated(self) -> None:
     plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
     if plugin_path:
         self.addDisplayComponent("main", os.path.join(plugin_path, "SimulationViewMainComponent.qml"))
         self.addDisplayComponent("menu", os.path.join(plugin_path, "SimulationViewMenuComponent.qml"))
     else:
         Logger.log("e", "Unable to find the path for %s", self.getPluginId())
Beispiel #17
0
 def _createConfigUI(self):
     if self._ui_view is None:
         Logger.log("d", "Creating ImageReader config UI")
         path = os.path.join(PluginRegistry.getInstance().getPluginPath("ImageReader"), "ConfigUI.qml")
         self._ui_view = Application.getInstance().createQmlComponent(path, {"manager": self})
         self._ui_view.setFlags(self._ui_view.flags() & ~Qt.WindowCloseButtonHint & ~Qt.WindowMinimizeButtonHint & ~Qt.WindowMaximizeButtonHint);
         self._disable_size_callbacks = False
Beispiel #18
0
 def _createViewFromQML(self):
     path = QUrl.fromLocalFile(
         os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), self._qml_url))
     self._component = QQmlComponent(Application.getInstance()._engine, path)
     self._context = QQmlContext(Application.getInstance()._engine.rootContext())
     self._context.setContextProperty("manager", self)
     self._view = self._component.create(self._context)
Beispiel #19
0
    def importProfile(self, file_name):
        if not file_name:
            return { "status": "error", "message": catalog.i18nc("@info:status", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, "Invalid path")}

        plugin_registry = PluginRegistry.getInstance()
        for plugin_id, meta_data in self._getIOPlugins("profile_reader"):
            profile_reader = plugin_registry.getPluginObject(plugin_id)
            try:
                profile = profile_reader.read(file_name) #Try to open the file with the profile reader.
            except Exception as e:
                #Note that this will fail quickly. That is, if any profile reader throws an exception, it will stop reading. It will only continue reading if the reader returned None.
                Logger.log("e", "Failed to import profile from %s: %s", file_name, str(e))
                return { "status": "error", "message": catalog.i18nc("@info:status", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, str(e))}
            if profile: #Success!
                profile.setReadOnly(False)

                new_name = self.createUniqueName("quality", "", os.path.splitext(os.path.basename(file_name))[0],
                                                 catalog.i18nc("@label", "Custom profile"))
                profile.setName(new_name)
                profile._id = new_name

                if self._machineHasOwnQualities():
                    profile.setDefinition(self._activeDefinition())
                    if self._machineHasOwnMaterials():
                        profile.addMetaDataEntry("material", self._activeMaterialId())
                else:
                    profile.setDefinition(ContainerRegistry.getInstance().findDefinitionContainers(id="fdmprinter")[0])
                ContainerRegistry.getInstance().addContainer(profile)

                return { "status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profile {0}", profile.getName()) }

        #If it hasn't returned by now, none of the plugins loaded the profile successfully.
        return { "status": "error", "message": catalog.i18nc("@info:status", "Profile {0} has an unknown file type.", file_name)}
    def __init__(self, current_versions):
        self._version_upgrades = {} #For each config type and each version, gives a set of upgrade plug-ins that can convert them to something else.
        self._get_version_functions = {} #For each config type, gives a function with which to get the version number from those files.
        self._storage_paths = {} #For each config type, a set of storage paths to search for old config files.
        self._current_versions = current_versions #To know which preference versions and types to upgrade to.

        self._registry = PluginRegistry.getInstance()
        PluginRegistry.addType("version_upgrade", self._addVersionUpgrade)
    def _createView(self):
        Logger.log("d", "Creating post processing plugin view.")

        ## Load all scripts in the scripts folder
        try:
            self.loadAllScripts(os.path.join(PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), "scripts"))
        except Exception as e:
            print("Exception occured", e)  # TODO: Debug code (far to general catch. Remove this once done testing)

        path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("PostProcessingPlugin"), "PostProcessingPlugin.qml"))
        self._component = QQmlComponent(Application.getInstance()._engine, path)

        # We need access to engine (although technically we can't)
        self._context = QQmlContext(Application.getInstance()._engine.rootContext())
        self._context.setContextProperty("manager", self)
        self._view = self._component.create(self._context)
        Logger.log("d", "Post processing view created.")
 def spawnFirmwareInterface(self, serial_port):
     if self._firmware_view is None:
         path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("Doodle3D"), "SettingsWindow.qml"))
         component = QQmlComponent(Application.getInstance()._engine, path)
         self._firmware_context = QQmlContext(Application.getInstance()._engine.rootContext())
         self._firmware_context.setContextProperty("manager", self)
         self._firmware_view = component.create(self._firmware_context)
     self._firmware_view.show()
Beispiel #23
0
    def getWriterByMimeType(self, mime):
        writer_data = PluginRegistry.getInstance().getAllMetaData(filter = {"mesh_writer": {}}, active_only = True)
        for entry in writer_data:
            for output in entry["mesh_writer"].get("output", []):
                if mime == output["mime_type"]:
                    return self._mesh_writers[entry["id"]]

        return None
Beispiel #24
0
    def getWriterByMimeType(self, mime: str) -> Optional["FileWriter"]:
        writer_data = PluginRegistry.getInstance().getAllMetaData(filter={self._writer_type: {}}, active_only=True)
        for entry in writer_data:
            for output in entry[self._writer_type].get("output", []):
                if mime == output["mime_type"]:
                    return self._writers[entry["id"]]

        return None
 def createControlInterface(self):
     if self._control_view is None:
         Logger.log("d", "Creating control interface for printer connection")
         path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "ControlWindow.qml"))
         component = QQmlComponent(Application.getInstance()._engine, path)
         self._control_context = QQmlContext(Application.getInstance()._engine.rootContext())
         self._control_context.setContextProperty("manager", self)
         self._control_view = component.create(self._control_context)
Beispiel #26
0
    def __eq__(self, other: object) -> bool:
        if type(other) is not type(self):
            return False
        other = cast(ContainerProvider, other)

        plugin_registry = PluginRegistry.getInstance()
        my_metadata = plugin_registry.getMetaData(self.getPluginId())
        other_metadata = plugin_registry.getMetaData(other.getPluginId())
        return my_metadata["container_provider"]["priority"] == other_metadata["container_provider"]["priority"]
Beispiel #27
0
 def _checkAlreadyInstalled(self, id):
     plugin_registry = PluginRegistry.getInstance()
     metadata = plugin_registry.getMetaData(id)
     if metadata != {}:
         return True
     else:
         if id in self._newly_installed_plugin_ids:
             return True  # We already installed this plugin, but the registry just doesn't know it yet.
         return False
Beispiel #28
0
 def _createSocket(self, protocol_file: str = None) -> None:
     if not protocol_file:
         plugin_path = PluginRegistry.getInstance().getPluginPath(self.getPluginId())
         if not plugin_path:
             Logger.log("e", "Could not get plugin path!", self.getPluginId())
             return
         protocol_file = os.path.abspath(os.path.join(plugin_path, "Cura.proto"))
     super()._createSocket(protocol_file)
     self._engine_is_fresh = True
Beispiel #29
0
 def _createViewFromQML(self):
     path = QUrl.fromLocalFile(os.path.join(PluginRegistry.getInstance().getPluginPath("3MFReader"), self._qml_url))
     self._component = QQmlComponent(Application.getInstance()._engine, path)
     self._context = QQmlContext(Application.getInstance()._engine.rootContext())
     self._context.setContextProperty("manager", self)
     self._view = self._component.create(self._context)
     if self._view is None:
         Logger.log("c", "QQmlComponent status %s", self._component.status())
         Logger.log("c", "QQmlComponent error string %s", self._component.errorString())
Beispiel #30
0
    def _getIOPlugins(self, io_type):
        plugin_registry = PluginRegistry.getInstance()
        active_plugin_ids = plugin_registry.getActivePlugins()

        result = []
        for plugin_id in active_plugin_ids:
            meta_data = plugin_registry.getMetaData(plugin_id)
            if io_type in meta_data:
                result.append( (plugin_id, meta_data) )
        return result
Beispiel #31
0
    def onFilenameAccepted(self):
        self._fileName = self._dialog.findChild(QObject,
                                                "nameField").property('text')
        if not self._fileName.endswith('.gcode') and '.' not in self._fileName:
            self._fileName += '.gcode'
        Logger.log("d",
                   self._name_id + " | Filename set to: " + self._fileName)

        self._dialog.deleteLater()

        # create the temp file for the gcode
        self._stream = StringIO()
        self._stage = OutputStage.writing
        self.writeStarted.emit(self)

        # show a progress message
        self._message = Message(
            catalog.i18nc("@info:progress",
                          "Sending to {}").format(self._name), 0, False, -1)
        self._message.show()

        Logger.log("d", self._name_id + " | Loading gcode...")

        # get the g-code through the GCodeWrite plugin
        # this serializes the actual scene and should produce the same output as "Save to File"
        gcode_writer = cast(
            MeshWriter,
            PluginRegistry.getInstance().getPluginObject("GCodeWriter"))
        success = gcode_writer.write(self._stream, None)
        if not success:
            Logger.log("e", "GCodeWrite failed.")
            return

        # start
        Logger.log("d", self._name_id + " | Connecting...")
        self._send('connect', [("password", self._duet_password),
                               self._timestamp()], self.onUploadReady)
Beispiel #32
0
    def _createAdditionalComponentsView(self) -> None:
        Logger.log("d", "Creating additional ui components for UM3.")

        # Create networking dialog
        plugin_path = PluginRegistry.getInstance().getPluginPath(
            "UM3NetworkPrinting")
        if not plugin_path:
            return
        path = os.path.join(plugin_path, "resources/qml/UM3InfoComponents.qml")
        self.__additional_components_view = CuraApplication.getInstance(
        ).createQmlComponent(path, {"manager": self})
        if not self.__additional_components_view:
            Logger.log("w", "Could not create ui components for UM3.")
            return

        # Create extra components
        CuraApplication.getInstance().addAdditionalComponent(
            "monitorButtons",
            self.__additional_components_view.findChild(
                QObject, "networkPrinterConnectButton"))
        CuraApplication.getInstance().addAdditionalComponent(
            "machinesDetailPane",
            self.__additional_components_view.findChild(
                QObject, "networkPrinterConnectionInfo"))
Beispiel #33
0
    def beginRendering(self):
        scene = self.getController().getScene()
        renderer = self.getRenderer()

        if not self._xray_shader:
            self._xray_shader = OpenGL.getInstance().createShaderProgram(
                os.path.join(
                    PluginRegistry.getInstance().getPluginPath("XRayView"),
                    "xray.shader"))
            self._xray_shader.setUniformValue("u_color", [0.1, 0.1, 0.2, 1.0])

        for node in BreadthFirstIterator(scene.getRoot()):
            if not node.render(renderer):
                if node.getMeshData() and node.isVisible():
                    renderer.queueNode(
                        node,
                        shader=self._xray_shader,
                        type=RenderBatch.RenderType.Solid,
                        blend_mode=RenderBatch.BlendMode.Additive,
                        sort=-10,
                        state_setup_callback=lambda gl: gl.glDepthFunc(
                            gl.GL_ALWAYS),
                        state_teardown_callback=lambda gl: gl.glDepthFunc(
                            gl.GL_LESS))
Beispiel #34
0
    def render(self):
        if not self._shader:
            self._shader = OpenGL.getInstance().createShaderProgram(
                os.path.join(
                    PluginRegistry.getInstance().getPluginPath("XRayView"),
                    "xray.shader"))

        batch = RenderBatch(self._shader,
                            type=RenderBatch.RenderType.NoType,
                            backface_cull=False,
                            blend_mode=RenderBatch.BlendMode.Additive)
        for node in DepthFirstIterator(self._scene.getRoot()):
            if isinstance(node, SteSlicerSceneNode) and node.getMeshData(
            ) and node.isVisible():
                batch.addItem(node.getWorldTransformation(),
                              node.getMeshData())

        self.bind()

        self._gl.glDisable(self._gl.GL_DEPTH_TEST)
        batch.render(self._scene.getActiveCamera())
        self._gl.glEnable(self._gl.GL_DEPTH_TEST)

        self.release()
Beispiel #35
0
    def write(self,
              stream: BufferedIOBase,
              nodes: List[SceneNode],
              mode=MeshWriter.OutputMode.BinaryMode) -> bool:
        if mode != MeshWriter.OutputMode.BinaryMode:
            Logger.log("e", "GCodeGzWriter does not support text mode.")
            self.setInformation(
                catalog.i18nc("@error:not supported",
                              "GCodeGzWriter does not support text mode."))
            return False

        #Get the g-code from the g-code writer.
        gcode_textio = StringIO()  #We have to convert the g-code into bytes.
        gcode_writer = cast(
            MeshWriter,
            PluginRegistry.getInstance().getPluginObject("GCodeWriter"))
        success = gcode_writer.write(gcode_textio, None)
        if not success:  #Writing the g-code failed. Then I can also not write the gzipped g-code.
            self.setInformation(gcode_writer.getInformation())
            return False

        result = gzip.compress(gcode_textio.getvalue().encode("utf-8"))
        stream.write(result)
        return True
Beispiel #36
0
    def _onToolsChanged(self):
        self.clear()

        tools = self._controller.getAllTools()
        for name in tools:
            toolMetaData = PluginRegistry.getInstance().getMetaData(name).get("tool", {})

            # Skip tools that are marked as not visible
            if "visible" in toolMetaData and not toolMetaData["visible"]:
                continue

            # Optional metadata elements
            description = toolMetaData.get("description", "")
            iconName = toolMetaData.get("icon", "default.png")

            self.appendItem({
                "id": name,
                "name": toolMetaData.get("name", name),
                "icon": iconName,
                "active": False,
                "description": description
            })

        self.sort(lambda t: t["name"])
Beispiel #37
0
 def loadChangeLogs(self):
     self._change_logs = collections.OrderedDict()
     with open(
             os.path.join(
                 PluginRegistry.getInstance().getPluginPath(
                     self.getPluginId()), "ChangeLog.txt"), "r", -1,
             "utf-8") as f:
         open_version = None
         open_header = None
         for line in f:
             line = line.replace("\n", "")
             if "[" in line and "]" in line:
                 line = line.replace("[", "")
                 line = line.replace("]", "")
                 open_version = Version(line)
                 self._change_logs[Version(
                     line)] = collections.OrderedDict()
             elif line.startswith("*"):
                 open_header = line.replace("*", "")
                 self._change_logs[open_version][open_header] = []
             else:
                 if line != "":
                     self._change_logs[open_version][open_header].append(
                         line)
Beispiel #38
0
    def importProfile(self, file_name):
        if not file_name:
            return { "status": "error", "message": catalog.i18nc("@info:status", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, "Invalid path")}

        plugin_registry = PluginRegistry.getInstance()
        container_registry = ContainerRegistry.getInstance()
        for plugin_id, meta_data in self._getIOPlugins("profile_reader"):
            profile_reader = plugin_registry.getPluginObject(plugin_id)
            try:
                profile_or_list = profile_reader.read(file_name) # Try to open the file with the profile reader.
            except Exception as e:
                #Note that this will fail quickly. That is, if any profile reader throws an exception, it will stop reading. It will only continue reading if the reader returned None.
                Logger.log("e", "Failed to import profile from %s: %s", file_name, str(e))
                return { "status": "error", "message": catalog.i18nc("@info:status", "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>", file_name, str(e))}
            if profile_or_list: # Success!
                name_seed = os.path.splitext(os.path.basename(file_name))[0]
                if type(profile_or_list) is not list:
                    profile = profile_or_list
                    self._configureProfile(profile, name_seed)
                    return { "status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profile {0}", profile.getName()) }
                else:
                    for profile in profile_or_list:
                        profile.setDirty(True)  # Ensure the profiles are correctly saved
                        if profile.getId() != "":
                            container_registry.addContainer(profile)
                        else:
                            self._configureProfile(profile, name_seed)

                    if len(profile_or_list) == 1:
                        return {"status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profile {0}", profile_or_list[0].getName())}
                    else:
                        profile_names = ", ".join([profile.getName() for profile in profile_or_list])
                        return { "status": "ok", "message": catalog.i18nc("@info:status", "Successfully imported profiles {0}", profile_names) }

        #If it hasn't returned by now, none of the plugins loaded the profile successfully.
        return { "status": "error", "message": catalog.i18nc("@info:status", "Profile {0} has an unknown file type.", file_name)}
Beispiel #39
0
 def _createCloudFlowStartMessage(self):
     self._start_cloud_flow_message = Message(
         text=i18n_catalog.i18nc(
             "@info:status",
             "Send and monitor print jobs from anywhere using your Ultimaker account."
         ),
         lifetime=0,
         image_source=QUrl.fromLocalFile(
             os.path.join(
                 PluginRegistry.getInstance().getPluginPath(
                     "UM3NetworkPrinting"), "resources", "svg",
                 "cloud-flow-start.svg")),
         image_caption=i18n_catalog.i18nc(
             "@info:status Ultimaker Cloud is a brand name and shouldn't be translated.",
             "Connect to Ultimaker Cloud"),
         option_text=i18n_catalog.i18nc(
             "@action", "Don't ask me again for this printer."),
         option_state=False)
     self._start_cloud_flow_message.addAction(
         "", i18n_catalog.i18nc("@action", "Get started"), "", "")
     self._start_cloud_flow_message.optionToggled.connect(
         self._onDontAskMeAgain)
     self._start_cloud_flow_message.actionTriggered.connect(
         self._onCloudFlowStarted)
Beispiel #40
0
    def _onStagesChanged(self):
        items = []
        stages = self._controller.getAllStages()

        for stage_id, stage in stages.items():
            view_meta_data = PluginRegistry.getInstance().getMetaData(stage_id).get("stage", {})

            # Skip view modes that are marked as not visible
            if "visible" in view_meta_data and not view_meta_data["visible"]:
                continue

            # Metadata elements
            name = view_meta_data.get("name", stage_id)
            weight = view_meta_data.get("weight", 99)

            items.append({
                "id": stage_id,
                "name": name,
                "stage": stage,
                "weight": weight
            })

        items.sort(key=lambda t: t["weight"])
        self.setItems(items)
Beispiel #41
0
 def loadChangeLogs(self):
     self._change_logs = collections.OrderedDict()
     with open(
             os.path.join(
                 PluginRegistry.getInstance().getPluginPath(
                     self.getPluginId()), "ChangeLog.txt"), "r", -1,
             "utf-8") as f:
         open_version = None
         open_header = ""  # Initialise to an empty header in case there is no "*" in the first line of the changelog
         for line in f:
             line = line.replace("\n", "")
             if "[" in line and "]" in line:
                 line = line.replace("[", "")
                 line = line.replace("]", "")
                 open_version = Version(line)
                 open_header = ""
                 self._change_logs[open_version] = collections.OrderedDict()
             elif line.startswith("*"):
                 open_header = line.replace("*", "")
                 self._change_logs[open_version][open_header] = []
             elif line != "":
                 if open_header not in self._change_logs[open_version]:
                     self._change_logs[open_version][open_header] = []
                 self._change_logs[open_version][open_header].append(line)
Beispiel #42
0
 def addContainerType(cls, container):
     plugin_id = container.getPluginId()
     metadata = PluginRegistry.getInstance().getMetaData(plugin_id)
     if "settings_container" not in metadata or "mimetype" not in metadata["settings_container"]:
         raise Exception("Plugin {plugin} has incorrect metadata: Expected a 'settings_container' block with a 'mimetype' entry".format(plugin = plugin_id))
     cls.addContainerTypeByName(container.__class__, plugin_id, metadata["settings_container"]["mimetype"])
Beispiel #43
0
    def importProfile(self, file_name):
        Logger.log("d", "Attempting to import profile %s", file_name)
        if not file_name:
            return {
                "status":
                "error",
                "message":
                catalog.i18nc(
                    "@info:status",
                    "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>",
                    file_name, "Invalid path")
            }

        plugin_registry = PluginRegistry.getInstance()
        extension = file_name.split(".")[-1]

        global_container_stack = Application.getInstance(
        ).getGlobalContainerStack()
        if not global_container_stack:
            return

        machine_extruders = list(
            ExtruderManager.getInstance().getMachineExtruders(
                global_container_stack.getId()))
        machine_extruders.sort(key=lambda k: k.getMetaDataEntry("position"))

        for plugin_id, meta_data in self._getIOPlugins("profile_reader"):
            if meta_data["profile_reader"][0]["extension"] != extension:
                continue

            profile_reader = plugin_registry.getPluginObject(plugin_id)
            try:
                profile_or_list = profile_reader.read(
                    file_name)  # Try to open the file with the profile reader.
            except Exception as e:
                # Note that this will fail quickly. That is, if any profile reader throws an exception, it will stop reading. It will only continue reading if the reader returned None.
                Logger.log(
                    "e",
                    "Failed to import profile from %s: %s while using profile reader. Got exception %s",
                    file_name, profile_reader.getPluginId(), str(e))
                return {
                    "status":
                    "error",
                    "message":
                    catalog.i18nc(
                        "@info:status",
                        "Failed to import profile from <filename>{0}</filename>: <message>{1}</message>",
                        file_name, str(e))
                }
            if profile_or_list:  # Success!
                name_seed = os.path.splitext(os.path.basename(file_name))[0]
                new_name = self.uniqueName(name_seed)
                if type(profile_or_list) is not list:
                    profile = profile_or_list
                    self._configureProfile(profile, name_seed, new_name)
                    return {
                        "status":
                        "ok",
                        "message":
                        catalog.i18nc("@info:status",
                                      "Successfully imported profile {0}",
                                      profile.getName())
                    }
                else:
                    profile_index = -1
                    global_profile = None

                    for profile in profile_or_list:
                        if profile_index >= 0:
                            if len(machine_extruders) > profile_index:
                                extruder_id = Application.getInstance(
                                ).getMachineManager().getQualityDefinitionId(
                                    machine_extruders[profile_index].getBottom(
                                    ))
                                # Ensure the extruder profiles get non-conflicting names
                                # NB: these are not user-facing
                                if "extruder" in profile.getMetaData():
                                    profile.setMetaDataEntry(
                                        "extruder", extruder_id)
                                else:
                                    profile.addMetaDataEntry(
                                        "extruder", extruder_id)
                                profile_id = (extruder_id + "_" +
                                              name_seed).lower().replace(
                                                  " ", "_")
                            elif profile_index == 0:
                                # Importing a multiextrusion profile into a single extrusion machine; merge 1st extruder profile into global profile
                                profile._id = self.uniqueName(
                                    "temporary_profile")
                                self.addContainer(profile)
                                ContainerManager.getInstance().mergeContainers(
                                    global_profile.getId(), profile.getId())
                                self.removeContainer(profile.getId())
                                break
                            else:
                                # The imported composite profile has a profile for an extruder that this machine does not have. Ignore this extruder-profile
                                break
                        else:
                            global_profile = profile
                            profile_id = (
                                global_container_stack.getBottom().getId() +
                                "_" + name_seed).lower().replace(" ", "_")

                        self._configureProfile(profile, profile_id, new_name)

                        profile_index += 1

                    return {
                        "status":
                        "ok",
                        "message":
                        catalog.i18nc("@info:status",
                                      "Successfully imported profile {0}",
                                      profile_or_list[0].getName())
                    }

        # If it hasn't returned by now, none of the plugins loaded the profile successfully.
        return {
            "status":
            "error",
            "message":
            catalog.i18nc(
                "@info:status",
                "Profile {0} has an unknown file type or is corrupted.",
                file_name)
        }
Beispiel #44
0
 def _onDownloadFinished(self, success_items: Dict[str, str],
                         error_items: List[str]) -> None:
     # todo handle error items
     plugin_path = PluginRegistry.getInstance().getPluginPath(
         self.getPluginId())
     self._license_presenter.present(plugin_path, success_items)
    def addProvider(self, provider: ContainerProvider) -> None:
        """Adds a container provider to search through containers in."""

        self._providers.append(provider)
        # Re-sort every time. It's quadratic, but there shouldn't be that many providers anyway...
        self._providers.sort(key = lambda provider: PluginRegistry.getInstance().getMetaData(provider.getPluginId())["container_provider"].get("priority", 0))
 def _createViewFromQML(self):
     path = os.path.join(
         PluginRegistry.getInstance().getPluginPath("3MFReader"),
         self._qml_url)
     self._view = Application.getInstance().createQmlComponent(
         path, {"manager": self})
Beispiel #47
0
    def event(self, event):
        modifiers = QApplication.keyboardModifiers()
        ctrl_is_active = modifiers & Qt.ControlModifier
        shift_is_active = modifiers & Qt.ShiftModifier
        if event.type == Event.KeyPressEvent and ctrl_is_active:
            amount = 10 if shift_is_active else 1
            if event.key == KeyEvent.UpKey:
                self.setLayer(self._current_layer_num + amount)
                return True
            if event.key == KeyEvent.DownKey:
                self.setLayer(self._current_layer_num - amount)
                return True

        if event.type == Event.ViewActivateEvent:
            # FIX: on Max OS X, somehow QOpenGLContext.currentContext() can become None during View switching.
            # This can happen when you do the following steps:
            #   1. Start Cura
            #   2. Load a model
            #   3. Switch to Custom mode
            #   4. Select the model and click on the per-object tool icon
            #   5. Switch view to Layer view or X-Ray
            #   6. Cura will very likely crash
            # It seems to be a timing issue that the currentContext can somehow be empty, but I have no clue why.
            # This fix tries to reschedule the view changing event call on the Qt thread again if the current OpenGL
            # context is None.
            if Platform.isOSX():
                if QOpenGLContext.currentContext() is None:
                    Logger.log("d", "current context of OpenGL is empty on Mac OS X, will try to create shaders later")
                    CuraApplication.getInstance().callLater(lambda e=event: self.event(e))
                    return

            # Make sure the SimulationPass is created
            layer_pass = self.getSimulationPass()
            self.getRenderer().addRenderPass(layer_pass)

            # Make sure the NozzleNode is add to the root
            nozzle = self.getNozzleNode()
            nozzle.setParent(self.getController().getScene().getRoot())
            nozzle.setVisible(False)

            Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged)
            self._onGlobalStackChanged()

            if not self._simulationview_composite_shader:
                self._simulationview_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), "simulationview_composite.shader"))
                theme = Application.getInstance().getTheme()
                self._simulationview_composite_shader.setUniformValue("u_background_color", Color(*theme.getColor("viewport_background").getRgb()))
                self._simulationview_composite_shader.setUniformValue("u_outline_color", Color(*theme.getColor("model_selection_outline").getRgb()))

            if not self._composite_pass:
                self._composite_pass = self.getRenderer().getRenderPass("composite")

            self._old_layer_bindings = self._composite_pass.getLayerBindings()[:] # make a copy so we can restore to it later
            self._composite_pass.getLayerBindings().append("simulationview")
            self._old_composite_shader = self._composite_pass.getCompositeShader()
            self._composite_pass.setCompositeShader(self._simulationview_composite_shader)

        elif event.type == Event.ViewDeactivateEvent:
            self._wireprint_warning_message.hide()
            Application.getInstance().globalContainerStackChanged.disconnect(self._onGlobalStackChanged)
            if self._global_container_stack:
                self._global_container_stack.propertyChanged.disconnect(self._onPropertyChanged)

            self._nozzle_node.setParent(None)
            self.getRenderer().removeRenderPass(self._layer_pass)
            self._composite_pass.setLayerBindings(self._old_layer_bindings)
            self._composite_pass.setCompositeShader(self._old_composite_shader)
Beispiel #48
0
 def __eq__(self, other: "ContainerProvider"):
     plugin_registry = PluginRegistry.getInstance()
     my_metadata = plugin_registry.getMetaData(self.getPluginId())
     other_metadata = plugin_registry.getMetaData(other.getPluginId())
     return my_metadata["container_provider"]["priority"] == other_metadata[
         "container_provider"]["priority"]
Beispiel #49
0
 def _createSocket(self):
     super()._createSocket(os.path.abspath(os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), "Cura.proto")))
Beispiel #50
0
 def _plugin_path(self):
     return PluginRegistry.getInstance().getPluginPath(self._get_plugin_directory_name())
Beispiel #51
0
 def registerObjects(
     self, engine
 ) -> None:  #type: ignore #Don't type engine, because the type depends on the platform you're running on so it always gives an error somewhere.
     engine.rootContext().setContextProperty("PluginRegistry",
                                             PluginRegistry.getInstance())
Beispiel #52
0
    def __init__(self,
                 serial_port: str,
                 baud_rate: Optional[int] = None) -> None:
        super().__init__(serial_port,
                         connection_type=ConnectionType.UsbConnection)
        self.setName(catalog.i18nc("@item:inmenu", "USB printing"))
        self.setShortDescription(
            catalog.i18nc("@action:button Preceded by 'Ready to'.",
                          "Print via USB"))
        self.setDescription(catalog.i18nc("@info:tooltip", "Print via USB"))
        self.setIconName("print")

        self._serial = None  # type: Optional[Serial]
        self._serial_port = serial_port
        self._address = serial_port

        self._timeout = 3

        # List of gcode lines to be printed
        self._gcode = []  # type: List[str]
        self._gcode_position = 0

        self._use_auto_detect = True

        self._baud_rate = baud_rate

        self._all_baud_rates = [
            115200, 250000, 500000, 230400, 57600, 38400, 19200, 9600
        ]

        # Instead of using a timer, we really need the update to be as a thread, as reading from serial can block.
        self._update_thread = Thread(target=self._update,
                                     daemon=True,
                                     name="USBPrinterUpdate")

        self._last_temperature_request = None  # type: Optional[int]
        self._firmware_idle_count = 0

        self._is_printing = False  # A print is being sent.

        ## Set when print is started in order to check running time.
        self._print_start_time = None  # type: Optional[float]
        self._print_estimated_time = None  # type: Optional[int]

        self._accepts_commands = True

        self._paused = False
        self._printer_busy = False  # When printer is preheating and waiting (M190/M109), or when waiting for action on the printer

        self.setConnectionText(
            catalog.i18nc("@info:status", "Connected via USB"))

        # Queue for commands that need to be sent.
        self._command_queue = Queue()  # type: Queue
        # Event to indicate that an "ok" was received from the printer after sending a command.
        self._command_received = Event()
        self._command_received.set()

        self._firmware_name_requested = False
        self._firmware_updater = AvrFirmwareUpdater(self)

        plugin_path = cast(
            str,
            PluginRegistry.getInstance().getPluginPath("USBPrinting"))
        self._monitor_view_qml_path = os.path.join(plugin_path,
                                                   "MonitorItem.qml")

        CuraApplication.getInstance().getOnExitCallbackManager().addCallback(
            self._checkActivePrintingUponAppExit)
Beispiel #53
0
 def addProvider(self, provider: "PluginObject"):
     self._providers.append(provider)
     #Re-sort every time. It's quadratic, but there shouldn't be that many providers anyway...
     self._providers.sort(key = lambda provider: PluginRegistry.getInstance().getMetaData(provider.getPluginId())["container_provider"].get("priority", 0))
Beispiel #54
0
 def registerObjects(self, engine):
     engine.rootContext().setContextProperty("PluginRegistry",
                                             PluginRegistry.getInstance())
Beispiel #55
0
 def _onDiscrepancies(self, model: SubscribedPackagesModel) -> None:
     plugin_path = PluginRegistry.getInstance().getPluginPath(
         self.getPluginId())
     self._discrepancies_presenter.present(plugin_path, model)
    def spawnFirmwareInterface(self, serial_port):
        if self._firmware_view is None:
            path = os.path.join(PluginRegistry.getInstance().getPluginPath("USBPrinting"), "FirmwareUpdateWindow.qml")
            self._firmware_view = Application.getInstance().createQmlComponent(path, {"manager": self})

        self._firmware_view.show()
Beispiel #57
0
 def createChangelogWindow(self):
     path = os.path.join(
         PluginRegistry.getInstance().getPluginPath(self.getPluginId()),
         "ChangeLog.qml")
     self._changelog_window = Application.getInstance().createQmlComponent(
         path, {"manager": self})
Beispiel #58
0
    def __init__(self, name, version, **kwargs):
        if (Application._instance != None):
            raise ValueError("Duplicate singleton creation")

        # If the constructor is called and there is no instance, set the instance to self.
        # This is done because we can't make constructor private
        Application._instance = self

        self._application_name = name
        self._version = version

        os.putenv(
            "UBUNTU_MENUPROXY", "0"
        )  #For Ubuntu Unity this makes Qt use its own menu bar rather than pass it on to Unity.

        Signal._app = self
        Resources.ApplicationIdentifier = name
        i18nCatalog.setApplication(self)

        Resources.addSearchPath(os.path.dirname(sys.executable))
        Resources.addSearchPath(
            os.path.join(Application.getInstallPrefix(), "share", "uranium"))
        Resources.addSearchPath(
            os.path.join(Application.getInstallPrefix(), "Resources",
                         "uranium"))
        Resources.addSearchPath(
            os.path.join(Application.getInstallPrefix(), "Resources",
                         self.getApplicationName()))
        if not hasattr(sys, "frozen"):
            Resources.addSearchPath(
                os.path.join(os.path.abspath(os.path.dirname(__file__)), ".."))

        self._main_thread = threading.current_thread()

        super().__init__(
            **kwargs)  # Call super to make multiple inheritence work.

        self._renderer = None

        PluginRegistry.addType("backend", self.setBackend)
        PluginRegistry.addType("logger", Logger.addLogger)
        PluginRegistry.addType("extension", self.addExtension)

        preferences = Preferences.getInstance()
        preferences.addPreference("general/language", "en")
        try:
            preferences.readFromFile(
                Resources.getPath(Resources.Preferences,
                                  self._application_name + ".cfg"))
        except FileNotFoundError:
            pass

        self._controller = Controller(self)
        self._mesh_file_handler = MeshFileHandler()
        self._extensions = []
        self._backend = None
        self._output_device_manager = OutputDeviceManager()
        self._machine_manager = MachineManager(self._application_name)

        self._required_plugins = []

        self._operation_stack = OperationStack()

        self._plugin_registry = PluginRegistry.getInstance()

        self._plugin_registry.addPluginLocation(
            os.path.join(Application.getInstallPrefix(), "lib", "uranium"))
        self._plugin_registry.addPluginLocation(
            os.path.join(os.path.dirname(sys.executable), "plugins"))
        self._plugin_registry.addPluginLocation(
            os.path.join(Application.getInstallPrefix(), "Resources",
                         "uranium", "plugins"))
        self._plugin_registry.addPluginLocation(
            os.path.join(Application.getInstallPrefix(), "Resources",
                         self.getApplicationName(), "plugins"))
        # Locally installed plugins
        self._plugin_registry.addPluginLocation(
            os.path.join(Resources.getStoragePath(Resources.Resources),
                         "plugins"))
        if not hasattr(sys, "frozen"):
            self._plugin_registry.addPluginLocation(
                os.path.join(os.path.abspath(os.path.dirname(__file__)), "..",
                             "plugins"))

        self._plugin_registry.setApplication(self)

        self._parsed_command_line = None
        self.parseCommandLine()

        self._visible_messages = []
        self._message_lock = threading.Lock()
        self.showMessageSignal.connect(self.showMessage)
        self.hideMessageSignal.connect(self.hideMessage)
Beispiel #59
0
 def _createDialog(self, qml_name):
     Logger.log("d", "Creating dialog [%s]", qml_name)
     file_path = os.path.join(PluginRegistry.getInstance().getPluginPath(self.getPluginId()), qml_name)
     dialog = Application.getInstance().createQmlComponent(file_path, {"manager": self})
     return dialog
Beispiel #60
0
    def render(self):
        if not self._layer_shader:
            if self._compatibility_mode:
                shader_filename = "layers.shader"
                shadow_shader_filename = "layers_shadow.shader"
            else:
                shader_filename = "layers3d.shader"
                shadow_shader_filename = "layers3d_shadow.shader"
            self._layer_shader = OpenGL.getInstance().createShaderProgram(
                os.path.join(
                    PluginRegistry.getInstance().getPluginPath(
                        "SimulationView"), shader_filename))
            self._layer_shadow_shader = OpenGL.getInstance(
            ).createShaderProgram(
                os.path.join(
                    PluginRegistry.getInstance().getPluginPath(
                        "SimulationView"), shadow_shader_filename))
            self._current_shader = self._layer_shader
        # Use extruder 0 if the extruder manager reports extruder index -1 (for single extrusion printers)
        self._layer_shader.setUniformValue(
            "u_active_extruder",
            float(max(0, self._extruder_manager.activeExtruderIndex)))
        if not self._compatibility_mode:
            self._layer_shader.setUniformValue(
                "u_starts_color",
                Color(*Application.getInstance().getTheme().getColor(
                    "layerview_starts").getRgb()))

        if self._layer_view:
            self._layer_shader.setUniformValue(
                "u_max_feedrate", self._layer_view.getMaxFeedrate())
            self._layer_shader.setUniformValue(
                "u_min_feedrate", self._layer_view.getMinFeedrate())
            self._layer_shader.setUniformValue(
                "u_max_thickness", self._layer_view.getMaxThickness())
            self._layer_shader.setUniformValue(
                "u_min_thickness", self._layer_view.getMinThickness())
            self._layer_shader.setUniformValue(
                "u_max_line_width", self._layer_view.getMaxLineWidth())
            self._layer_shader.setUniformValue(
                "u_min_line_width", self._layer_view.getMinLineWidth())
            self._layer_shader.setUniformValue(
                "u_max_flow_rate", self._layer_view.getMaxFlowRate())
            self._layer_shader.setUniformValue(
                "u_min_flow_rate", self._layer_view.getMinFlowRate())
            self._layer_shader.setUniformValue(
                "u_layer_view_type", self._layer_view.getSimulationViewType())
            self._layer_shader.setUniformValue(
                "u_extruder_opacity", self._layer_view.getExtruderOpacities())
            self._layer_shader.setUniformValue(
                "u_show_travel_moves", self._layer_view.getShowTravelMoves())
            self._layer_shader.setUniformValue(
                "u_show_helpers", self._layer_view.getShowHelpers())
            self._layer_shader.setUniformValue("u_show_skin",
                                               self._layer_view.getShowSkin())
            self._layer_shader.setUniformValue(
                "u_show_infill", self._layer_view.getShowInfill())
            self._layer_shader.setUniformValue(
                "u_show_starts", self._layer_view.getShowStarts())
        else:
            #defaults
            self._layer_shader.setUniformValue("u_max_feedrate", 1)
            self._layer_shader.setUniformValue("u_min_feedrate", 0)
            self._layer_shader.setUniformValue("u_max_thickness", 1)
            self._layer_shader.setUniformValue("u_min_thickness", 0)
            self._layer_shader.setUniformValue("u_max_flow_rate", 1)
            self._layer_shader.setUniformValue("u_min_flow_rate", 0)
            self._layer_shader.setUniformValue("u_max_line_width", 1)
            self._layer_shader.setUniformValue("u_min_line_width", 0)
            self._layer_shader.setUniformValue("u_layer_view_type", 1)
            self._layer_shader.setUniformValue(
                "u_extruder_opacity",
                [[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]])
            self._layer_shader.setUniformValue("u_show_travel_moves", 0)
            self._layer_shader.setUniformValue("u_show_helpers", 1)
            self._layer_shader.setUniformValue("u_show_skin", 1)
            self._layer_shader.setUniformValue("u_show_infill", 1)
            self._layer_shader.setUniformValue("u_show_starts", 1)

        if not self._tool_handle_shader:
            self._tool_handle_shader = OpenGL.getInstance(
            ).createShaderProgram(
                Resources.getPath(Resources.Shaders, "toolhandle.shader"))

        if not self._nozzle_shader:
            self._nozzle_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "color.shader"))
            self._nozzle_shader.setUniformValue(
                "u_color",
                Color(*Application.getInstance().getTheme().getColor(
                    "layerview_nozzle").getRgb()))

        if not self._disabled_shader:
            self._disabled_shader = OpenGL.getInstance().createShaderProgram(
                Resources.getPath(Resources.Shaders, "striped.shader"))
            self._disabled_shader.setUniformValue(
                "u_diffuseColor1",
                Color(*Application.getInstance().getTheme().getColor(
                    "model_unslicable").getRgb()))
            self._disabled_shader.setUniformValue(
                "u_diffuseColor2",
                Color(*Application.getInstance().getTheme().getColor(
                    "model_unslicable_alt").getRgb()))
            self._disabled_shader.setUniformValue("u_width", 50.0)
            self._disabled_shader.setUniformValue("u_opacity", 0.6)

        self.bind()

        tool_handle_batch = RenderBatch(self._tool_handle_shader,
                                        type=RenderBatch.RenderType.Overlay,
                                        backface_cull=True)
        disabled_batch = RenderBatch(self._disabled_shader)
        head_position = None  # Indicates the current position of the print head
        nozzle_node = None

        for node in DepthFirstIterator(self._scene.getRoot()):

            if isinstance(node, ToolHandle):
                tool_handle_batch.addItem(node.getWorldTransformation(),
                                          mesh=node.getSolidMesh())

            elif isinstance(node, NozzleNode):
                nozzle_node = node
                nozzle_node.setVisible(
                    False)  # Don't set to true, we render it separately!

            elif getattr(node, "_outside_buildarea", False) and isinstance(
                    node, SceneNode) and node.getMeshData() and node.isVisible(
                    ) and not node.callDecoration("isNonPrintingMesh"):
                disabled_batch.addItem(node.getWorldTransformation(copy=False),
                                       node.getMeshData())

            elif isinstance(node, SceneNode) and (node.getMeshData(
            ) or node.callDecoration("isBlockSlicing")) and node.isVisible():
                layer_data = node.callDecoration("getLayerData")
                if not layer_data:
                    continue

                # Render all layers below a certain number as line mesh instead of vertices.
                if self._layer_view._current_layer_num > -1 and (
                    (not self._layer_view._only_show_top_layers) or
                    (not self._layer_view.getCompatibilityMode())):
                    start = 0
                    end = 0
                    element_counts = layer_data.getElementCounts()
                    for layer in sorted(element_counts.keys()):
                        # In the current layer, we show just the indicated paths
                        if layer == self._layer_view._current_layer_num:
                            # We look for the position of the head, searching the point of the current path
                            index = self._layer_view._current_path_num
                            offset = 0
                            for polygon in layer_data.getLayer(layer).polygons:
                                # The size indicates all values in the two-dimension array, and the second dimension is
                                # always size 3 because we have 3D points.
                                if index >= polygon.data.size // 3 - offset:
                                    index -= polygon.data.size // 3 - offset
                                    offset = 1  # This is to avoid the first point when there is more than one polygon, since has the same value as the last point in the previous polygon
                                    continue
                                # The head position is calculated and translated
                                head_position = Vector(
                                    polygon.data[index + offset][0],
                                    polygon.data[index + offset][1],
                                    polygon.data[index + offset]
                                    [2]) + node.getWorldPosition()
                                break
                            break
                        if self._layer_view._minimum_layer_num > layer:
                            start += element_counts[layer]
                        end += element_counts[layer]

                    # Calculate the range of paths in the last layer
                    current_layer_start = end
                    current_layer_end = end + self._layer_view._current_path_num * 2  # Because each point is used twice

                    # This uses glDrawRangeElements internally to only draw a certain range of lines.
                    # All the layers but the current selected layer are rendered first
                    if self._old_current_path != self._layer_view._current_path_num:
                        self._current_shader = self._layer_shadow_shader
                        self._switching_layers = False
                    if not self._layer_view.isSimulationRunning(
                    ) and self._old_current_layer != self._layer_view._current_layer_num:
                        self._current_shader = self._layer_shader
                        self._switching_layers = True

                    # The first line does not have a previous line: add a MoveCombingType in front for start detection
                    # this way the first start of the layer can also be drawn
                    prev_line_types = numpy.concatenate([
                        numpy.asarray([LayerPolygon.MoveCombingType],
                                      dtype=numpy.float32),
                        layer_data._attributes["line_types"]["value"]
                    ])
                    # Remove the last element
                    prev_line_types = prev_line_types[
                        0:layer_data._attributes["line_types"]["value"].size]
                    layer_data._attributes["prev_line_types"] = {
                        'opengl_type': 'float',
                        'value': prev_line_types,
                        'opengl_name': 'a_prev_line_type'
                    }

                    layers_batch = RenderBatch(
                        self._current_shader,
                        type=RenderBatch.RenderType.Solid,
                        mode=RenderBatch.RenderMode.Lines,
                        range=(start, end),
                        backface_cull=True)
                    layers_batch.addItem(node.getWorldTransformation(),
                                         layer_data)
                    layers_batch.render(self._scene.getActiveCamera())

                    # Current selected layer is rendered
                    current_layer_batch = RenderBatch(
                        self._layer_shader,
                        type=RenderBatch.RenderType.Solid,
                        mode=RenderBatch.RenderMode.Lines,
                        range=(current_layer_start, current_layer_end))
                    current_layer_batch.addItem(node.getWorldTransformation(),
                                                layer_data)
                    current_layer_batch.render(self._scene.getActiveCamera())

                    self._old_current_layer = self._layer_view._current_layer_num
                    self._old_current_path = self._layer_view._current_path_num

                # Create a new batch that is not range-limited
                batch = RenderBatch(self._layer_shader,
                                    type=RenderBatch.RenderType.Solid)

                if self._layer_view.getCurrentLayerMesh():
                    batch.addItem(node.getWorldTransformation(),
                                  self._layer_view.getCurrentLayerMesh())

                if self._layer_view.getCurrentLayerJumps():
                    batch.addItem(node.getWorldTransformation(),
                                  self._layer_view.getCurrentLayerJumps())

                if len(batch.items) > 0:
                    batch.render(self._scene.getActiveCamera())

        # The nozzle is drawn when once we know the correct position of the head,
        # but the user is not using the layer slider, and the compatibility mode is not enabled
        if not self._switching_layers and not self._compatibility_mode and self._layer_view.getActivity(
        ) and nozzle_node is not None:
            if head_position is not None:
                nozzle_node.setPosition(head_position)
                nozzle_batch = RenderBatch(
                    self._nozzle_shader,
                    type=RenderBatch.RenderType.Transparent)
                nozzle_batch.addItem(nozzle_node.getWorldTransformation(),
                                     mesh=nozzle_node.getMeshData())
                nozzle_batch.render(self._scene.getActiveCamera())

        if len(disabled_batch.items) > 0:
            disabled_batch.render(self._scene.getActiveCamera())

        # Render toolhandles on top of the layerview
        if len(tool_handle_batch.items) > 0:
            tool_handle_batch.render(self._scene.getActiveCamera())

        self.release()