def _updateTimeQualitySettings(self): if not self._current_settings or not self._enabled: return if not self._low_quality_settings: self._low_quality_settings = MachineSettings() self._low_quality_settings.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, self._current_settings.getTypeID() + ".json")) self._low_quality_settings.loadValuesFromFile(Resources.getPath(Resources.SettingsLocation, "profiles", "low_quality.conf")) if not self._high_quality_settings: self._high_quality_settings = MachineSettings() self._high_quality_settings.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, self._current_settings.getTypeID() + ".json")) self._high_quality_settings.loadValuesFromFile(Resources.getPath(Resources.SettingsLocation, "profiles", "high_quality.conf")) for key, options in self._interpolation_settings.items(): minimum_value = None if options["minimum"] == "low": minimum_value = self._low_quality_settings.getSettingValueByKey(key) elif options["minimum"] == "high": minimum_value = self._high_quality_settings.getSettingValueByKey(key) else: continue maximum_value = None if options["maximum"] == "low": maximum_value = self._low_quality_settings.getSettingValueByKey(key) elif options["maximum"] == "high": maximum_value = self._high_quality_settings.getSettingValueByKey(key) else: continue setting_value = round(minimum_value + (maximum_value - minimum_value) * (self._time_quality_value / 100), options["precision"]) self._current_settings.setSettingValueByKey(key, setting_value)
def __init__(self, width, height): super().__init__("selection", width, height, -999) self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "selection.shader")) self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader")) self._gl = OpenGL.getInstance().getBindingsObject() self._scene = Application.getInstance().getController().getScene() self._renderer = Application.getInstance().getRenderer() self._selection_map = {} self._toolhandle_selection_map = { self._dropAlpha(ToolHandle.DisabledSelectionColor): ToolHandle.NoAxis, self._dropAlpha(ToolHandle.XAxisSelectionColor): ToolHandle.XAxis, self._dropAlpha(ToolHandle.YAxisSelectionColor): ToolHandle.YAxis, self._dropAlpha(ToolHandle.ZAxisSelectionColor): ToolHandle.ZAxis, self._dropAlpha(ToolHandle.AllAxisSelectionColor): ToolHandle.AllAxis, ToolHandle.DisabledSelectionColor: ToolHandle.NoAxis, ToolHandle.XAxisSelectionColor: ToolHandle.XAxis, ToolHandle.YAxisSelectionColor: ToolHandle.YAxis, ToolHandle.ZAxisSelectionColor: ToolHandle.ZAxis, ToolHandle.AllAxisSelectionColor: ToolHandle.AllAxis } self._output = None
def beginRendering(self): scene = self.getController().getScene() renderer = self.getRenderer() if not self._enabled_shader: self._enabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "overhang.shader")) if not self._disabled_shader: self._disabled_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "striped.shader")) self._disabled_shader.setUniformValue("u_diffuseColor1", [0.48, 0.48, 0.48, 1.0]) self._disabled_shader.setUniformValue("u_diffuseColor2", [0.68, 0.68, 0.68, 1.0]) self._disabled_shader.setUniformValue("u_width", 50.0) if Application.getInstance().getGlobalContainerStack(): if Preferences.getInstance().getValue("view/show_overhang"): angle = Application.getInstance().getGlobalContainerStack().getProperty("support_angle", "value") if angle is not None: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - angle))) else: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) #Overhang angle of 0 causes no area at all to be marked as overhang. else: self._enabled_shader.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) for node in DepthFirstIterator(scene.getRoot()): if not node.render(renderer): if node.getMeshData() and node.isVisible(): # TODO: Find a better way to handle this #if node.getBoundingBoxMesh(): # renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(),mode = Renderer.RenderLines) uniforms = {} if self._extruders_model.rowCount() > 0: # Get color to render this mesh in from ExtrudersModel extruder_index = 0 extruder_id = node.callDecoration("getActiveExtruder") if extruder_id: extruder_index = max(0, self._extruders_model.find("id", extruder_id)) extruder_color = self._extruders_model.getItem(extruder_index)["colour"] try: # Colors are passed as rgb hex strings (eg "#ffffff"), and the shader needs # an rgba list of floats (eg [1.0, 1.0, 1.0, 1.0]) uniforms["diffuse_color"] = [ int(extruder_color[1:3], 16) / 255, int(extruder_color[3:5], 16) / 255, int(extruder_color[5:7], 16) / 255, 1.0 ] except ValueError: pass if hasattr(node, "_outside_buildarea"): if node._outside_buildarea: renderer.queueNode(node, shader = self._disabled_shader) else: renderer.queueNode(node, shader = self._enabled_shader, uniforms = uniforms) else: renderer.queueNode(node, material = self._enabled_shader, uniforms = uniforms) if node.callDecoration("isGroup"): renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(), mode = Renderer.RenderLines)
def beginRendering(self): scene = self.getController().getScene() renderer = self.getRenderer() renderer.setRenderSelection(False) if not self._material: self._material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "vertexcolor.frag")) self._material.setUniformValue("u_color", [1.0, 0.0, 0.0, 1.0]) self._selection_material = renderer.createMaterial(Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "color.frag")) self._selection_material.setUniformValue("u_color", Color(35, 35, 35, 128)) for node in DepthFirstIterator(scene.getRoot()): # We do not want to render ConvexHullNode as it conflicts with the bottom layers. # However, it is somewhat relevant when the node is selected, so do render it then. if type(node) is ConvexHullNode and not Selection.isSelected(node.getWatchedNode()): continue if not node.render(renderer): if node.getMeshData() and node.isVisible(): if Selection.isSelected(node): renderer.queueNode(node, material = self._selection_material, transparent = True) 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._current_layer_num - self._solid_layers > -1: start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer, counts in element_counts.items(): if layer + self._solid_layers > self._current_layer_num: break end += counts # This uses glDrawRangeElements internally to only draw a certain range of lines. renderer.queueNode(node, mesh = layer_data, material = self._material, mode = Renderer.RenderLines, start = start, end = end) # We currently recreate the current "solid" layers every time a if not self._current_layer_mesh: self._current_layer_mesh = MeshData() for i in range(self._solid_layers): layer = self._current_layer_num - i if layer < 0: continue layer_mesh = layer_data.getLayer(layer).createMesh() if not layer_mesh or layer_mesh.getVertices() is None: continue self._current_layer_mesh.addVertices(layer_mesh.getVertices()) # Scale layer color by a brightness factor based on the current layer number # This will result in a range of 0.5 - 1.0 to multiply colors by. brightness = (2.0 - (i / self._solid_layers)) / 2.0 self._current_layer_mesh.addColors(layer_mesh.getColors() * brightness) renderer.queueNode(node, mesh = self._current_layer_mesh, material = self._material)
def loadQtTranslation(self, file, language = "default"): #TODO Add support for specifying a language from preferences path = None if language == "default": # If we have a language set in the environment, try and use that. lang = os.getenv("LANGUAGE") if lang: try: path = Resources.getPath(Resources.i18nLocation, lang, "LC_MESSAGES", file + ".qm") except FileNotFoundError: path = None # If looking up the language from the enviroment fails, try and use Qt's system locale instead. if not path: locale = QLocale.system() # First, try and find a directory for any of the provided languages for lang in locale.uiLanguages(): try: path = Resources.getPath(Resources.i18nLocation, lang, "LC_MESSAGES", file + ".qm") language = lang except FileNotFoundError: pass else: break # If that fails, see if we can extract a language "class" from the # preferred language. This will turn "en-GB" into "en" for example. if not path: lang = locale.uiLanguages()[0] lang = lang[0:lang.find("-")] try: path = Resources.getPath(Resources.i18nLocation, lang, "LC_MESSAGES", file + ".qm") language = lang except FileNotFoundError: pass else: path = Resources.getPath(Resources.i18nLocation, language, "LC_MESSAGES", file + ".qm") # If all else fails, fall back to english. if not path: Logger.log("w", "Could not find any translations matching {0} for file {1}, falling back to english".format(language, file)) try: path = Resources.getPath(Resources.i18nLocation, "en", "LC_MESSAGES", file + ".qm") except FileNotFoundError: Logger.log("w", "Could not find English translations for file {0}. Switching to developer english.".format(file)) return translator = QTranslator() if not translator.load(path): Logger.log("e", "Unable to load translations %s", file) return # Store a reference to the translator. # This prevents the translator from being destroyed before Qt has a chance to use it. self._translators[file] = translator # Finally, install the translator so Qt can use it. self.installTranslator(translator)
def run(self): self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Setting up scene...")) controller = self.getController() controller.setActiveView("SolidView") controller.setCameraTool("CameraTool") controller.setSelectionTool("SelectionTool") t = controller.getTool("TranslateTool") if t: t.setEnabledAxis([ToolHandle.XAxis, ToolHandle.YAxis,ToolHandle.ZAxis]) Selection.selectionChanged.connect(self.onSelectionChanged) root = controller.getScene().getRoot() self._platform = Scene_Platform(root) self._volume = BuildVolume.BuildVolume(root) self.getRenderer().setBackgroundColor(QColor(245, 245, 245)) self._physics = PlatformPhysics.PlatformPhysics(controller, self._volume) camera = Camera("3d", root) camera.setPosition(Vector(-80, 250, 700)) camera.setPerspective(True) camera.lookAt(Vector(0, 0, 0)) controller.getScene().setActiveCamera("3d") self.getController().getTool("CameraTool").setOrigin(Vector(0, 100, 0)) self._camera_animation = CameraAnimation.CameraAnimation() self._camera_animation.setCameraTool(self.getController().getTool("CameraTool")) self.showSplashMessage(self._i18n_catalog.i18nc("@info:progress", "Loading interface...")) # Initialise extruder so as to listen to global container stack changes before the first global container stack is set. cura.Settings.ExtruderManager.getInstance() qmlRegisterSingletonType(cura.Settings.MachineManager, "Cura", 1, 0, "MachineManager", cura.Settings.MachineManager.createMachineManager) qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager) self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml")) self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles)) self.initializeEngine() if self._engine.rootObjects: self.closeSplash() for file in self.getCommandLineOption("file", []): self._openFile(file) for file_name in self._open_file_queue: #Open all the files that were queued up while plug-ins were loading. self._openFile(file_name) self._started = True self.exec_()
def _createCustomFdmPrinterExtruderStack(self, machine_id: str, position: int, quality_id: str, material_id: str): stack_id = "custom_extruder_%s" % (position + 1) if self._current_fdm_printer_count > 1: stack_id += " #%s" % self._current_fdm_printer_count definition_id = "custom_extruder_%s" % (position + 1) # create a definition changes container for this stack definition_changes_parser = self._getCustomFdmPrinterDefinitionChanges(stack_id) definition_changes_id = definition_changes_parser["general"]["name"] # create a user settings container user_settings_parser = self._getCustomFdmPrinterUserSettings(stack_id) user_settings_id = user_settings_parser["general"]["name"] parser = configparser.ConfigParser() parser.add_section("general") parser["general"]["version"] = str(2) parser["general"]["name"] = "Extruder %s" % (position + 1) parser["general"]["id"] = stack_id parser.add_section("metadata") parser["metadata"]["type"] = "extruder_train" parser["metadata"]["machine"] = machine_id parser["metadata"]["position"] = str(position) parser.add_section("containers") parser["containers"]["0"] = user_settings_id parser["containers"]["1"] = "empty_quality_changes" parser["containers"]["2"] = quality_id parser["containers"]["3"] = material_id parser["containers"]["4"] = "empty_variant" parser["containers"]["5"] = definition_changes_id parser["containers"]["6"] = definition_id definition_changes_output = io.StringIO() definition_changes_parser.write(definition_changes_output) definition_changes_filename = quote_plus(definition_changes_id) + ".inst.cfg" user_settings_output = io.StringIO() user_settings_parser.write(user_settings_output) user_settings_filename = quote_plus(user_settings_id) + ".inst.cfg" extruder_output = io.StringIO() parser.write(extruder_output) extruder_filename = quote_plus(stack_id) + ".extruder.cfg" extruder_stack_dir = Resources.getPath(CuraApplication.ResourceTypes.ExtruderStack) definition_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.DefinitionChangesContainer) user_settings_dir = Resources.getPath(CuraApplication.ResourceTypes.UserInstanceContainer) with open(os.path.join(definition_changes_dir, definition_changes_filename), "w", encoding = "utf-8") as f: f.write(definition_changes_output.getvalue()) with open(os.path.join(user_settings_dir, user_settings_filename), "w", encoding = "utf-8") as f: f.write(user_settings_output.getvalue()) with open(os.path.join(extruder_stack_dir, extruder_filename), "w", encoding = "utf-8") as f: f.write(extruder_output.getvalue())
def __init__(self, **kwargs): plugin_path = "" if sys.platform == "win32": plugin_path = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "PyQt5", "plugins") Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path)) QCoreApplication.addLibraryPath(plugin_path) elif sys.platform == "darwin": plugin_path = os.path.join(Application.getInstallPrefix(), "Resources", "plugins") if plugin_path: Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path)) QCoreApplication.addLibraryPath(plugin_path) os.environ["QSG_RENDER_LOOP"] = "basic" super().__init__(sys.argv, **kwargs) self._main_qml = "main.qml" self._engine = None self._renderer = None self.setAttribute(Qt.AA_UseDesktopOpenGL) try: self._splash = QSplashScreen(QPixmap(Resources.getPath(Resources.ImagesLocation, self.getApplicationName() + ".png"))) except FileNotFoundError: self._splash = None else: self._splash.show() self.processEvents() signal.signal(signal.SIGINT, signal.SIG_DFL) # This is done here as a lot of plugins require a correct gl context. If you want to change the framework, # these checks need to be done in your <framework>Application.py class __init__(). i18n_catalog = i18nCatalog("uranium") self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading plugins...")) self._loadPlugins() self._plugin_registry.checkRequiredPlugins(self.getRequiredPlugins()) self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading machines...")) self.loadMachines() self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading preferences...")) try: file = Resources.getPath(Resources.PreferencesLocation, self.getApplicationName() + ".cfg") Preferences.getInstance().readFromFile(file) except FileNotFoundError: pass self._translators = {} self.showSplashMessage(i18n_catalog.i18nc("Splash screen message", "Loading translations...")) self.loadQtTranslation("uranium_qt") self.loadQtTranslation(self.getApplicationName() + "_qt")
def render(self, renderer): if not self._material: self._material = renderer.createMaterial( Resources.getPath(Resources.ShadersLocation, "basic.vert"), Resources.getPath(Resources.ShadersLocation, "color.frag"), ) self._material.setUniformValue("u_color", Color(35, 35, 35, 128)) if self.getParent(): renderer.queueNode(self, material=self._material, transparent=True) return True
def __init__(self, width, height): super().__init__("selection", width, height, -999) self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "selection.shader")) self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader")) self._gl = OpenGL.getInstance().getBindingsObject() self._scene = Application.getInstance().getController().getScene() self._renderer = Application.getInstance().getRenderer() self._selection_map = {} self._output = None
def _onActiveMachineChanged(self): if self._settings: self.setMeshData(None) app = Application.getInstance() self._settings = app.getActiveMachine() if self._settings: mesh = self._settings.getPlatformMesh() self.setMeshData(app.getMeshFileHandler().read(Resources.getPath(Resources.MeshesLocation, mesh), app.getStorageDevice("LocalFileStorage"), center = False)) self._texture = self._settings.getPlatformTexture() if self._material and self._texture: self._material.setUniformTexture("u_texture", Resources.getPath(Resources.ImagesLocation, self._texture))
def render(self, renderer): if not self.getMeshData(): return True if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader")) self._grid_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "grid.shader")) renderer.queueNode(self, mode = RenderBatch.RenderMode.Lines) renderer.queueNode(self, mesh = self._grid_mesh, shader = self._grid_shader, backface_cull = True) if self._disallowed_area_mesh: renderer.queueNode(self, mesh = self._disallowed_area_mesh, shader = self._shader, transparent = True, backface_cull = True, sort = -9) return True
def _initialize(self): profile = QOpenGLVersionProfile() profile.setVersion(2, 0) self._gl = QOpenGLContext.currentContext().versionFunctions(profile) self._gl.initializeOpenGLFunctions() self._default_material = self.createMaterial( Resources.getPath(Resources.Shaders, "default.vert"), Resources.getPath(Resources.Shaders, "default.frag") ) self._default_material.setUniformValue("u_ambientColor", Color(0.3, 0.3, 0.3, 1.0)) self._default_material.setUniformValue("u_diffuseColor", Color(0.5, 0.5, 0.5, 1.0)) self._default_material.setUniformValue("u_specularColor", Color(0.7, 0.7, 0.7, 1.0)) self._default_material.setUniformValue("u_shininess", 20.) self._selection_buffer = self.createFrameBuffer(128, 128) self._selection_material = self.createMaterial( Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "color.frag") ) self._handle_material = self.createMaterial( Resources.getPath(Resources.Shaders, "basic.vert"), Resources.getPath(Resources.Shaders, "vertexcolor.frag") ) self._outline_material = self.createMaterial( Resources.getPath(Resources.Shaders, "outline.vert"), Resources.getPath(Resources.Shaders, "outline.frag") ) self._initialized = True
def beginRendering(self): scene = self.getController().getScene() renderer = self.getRenderer() if not self._enabled_material: if Preferences.getInstance().getValue("view/show_overhang"): self._enabled_material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "default.vert"), Resources.getPath(Resources.ShadersLocation, "overhang.frag")) else: self._enabled_material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "default.vert"), Resources.getPath(Resources.ShadersLocation, "default.frag")) self._enabled_material.setUniformValue("u_ambientColor", Color(0.3, 0.3, 0.3, 1.0)) self._enabled_material.setUniformValue("u_diffuseColor", self.EnabledColor) self._enabled_material.setUniformValue("u_specularColor", Color(1.0, 1.0, 1.0, 1.0)) self._enabled_material.setUniformValue("u_overhangColor", Color(1.0, 0.0, 0.0, 1.0)) self._enabled_material.setUniformValue("u_shininess", 50.0) if not self._disabled_material: self._disabled_material = renderer.createMaterial(Resources.getPath(Resources.ShadersLocation, "default.vert"), Resources.getPath(Resources.ShadersLocation, "default.frag")) self._disabled_material.setUniformValue("u_ambientColor", Color(0.3, 0.3, 0.3, 1.0)) self._disabled_material.setUniformValue("u_diffuseColor", self.DisabledColor) self._disabled_material.setUniformValue("u_specularColor", Color(1.0, 1.0, 1.0, 1.0)) self._disabled_material.setUniformValue("u_overhangColor", Color(1.0, 0.0, 0.0, 1.0)) self._disabled_material.setUniformValue("u_shininess", 50.0) if Application.getInstance().getActiveMachine(): machine = Application.getInstance().getActiveMachine() if machine.getSettingValueByKey("support_enable"): angle = machine.getSettingValueByKey("support_angle") if angle != None: self._enabled_material.setUniformValue("u_overhangAngle", math.cos(math.radians(90 - angle))) else: self._enabled_material.setUniformValue("u_overhangAngle", math.cos(math.radians(0))) for node in DepthFirstIterator(scene.getRoot()): if not node.render(renderer): if node.getMeshData() and node.isVisible(): # TODO: Find a better way to handle this #if node.getBoundingBoxMesh(): # renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(),mode = Renderer.RenderLines) if hasattr(node, "_outside_buildarea"): if node._outside_buildarea: renderer.queueNode(node, material = self._disabled_material) else: renderer.queueNode(node, material = self._enabled_material) else: renderer.queueNode(node, material = self._enabled_material) if node.callDecoration("isGroup"): renderer.queueNode(scene.getRoot(), mesh = node.getBoundingBoxMesh(),mode = Renderer.RenderLines)
def render(self, renderer): if not self._material: self._material = renderer.createMaterial( Resources.getPath(Resources.Shaders, "default.vert"), Resources.getPath(Resources.Shaders, "platform.frag") ) self._material.setUniformValue("u_ambientColor", [0.3, 0.3, 0.3, 1.0]) self._material.setUniformValue("u_diffuseColor", [1.0, 1.0, 1.0, 1.0]) self._material.setUniformValue("u_opacity", 0.5) if self._texture: self._material.setUniformTexture("u_texture", Resources.getPath(Resources.Images, self._texture)) if self.getMeshData(): renderer.queueNode(self, material = self._material, transparent = True) return True
def createMaterial(self): self._material = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader")) self._material.setUniformValue("u_ambientColor", Color(0.3, 0.3, 0.3, 1.0)) self._material.setUniformValue("u_diffuseColor", self._color) self._material.setUniformValue("u_specularColor", Color(1.0, 1.0, 1.0, 1.0)) self._material.setUniformValue("u_shininess", 50.0)
def _createExtruderQualityChangesForSingleExtrusionMachine(self, filename, global_quality_changes): suffix = "_" + quote_plus(global_quality_changes["general"]["name"].lower()) machine_name = os.path.os.path.basename(filename).replace(".inst.cfg", "").replace(suffix, "") # Why is this here?! # When we load a .curaprofile file the deserialize will trigger a version upgrade, creating a dangling file. # This file can be recognized by it's lack of a machine name in the target filename. # So when we detect that situation here, we don't create the file and return. if machine_name == "": return new_filename = machine_name + "_" + "fdmextruder" + suffix extruder_quality_changes_parser = configparser.ConfigParser(interpolation = None) extruder_quality_changes_parser.add_section("general") extruder_quality_changes_parser["general"]["version"] = str(2) extruder_quality_changes_parser["general"]["name"] = global_quality_changes["general"]["name"] extruder_quality_changes_parser["general"]["definition"] = global_quality_changes["general"]["definition"] extruder_quality_changes_parser.add_section("metadata") extruder_quality_changes_parser["metadata"]["quality_type"] = global_quality_changes["metadata"]["quality_type"] extruder_quality_changes_parser["metadata"]["type"] = global_quality_changes["metadata"]["type"] extruder_quality_changes_parser["metadata"]["setting_version"] = str(4) extruder_quality_changes_parser["metadata"]["extruder"] = "fdmextruder" extruder_quality_changes_output = io.StringIO() extruder_quality_changes_parser.write(extruder_quality_changes_output) extruder_quality_changes_filename = quote_plus(new_filename) + ".inst.cfg" quality_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.QualityInstanceContainer) with open(os.path.join(quality_changes_dir, extruder_quality_changes_filename), "w") as f: f.write(extruder_quality_changes_output.getvalue())
def _getSingleExtrusionMachineQualityChanges(self, quality_changes_container): quality_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.QualityInstanceContainer) quality_changes_containers = [] for item in os.listdir(quality_changes_dir): file_path = os.path.join(quality_changes_dir, item) if not os.path.isfile(file_path): continue parser = configparser.ConfigParser(interpolation = None) try: parser.read([file_path]) except: # skip, it is not a valid stack file continue if not parser.has_option("metadata", "type"): continue if "quality_changes" != parser["metadata"]["type"]: continue if not parser.has_option("general", "name"): continue if quality_changes_container["general"]["name"] != parser["general"]["name"]: continue quality_changes_containers.append(parser) return quality_changes_containers
def updateAllFirmware(self): self.spawnFirmwareInterface("") for printer_connection in self._printer_connections: try: self._printer_connections[printer_connection].updateFirmware(Resources.getPath(CuraApplication.ResourceTypes.Firmware, self._getDefaultFirmwareName())) except FileNotFoundError: continue
def restore(self) -> bool: if not self.zip_file or not self.meta_data or not self.meta_data.get("cura_release", None): # We can restore without the minimum required information. Logger.log("w", "Tried to restore a Cura backup without having proper data or meta data.") self._showMessage( self.catalog.i18nc("@info:backup_failed", "Tried to restore a Cura backup without having proper data or meta data.")) return False current_version = self._application.getVersion() version_to_restore = self.meta_data.get("cura_release", "master") if current_version < version_to_restore: # Cannot restore version newer than current because settings might have changed. Logger.log("d", "Tried to restore a Cura backup of version {version_to_restore} with cura version {current_version}".format(version_to_restore = version_to_restore, current_version = current_version)) self._showMessage( self.catalog.i18nc("@info:backup_failed", "Tried to restore a Cura backup that is higher than the current version.")) return False version_data_dir = Resources.getDataStoragePath() archive = ZipFile(io.BytesIO(self.zip_file), "r") extracted = self._extractArchive(archive, version_data_dir) # Under Linux, preferences are stored elsewhere, so we copy the file to there. if Platform.isLinux(): preferences_file_name = self._application.getApplicationName() preferences_file = Resources.getPath(Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join(version_data_dir, "{}.cfg".format(preferences_file_name)) Logger.log("d", "Moving preferences file from %s to %s", backup_preferences_file, preferences_file) shutil.move(backup_preferences_file, preferences_file) return extracted
def __init__(self, **kwargs): plugin_path = "" if sys.platform == "win32": if hasattr(sys, "frozen"): plugin_path = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), "PyQt5", "plugins") Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path)) QCoreApplication.addLibraryPath(plugin_path) else: import site for dir in site.getsitepackages(): QCoreApplication.addLibraryPath(os.path.join(dir, "PyQt5", "plugins")) elif sys.platform == "darwin": plugin_path = os.path.join(Application.getInstallPrefix(), "Resources", "plugins") if plugin_path: Logger.log("i", "Adding QT5 plugin path: %s" % (plugin_path)) QCoreApplication.addLibraryPath(plugin_path) os.environ["QSG_RENDER_LOOP"] = "basic" super().__init__(sys.argv, **kwargs) self._plugins_loaded = False #Used to determine when it's safe to use the plug-ins. self._main_qml = "main.qml" self._engine = None self._renderer = None self._main_window = None self._shutting_down = False self._qml_import_paths = [] self._qml_import_paths.append(os.path.join(os.path.dirname(sys.executable), "qml")) self._qml_import_paths.append(os.path.join(Application.getInstallPrefix(), "Resources", "qml")) self.setAttribute(Qt.AA_UseDesktopOpenGL) try: self._splash = self._createSplashScreen() except FileNotFoundError: self._splash = None else: self._splash.show() self.processEvents() signal.signal(signal.SIGINT, signal.SIG_DFL) # This is done here as a lot of plugins require a correct gl context. If you want to change the framework, # these checks need to be done in your <framework>Application.py class __init__(). i18n_catalog = i18nCatalog("uranium") self.showSplashMessage(i18n_catalog.i18nc("@info:progress", "Loading plugins...")) self._loadPlugins() self.parseCommandLine() Logger.log("i", "Command line arguments: %s", self._parsed_command_line) self._plugin_registry.checkRequiredPlugins(self.getRequiredPlugins()) self.showSplashMessage(i18n_catalog.i18nc("@info:progress", "Loading preferences...")) try: file = Resources.getPath(Resources.Preferences, self.getApplicationName() + ".cfg") Preferences.getInstance().readFromFile(file) except FileNotFoundError: pass
def _onActiveMachineChanged(self): if self._settings: self.setMeshData(None) app = Application.getInstance() self._settings = app.getActiveMachine() if self._settings: mesh = self._settings.getPlatformMesh() if not mesh: mesh = "" # Dirty hack to ensure that if no mesh is set it doesn't crash. self.setMeshData(app.getMeshFileHandler().read(Resources.getPath(Resources.MeshesLocation, mesh), center = False).getMeshData()) self._texture = self._settings.getPlatformTexture() if self._material and self._texture: self._material.setUniformTexture("u_texture", Resources.getPath(Resources.ImagesLocation, self._texture))
def registerObjects(self, engine): engine.rootContext().setContextProperty("Printer", self) engine.rootContext().setContextProperty("CuraApplication", self) self._print_information = PrintInformation.PrintInformation() engine.rootContext().setContextProperty("PrintInformation", self._print_information) self._cura_actions = CuraActions.CuraActions(self) engine.rootContext().setContextProperty("CuraActions", self._cura_actions) qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type") qmlRegisterType(cura.Settings.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") qmlRegisterType(cura.Settings.ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") qmlRegisterType(cura.Settings.MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") qmlRegisterSingletonType(cura.Settings.ContainerManager, "Cura", 1, 0, "ContainerManager", cura.Settings.ContainerManager.createContainerManager) qmlRegisterSingletonType(QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")), "Cura", 1, 0, "Actions") engine.rootContext().setContextProperty("ExtruderManager", cura.Settings.ExtruderManager.getInstance()) for path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.QmlFiles): type_name = os.path.splitext(os.path.basename(path))[0] if type_name in ("Cura", "Actions"): continue qmlRegisterType(QUrl.fromLocalFile(path), "Cura", 1, 0, type_name)
def _initialize(self): OpenGL.setInstance(QtOpenGL()) self._gl = OpenGL.getInstance().getBindingsObject() self._default_material = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader")) self._render_passes.add(DefaultPass(self._viewport_width, self._viewport_height)) self._render_passes.add(SelectionPass(self._viewport_width, self._viewport_height)) self._render_passes.add(CompositePass(self._viewport_width, self._viewport_height)) buffer = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer) buffer.create() buffer.bind() buffer.allocate(120) data = numpy.array([ -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 ], dtype = numpy.float32).tostring() buffer.write(0, data, len(data)) buffer.release() self._quad_buffer = buffer self._initialized = True
def registerObjects(self, engine): engine.rootContext().setContextProperty("Printer", self) engine.rootContext().setContextProperty("CuraApplication", self) self._print_information = PrintInformation.PrintInformation() engine.rootContext().setContextProperty("PrintInformation", self._print_information) self._cura_actions = CuraActions.CuraActions(self) engine.rootContext().setContextProperty("CuraActions", self._cura_actions) qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type") qmlRegisterType(cura.Settings.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") qmlRegisterType(cura.Settings.ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") qmlRegisterSingletonType(cura.Settings.ProfilesModel, "Cura", 1, 0, "ProfilesModel", cura.Settings.ProfilesModel.createProfilesModel) qmlRegisterType(cura.Settings.QualityAndUserProfilesModel, "Cura", 1, 0, "QualityAndUserProfilesModel") qmlRegisterType(cura.Settings.UserProfilesModel, "Cura", 1, 0, "UserProfilesModel") qmlRegisterType(cura.Settings.MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") qmlRegisterType(cura.Settings.QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel") qmlRegisterType(cura.Settings.MachineNameValidator, "Cura", 1, 0, "MachineNameValidator") qmlRegisterSingletonType(cura.Settings.ContainerManager, "Cura", 1, 0, "ContainerManager", cura.Settings.ContainerManager.createContainerManager) # As of Qt5.7, it is necessary to get rid of any ".." in the path for the singleton to work. actions_url = QUrl.fromLocalFile(os.path.abspath(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml"))) qmlRegisterSingletonType(actions_url, "Cura", 1, 0, "Actions") engine.rootContext().setContextProperty("ExtruderManager", cura.Settings.ExtruderManager.getInstance()) for path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.QmlFiles): type_name = os.path.splitext(os.path.basename(path))[0] if type_name in ("Cura", "Actions"): continue qmlRegisterType(QUrl.fromLocalFile(path), "Cura", 1, 0, type_name)
def _onGlobalContainerStackChanged(self): if self._global_container_stack: self.setMeshData(None) self._global_container_stack = Application.getInstance().getGlobalContainerStack() if self._global_container_stack: container = self._global_container_stack.findContainer({ "platform": "*" }) if container: mesh_file = container.getMetaDataEntry("platform") path = Resources.getPath(Resources.Meshes, mesh_file) if self._load_platform_job: # This prevents a previous load job from triggering texture loads. self._load_platform_job.finished.disconnect(self._onPlatformLoaded) # Perform platform mesh loading in the background self._load_platform_job = _LoadPlatformJob(path) self._load_platform_job.finished.connect(self._onPlatformLoaded) self._load_platform_job.start() offset = container.getMetaDataEntry("platform_offset") if offset: if len(offset) == 3: self.setPosition(Vector(offset[0], offset[1], offset[2])) else: Logger.log("w", "Platform offset is invalid: %s", str(offset)) self.setPosition(Vector(0.0, 0.0, 0.0)) else: self.setPosition(Vector(0.0, 0.0, 0.0))
def _loadCachedDefinition(self, definition_id: str, path: str) -> None: try: cache_path = Resources.getPath(Resources.Cache, "definitions", self._application.getVersion(), definition_id) cache_mtime = os.path.getmtime(cache_path) definition_mtime = os.path.getmtime(path) if definition_mtime > cache_mtime: # The definition is newer than the cached version, so ignore the cached version. Logger.log("d", "Definition file %s is newer than cache, ignoring cached version", path) return None definition = None with open(cache_path, "rb") as f: definition = pickle.load(f) for file_path in definition.getInheritedFiles(): if os.path.getmtime(file_path) > cache_mtime: return None return definition except FileNotFoundError: return None except Exception as e: # We could not load a cached version for some reason. Ignore it. Logger.logException("d", "Could not load cached definition for %s", path) return None
def _findQualityChangesContainerInCuraFolder(self, name): quality_changes_dir = Resources.getPath(CuraApplication.ResourceTypes.QualityInstanceContainer) instance_container = None for item in os.listdir(quality_changes_dir): file_path = os.path.join(quality_changes_dir, item) if not os.path.isfile(file_path): continue parser = configparser.ConfigParser() try: parser.read([file_path]) except: # skip, it is not a valid stack file continue if not parser.has_option("general", "name"): continue if parser["general"]["name"] == name: # load the container container_id = os.path.basename(file_path).replace(".inst.cfg", "") instance_container = InstanceContainer(container_id) with open(file_path, "r") as f: serialized = f.read() instance_container.deserialize(serialized, file_path) self.addContainer(instance_container) break return instance_container
def loadValuesFromFile(self, file_name): config = configparser.ConfigParser() config.read(file_name) if not self._categories: try: self.loadSettingsFromFile(Resources.getPath(Resources.SettingsLocation, config["General"]["settings_json_file"])) except KeyError: Logger.log('e' , "Linked json file from preferences not found") self._name = config.get("General", "name", fallback = "Unknown Machine") visibility = config.get("General", "visibility", fallback = None) if visibility: values = visibility.split(",") for setting in self.getAllSettings(): if setting.getKey() in values: setting.setVisible(True) else: setting.setVisible(False) for name, section in config.items(): for key in section: setting = self.getSettingByKey(key) if setting is not None: setting.setValue(section[key])
def restore(self) -> bool: if not self.zip_file or not self.meta_data or not self.meta_data.get( "cura_release", None): # We can restore without the minimum required information. Logger.log( "w", "Tried to restore a Cura backup without having proper data or meta data." ) self._showMessage( self.catalog.i18nc( "@info:backup_failed", "Tried to restore a Cura backup without having proper data or meta data." )) return False current_version = CuraApplication.getInstance().getVersion() version_to_restore = self.meta_data.get("cura_release", "master") if current_version != version_to_restore: # Cannot restore version older or newer than current because settings might have changed. # Restoring this will cause a lot of issues so we don't allow this for now. self._showMessage( self.catalog.i18nc( "@info:backup_failed", "Tried to restore a Cura backup that does not match your current version." )) return False version_data_dir = Resources.getDataStoragePath() archive = ZipFile(io.BytesIO(self.zip_file), "r") extracted = self._extractArchive(archive, version_data_dir) # Under Linux, preferences are stored elsewhere, so we copy the file to there. if Platform.isLinux(): preferences_file_name = CuraApplication.getInstance( ).getApplicationName() preferences_file = Resources.getPath( Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join( version_data_dir, "{}.cfg".format(preferences_file_name)) Logger.log("d", "Moving preferences file from %s to %s", backup_preferences_file, preferences_file) shutil.move(backup_preferences_file, preferences_file) return extracted
def _findQualityChangesContainerInCuraFolder(self, name): quality_changes_dir = Resources.getPath( cura.CuraApplication.CuraApplication.ResourceTypes. QualityChangesInstanceContainer) instance_container = None for item in os.listdir(quality_changes_dir): file_path = os.path.join(quality_changes_dir, item) if not os.path.isfile(file_path): continue parser = configparser.ConfigParser(interpolation=None) try: parser.read([file_path]) except: # skip, it is not a valid stack file continue if not parser.has_option("general", "name"): continue if parser["general"]["name"] == name: # load the container container_id = os.path.basename(file_path).replace( ".inst.cfg", "") if self.findInstanceContainers(id=container_id): # this container is already in the registry, skip it continue instance_container = InstanceContainer(container_id) with open(file_path, "r", encoding="utf-8") as f: serialized = f.read() try: instance_container.deserialize(serialized, file_path) except ContainerFormatError: Logger.logException( "e", "Unable to deserialize InstanceContainer %s", file_path) continue self.addContainer(instance_container) break return instance_container
def test_serialize(container_data, equals_file, loaded_container_registry): instance_container = UM.Settings.InstanceContainer("test") definition = loaded_container_registry.findDefinitionContainers(id = container_data["definition"])[0] instance_container.setDefinition(definition) instance_container.setName(container_data["name"]) if "metadata" in container_data: instance_container.setMetaData(container_data["metadata"]) if "values" in container_data: for key, value in container_data["values"].items(): instance_container.setProperty(key, "value", value) result = instance_container.serialize() path = Resources.getPath(Resources.InstanceContainers, equals_file) with open(path) as data: assert data.readline() in result
def _updateTexture(self): if not self._global_container_stack or not OpenGL.getInstance(): return container = self._global_container_stack.findContainer( {"platform_texture": "*"}) if container: texture_file = container.getMetaDataEntry("platform_texture") if texture_file: self._texture = OpenGL.getInstance().createTexture() self._texture.load( Resources.getPath(Resources.Images, texture_file)) if self._shader: self._shader.setTexture(0, self._texture) else: self._texture = None if self._shader: self._shader.setTexture(0, None)
def getEngineCommand(self) -> List[str]: json_path = Resources.getPath(Resources.DefinitionContainers, "fdmprinter.def.json") command = [ self._application.getPreferences().getValue("backend/location"), "connect", "127.0.0.1:{0}".format(self._port), "-j", json_path, "" ] parser = argparse.ArgumentParser(prog="cura", add_help=False) parser.add_argument( "--debug", action="store_true", default=False, help="Turn on the debug mode by setting this option.") known_args = vars(parser.parse_known_args()[0]) if known_args["debug"]: command.append("-vvv") return command
def __init__(self): Resources.addResourcePath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura")) if not hasattr(sys, "frozen"): Resources.addResourcePath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..")) super().__init__(name = "cura", version = "master") self.setWindowIcon(QIcon(Resources.getPath(Resources.ImagesLocation, "cura-icon.png"))) self.setRequiredPlugins([ "CuraEngineBackend", "MeshView", "LayerView", "STLReader", "SelectionTool", "CameraTool", "GCodeWriter", "LocalFileStorage" ]) self._physics = None self._volume = None self._platform = None self._output_devices = {} self._print_information = None self._i18n_catalog = None self._previous_active_tool = None self.activeMachineChanged.connect(self._onActiveMachineChanged) Preferences.getInstance().addPreference("cura/active_machine", "") Preferences.getInstance().addPreference("cura/active_mode", "simple") Preferences.getInstance().addPreference("cura/recent_files", "") Preferences.getInstance().addPreference("cura/categories_expanded", "") JobQueue.getInstance().jobFinished.connect(self._onJobFinished) self._recent_files = [] files = Preferences.getInstance().getValue("cura/recent_files").split(";") for f in files: if not os.path.isfile(f): continue self._recent_files.append(QUrl.fromLocalFile(f))
def beginRendering(self) -> None: scene = self.getController().getScene() renderer = self.getRenderer() if not self._ghost_shader: self._ghost_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader")) theme = CuraApplication.getInstance().getTheme() if theme is not None: self._ghost_shader.setUniformValue("u_color", Color(*theme.getColor("layerview_ghost").getRgb())) for node in DepthFirstIterator(scene.getRoot()): # We do not want to render ConvexHullNode as it conflicts with the bottom layers. # However, it is somewhat relevant when the node is selected, so do render it then. if type(node) is ConvexHullNode and not Selection.isSelected(cast(ConvexHullNode, node).getWatchedNode()): continue if not node.render(renderer): if (node.getMeshData()) and node.isVisible(): renderer.queueNode(node, transparent = True, shader = self._ghost_shader)
def _acquireNextUniqueCustomFdmPrinterExtruderStackIdIndex(self): extruder_stack_dir = Resources.getPath(CuraApplication.ResourceTypes.ExtruderStack) file_name_list = os.listdir(extruder_stack_dir) file_name_list = [os.path.basename(file_name) for file_name in file_name_list] while True: self._current_fdm_printer_count += 1 stack_id_exists = False for position in range(8): stack_id = "custom_extruder_%s" % (position + 1) if self._current_fdm_printer_count > 1: stack_id += " #%s" % self._current_fdm_printer_count if stack_id in file_name_list: stack_id_exists = True break if not stack_id_exists: break return self._current_fdm_printer_count
def test_readWrite(): preferences = Preferences() path = Resources.getPath(Resources.Preferences, "preferences_test.cfg") preferences.readFromFile(path) # Check if it has been loaded correctly assert preferences.getValue("general/foo") == "omgzomg" assert preferences.getValue("general/derp") == True # Write contents of the preference to a buffer in_memory_storage = StringIO() preferences.writeToFile(in_memory_storage) # type: ignore new_preferences = Preferences() # For some reason, if write was used, the read doesn't work. If we do it like this, it does work. new_preferences.readFromFile(StringIO(in_memory_storage.getvalue())) assert preferences.getValue("general/foo") == new_preferences.getValue("general/foo") assert preferences.getValue("test/more_test") == new_preferences.getValue("test/more_test")
def openSyncAllWindow(self): self.reset() if self.sync_all_dialog is None: qml_path = Resources.getPath( cura.CuraApplication.CuraApplication.ResourceTypes.QmlFiles, "Preferences", "Materials", "MaterialsSyncDialog.qml") self.sync_all_dialog = cura.CuraApplication.CuraApplication.getInstance( ).createQmlComponent(qml_path, {}) if self.sync_all_dialog is None: # Failed to load QML file. return self.sync_all_dialog.setProperty("syncModel", self) self.sync_all_dialog.setProperty("pageIndex", 0) # Return to first page. self.sync_all_dialog.setProperty( "hasExportedUsb", False) # If the user exported USB before, reset that page. self.sync_all_dialog.show()
def registerObjects(self, engine): engine.rootContext().setContextProperty("Printer", self) engine.rootContext().setContextProperty("CuraApplication", self) self._print_information = PrintInformation.PrintInformation() engine.rootContext().setContextProperty("PrintInformation", self._print_information) self._cura_actions = CuraActions.CuraActions(self) engine.rootContext().setContextProperty("CuraActions", self._cura_actions) qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type") qmlRegisterType(cura.Settings.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") qmlRegisterType(cura.Settings.ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") qmlRegisterType(cura.Settings.MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") qmlRegisterType(cura.Settings.QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel") qmlRegisterSingletonType( cura.Settings.ContainerManager, "Cura", 1, 0, "ContainerManager", cura.Settings.ContainerManager.createContainerManager) qmlRegisterSingletonType( QUrl.fromLocalFile( Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")), "Cura", 1, 0, "Actions") engine.rootContext().setContextProperty( "ExtruderManager", cura.Settings.ExtruderManager.getInstance()) for path in Resources.getAllResourcesOfType( CuraApplication.ResourceTypes.QmlFiles): type_name = os.path.splitext(os.path.basename(path))[0] if type_name in ("Cura", "Actions"): continue qmlRegisterType(QUrl.fromLocalFile(path), "Cura", 1, 0, type_name)
def render(self, renderer): if not self.isVisible(): return True if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "platform.shader")) if not self._shader: # Failed to compile (it already adds a log entry about this then). return True # It'll try to compile every frame, which is bad for performance but it won't crash at least. if self._texture: self._shader.setTexture(0, self._texture) else: self._updateTexture() if self.getMeshData(): renderer.queueNode(self, shader=self._shader, transparent=True, backface_cull=True, sort=-10) return True
def _collectOrdinalFiles(resource_type: int, include: List[str]) -> Tuple[Dict[int, str], int]: result = {} # type: Dict[int, str] highest = -1 try: folder_path = Resources.getPath(resource_type, "whats_new") for _, _, files in os.walk(folder_path): for filename in files: basename = os.path.basename(filename) base, ext = os.path.splitext(basename) if ext.lower() not in include or not base.isdigit(): continue page_no = int(base) highest = max(highest, page_no) result[page_no] = os.path.join(folder_path, filename) except FileNotFoundError: Logger.logException( "w", "Could not find 'whats_new' folder for resource-type {0}". format(resource_type)) return result, highest
def _loadChangeLogText(self) -> str: # Load change log texts and organize them with a dict file_path = Resources.getPath(Resources.Texts, "change_log.txt") change_logs_dict = {} # type: Dict[Version, Dict[str, List[str]]] with open(file_path, "r", encoding = "utf-8") as f: open_version = None # type: Optional[Version] 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) if open_version > Version([14, 99, 99]): # Bit of a hack: We released the 15.x.x versions before 2.x open_version = Version([0, open_version.getMinor(), open_version.getRevision(), open_version.getPostfixVersion()]) open_header = "" change_logs_dict[open_version] = collections.OrderedDict() elif line.startswith("*"): open_header = line.replace("*", "") change_logs_dict[cast(Version, open_version)][open_header] = [] elif line != "": if open_header not in change_logs_dict[cast(Version, open_version)]: change_logs_dict[cast(Version, open_version)][open_header] = [] change_logs_dict[cast(Version, open_version)][open_header].append(line) # Format changelog text content = "" for version in sorted(change_logs_dict.keys(), reverse = True): text_version = version if version < Version([1, 0, 0]): # Bit of a hack: We released the 15.x.x versions before 2.x text_version = Version([15, version.getMinor(), version.getRevision(), version.getPostfixVersion()]) content += "<h1>" + str(text_version) + "</h1><br>" content += "" for change in change_logs_dict[version]: if str(change) != "": content += "<b>" + str(change) + "</b><br>" for line in change_logs_dict[version][change]: content += str(line) + "<br>" content += "<br>" return content
def adjust_theme(self): """ Makes the tooltips wider, if displaying articles in the tooltips. """ application = CuraApplication.getInstance() preferences = application.getPreferences() if preferences.getValue( "settings_guide/show+articles+in+setting+tooltips+%28requires+restart%29" ): preferences.addPreference("general/theme", application.default_theme) theme_name = preferences.getValue("general/theme") if theme_name.endswith("_settingsguideadjust"): return # Already adjusted. theme_path = Resources.getPath(Resources.Themes, theme_name) # Create a new theme where we can adjust the tooltip. new_theme_name = theme_name + "_settingsguideadjust" new_theme_path = Resources.getStoragePath(Resources.Themes, new_theme_name) try: shutil.copytree(theme_path, new_theme_path) except OSError: # Already exists. Happens when the user manually adjusted the theme back in the preferences screen. try: os.removedirs(new_theme_path) shutil.copytree(theme_path, new_theme_path) except OSError: pass # Perhaps no rights? # Adjust the tooltip width. with open(os.path.join(theme_path, "theme.json")) as f: adjusted_theme = json.load(f) if "sizes" not in adjusted_theme: adjusted_theme["sizes"] = {} adjusted_theme["sizes"]["tooltip"] = [50.0, 10.0] with open(os.path.join(new_theme_path, "theme.json"), "w") as f: json.dump(adjusted_theme, f) # Enable the new theme. preferences.setValue("general/theme", new_theme_name) application.default_theme = new_theme_name
def _loadCachedDefinition(self, definition_id) -> Optional[DefinitionContainer]: """Load a pre-parsed definition container. Definition containers can be quite expensive to load, so this loads a pickled version of the definition if one is available. :param definition_id: The ID of the definition to load from the cache. :return: If a cached version was available, return it. If not, return ``None``. """ definition_path = self._id_to_path[definition_id] try: cache_path = Resources.getPath(Resources.Cache, "definitions", Application.getInstance().getVersion(), definition_id) cache_mtime = os.path.getmtime(cache_path) definition_mtime = os.path.getmtime(definition_path) except FileNotFoundError: # Cache doesn't exist yet. return None except PermissionError: # No read permission. return None if definition_mtime > cache_mtime: # The definition is newer than the cached version, so ignore the cached version. Logger.log("d", "Definition file {path} is newer than cache. Ignoring cached version.".format(path = definition_path)) return None try: with open(cache_path, "rb") as f: definition = pickle.load(f) except Exception as e: #TODO: Switch to multi-catch once we've upgraded to Python 3.6. Catch: OSError, PermissionError, IOError, AttributeError, EOFError, ImportError, IndexError and UnpicklingError. Logger.log("w", "Failed to load definition {definition_id} from cached file: {error_msg}".format(definition_id = definition_id, error_msg = str(e))) return None try: for file_path in definition.getInheritedFiles(): if os.path.getmtime(file_path) > cache_mtime: return None except FileNotFoundError: return None # Cache for parent doesn't exist yet. return definition
def makeFromCurrent(self) -> None: cura_release = self._application.getVersion() version_data_dir = Resources.getDataStoragePath() Logger.log("d", "Creating backup for Cura %s, using folder %s", cura_release, version_data_dir) # Ensure all current settings are saved. self._application.saveSettings() # We copy the preferences file to the user data directory in Linux as it's in a different location there. # When restoring a backup on Linux, we move it back. if Platform.isLinux(): #TODO: This should check for the config directory not being the same as the data directory, rather than hard-coding that to Linux systems. preferences_file_name = self._application.getApplicationName() preferences_file = Resources.getPath(Resources.Preferences, "{}.cfg".format(preferences_file_name)) backup_preferences_file = os.path.join(version_data_dir, "{}.cfg".format(preferences_file_name)) if os.path.exists(preferences_file) and (not os.path.exists(backup_preferences_file) or not os.path.samefile(preferences_file, backup_preferences_file)): Logger.log("d", "Copying preferences file from %s to %s", preferences_file, backup_preferences_file) shutil.copyfile(preferences_file, backup_preferences_file) # Create an empty buffer and write the archive to it. buffer = io.BytesIO() archive = self._makeArchive(buffer, version_data_dir) if archive is None: return files = archive.namelist() # Count the metadata items. We do this in a rather naive way at the moment. machine_count = len([s for s in files if "machine_instances/" in s]) - 1 material_count = len([s for s in files if "materials/" in s]) - 1 profile_count = len([s for s in files if "quality_changes/" in s]) - 1 plugin_count = len([s for s in files if "plugin.json" in s]) # Store the archive and metadata so the BackupManager can fetch them when needed. self.zip_file = buffer.getvalue() self.meta_data = { "cura_release": cura_release, "machine_count": str(machine_count), "material_count": str(material_count), "profile_count": str(profile_count), "plugin_count": str(plugin_count) }
def _keyIsValid(self) -> bool: try: path = os.path.join( Resources.getPath( self._application.ResourceTypes.Certificates), "license_cert.pem") with open(path, 'rb') as f: certificate = f.read() key = BytesIO(bytes.fromhex(self.licenseKey)) lic = License.load(key, b'StereotechSTESlicerProFeatures') lic.verify(certificate) return True except License.InvalidSignatureException: Logger.log("w", "License key is wrong!") return False except FileNotFoundError: Logger.log("w", "Certificate not found!") return False except Exception as e: Logger.log("w", "License error: %s", str(e)) return False
def render(self, renderer): if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "default.shader")) self._shader.setUniformValue("u_color", self._color) if self.getParent(): renderer.queueNode(self, transparent=True, shader=self._shader, backface_cull=True, sort=-8) if self._convex_hull_head_mesh: renderer.queueNode(self, shader=self._shader, transparent=True, mesh=self._convex_hull_head_mesh, backface_cull=True, sort=-8) return True
def render(self, renderer): if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "platform.shader")) #self._shader.setUniformValue("u_plateColor", Color(*theme.getColor("buildplate").getRgb())) self._shader.setUniformValue("u_opacity", 1.0) self._color = Color(0, 0, 0) self._shader.setUniformValue("u_diffuseColor", self._color) if self._texture: self._shader.setTexture(0, self._texture) else: self._updateTexture() if self.getMeshData(): renderer.queueNode(self, shader=self._shader, transparent=False, backface_cull=True, sort=-10) return True
def test_serialize(container_data, equals_file, loaded_container_registry): instance_container = UM.Settings.InstanceContainer.InstanceContainer( "test") if "metadata" in container_data: instance_container.setMetaData(container_data["metadata"]) instance_container.setDefinition(container_data["definition"]) instance_container.setName(container_data["name"]) if "values" in container_data: for key, value in container_data["values"].items(): instance_container.setProperty(key, "value", value) with unittest.mock.patch( "UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", unittest.mock.MagicMock(return_value=loaded_container_registry)): result = instance_container.serialize() path = Resources.getPath(Resources.InstanceContainers, equals_file) with open(path, encoding="utf-8") as data: assert data.readline() in result
def updateAllFirmware(self): if not self._printer_connections: Message( i18n_catalog.i18nc( "@info", "Cannot update firmware, there were no connected printers found." )).show() return self.spawnFirmwareInterface("") for printer_connection in self._printer_connections: try: self._printer_connections[printer_connection].updateFirmware( Resources.getPath(CuraApplication.ResourceTypes.Firmware, self._getDefaultFirmwareName())) except FileNotFoundError: self._printer_connections[printer_connection].setProgress( 100, 100) Logger.log("w", "No firmware found for printer %s", printer_connection) continue
def _initialize(self) -> None: supports_vao = OpenGLContext.supportsVertexArrayObjects() # fill the OpenGLContext.properties Logger.log("d", "Support for Vertex Array Objects: %s", supports_vao) OpenGL() self._gl = OpenGL.getInstance().getBindingsObject() default_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "default.shader")) # type: Optional[ShaderProgram] if default_shader is None: return self._default_material = default_shader self.addRenderPass(DefaultPass(self._viewport_width, self._viewport_height)) self.addRenderPass(SelectionPass(self._viewport_width, self._viewport_height)) self.addRenderPass(CompositePass(self._viewport_width, self._viewport_height)) buffer = QOpenGLBuffer(QOpenGLBuffer.VertexBuffer) buffer.create() buffer.bind() buffer.allocate(120) data = numpy.array([ -1.0, -1.0, 0.0, 1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0 ], dtype = numpy.float32).tobytes() buffer.write(0, data, len(data)) buffer.release() self._quad_buffer = buffer self._initialized = True self.initialized.emit()
def _onGlobalContainerStackChanged(self): if self._global_container_stack: self.setMeshData(None) self._global_container_stack = Application.getInstance( ).getGlobalContainerStack() if self._global_container_stack: container = self._global_container_stack.findContainer( {"platform": "*"}) if container: mesh_file = container.getMetaDataEntry("platform") try: path = Resources.getPath(Resources.Meshes, mesh_file) except FileNotFoundError: Logger.log("w", "Unable to find the platform mesh %s", mesh_file) path = "" if self._load_platform_job: # This prevents a previous load job from triggering texture loads. self._load_platform_job.finished.disconnect( self._onPlatformLoaded) # Perform platform mesh loading in the background self._load_platform_job = _LoadPlatformJob(path) self._load_platform_job.finished.connect( self._onPlatformLoaded) self._load_platform_job.start() offset = container.getMetaDataEntry("platform_offset") if offset: if len(offset) == 3: self.setPosition( Vector(offset[0], offset[1], offset[2])) else: Logger.log("w", "Platform offset is invalid: %s", str(offset)) self.setPosition(Vector(0.0, 0.0, 0.0)) else: self.setPosition(Vector(0.0, 0.0, 0.0))
def beginRendering(self): scene = self.getController().getScene() renderer = self.getRenderer() if not self._selection_shader: self._selection_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader")) self._selection_shader.setUniformValue("u_color", Color(32, 32, 32, 128)) for node in DepthFirstIterator(scene.getRoot()): # We do not want to render ConvexHullNode as it conflicts with the bottom layers. # However, it is somewhat relevant when the node is selected, so do render it then. if type(node) is ConvexHullNode and not Selection.isSelected(node.getWatchedNode()): continue if not node.render(renderer): if node.getMeshData() and node.isVisible(): if Selection.isSelected(node): renderer.queueNode(node, transparent = True, shader = self._selection_shader) 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._current_layer_num - self._solid_layers > -1: start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer, counts in element_counts.items(): if layer + self._solid_layers > self._current_layer_num: break end += counts # This uses glDrawRangeElements internally to only draw a certain range of lines. renderer.queueNode(node, mesh = layer_data, mode = RenderBatch.RenderMode.Lines, range = (start, end)) if self._current_layer_mesh: renderer.queueNode(node, mesh = self._current_layer_mesh) if self._current_layer_jumps: renderer.queueNode(node, mesh = self._current_layer_jumps)
def getProperty(self, key, property_name, context = None): definition = self._getDefinition(key) if not definition: return None try: value = getattr(definition, property_name) if value is None and property_name == "value": value = getattr(definition, "default_value") if key in ["machine_start_gcode", "machine_end_gcode", "machine_wipe_gcode","machine_abort_gcode", "machine_level_x_axis_gcode", "machine_extruder_start_code", "machine_extruder_end_code"]: value_from_file = getattr(definition, "default_value_from_file") if value_from_file != None: try: path = Resources.getPath(Resources.GCodes, value_from_file + ".gcode") with open(path, encoding = "utf-8") as f: value = f.read() except FileNotFoundError: return None return value except AttributeError: return None
def render(self): if not self._shader: self._shader = OpenGL.getInstance().createShaderProgram( Resources.getPath(Resources.Shaders, "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, CuraSceneNode) and node.getMeshData() and node.isVisible(): batch.addItem(node.getWorldTransformation(copy=False), 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()
def beginRendering(self): scene = self.getController().getScene() renderer = self.getRenderer() if not self._xray_shader: self._xray_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "xray.shader")) self._xray_shader.setUniformValue("u_color", Color(*Application.getInstance().getTheme().getColor("xray").getRgb())) for node in BreadthFirstIterator(scene.getRoot()): # We do not want to render ConvexHullNode as it conflicts with the bottom of the X-Ray (z-fighting). if type(node) is ConvexHullNode: continue 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) )
def getDefaultFirmwareName(self) -> str: machine_has_heated_bed = self.getProperty("machine_heated_bed", "value") machine_has_heated_chamber=self.getProperty("machine_heated_chamber", "value") baudrate = 250000 if Platform.isLinux(): # Linux prefers a baudrate of 115200 here because older versions of # pySerial did not support a baudrate of 250000 baudrate = 115200 # If a firmware file is available, it should be specified in the definition for the printer hex_file = self.getMetaDataEntry("firmware_file", None) if machine_has_heated_bed: hex_file = self.getMetaDataEntry("firmware_hbk_file", hex_file) if not hex_file: Logger.log("w", "There is no firmware for machine %s.", self.getBottom().id) return "" try: return Resources.getPath(cura.CuraApplication.CuraApplication.ResourceTypes.Firmware, hex_file.format(baudrate=baudrate)) except FileNotFoundError: Logger.log("w", "Firmware file %s not found.", hex_file) return ""
def _updateTexture(self): if not self._global_container_stack or not OpenGL.getInstance(): return self._texture = OpenGL.getInstance().createTexture() container = self._global_container_stack.findContainer( {"platform_texture": "*"}) if container: texture_file = container.getMetaDataEntry("platform_texture") try: self._texture.load( Resources.getPath(Resources.Images, texture_file)) except FileNotFoundError: Logger.log( "w", "Unable to find platform texture [%s] as specified in the definition", texture_file) # Note: if no texture file is specified, a 1 x 1 pixel transparent image is created # by UM.GL.QtTexture to prevent rendering issues if self._shader: self._shader.setTexture(0, self._texture)
def loadQtTranslation(self, file, language = "default"): #TODO Add support for specifying a language from preferences path = None if language == "default": path = self._getDefaultLanguage(file) else: path = Resources.getPath(Resources.i18n, language, "LC_MESSAGES", file + ".qm") # If all else fails, fall back to english. if not path: Logger.log("w", "Could not find any translations matching {0} for file {1}, falling back to english".format(language, file)) try: path = Resources.getPath(Resources.i18n, "en", "LC_MESSAGES", file + ".qm") except FileNotFoundError: Logger.log("w", "Could not find English translations for file {0}. Switching to developer english.".format(file)) return translator = QTranslator() if not translator.load(path): Logger.log("e", "Unable to load translations %s", file) return # Store a reference to the translator. # This prevents the translator from being destroyed before Qt has a chance to use it. self._translators[file] = translator # Finally, install the translator so Qt can use it. self.installTranslator(translator)