From 14afd9eab7687a26a49d730c0aef1883b51eb570 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Mon, 21 Nov 2016 21:36:08 +0100 Subject: [PATCH 001/156] Heaps to changes to get the Cura code through the type checker (with minimal checking). CURA-2917 --- CMakeLists.txt | 2 +- cura/CuraApplication.py | 58 +++++---- cura/PrintInformation.py | 4 +- cura/Settings/ContainerManager.py | 44 +++---- cura/Settings/ExtruderManager.py | 114 +++++++++--------- cura/Settings/ExtrudersModel.py | 4 +- cura/Settings/MachineManager.py | 113 ++++++++--------- .../MaterialSettingsVisibilityHandler.py | 4 +- cura/Settings/QualitySettingsModel.py | 23 ++-- cura/Settings/__init__.py | 11 -- cura_app.py | 3 - .../CuraEngineBackend/CuraEngineBackend.py | 4 +- .../MachineSettingsAction.py | 18 +-- .../PerObjectSettingVisibilityHandler.py | 4 +- plugins/SolidView/SolidView.py | 3 +- .../VersionUpgrade21to22/Profile.py | 2 +- .../XmlMaterialProfile/XmlMaterialProfile.py | 34 +++--- 17 files changed, 228 insertions(+), 217 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 40fac2ca2f..9c6c64fce1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,7 +61,7 @@ if(NOT ${URANIUM_SCRIPTS_DIR} STREQUAL "") endif() endif() -find_package(PythonInterp 3.4.0 REQUIRED) +find_package(PythonInterp 3.5.0 REQUIRED) install(DIRECTORY resources DESTINATION ${CMAKE_INSTALL_DATADIR}/cura) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 80bd4eb9a9..c9c72ceed7 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -42,7 +42,14 @@ from . import CuraSplashScreen from . import CameraImageProvider from . import MachineActionManager -import cura.Settings +from cura.Settings.MachineManager import MachineManager +from cura.Settings.ExtruderManager import ExtruderManager +from cura.Settings.CuraContainerRegistry import CuraContainerRegistry +from cura.Settings.ExtrudersModel import ExtrudersModel +from cura.Settings.ContainerSettingsModel import ContainerSettingsModel +from cura.Settings.MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler +from cura.Settings.QualitySettingsModel import QualitySettingsModel +from cura.Settings.ContainerManager import ContainerManager from PyQt5.QtCore import pyqtSlot, QUrl, pyqtSignal, pyqtProperty, QEvent, Q_ENUMS from PyQt5.QtGui import QColor, QIcon @@ -57,11 +64,13 @@ import urllib numpy.seterr(all="ignore") -try: - from cura.CuraVersion import CuraVersion, CuraBuildType -except ImportError: - CuraVersion = "master" # [CodeStyle: Reflecting imported value] - CuraBuildType = "" +MYPY = False +if not MYPY: + try: + from cura.CuraVersion import CuraVersion, CuraBuildType + except ImportError: + CuraVersion = "master" # [CodeStyle: Reflecting imported value] + CuraBuildType = "" class CuraApplication(QtApplication): class ResourceTypes: @@ -77,6 +86,8 @@ class CuraApplication(QtApplication): Q_ENUMS(ResourceTypes) def __init__(self): + super().__init__(name = "cura", version = CuraVersion, buildtype = CuraBuildType) + Resources.addSearchPath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura", "resources")) if not hasattr(sys, "frozen"): Resources.addSearchPath(os.path.join(os.path.abspath(os.path.dirname(__file__)), "..", "resources")) @@ -92,8 +103,8 @@ class CuraApplication(QtApplication): SettingDefinition.addSupportedProperty("resolve", DefinitionPropertyType.Function, default = None) SettingDefinition.addSettingType("extruder", None, str, Validator) - SettingFunction.registerOperator("extruderValues", cura.Settings.ExtruderManager.getExtruderValues) - SettingFunction.registerOperator("extruderValue", cura.Settings.ExtruderManager.getExtruderValue) + SettingFunction.registerOperator("extruderValues", ExtruderManager.getExtruderValues) + SettingFunction.registerOperator("extruderValue", ExtruderManager.getExtruderValue) ## Add the 4 types of profiles to storage. Resources.addStorageType(self.ResourceTypes.QualityInstanceContainer, "quality") @@ -112,11 +123,12 @@ class CuraApplication(QtApplication): ## Initialise the version upgrade manager with Cura's storage paths. import UM.VersionUpgradeManager #Needs to be here to prevent circular dependencies. - self._version_upgrade_manager = UM.VersionUpgradeManager.VersionUpgradeManager( + + UM.VersionUpgradeManager.VersionUpgradeManager.getInstance().setCurrentVersions( { - ("quality", UM.Settings.InstanceContainer.Version): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"), - ("machine_stack", UM.Settings.ContainerStack.Version): (self.ResourceTypes.MachineStack, "application/x-uranium-containerstack"), - ("preferences", UM.Preferences.Version): (Resources.Preferences, "application/x-uranium-preferences") + ("quality", UM.Settings.InstanceContainer.InstanceContainer.Version): (self.ResourceTypes.QualityInstanceContainer, "application/x-uranium-instancecontainer"), + ("machine_stack", UM.Settings.ContainerStack.ContainerStack.Version): (self.ResourceTypes.MachineStack, "application/x-uranium-containerstack"), + ("preferences", Preferences.Version): (Resources.Preferences, "application/x-uranium-preferences") } ) @@ -125,7 +137,6 @@ class CuraApplication(QtApplication): self._additional_components = {} # Components to add to certain areas in the interface - super().__init__(name = "cura", version = CuraVersion, buildtype = CuraBuildType) self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png"))) @@ -267,6 +278,9 @@ class CuraApplication(QtApplication): self._recent_files.append(QUrl.fromLocalFile(f)) + def getContainerRegistry(self): + return CuraContainerRegistry.getInstance() + def _onEngineCreated(self): self._engine.addImageProvider("camera", CameraImageProvider.CameraImageProvider()) @@ -418,8 +432,8 @@ class CuraApplication(QtApplication): 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", self.getMachineManager) + ExtruderManager.getInstance() + qmlRegisterSingletonType(MachineManager, "Cura", 1, 0, "MachineManager", self.getMachineManager) qmlRegisterSingletonType(MachineActionManager.MachineActionManager, "Cura", 1, 0, "MachineActionManager", self.getMachineActionManager) self.setMainQml(Resources.getPath(self.ResourceTypes.QmlFiles, "Cura.qml")) @@ -440,7 +454,7 @@ class CuraApplication(QtApplication): def getMachineManager(self, *args): if self._machine_manager is None: - self._machine_manager = cura.Settings.MachineManager.createMachineManager() + self._machine_manager = MachineManager.createMachineManager() return self._machine_manager ## Get the machine action manager @@ -476,17 +490,17 @@ class CuraApplication(QtApplication): qmlRegisterUncreatableType(CuraApplication, "Cura", 1, 0, "ResourceTypes", "Just an Enum type") - qmlRegisterType(cura.Settings.ExtrudersModel, "Cura", 1, 0, "ExtrudersModel") + qmlRegisterType(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") + qmlRegisterType(ContainerSettingsModel, "Cura", 1, 0, "ContainerSettingsModel") + qmlRegisterType(MaterialSettingsVisibilityHandler, "Cura", 1, 0, "MaterialSettingsVisibilityHandler") + qmlRegisterType(QualitySettingsModel, "Cura", 1, 0, "QualitySettingsModel") - qmlRegisterSingletonType(cura.Settings.ContainerManager, "Cura", 1, 0, "ContainerManager", cura.Settings.ContainerManager.createContainerManager) + qmlRegisterSingletonType(ContainerManager, "Cura", 1, 0, "ContainerManager", ContainerManager.createContainerManager) qmlRegisterSingletonType(QUrl.fromLocalFile(Resources.getPath(CuraApplication.ResourceTypes.QmlFiles, "Actions.qml")), "Cura", 1, 0, "Actions") - engine.rootContext().setContextProperty("ExtruderManager", cura.Settings.ExtruderManager.getInstance()) + engine.rootContext().setContextProperty("ExtruderManager", ExtruderManager.getInstance()) for path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.QmlFiles): type_name = os.path.splitext(os.path.basename(path))[0] diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 096170ba22..b4be3aa924 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -7,7 +7,7 @@ from UM.Application import Application from UM.Qt.Duration import Duration from UM.Preferences import Preferences -import cura.Settings.ExtruderManager +from cura.Settings.ExtruderManager import ExtruderManager import math import os.path @@ -85,7 +85,7 @@ class PrintInformation(QObject): r = Application.getInstance().getGlobalContainerStack().getProperty("material_diameter", "value") / 2 self._material_lengths = [] self._material_weights = [] - extruder_stacks = list(cura.Settings.ExtruderManager.getInstance().getMachineExtruders(Application.getInstance().getGlobalContainerStack().getId())) + extruder_stacks = list(ExtruderManager.getInstance().getMachineExtruders(Application.getInstance().getGlobalContainerStack().getId())) for index, amount in enumerate(material_amounts): ## Find the right extruder stack. As the list isn't sorted because it's a annoying generator, we do some # list comprehension filtering to solve this for us. diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 8957f386fc..c25a881b57 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -8,17 +8,19 @@ from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal, QUrl from PyQt5.QtWidgets import QMessageBox import UM.PluginRegistry -import UM.Settings import UM.SaveFile import UM.Platform import UM.MimeTypeDatabase import UM.Logger -import cura.Settings - +from UM.Application import Application from UM.MimeTypeDatabase import MimeTypeNotFoundError +from UM.Settings.ContainerRegistry import ContainerRegistry from UM.i18n import i18nCatalog + +from cura.Settings.ExtruderManager import ExtruderManager + catalog = i18nCatalog("cura") ## Manager class that contains common actions to deal with containers in Cura. @@ -30,7 +32,7 @@ class ContainerManager(QObject): def __init__(self, parent = None): super().__init__(parent) - self._registry = UM.Settings.ContainerRegistry.getInstance() + self._registry = ContainerRegistry.getInstance() self._container_name_filters = {} ## Create a duplicate of the specified container @@ -246,7 +248,7 @@ class ContainerManager(QObject): @pyqtSlot(str, result = bool) def isContainerUsed(self, container_id): UM.Logger.log("d", "Checking if container %s is currently used in the active stacks", container_id) - for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): if container_id in [child.getId() for child in stack.getContainers()]: UM.Logger.log("d", "The container is in use by %s", stack.getId()) return True @@ -357,12 +359,12 @@ class ContainerManager(QObject): except MimeTypeNotFoundError: return { "status": "error", "message": "Could not determine mime type of file" } - container_type = UM.Settings.ContainerRegistry.getContainerForMimeType(mime_type) + container_type = ContainerRegistry.getContainerForMimeType(mime_type) if not container_type: return { "status": "error", "message": "Could not find a container to handle the specified file."} container_id = urllib.parse.unquote_plus(mime_type.stripExtension(os.path.basename(file_url))) - container_id = UM.Settings.ContainerRegistry.getInstance().uniqueName(container_id) + container_id = ContainerRegistry.getInstance().uniqueName(container_id) container = container_type(container_id) @@ -374,7 +376,7 @@ class ContainerManager(QObject): container.setName(container_id) - UM.Settings.ContainerRegistry.getInstance().addContainer(container) + ContainerRegistry.getInstance().addContainer(container) return { "status": "success", "message": "Successfully imported container {0}".format(container.getName()) } @@ -386,13 +388,13 @@ class ContainerManager(QObject): # \return \type{bool} True if successful, False if not. @pyqtSlot(result = bool) def updateQualityChanges(self): - global_stack = UM.Application.getInstance().getGlobalContainerStack() + global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack: return False - UM.Application.getInstance().getMachineManager().blurSettings.emit() + Application.getInstance().getMachineManager().blurSettings.emit() - for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): # Find the quality_changes container for this stack and merge the contents of the top container into it. quality_changes = stack.findContainer(type = "quality_changes") if not quality_changes or quality_changes.isReadOnly(): @@ -401,17 +403,17 @@ class ContainerManager(QObject): self._performMerge(quality_changes, stack.getTop()) - UM.Application.getInstance().getMachineManager().activeQualityChanged.emit() + Application.getInstance().getMachineManager().activeQualityChanged.emit() return True ## Clear the top-most (user) containers of the active stacks. @pyqtSlot() def clearUserContainers(self): - UM.Application.getInstance().getMachineManager().blurSettings.emit() + Application.getInstance().getMachineManager().blurSettings.emit() # Go through global and extruder stacks and clear their topmost container (the user settings). - for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): stack.getTop().clear() ## Create quality changes containers from the user containers in the active stacks. @@ -423,7 +425,7 @@ class ContainerManager(QObject): # \return \type{bool} True if the operation was successfully, False if not. @pyqtSlot(result = bool) def createQualityChanges(self): - global_stack = UM.Application.getInstance().getGlobalContainerStack() + global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack: return False @@ -432,12 +434,12 @@ class ContainerManager(QObject): UM.Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) return False - UM.Application.getInstance().getMachineManager().blurSettings.emit() + Application.getInstance().getMachineManager().blurSettings.emit() - unique_name = UM.Settings.ContainerRegistry.getInstance().uniqueName(quality_container.getName()) + unique_name = ContainerRegistry.getInstance().uniqueName(quality_container.getName()) # Go through the active stacks and create quality_changes containers from the user containers. - for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): user_container = stack.getTop() quality_container = stack.findContainer(type = "quality") quality_changes_container = stack.findContainer(type = "quality_changes") @@ -541,7 +543,7 @@ class ContainerManager(QObject): container_type = containers[0].getMetaDataEntry("type") if container_type == "quality": for container in self._getFilteredContainers(name = quality_name, type = "quality"): - for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): new_changes = self._createQualityChanges(container, new_name, stack.getId()) UM.Settings.ContainerRegistry.getInstance().addContainer(new_changes) elif container_type == "quality_changes": @@ -620,7 +622,7 @@ class ContainerManager(QObject): # # \return A generator that iterates over the list of containers matching the search criteria. def _getFilteredContainers(self, **kwargs): - global_stack = UM.Application.getInstance().getGlobalContainerStack() + global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack: return False @@ -635,7 +637,7 @@ class ContainerManager(QObject): material_ids = [] if filter_by_material: - for stack in cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): + for stack in ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks(): material_ids.append(stack.findContainer(type = "material").getId()) containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 1359ab77b6..adb0b38e8e 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -3,11 +3,14 @@ from PyQt5.QtCore import pyqtSignal, pyqtProperty, pyqtSlot, QObject, QVariant #For communicating data and events to Qt. -import UM.Application #To get the global container stack to find the current machine. -import UM.Logger -import UM.Settings.ContainerRegistry #Finding containers by ID. -import UM.Settings.SettingFunction - +from UM.Application import Application #To get the global container stack to find the current machine. +from UM.Logger import Logger +from UM.Settings.ContainerRegistry import ContainerRegistry #Finding containers by ID. +from UM.Settings.InstanceContainer import InstanceContainer +from UM.Settings.SettingFunction import SettingFunction +from UM.Settings.ContainerStack import ContainerStack +from UM.Settings.DefinitionContainer import DefinitionContainer +from typing import Optional ## Manages all existing extruder stacks. # @@ -22,9 +25,12 @@ class ExtruderManager(QObject): ## Registers listeners and such to listen to changes to the extruders. def __init__(self, parent = None): super().__init__(parent) - self._extruder_trains = { } #Per machine, a dictionary of extruder container stack IDs. - self._active_extruder_index = 0 - UM.Application.getInstance().globalContainerStackChanged.connect(self.__globalContainerStackChanged) + + # Per machine, a dictionary of extruder container stack IDs. + self._extruder_trains = {} # type: Dict[str, Dict[str, ContainerStack]] + + self._active_extruder_index = 0 # type: int + Application.getInstance().globalContainerStackChanged.connect(self.__globalContainerStackChanged) self._addCurrentMachineExtruders() ## Gets the unique identifier of the currently active extruder stack. @@ -34,31 +40,31 @@ class ExtruderManager(QObject): # # \return The unique ID of the currently active extruder stack. @pyqtProperty(str, notify = activeExtruderChanged) - def activeExtruderStackId(self): - if not UM.Application.getInstance().getGlobalContainerStack(): + def activeExtruderStackId(self) -> Optional[str]: + if not Application.getInstance().getGlobalContainerStack(): return None # No active machine, so no active extruder. try: - return self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()][str(self._active_extruder_index)].getId() + return self._extruder_trains[Application.getInstance().getGlobalContainerStack().getId()][str(self._active_extruder_index)].getId() except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong. return None @pyqtProperty(int, notify = extrudersChanged) - def extruderCount(self): - if not UM.Application.getInstance().getGlobalContainerStack(): + def extruderCount(self) -> int: + if not Application.getInstance().getGlobalContainerStack(): return 0 # No active machine, so no extruders. - return len(self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]) + return len(self._extruder_trains[Application.getInstance().getGlobalContainerStack().getId()]) @pyqtProperty("QVariantMap", notify=extrudersChanged) def extruderIds(self): map = {} - for position in self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]: - map[position] = self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()][position].getId() + for position in self._extruder_trains[Application.getInstance().getGlobalContainerStack().getId()]: + map[position] = self._extruder_trains[Application.getInstance().getGlobalContainerStack().getId()][position].getId() return map @pyqtSlot(str, result = str) - def getQualityChangesIdByExtruderStackId(self, id): - for position in self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()]: - extruder = self._extruder_trains[UM.Application.getInstance().getGlobalContainerStack().getId()][position] + def getQualityChangesIdByExtruderStackId(self, id: str) -> str: + for position in self._extruder_trains[Application.getInstance().getGlobalContainerStack().getId()]: + extruder = self._extruder_trains[Application.getInstance().getGlobalContainerStack().getId()][position] if extruder.getId() == id: return extruder.findContainer(type = "quality_changes").getId() @@ -75,7 +81,7 @@ class ExtruderManager(QObject): # # \return The extruder manager. @classmethod - def getInstance(cls): + def getInstance(cls) -> 'ExtruderManager': if not cls.__instance: cls.__instance = ExtruderManager() return cls.__instance @@ -84,16 +90,16 @@ class ExtruderManager(QObject): # # \param index The index of the new active extruder. @pyqtSlot(int) - def setActiveExtruderIndex(self, index): + def setActiveExtruderIndex(self, index: int) -> None: self._active_extruder_index = index self.activeExtruderChanged.emit() @pyqtProperty(int, notify = activeExtruderChanged) - def activeExtruderIndex(self): + def activeExtruderIndex(self) -> int: return self._active_extruder_index - def getActiveExtruderStack(self): - global_container_stack = UM.Application.getInstance().getGlobalContainerStack() + def getActiveExtruderStack(self) -> ContainerStack: + global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: if global_container_stack.getId() in self._extruder_trains: if str(self._active_extruder_index) in self._extruder_trains[global_container_stack.getId()]: @@ -102,7 +108,7 @@ class ExtruderManager(QObject): ## Get an extruder stack by index def getExtruderStack(self, index): - global_container_stack = UM.Application.getInstance().getGlobalContainerStack() + global_container_stack = Application.getInstance().getGlobalContainerStack() if global_container_stack: if global_container_stack.getId() in self._extruder_trains: if str(index) in self._extruder_trains[global_container_stack.getId()]: @@ -114,19 +120,19 @@ class ExtruderManager(QObject): # # \param machine_definition The machine definition to add the extruders for. # \param machine_id The machine_id to add the extruders for. - def addMachineExtruders(self, machine_definition, machine_id): + def addMachineExtruders(self, machine_definition: DefinitionContainer, machine_id: str) -> None: changed = False machine_definition_id = machine_definition.getId() if machine_id not in self._extruder_trains: self._extruder_trains[machine_id] = { } changed = True - container_registry = UM.Settings.ContainerRegistry.getInstance() + container_registry = ContainerRegistry.getInstance() if container_registry: # Add the extruder trains that don't exist yet. for extruder_definition in container_registry.findDefinitionContainers(machine = machine_definition_id): position = extruder_definition.getMetaDataEntry("position", None) if not position: - UM.Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.getId()) + Logger.log("w", "Extruder definition %s specifies no position metadata entry.", extruder_definition.getId()) if not container_registry.findContainerStacks(machine = machine_id, position = position): # Doesn't exist yet. self.createExtruderTrain(extruder_definition, machine_definition, position, machine_id) changed = True @@ -138,7 +144,7 @@ class ExtruderManager(QObject): # Make sure the next stack is a stack that contains only the machine definition if not extruder_train.getNextStack(): - shallow_stack = UM.Settings.ContainerStack(machine_id + "_shallow") + shallow_stack = ContainerStack(machine_id + "_shallow") shallow_stack.addContainer(machine_definition) extruder_train.setNextStack(shallow_stack) changed = True @@ -157,14 +163,15 @@ class ExtruderManager(QObject): # \param machine_definition The machine that the extruder train belongs to. # \param position The position of this extruder train in the extruder slots of the machine. # \param machine_id The id of the "global" stack this extruder is linked to. - def createExtruderTrain(self, extruder_definition, machine_definition, position, machine_id): + def createExtruderTrain(self, extruder_definition: DefinitionContainer, machine_definition: DefinitionContainer, + position, machine_id: str) -> None: # Cache some things. - container_registry = UM.Settings.ContainerRegistry.getInstance() + container_registry = ContainerRegistry.getInstance() machine_definition_id = machine_definition.getId() # Create a container stack for this extruder. extruder_stack_id = container_registry.uniqueName(extruder_definition.getId()) - container_stack = UM.Settings.ContainerStack(extruder_stack_id) + container_stack = ContainerStack(extruder_stack_id) container_stack.setName(extruder_definition.getName()) # Take over the display name to display the stack with. container_stack.addMetaDataEntry("type", "extruder_train") container_stack.addMetaDataEntry("machine", machine_id) @@ -184,7 +191,7 @@ class ExtruderManager(QObject): if len(preferred_variants) >= 1: variant = preferred_variants[0] else: - UM.Logger.log("w", "The preferred variant \"%s\" of machine %s doesn't exist or is not a variant profile.", preferred_variant_id, machine_id) + Logger.log("w", "The preferred variant \"%s\" of machine %s doesn't exist or is not a variant profile.", preferred_variant_id, machine_id) # And leave it at the default variant. container_stack.addContainer(variant) @@ -213,7 +220,7 @@ class ExtruderManager(QObject): if len(preferred_materials) >= 1: material = preferred_materials[0] else: - UM.Logger.log("w", "The preferred material \"%s\" of machine %s doesn't exist or is not a material profile.", preferred_material_id, machine_id) + Logger.log("w", "The preferred material \"%s\" of machine %s doesn't exist or is not a material profile.", preferred_material_id, machine_id) # And leave it at the default material. container_stack.addContainer(material) @@ -232,11 +239,11 @@ class ExtruderManager(QObject): if preferred_quality: search_criteria["id"] = preferred_quality - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) if not containers and preferred_quality: - UM.Logger.log("w", "The preferred quality \"%s\" of machine %s doesn't exist or is not a quality profile.", preferred_quality, machine_id) + Logger.log("w", "The preferred quality \"%s\" of machine %s doesn't exist or is not a quality profile.", preferred_quality, machine_id) search_criteria.pop("id", None) - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) if containers: quality = containers[0] @@ -249,7 +256,7 @@ class ExtruderManager(QObject): if user_profile: # There was already a user profile, loaded from settings. user_profile = user_profile[0] else: - user_profile = UM.Settings.InstanceContainer(extruder_stack_id + "_current_settings") # Add an empty user profile. + user_profile = InstanceContainer(extruder_stack_id + "_current_settings") # Add an empty user profile. user_profile.addMetaDataEntry("type", "user") user_profile.addMetaDataEntry("extruder", extruder_stack_id) user_profile.setDefinition(machine_definition) @@ -258,7 +265,7 @@ class ExtruderManager(QObject): # Make sure the next stack is a stack that contains only the machine definition if not container_stack.getNextStack(): - shallow_stack = UM.Settings.ContainerStack(machine_id + "_shallow") + shallow_stack = ContainerStack(machine_id + "_shallow") shallow_stack.addContainer(machine_definition) container_stack.setNextStack(shallow_stack) @@ -269,26 +276,25 @@ class ExtruderManager(QObject): # \param machine_id The machine to remove the extruders for. def removeMachineExtruders(self, machine_id): for extruder in self.getMachineExtruders(machine_id): - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "user", extruder = extruder.getId()) + containers = ContainerRegistry.getInstance().findInstanceContainers(type = "user", extruder = extruder.getId()) for container in containers: - UM.Settings.ContainerRegistry.getInstance().removeContainer(container.getId()) - UM.Settings.ContainerRegistry.getInstance().removeContainer(extruder.getId()) + ContainerRegistry.getInstance().removeContainer(container.getId()) + ContainerRegistry.getInstance().removeContainer(extruder.getId()) ## Returns extruders for a specific machine. # # \param machine_id The machine to get the extruders of. def getMachineExtruders(self, machine_id): if machine_id not in self._extruder_trains: - UM.Logger.log("w", "Tried to get the extruder trains for machine %s, which doesn't exist.", machine_id) - return - for name in self._extruder_trains[machine_id]: - yield self._extruder_trains[machine_id][name] + Logger.log("w", "Tried to get the extruder trains for machine %s, which doesn't exist.", machine_id) + return [] + return [self._extruder_trains[machine_id][name] for name in self._extruder_trains[machine_id]] ## Returns a generator that will iterate over the global stack and per-extruder stacks. # # The first generated element is the global container stack. After that any extruder stacks are generated. def getActiveGlobalAndExtruderStacks(self): - global_stack = UM.Application.getInstance().getGlobalContainerStack() + global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack: return @@ -298,13 +304,13 @@ class ExtruderManager(QObject): for name in self._extruder_trains[global_id]: yield self._extruder_trains[global_id][name] - def __globalContainerStackChanged(self): + def __globalContainerStackChanged(self) -> None: self._addCurrentMachineExtruders() self.activeExtruderChanged.emit() ## Adds the extruders of the currently active machine. - def _addCurrentMachineExtruders(self): - global_stack = UM.Application.getInstance().getGlobalContainerStack() + def _addCurrentMachineExtruders(self) -> None: + global_stack = Application.getInstance().getGlobalContainerStack() if global_stack and global_stack.getBottom(): self.addMachineExtruders(global_stack.getBottom(), global_stack.getId()) @@ -318,7 +324,7 @@ class ExtruderManager(QObject): # If no extruder has the value, the list will contain the global value. @staticmethod def getExtruderValues(key): - global_stack = UM.Application.getInstance().getGlobalContainerStack() + global_stack = Application.getInstance().getGlobalContainerStack() result = [] for extruder in ExtruderManager.getInstance().getMachineExtruders(global_stack.getId()): @@ -327,7 +333,7 @@ class ExtruderManager(QObject): if not value: continue - if isinstance(value, UM.Settings.SettingFunction): + if isinstance(value, SettingFunction): value = value(extruder) result.append(value) @@ -363,9 +369,9 @@ class ExtruderManager(QObject): if extruder: value = extruder.getRawProperty(key, "value") - if isinstance(value, UM.Settings.SettingFunction): + if isinstance(value, SettingFunction): value = value(extruder) else: #Just a value from global. - value = UM.Application.getInstance().getGlobalContainerStack().getProperty(key, "value") + value = Application.getInstance().getGlobalContainerStack().getProperty(key, "value") return value diff --git a/cura/Settings/ExtrudersModel.py b/cura/Settings/ExtrudersModel.py index 155f1a0df1..4c5a755007 100644 --- a/cura/Settings/ExtrudersModel.py +++ b/cura/Settings/ExtrudersModel.py @@ -5,7 +5,7 @@ from PyQt5.QtCore import Qt, pyqtSignal, pyqtProperty import UM.Qt.ListModel -from . import ExtruderManager +from cura.Settings.ExtruderManager import ExtruderManager ## Model that holds extruders. # @@ -100,7 +100,7 @@ class ExtrudersModel(UM.Qt.ListModel.ListModel): self.clear() changed = True - global_container_stack = UM.Application.getInstance().getGlobalContainerStack() + global_container_stack = UM.Application.Application.getInstance().getGlobalContainerStack() if global_container_stack: if self._add_global: material = global_container_stack.findContainer({ "type": "material" }) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 823e59b4b8..9165d49e15 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1,5 +1,6 @@ # Copyright (c) 2016 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. +from typing import Union from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal from PyQt5.QtWidgets import QMessageBox @@ -7,13 +8,14 @@ from PyQt5.QtWidgets import QMessageBox from UM.Application import Application from UM.Preferences import Preferences from UM.Logger import Logger - +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.SettingRelation import RelationType - -import UM.Settings +from UM.Settings.ContainerStack import ContainerStack +from UM.Settings.Validator import ValidatorState from cura.PrinterOutputDevice import PrinterOutputDevice -from . import ExtruderManager +from cura.Settings.ExtruderManager import ExtruderManager from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") @@ -24,8 +26,8 @@ class MachineManager(QObject): def __init__(self, parent = None): super().__init__(parent) - self._active_container_stack = None - self._global_container_stack = None + self._active_container_stack = None # type: ContainerStack + self._global_container_stack = None # type: ContainerStack Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged) ## When the global container is changed, active material probably needs to be updated. @@ -47,10 +49,10 @@ class MachineManager(QObject): self.globalValueChanged.connect(self.activeStackChanged) ExtruderManager.getInstance().activeExtruderChanged.connect(self.activeStackChanged) - self._empty_variant_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_variant")[0] - self._empty_material_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_material")[0] - self._empty_quality_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality")[0] - self._empty_quality_changes_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality_changes")[0] + self._empty_variant_container = ContainerRegistry.getInstance().findInstanceContainers(id = "empty_variant")[0] + self._empty_material_container = ContainerRegistry.getInstance().findInstanceContainers(id = "empty_material")[0] + self._empty_quality_container = ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality")[0] + self._empty_quality_changes_container = ContainerRegistry.getInstance().findInstanceContainers(id = "empty_quality_changes")[0] Preferences.getInstance().addPreference("cura/active_machine", "") @@ -84,7 +86,7 @@ class MachineManager(QObject): outputDevicesChanged = pyqtSignal() - def _onOutputDevicesChanged(self): + def _onOutputDevicesChanged(self) -> None: for printer_output_device in self._printer_output_devices: printer_output_device.hotendIdChanged.disconnect(self._onHotendIdChanged) printer_output_device.materialIdChanged.disconnect(self._onMaterialIdChanged) @@ -103,14 +105,15 @@ class MachineManager(QObject): def printerOutputDevices(self): return self._printer_output_devices - def _onHotendIdChanged(self, index, hotend_id): + def _onHotendIdChanged(self, index: Union[str,int], hotend_id: str) -> None: if not self._global_container_stack: return - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type="variant", definition=self._global_container_stack.getBottom().getId(), name=hotend_id) + containers = ContainerRegistry.getInstance().findInstanceContainers(type="variant", definition=self._global_container_stack.getBottom().getId(), name=hotend_id) if containers: # New material ID is known extruder_manager = ExtruderManager.getInstance() - extruders = list(extruder_manager.getMachineExtruders(self.activeMachineId)) + machine_id = self.activeMachineId + extruders = extruder_manager.getMachineExtruders(machine_id) matching_extruder = None for extruder in extruders: if str(index) == extruder.getMetaDataEntry("position"): @@ -147,7 +150,7 @@ class MachineManager(QObject): if self._global_container_stack.getMetaDataEntry("has_machine_materials", False): definition_id = self._global_container_stack.getBottom().getId() extruder_manager = ExtruderManager.getInstance() - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material", definition = definition_id, GUID = material_id) + containers = ContainerRegistry.getInstance().findInstanceContainers(type = "material", definition = definition_id, GUID = material_id) if containers: # New material ID is known extruders = list(extruder_manager.getMachineExtruders(self.activeMachineId)) matching_extruder = None @@ -262,7 +265,7 @@ class MachineManager(QObject): changed_validation_state = self._active_container_stack.getProperty(key, property_name) else: changed_validation_state = self._global_container_stack.getProperty(key, property_name) - if changed_validation_state in (UM.Settings.ValidatorState.Exception, UM.Settings.ValidatorState.MaximumError, UM.Settings.ValidatorState.MinimumError): + if changed_validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError): self._active_stack_valid = False self.activeValidationChanged.emit() else: @@ -273,19 +276,19 @@ class MachineManager(QObject): self.activeStackChanged.emit() @pyqtSlot(str) - def setActiveMachine(self, stack_id): - containers = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = stack_id) + def setActiveMachine(self, stack_id: str) -> None: + containers = ContainerRegistry.getInstance().findContainerStacks(id = stack_id) if containers: Application.getInstance().setGlobalContainerStack(containers[0]) @pyqtSlot(str, str) - def addMachine(self, name, definition_id): - container_registry = UM.Settings.ContainerRegistry.getInstance() + def addMachine(self, name: str, definition_id: str) -> None: + container_registry = ContainerRegistry.getInstance() definitions = container_registry.findDefinitionContainers(id = definition_id) if definitions: definition = definitions[0] name = self._createUniqueName("machine", "", name, definition.getName()) - new_global_stack = UM.Settings.ContainerStack(name) + new_global_stack = ContainerStack(name) new_global_stack.addMetaDataEntry("type", "machine") container_registry.addContainer(new_global_stack) @@ -293,7 +296,7 @@ class MachineManager(QObject): material_instance_container = self._updateMaterialContainer(definition, variant_instance_container) quality_instance_container = self._updateQualityContainer(definition, variant_instance_container, material_instance_container) - current_settings_instance_container = UM.Settings.InstanceContainer(name + "_current_settings") + current_settings_instance_container = InstanceContainer(name + "_current_settings") current_settings_instance_container.addMetaDataEntry("machine", name) current_settings_instance_container.addMetaDataEntry("type", "user") current_settings_instance_container.setDefinition(definitions[0]) @@ -321,8 +324,9 @@ class MachineManager(QObject): # \param new_name \type{string} Base name, which may not be unique # \param fallback_name \type{string} Name to use when (stripped) new_name is empty # \return \type{string} Name that is unique for the specified type and name/id - def _createUniqueName(self, container_type, current_name, new_name, fallback_name): - return UM.Settings.ContainerRegistry.getInstance().createUniqueName(container_type, current_name, new_name, fallback_name) + def _createUniqueName(self, container_type: str, current_name: str, new_name: str, fallback_name: str) -> str: + Logger.log('d', str(ContainerRegistry.getInstance())) + return ContainerRegistry.getInstance().createUniqueName(container_type, current_name, new_name, fallback_name) ## Convenience function to check if a stack has errors. def _checkStackForErrors(self, stack): @@ -331,7 +335,7 @@ class MachineManager(QObject): for key in stack.getAllKeys(): validation_state = stack.getProperty(key, "validationState") - if validation_state in (UM.Settings.ValidatorState.Exception, UM.Settings.ValidatorState.MaximumError, UM.Settings.ValidatorState.MinimumError): + if validation_state in (ValidatorState.Exception, ValidatorState.MaximumError, ValidatorState.MinimumError): return True return False @@ -364,39 +368,39 @@ class MachineManager(QObject): # Note that the _active_stack_valid is cached due to performance issues # Calling _checkStackForErrors on every change is simply too expensive @pyqtProperty(bool, notify = activeValidationChanged) - def isActiveStackValid(self): + def isActiveStackValid(self) -> bool: return bool(self._active_stack_valid) @pyqtProperty(str, notify = activeStackChanged) - def activeUserProfileId(self): + def activeUserProfileId(self) -> str: if self._active_container_stack: return self._active_container_stack.getTop().getId() return "" @pyqtProperty(str, notify = globalContainerChanged) - def activeMachineName(self): + def activeMachineName(self) -> str: if self._global_container_stack: return self._global_container_stack.getName() return "" @pyqtProperty(str, notify = globalContainerChanged) - def activeMachineId(self): + def activeMachineId(self) -> str: if self._global_container_stack: return self._global_container_stack.getId() return "" @pyqtProperty(str, notify = activeStackChanged) - def activeStackId(self): + def activeStackId(self) -> str: if self._active_container_stack: return self._active_container_stack.getId() return "" @pyqtProperty(str, notify = activeMaterialChanged) - def activeMaterialName(self): + def activeMaterialName(self) -> str: if self._active_container_stack: material = self._active_container_stack.findContainer({"type":"material"}) if material: @@ -405,7 +409,7 @@ class MachineManager(QObject): return "" @pyqtProperty(str, notify=activeMaterialChanged) - def activeMaterialId(self): + def activeMaterialId(self) -> str: if self._active_container_stack: material = self._active_container_stack.findContainer({"type": "material"}) if material: @@ -430,7 +434,7 @@ class MachineManager(QObject): return result @pyqtProperty(str, notify=activeQualityChanged) - def activeQualityMaterialId(self): + def activeQualityMaterialId(self) -> str: if self._active_container_stack: quality = self._active_container_stack.findContainer({"type": "quality"}) if quality: @@ -478,8 +482,8 @@ class MachineManager(QObject): ## Check if a container is read_only @pyqtSlot(str, result = bool) - def isReadOnly(self, container_id): - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = container_id) + def isReadOnly(self, container_id) -> bool: + containers = ContainerRegistry.getInstance().findInstanceContainers(id = container_id) if not containers or not self._active_container_stack: return True return containers[0].isReadOnly() @@ -499,7 +503,7 @@ class MachineManager(QObject): @pyqtSlot(str) def setActiveMaterial(self, material_id): - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = material_id) + containers = ContainerRegistry.getInstance().findInstanceContainers(id = material_id) if not containers or not self._active_container_stack: return @@ -532,7 +536,7 @@ class MachineManager(QObject): @pyqtSlot(str) def setActiveVariant(self, variant_id): - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = variant_id) + containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant_id) if not containers or not self._active_container_stack: return old_variant = self._active_container_stack.findContainer({"type": "variant"}) @@ -541,7 +545,6 @@ class MachineManager(QObject): variant_index = self._active_container_stack.getContainerIndex(old_variant) self._active_container_stack.replaceContainer(variant_index, containers[0]) - preferred_material = None if old_material: preferred_material_name = old_material.getName() self.setActiveMaterial(self._updateMaterialContainer(self._global_container_stack.getBottom(), containers[0], preferred_material_name).id) @@ -550,7 +553,7 @@ class MachineManager(QObject): @pyqtSlot(str) def setActiveQuality(self, quality_id): - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = quality_id) + containers = ContainerRegistry.getInstance().findInstanceContainers(id = quality_id) if not containers or not self._global_container_stack: return @@ -563,7 +566,7 @@ class MachineManager(QObject): quality_container = containers[0] elif container_type == "quality_changes": quality_changes_container = containers[0] - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers( + containers = ContainerRegistry.getInstance().findInstanceContainers( quality_type = quality_changes_container.getMetaDataEntry("quality")) if not containers: Logger.log("e", "Could not find quality %s for changes %s, not changing quality", quality_changes_container.getMetaDataEntry("quality"), quality_changes_container.getId()) @@ -591,10 +594,10 @@ class MachineManager(QObject): else: criteria["definition"] = "fdmprinter" - stack_quality = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + stack_quality = ContainerRegistry.getInstance().findInstanceContainers(**criteria) if not stack_quality: criteria.pop("extruder") - stack_quality = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + stack_quality = ContainerRegistry.getInstance().findInstanceContainers(**criteria) if not stack_quality: stack_quality = quality_container else: @@ -603,7 +606,7 @@ class MachineManager(QObject): stack_quality = stack_quality[0] if quality_changes_container != self._empty_quality_changes_container: - stack_quality_changes = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(name = quality_changes_container.getName(), extruder = extruder_id)[0] + stack_quality_changes = ContainerRegistry.getInstance().findInstanceContainers(name = quality_changes_container.getName(), extruder = extruder_id)[0] else: stack_quality_changes = self._empty_quality_changes_container @@ -683,7 +686,7 @@ class MachineManager(QObject): @pyqtSlot(str, str) def renameMachine(self, machine_id, new_name): - containers = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = machine_id) + containers = ContainerRegistry.getInstance().findContainerStacks(id = machine_id) if containers: new_name = self._createUniqueName("machine", containers[0].getName(), new_name, containers[0].getBottom().getName()) containers[0].setName(new_name) @@ -696,13 +699,13 @@ class MachineManager(QObject): ExtruderManager.getInstance().removeMachineExtruders(machine_id) - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "user", machine = machine_id) + containers = ContainerRegistry.getInstance().findInstanceContainers(type = "user", machine = machine_id) for container in containers: - UM.Settings.ContainerRegistry.getInstance().removeContainer(container.getId()) - UM.Settings.ContainerRegistry.getInstance().removeContainer(machine_id) + ContainerRegistry.getInstance().removeContainer(container.getId()) + ContainerRegistry.getInstance().removeContainer(machine_id) if activate_new_machine: - stacks = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(type = "machine") + stacks = ContainerRegistry.getInstance().findContainerStacks(type = "machine") if stacks: Application.getInstance().setGlobalContainerStack(stacks[0]) @@ -743,7 +746,7 @@ class MachineManager(QObject): # \returns DefinitionID (string) if found, None otherwise @pyqtSlot(str, result = str) def getDefinitionByMachineId(self, machine_id): - containers = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id=machine_id) + containers = ContainerRegistry.getInstance().findContainerStacks(id=machine_id) if containers: return containers[0].getBottom().getId() @@ -758,10 +761,10 @@ class MachineManager(QObject): containers = [] preferred_variant = definition.getMetaDataEntry("preferred_variant") if preferred_variant: - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id, id = preferred_variant) + containers = ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id, id = preferred_variant) if not containers: - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id) + containers = ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = definition.id) if containers: return containers[0] @@ -789,7 +792,7 @@ class MachineManager(QObject): if preferred_material: search_criteria["id"] = preferred_material - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) if containers: return containers[0] @@ -798,14 +801,14 @@ class MachineManager(QObject): search_criteria.pop("name", None) search_criteria.pop("id", None) - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) if containers: return containers[0] return self._empty_material_container def _updateQualityContainer(self, definition, variant_container, material_container = None, preferred_quality_name = None): - container_registry = UM.Settings.ContainerRegistry.getInstance() + container_registry = ContainerRegistry.getInstance() search_criteria = { "type": "quality" } if definition.getMetaDataEntry("has_machine_quality"): @@ -870,7 +873,7 @@ class MachineManager(QObject): # \param preferred_quality_changes_name The name of the quality-changes to # pick, if any such quality-changes profile is available. def _updateQualityChangesContainer(self, quality_type, preferred_quality_changes_name = None): - container_registry = UM.Settings.ContainerRegistry.getInstance() # Cache. + container_registry = ContainerRegistry.getInstance() # Cache. search_criteria = { "type": "quality_changes" } search_criteria["quality"] = quality_type diff --git a/cura/Settings/MaterialSettingsVisibilityHandler.py b/cura/Settings/MaterialSettingsVisibilityHandler.py index 7286f509bf..8a16832f5e 100644 --- a/cura/Settings/MaterialSettingsVisibilityHandler.py +++ b/cura/Settings/MaterialSettingsVisibilityHandler.py @@ -1,9 +1,9 @@ # Copyright (c) 2016 Ultimaker B.V. # Uranium is released under the terms of the AGPLv3 or higher. -import UM.Settings.Models +from UM.Settings.Models.SettingVisibilityHandler import SettingVisibilityHandler -class MaterialSettingsVisibilityHandler(UM.Settings.Models.SettingVisibilityHandler): +class MaterialSettingsVisibilityHandler(SettingVisibilityHandler): def __init__(self, parent = None, *args, **kwargs): super().__init__(parent = parent, *args, **kwargs) diff --git a/cura/Settings/QualitySettingsModel.py b/cura/Settings/QualitySettingsModel.py index 4362dd51d8..589b0da7cb 100644 --- a/cura/Settings/QualitySettingsModel.py +++ b/cura/Settings/QualitySettingsModel.py @@ -5,11 +5,10 @@ import collections from PyQt5.QtCore import pyqtProperty, pyqtSignal, Qt -import UM.Application import UM.Logger import UM.Qt -import UM.Settings - +from UM.Application import Application +from UM.Settings.ContainerRegistry import ContainerRegistry class QualitySettingsModel(UM.Qt.ListModel.ListModel): KeyRole = Qt.UserRole + 1 @@ -75,7 +74,7 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): settings = collections.OrderedDict() definition_container = UM.Application.getInstance().getGlobalContainerStack().getBottom() - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = self._quality) + containers = ContainerRegistry.getInstance().findInstanceContainers(id = self._quality) if not containers: UM.Logger.log("w", "Could not find a quality container with id %s", self._quality) return @@ -97,7 +96,7 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): if self._material: criteria["material"] = self._material - quality_container = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + quality_container = ContainerRegistry.getInstance().findInstanceContainers(**criteria) if not quality_container: UM.Logger.log("w", "Could not find a quality container matching quality changes %s", quality_changes_container.getId()) return @@ -113,22 +112,22 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): criteria["extruder"] = self._extruder_id - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria) if not containers: # Try again, this time without extruder new_criteria = criteria.copy() new_criteria.pop("extruder") - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**new_criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**new_criteria) if not containers: # Try again, this time without material criteria.pop("material") - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria) if not containers: # Try again, this time without material or extruder criteria.pop("extruder") # "material" has already been popped - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria) if not containers: UM.Logger.log("Could not find any quality containers matching the search criteria %s" % str(criteria)) @@ -136,7 +135,7 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): if quality_changes_container: criteria = {"type": "quality_changes", "quality": quality_type, "extruder": self._extruder_id, "definition": definition_id } - changes = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + changes = ContainerRegistry.getInstance().findInstanceContainers(**criteria) if changes: containers.extend(changes) @@ -154,9 +153,9 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): user_value = None if not self._extruder_id: - user_value = UM.Application.getInstance().getGlobalContainerStack().getTop().getProperty(definition.key, "value") + user_value = Application.getInstance().getGlobalContainerStack().getTop().getProperty(definition.key, "value") else: - extruder_stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = self._extruder_id) + extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = self._extruder_id) if extruder_stack: user_value = extruder_stack[0].getTop().getProperty(definition.key, "value") diff --git a/cura/Settings/__init__.py b/cura/Settings/__init__.py index 5daa00c84f..c00ee15ebf 100644 --- a/cura/Settings/__init__.py +++ b/cura/Settings/__init__.py @@ -1,13 +1,2 @@ # Copyright (c) 2016 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. - -from .MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler -from .ContainerManager import ContainerManager -from .ContainerSettingsModel import ContainerSettingsModel -from .CuraContainerRegistry import CuraContainerRegistry -from .ExtruderManager import ExtruderManager -from .ExtrudersModel import ExtrudersModel -from .MachineManager import MachineManager -from .MaterialSettingsVisibilityHandler import MaterialSettingsVisibilityHandler -from .SettingOverrideDecorator import SettingOverrideDecorator -from .QualitySettingsModel import QualitySettingsModel diff --git a/cura_app.py b/cura_app.py index 5c3ea811b5..6c75e49fb7 100755 --- a/cura_app.py +++ b/cura_app.py @@ -55,8 +55,5 @@ if Platform.isWindows() and hasattr(sys, "frozen"): sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w") sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w") -# Force an instance of CuraContainerRegistry to be created and reused later. -cura.Settings.CuraContainerRegistry.getInstance() - app = cura.CuraApplication.CuraApplication.getInstance() app.run() diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index 9e6bec45e4..ff4a92a6e0 100644 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -82,7 +82,7 @@ class CuraEngineBackend(Backend): self._onGlobalStackChanged() self._active_extruder_stack = None - cura.Settings.ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged) + cura.Settings.ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged) self._onActiveExtruderChanged() # When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired. @@ -449,7 +449,7 @@ class CuraEngineBackend(Backend): if self._active_extruder_stack: self._active_extruder_stack.containersChanged.disconnect(self._onChanged) - self._active_extruder_stack = cura.Settings.ExtruderManager.getInstance().getActiveExtruderStack() + self._active_extruder_stack = cura.Settings.ExtruderManager.ExtruderManager.getInstance().getActiveExtruderStack() if self._active_extruder_stack: self._active_extruder_stack.containersChanged.connect(self._onChanged) diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index a37aa9c5cb..56206e010f 100644 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -9,7 +9,7 @@ import cura.Settings.CuraContainerRegistry import UM.Application import UM.Settings.InstanceContainer import UM.Settings.DefinitionContainer -import UM.Logger +from UM.Logger import Logger import UM.i18n catalog = UM.i18n.i18nCatalog("cura") @@ -19,10 +19,10 @@ class MachineSettingsAction(MachineAction): super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings")) self._qml_url = "MachineSettingsAction.qml" - cura.Settings.CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) + cura.Settings.CuraContainerRegistry.CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) def _reset(self): - global_container_stack = UM.Application.getInstance().getGlobalContainerStack() + global_container_stack = UM.Application.Application.getInstance().getGlobalContainerStack() if global_container_stack: variant = global_container_stack.findContainer({"type": "variant"}) if variant and variant.getId() == "empty_variant": @@ -39,28 +39,28 @@ class MachineSettingsAction(MachineAction): def _onContainerAdded(self, container): # Add this action as a supported action to all machine definitions - if isinstance(container, UM.Settings.DefinitionContainer) and container.getMetaDataEntry("type") == "machine": + if isinstance(container, UM.Settings.DefinitionContainer.DefinitionContainer) and container.getMetaDataEntry("type") == "machine": if container.getProperty("machine_extruder_count", "value") > 1: # Multiextruder printers are not currently supported - UM.Logger.log("d", "Not attaching MachineSettingsAction to %s; Multi-extrusion printers are not supported", container.getId()) + Logger.log("d", "Not attaching MachineSettingsAction to %s; Multi-extrusion printers are not supported", container.getId()) return if container.getMetaDataEntry("has_variants", False): # Machines that use variants are not currently supported - UM.Logger.log("d", "Not attaching MachineSettingsAction to %s; Machines that use variants are not supported", container.getId()) + Logger.log("d", "Not attaching MachineSettingsAction to %s; Machines that use variants are not supported", container.getId()) return - UM.Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) + UM.Application.Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) @pyqtSlot() def forceUpdate(self): # Force rebuilding the build volume by reloading the global container stack. # This is a bit of a hack, but it seems quick enough. - UM.Application.getInstance().globalContainerStackChanged.emit() + UM.Application.Application.getInstance().globalContainerStackChanged.emit() @pyqtSlot() def updateHasMaterialsMetadata(self): # Updates the has_materials metadata flag after switching gcode flavor - global_container_stack = UM.Application.getInstance().getGlobalContainerStack() + global_container_stack = UM.Application.Application.getInstance().getGlobalContainerStack() if global_container_stack: definition = global_container_stack.getBottom() if definition.getProperty("machine_gcode_flavor", "value") == "UltiGCode" and not definition.getMetaDataEntry("has_materials", False): diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py index b4086291ca..42b30969be 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py +++ b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py @@ -6,14 +6,14 @@ from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal from UM.Application import Application from UM.Settings.SettingInstance import SettingInstance from UM.Logger import Logger -import UM.Settings.Models +import UM.Settings.Models.SettingVisibilityHandler from cura.Settings.ExtruderManager import ExtruderManager #To get global-inherits-stack setting values from different extruders. from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator ## The per object setting visibility handler ensures that only setting # definitions that have a matching instance Container are returned as visible. -class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHandler): +class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHandler.SettingVisibilityHandler): def __init__(self, parent = None, *args, **kwargs): super().__init__(parent = parent, *args, **kwargs) diff --git a/plugins/SolidView/SolidView.py b/plugins/SolidView/SolidView.py index 3e3501a83f..d5995a1390 100644 --- a/plugins/SolidView/SolidView.py +++ b/plugins/SolidView/SolidView.py @@ -13,6 +13,7 @@ from UM.Settings.Validator import ValidatorState from UM.View.GL.OpenGL import OpenGL import cura.Settings +import cura.Settings.ExtrudersModel import math @@ -26,7 +27,7 @@ class SolidView(View): self._enabled_shader = None self._disabled_shader = None - self._extruders_model = cura.Settings.ExtrudersModel() + self._extruders_model = cura.Settings.ExtrudersModel.ExtrudersModel() def beginRendering(self): scene = self.getController().getScene() diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py b/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py index 4ac86f9a1d..84cbc390a7 100644 --- a/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py +++ b/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py @@ -25,7 +25,7 @@ class Profile: # # \param serialised A string with the contents of a profile. # \param filename The supposed filename of the profile, without extension. - def __init__(self, serialised, filename): + def __init__(self, serialised: str, filename: str): self._filename = filename parser = configparser.ConfigParser(interpolation = None) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 77f775ee27..fabd84963a 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -11,11 +11,11 @@ from UM.Logger import Logger from UM.Util import parseBool import UM.Dictionary - -import UM.Settings +from UM.Settings.InstanceContainer import InstanceContainer +from UM.Settings.ContainerRegistry import ContainerRegistry ## Handles serializing and deserializing material containers from an XML file -class XmlMaterialProfile(UM.Settings.InstanceContainer): +class XmlMaterialProfile(InstanceContainer): def __init__(self, container_id, *args, **kwargs): super().__init__(container_id, *args, **kwargs) @@ -24,7 +24,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): base_file = self.getMetaDataEntry("base_file", None) if base_file != self.id: - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = base_file) + containers = ContainerRegistry.getInstance().findInstanceContainers(id = base_file) if containers: new_basefile = containers[0].duplicate(self.getMetaDataEntry("brand") + "_" + new_id, new_name) base_file = new_basefile.id @@ -33,14 +33,14 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): new_id = self.getMetaDataEntry("brand") + "_" + new_id + "_" + self.getDefinition().getId() variant = self.getMetaDataEntry("variant") if variant: - variant_containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = variant) + variant_containers = ContainerRegistry.getInstance().findInstanceContainers(id = variant) if variant_containers: new_id += "_" + variant_containers[0].getName().replace(" ", "_") has_base_file = True else: has_base_file = False - new_id = UM.Settings.ContainerRegistry.getInstance().createUniqueName("material", self._id, new_id, "") + new_id = ContainerRegistry.getInstance().createUniqueName("material", self._id, new_id, "") result = super().duplicate(new_id, new_name) if has_base_file: result.setMetaDataEntry("base_file", base_file) @@ -53,7 +53,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): super().setReadOnly(read_only) basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is none, this is a basefile. - for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): + for container in ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): container._read_only = read_only ## Overridden from InstanceContainer @@ -65,7 +65,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is none, this is a basefile. # Update all containers that share GUID and basefile - for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): + for container in ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): container.setMetaData(copy.deepcopy(self._metadata)) ## Overridden from InstanceContainer, similar to setMetaDataEntry. @@ -84,7 +84,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): basefile = self.getMetaDataEntry("base_file", self._id) # if basefile is none, this is a basefile. # Update the basefile as well, this is actually what we're trying to do # Update all containers that share GUID and basefile - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile) + containers = ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile) for container in containers: container.setName(new_name) @@ -96,12 +96,12 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): super().setProperty(key, property_name, property_value) basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is none, this is a basefile. - for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): + for container in ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): container._dirty = True ## Overridden from InstanceContainer def serialize(self): - registry = UM.Settings.ContainerRegistry.getInstance() + registry = ContainerRegistry.getInstance() base_file = self.getMetaDataEntry("base_file", "") if base_file and self.id != base_file: @@ -296,7 +296,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): self.addMetaDataEntry("properties", property_values) - self.setDefinition(UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id = "fdmprinter")[0]) + self.setDefinition(ContainerRegistry.getInstance().findDefinitionContainers(id = "fdmprinter")[0]) global_compatibility = True global_setting_values = {} @@ -336,7 +336,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): Logger.log("w", "Cannot create material for unknown machine %s", identifier.get("product")) continue - definitions = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id = machine_id) + definitions = ContainerRegistry.getInstance().findDefinitionContainers(id = machine_id) if not definitions: Logger.log("w", "No definition found for machine ID %s", machine_id) continue @@ -357,7 +357,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): new_material._dirty = False - UM.Settings.ContainerRegistry.getInstance().addContainer(new_material) + ContainerRegistry.getInstance().addContainer(new_material) hotends = machine.iterfind("./um:hotend", self.__namespaces) for hotend in hotends: @@ -365,10 +365,10 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): if hotend_id is None: continue - variant_containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = hotend_id) + variant_containers = ContainerRegistry.getInstance().findInstanceContainers(id = hotend_id) if not variant_containers: # It is not really properly defined what "ID" is so also search for variants by name. - variant_containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(definition = definition.id, name = hotend_id) + variant_containers = ContainerRegistry.getInstance().findInstanceContainers(definition = definition.id, name = hotend_id) if not variant_containers: Logger.log("d", "No variants found with ID or name %s for machine %s", hotend_id, definition.id) @@ -406,7 +406,7 @@ class XmlMaterialProfile(UM.Settings.InstanceContainer): new_hotend_material.setProperty(key, "value", value, definition) new_hotend_material._dirty = False - UM.Settings.ContainerRegistry.getInstance().addContainer(new_hotend_material) + ContainerRegistry.getInstance().addContainer(new_hotend_material) if not global_compatibility: # Change the type of this container so it is not shown as an option in menus. From 5884509af1f785d6c48b0af294ae9a989ecb2155 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Tue, 22 Nov 2016 11:51:18 +0100 Subject: [PATCH 002/156] More type checking fixes after the merge. CURA-2917 --- cura/QualityManager.py | 2 +- cura/Settings/ContainerManager.py | 2 +- cura/Settings/ProfilesModel.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cura/QualityManager.py b/cura/QualityManager.py index 0b4353442e..5b4d743ae9 100644 --- a/cura/QualityManager.py +++ b/cura/QualityManager.py @@ -18,7 +18,7 @@ class QualityManager: QualityManager.__instance = cls() return QualityManager.__instance - __instance = None + __instance = None # type: 'QualityManager' ## Find a quality by name for a specific machine definition and materials. # diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 91db12926d..3262f7cbb6 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -694,7 +694,7 @@ class ContainerManager(QObject): ContainerManager.__instance = cls() return ContainerManager.__instance - __instance = None + __instance = None # type: 'ContainerManager' # Factory function, used by QML @staticmethod diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index c03e074053..d60a633549 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -38,7 +38,7 @@ class ProfilesModel(InstanceContainersModel): ProfilesModel.__instance = cls() return ProfilesModel.__instance - __instance = None + __instance = None # type: 'ProfilesModel' ## Fetch the list of containers to display. # From 74e5798509b274908fc98b704fdc7848c6ab4e27 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Mon, 12 Dec 2016 16:05:35 +0100 Subject: [PATCH 003/156] Lots of import fixes. Eliminated the import hacks such as those used inside UM/Settings/__init__.py. CURA-2917 --- cura/BuildVolume.py | 6 +- cura/ConvexHullDecorator.py | 12 +-- cura/CuraApplication.py | 2 +- cura/PrinterOutputDevice.py | 6 +- cura/QualityManager.py | 32 ++++---- cura/Settings/ContainerManager.py | 78 ++++++++++--------- cura/Settings/MachineNameValidator.py | 8 +- cura/Settings/QualitySettingsModel.py | 4 +- cura/Settings/SettingInheritanceManager.py | 22 +++--- cura/Settings/SettingOverrideDecorator.py | 8 +- cura_app.py | 3 + plugins/3MFReader/ThreeMFReader.py | 3 +- .../CuraEngineBackend/CuraEngineBackend.py | 8 +- plugins/CuraEngineBackend/StartSliceJob.py | 7 +- plugins/GCodeWriter/GCodeWriter.py | 7 +- .../MachineSettingsAction.py | 28 +++---- .../PerObjectSettingVisibilityHandler.py | 3 +- .../UMOUpgradeSelection.py | 8 +- .../UpgradeFirmwareMachineAction.py | 13 ++-- .../XmlMaterialProfile/XmlMaterialProfile.py | 4 +- 20 files changed, 134 insertions(+), 128 deletions(-) diff --git a/cura/BuildVolume.py b/cura/BuildVolume.py index 603cda14d1..5fb2a82d36 100644 --- a/cura/BuildVolume.py +++ b/cura/BuildVolume.py @@ -2,6 +2,7 @@ # Cura is released under the terms of the AGPLv3 or higher. from cura.Settings.ExtruderManager import ExtruderManager +from UM.Settings.ContainerRegistry import ContainerRegistry from UM.i18n import i18nCatalog from UM.Scene.Platform import Platform from UM.Scene.Iterator.BreadthFirstIterator import BreadthFirstIterator @@ -23,9 +24,6 @@ catalog = i18nCatalog("cura") import numpy import copy -import UM.Settings.ContainerRegistry - - # Setting for clearance around the prime PRIME_CLEARANCE = 6.5 @@ -663,7 +661,7 @@ class BuildVolume(SceneNode): return self._global_container_stack.getProperty(setting_key, property) extruder_stack_id = ExtruderManager.getInstance().extruderIds[str(extruder_index)] - stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] + stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] return stack.getProperty(setting_key, property) ## Convenience function to calculate the disallowed radius around the edge. diff --git a/cura/ConvexHullDecorator.py b/cura/ConvexHullDecorator.py index c4b2fe0337..65c799619a 100644 --- a/cura/ConvexHullDecorator.py +++ b/cura/ConvexHullDecorator.py @@ -1,13 +1,13 @@ # Copyright (c) 2016 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. -from UM.Scene.SceneNodeDecorator import SceneNodeDecorator from UM.Application import Application -from cura.Settings.ExtruderManager import ExtruderManager from UM.Math.Polygon import Polygon -from . import ConvexHullNode +from UM.Scene.SceneNodeDecorator import SceneNodeDecorator +from UM.Settings.ContainerRegistry import ContainerRegistry -import UM.Settings.ContainerRegistry +from cura.Settings.ExtruderManager import ExtruderManager +from . import ConvexHullNode import numpy @@ -308,11 +308,11 @@ class ConvexHullDecorator(SceneNodeDecorator): extruder_stack_id = self._node.callDecoration("getActiveExtruder") if not extruder_stack_id: #Decoration doesn't exist. extruder_stack_id = ExtruderManager.getInstance().extruderIds["0"] - extruder_stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] + extruder_stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] return extruder_stack.getProperty(setting_key, property) else: #Limit_to_extruder is set. Use that one. extruder_stack_id = ExtruderManager.getInstance().extruderIds[str(extruder_index)] - stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] + stack = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0] return stack.getProperty(setting_key, property) ## Returns true if node is a descendant or the same as the root node. diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 0a121deeb4..5019519c53 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -124,7 +124,6 @@ class CuraApplication(QtApplication): Q_ENUMS(ResourceTypes) def __init__(self): - super().__init__(name = "cura", version = CuraVersion, buildtype = CuraBuildType) Resources.addSearchPath(os.path.join(QtApplication.getInstallPrefix(), "share", "cura", "resources")) if not hasattr(sys, "frozen"): @@ -187,6 +186,7 @@ class CuraApplication(QtApplication): self._additional_components = {} # Components to add to certain areas in the interface + super().__init__(name = "cura", version = CuraVersion, buildtype = CuraBuildType) self.setWindowIcon(QIcon(Resources.getPath(Resources.Images, "cura-icon.png"))) diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index 6eae259e1e..fc27b0a471 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -2,11 +2,11 @@ from UM.i18n import i18nCatalog from UM.OutputDevice.OutputDevice import OutputDevice from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject from PyQt5.QtWidgets import QMessageBox -import UM.Settings.ContainerRegistry + +from UM.Settings.ContainerRegistry import ContainerRegistry from enum import IntEnum # For the connection state tracking. from UM.Logger import Logger -from UM.Application import Application from UM.Signal import signalemitter i18n_catalog = i18nCatalog("cura") @@ -25,7 +25,7 @@ class PrinterOutputDevice(QObject, OutputDevice): def __init__(self, device_id, parent = None): super().__init__(device_id = device_id, parent = parent) - self._container_registry = UM.Settings.ContainerRegistry.getInstance() + self._container_registry = ContainerRegistry.getInstance() self._target_bed_temperature = 0 self._bed_temperature = 0 self._num_extruders = 1 diff --git a/cura/QualityManager.py b/cura/QualityManager.py index 5b4d743ae9..dc23b2bafa 100644 --- a/cura/QualityManager.py +++ b/cura/QualityManager.py @@ -1,12 +1,16 @@ # Copyright (c) 2016 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. -import UM.Application -import cura.Settings.ExtruderManager -import UM.Settings.ContainerRegistry - # This collects a lot of quality and quality changes related code which was split between ContainerManager # and the MachineManager and really needs to usable from both. +from typing import List + +from UM.Application import Application +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.DefinitionContainer import DefinitionContainer +from UM.Settings.InstanceContainer import InstanceContainer +from cura.Settings.ExtruderManager import ExtruderManager + class QualityManager: @@ -121,14 +125,14 @@ class QualityManager: # # \param machine_definition \type{DefinitionContainer} the machine definition. # \return \type{List[InstanceContainer]} the list of quality changes - def findAllQualityChangesForMachine(self, machine_definition): + def findAllQualityChangesForMachine(self, machine_definition: DefinitionContainer) -> List[InstanceContainer]: if machine_definition.getMetaDataEntry("has_machine_quality"): definition_id = machine_definition.getId() else: definition_id = "fdmprinter" filter_dict = { "type": "quality_changes", "extruder": None, "definition": definition_id } - quality_changes_list = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**filter_dict) + quality_changes_list = ContainerRegistry.getInstance().findInstanceContainers(**filter_dict) return quality_changes_list ## Find all usable qualities for a machine and extruders. @@ -177,7 +181,7 @@ class QualityManager: if base_material: # There is a basic material specified criteria = { "type": "material", "name": base_material, "definition": definition_id } - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria) containers = [basic_material for basic_material in containers if basic_material.getMetaDataEntry("variant") == material_container.getMetaDataEntry( "variant")] @@ -191,13 +195,13 @@ class QualityManager: def _getFilteredContainersForStack(self, machine_definition=None, material_containers=None, **kwargs): # Fill in any default values. if machine_definition is None: - machine_definition = UM.Application.getInstance().getGlobalContainerStack().getBottom() + machine_definition = Application.getInstance().getGlobalContainerStack().getBottom() quality_definition_id = machine_definition.getMetaDataEntry("quality_definition") if quality_definition_id is not None: - machine_definition = UM.Settings.ContainerRegistry.getInstance().findDefinitionContainers(id=quality_definition_id)[0] + machine_definition = ContainerRegistry.getInstance().findDefinitionContainers(id=quality_definition_id)[0] if material_containers is None: - active_stacks = cura.Settings.ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() + active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks() material_containers = [stack.findContainer(type="material") for stack in active_stacks] criteria = kwargs @@ -222,7 +226,7 @@ class QualityManager: if material_instance is not None: material_ids.add(material_instance.getId()) - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria) result = [] for container in containers: @@ -238,8 +242,8 @@ class QualityManager: # an extruder definition. # \return \type{DefinitionContainer} the parent machine definition. If the given machine # definition doesn't have a parent then it is simply returned. - def getParentMachineDefinition(self, machine_definition): - container_registry = UM.Settings.ContainerRegistry.getInstance() + def getParentMachineDefinition(self, machine_definition: DefinitionContainer) -> DefinitionContainer: + container_registry = ContainerRegistry.getInstance() machine_entry = machine_definition.getMetaDataEntry("machine") if machine_entry is None: @@ -274,6 +278,6 @@ class QualityManager: # This already is a 'global' machine definition. return machine_definition else: - container_registry = UM.Settings.ContainerRegistry.getInstance() + container_registry = ContainerRegistry.getInstance() whole_machine = container_registry.findDefinitionContainers(id=machine_entry)[0] return whole_machine diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 3262f7cbb6..eec4e2da1c 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -7,13 +7,15 @@ import urllib from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal, QUrl, QVariant from PyQt5.QtWidgets import QMessageBox -import UM.PluginRegistry +from UM.PluginRegistry import PluginRegistry import UM.SaveFile import UM.Platform import UM.MimeTypeDatabase -import UM.Logger +from UM.Logger import Logger from UM.Application import Application +from UM.Settings.ContainerStack import ContainerStack +from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Settings.InstanceContainer import InstanceContainer from cura.QualityManager import QualityManager @@ -35,7 +37,7 @@ class ContainerManager(QObject): def __init__(self, parent = None): super().__init__(parent) - self._registry = ContainerRegistry.getInstance() + self._container_registry = ContainerRegistry.getInstance() self._machine_manager = Application.getInstance().getMachineManager() self._container_name_filters = {} @@ -51,7 +53,7 @@ class ContainerManager(QObject): def duplicateContainer(self, container_id): containers = self._container_registry.findContainers(None, id = container_id) if not containers: - UM.Logger.log("w", "Could duplicate container %s because it was not found.", container_id) + Logger.log("w", "Could duplicate container %s because it was not found.", container_id) return "" container = containers[0] @@ -83,7 +85,7 @@ class ContainerManager(QObject): def renameContainer(self, container_id, new_id, new_name): containers = self._container_registry.findContainers(None, id = container_id) if not containers: - UM.Logger.log("w", "Could rename container %s because it was not found.", container_id) + Logger.log("w", "Could rename container %s because it was not found.", container_id) return False container = containers[0] @@ -111,7 +113,7 @@ class ContainerManager(QObject): def removeContainer(self, container_id): containers = self._container_registry.findContainers(None, id = container_id) if not containers: - UM.Logger.log("w", "Could remove container %s because it was not found.", container_id) + Logger.log("w", "Could remove container %s because it was not found.", container_id) return False self._container_registry.removeContainer(containers[0].getId()) @@ -131,20 +133,20 @@ class ContainerManager(QObject): def mergeContainers(self, merge_into_id, merge_id): containers = self._container_registry.findContainers(None, id = merge_into_id) if not containers: - UM.Logger.log("w", "Could merge into container %s because it was not found.", merge_into_id) + Logger.log("w", "Could merge into container %s because it was not found.", merge_into_id) return False merge_into = containers[0] containers = self._container_registry.findContainers(None, id = merge_id) if not containers: - UM.Logger.log("w", "Could not merge container %s because it was not found", merge_id) + Logger.log("w", "Could not merge container %s because it was not found", merge_id) return False merge = containers[0] if not isinstance(merge, type(merge_into)): - UM.Logger.log("w", "Cannot merge two containers of different types") + Logger.log("w", "Cannot merge two containers of different types") return False self._performMerge(merge_into, merge) @@ -160,11 +162,11 @@ class ContainerManager(QObject): def clearContainer(self, container_id): containers = self._container_registry.findContainers(None, id = container_id) if not containers: - UM.Logger.log("w", "Could clear container %s because it was not found.", container_id) + Logger.log("w", "Could clear container %s because it was not found.", container_id) return False if containers[0].isReadOnly(): - UM.Logger.log("w", "Cannot clear read-only container %s", container_id) + Logger.log("w", "Cannot clear read-only container %s", container_id) return False containers[0].clear() @@ -175,7 +177,7 @@ class ContainerManager(QObject): def getContainerMetaDataEntry(self, container_id, entry_name): containers = self._container_registry.findContainers(None, id=container_id) if not containers: - UM.Logger.log("w", "Could not get metadata of container %s because it was not found.", container_id) + Logger.log("w", "Could not get metadata of container %s because it was not found.", container_id) return "" result = containers[0].getMetaDataEntry(entry_name) @@ -200,13 +202,13 @@ class ContainerManager(QObject): def setContainerMetaDataEntry(self, container_id, entry_name, entry_value): containers = self._container_registry.findContainers(None, id = container_id) if not containers: - UM.Logger.log("w", "Could not set metadata of container %s because it was not found.", container_id) + Logger.log("w", "Could not set metadata of container %s because it was not found.", container_id) return False container = containers[0] if container.isReadOnly(): - UM.Logger.log("w", "Cannot set metadata of read-only container %s.", container_id) + Logger.log("w", "Cannot set metadata of read-only container %s.", container_id) return False entries = entry_name.split("/") @@ -234,13 +236,13 @@ class ContainerManager(QObject): def setContainerName(self, container_id, new_name): containers = self._container_registry.findContainers(None, id = container_id) if not containers: - UM.Logger.log("w", "Could not set name of container %s because it was not found.", container_id) + Logger.log("w", "Could not set name of container %s because it was not found.", container_id) return False container = containers[0] if container.isReadOnly(): - UM.Logger.log("w", "Cannot set name of read-only container %s.", container_id) + Logger.log("w", "Cannot set name of read-only container %s.", container_id) return False container.setName(new_name) @@ -264,11 +266,11 @@ class ContainerManager(QObject): @pyqtSlot(str, result = bool) def isContainerUsed(self, container_id): - UM.Logger.log("d", "Checking if container %s is currently used", container_id) + Logger.log("d", "Checking if container %s is currently used", container_id) containers = self._container_registry.findContainerStacks() for stack in containers: if container_id in [child.getId() for child in stack.getContainers()]: - UM.Logger.log("d", "The container is in use by %s", stack.getId()) + Logger.log("d", "The container is in use by %s", stack.getId()) return True return False @@ -423,7 +425,7 @@ class ContainerManager(QObject): # Find the quality_changes container for this stack and merge the contents of the top container into it. quality_changes = stack.findContainer(type = "quality_changes") if not quality_changes or quality_changes.isReadOnly(): - UM.Logger.log("e", "Could not update quality of a nonexistant or read only quality profile in stack %s", stack.getId()) + Logger.log("e", "Could not update quality of a nonexistant or read only quality profile in stack %s", stack.getId()) continue self._performMerge(quality_changes, stack.getTop()) @@ -457,13 +459,13 @@ class ContainerManager(QObject): # \return \type{bool} True if the operation was successfully, False if not. @pyqtSlot(str, result = bool) def createQualityChanges(self, base_name): - global_stack = UM.Application.getInstance().getGlobalContainerStack() + global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack: return False active_quality_name = self._machine_manager.activeQualityName if active_quality_name == "": - UM.Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) + Logger.log("w", "No quality container found in stack %s, cannot create profile", global_stack.getId()) return False self._machine_manager.blurSettings.emit() @@ -477,12 +479,12 @@ class ContainerManager(QObject): quality_container = stack.findContainer(type = "quality") quality_changes_container = stack.findContainer(type = "quality_changes") if not quality_container or not quality_changes_container: - UM.Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId()) + Logger.log("w", "No quality or quality changes container found in stack %s, ignoring it", stack.getId()) continue extruder_id = None if stack is global_stack else QualityManager.getInstance().getParentMachineDefinition(stack.getBottom()).getId() new_changes = self._createQualityChanges(quality_container, unique_name, - UM.Application.getInstance().getGlobalContainerStack().getBottom(), + Application.getInstance().getGlobalContainerStack().getBottom(), extruder_id) self._performMerge(new_changes, quality_changes_container, clear_settings = False) self._performMerge(new_changes, user_container) @@ -504,7 +506,7 @@ class ContainerManager(QObject): # \return \type{bool} True if successful, False if not. @pyqtSlot(str, result = bool) def removeQualityChanges(self, quality_name): - UM.Logger.log("d", "Attempting to remove the quality change containers with name %s", quality_name) + Logger.log("d", "Attempting to remove the quality change containers with name %s", quality_name) containers_found = False if not quality_name: @@ -514,7 +516,7 @@ class ContainerManager(QObject): activate_quality = quality_name == self._machine_manager.activeQualityName activate_quality_type = None - global_stack = UM.Application.getInstance().getGlobalContainerStack() + global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack or not quality_name: return "" machine_definition = global_stack.getBottom() @@ -526,7 +528,7 @@ class ContainerManager(QObject): self._container_registry.removeContainer(container.getId()) if not containers_found: - UM.Logger.log("d", "Unable to remove quality containers, as we did not find any by the name of %s", quality_name) + Logger.log("d", "Unable to remove quality containers, as we did not find any by the name of %s", quality_name) elif activate_quality: definition_id = "fdmprinter" if not self._machine_manager.filterQualityByMachine else self._machine_manager.activeDefinitionId @@ -549,15 +551,15 @@ class ContainerManager(QObject): # \return True if successful, False if not. @pyqtSlot(str, str, result = bool) def renameQualityChanges(self, quality_name, new_name): - UM.Logger.log("d", "User requested QualityChanges container rename of %s to %s", quality_name, new_name) + Logger.log("d", "User requested QualityChanges container rename of %s to %s", quality_name, new_name) if not quality_name or not new_name: return False if quality_name == new_name: - UM.Logger.log("w", "Unable to rename %s to %s, because they are the same.", quality_name, new_name) + Logger.log("w", "Unable to rename %s to %s, because they are the same.", quality_name, new_name) return True - global_stack = UM.Application.getInstance().getGlobalContainerStack() + global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack: return False @@ -574,7 +576,7 @@ class ContainerManager(QObject): container_registry.renameContainer(container.getId(), new_name, self._createUniqueId(stack_id, new_name)) if not containers_to_rename: - UM.Logger.log("e", "Unable to rename %s, because we could not find the profile", quality_name) + Logger.log("e", "Unable to rename %s, because we could not find the profile", quality_name) self._machine_manager.activeQualityChanged.emit() return True @@ -590,7 +592,7 @@ class ContainerManager(QObject): # \return A string containing the name of the duplicated containers, or an empty string if it failed. @pyqtSlot(str, str, result = str) def duplicateQualityOrQualityChanges(self, quality_name, base_name): - global_stack = UM.Application.getInstance().getGlobalContainerStack() + global_stack = Application.getInstance().getGlobalContainerStack() if not global_stack or not quality_name: return "" machine_definition = global_stack.getBottom() @@ -611,16 +613,16 @@ class ContainerManager(QObject): # \param material_instances \type{List[InstanceContainer]} # \return \type{str} the name of the newly created container. def _duplicateQualityOrQualityChangesForMachineType(self, quality_name, base_name, machine_definition, material_instances): - UM.Logger.log("d", "Attempting to duplicate the quality %s", quality_name) + Logger.log("d", "Attempting to duplicate the quality %s", quality_name) if base_name is None: base_name = quality_name # Try to find a Quality with the name. container = QualityManager.getInstance().findQualityByName(quality_name, machine_definition, material_instances) if container: - UM.Logger.log("d", "We found a quality to duplicate.") + Logger.log("d", "We found a quality to duplicate.") return self._duplicateQualityForMachineType(container, base_name, machine_definition) - UM.Logger.log("d", "We found a quality_changes to duplicate.") + Logger.log("d", "We found a quality_changes to duplicate.") # Assume it is a quality changes. return self._duplicateQualityChangesForMachineType(quality_name, base_name, machine_definition) @@ -667,11 +669,11 @@ class ContainerManager(QObject): def duplicateMaterial(self, material_id): containers = self._container_registry.findInstanceContainers(id=material_id) if not containers: - UM.Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", material_id) + Logger.log("d", "Unable to duplicate the material with id %s, because it doesn't exist.", material_id) return "" # Ensure all settings are saved. - UM.Application.getInstance().saveSettings() + Application.getInstance().saveSettings() # Create a new ID & container to hold the data. new_id = self._container_registry.uniqueName(material_id) @@ -717,12 +719,12 @@ class ContainerManager(QObject): self._container_name_filters = {} for plugin_id, container_type in self._container_registry.getContainerTypes(): # Ignore default container types since those are not plugins - if container_type in (UM.Settings.InstanceContainer, UM.Settings.ContainerStack, UM.Settings.DefinitionContainer): + if container_type in (InstanceContainer, ContainerStack, DefinitionContainer): continue serialize_type = "" try: - plugin_metadata = UM.PluginRegistry.getInstance().getMetaData(plugin_id) + plugin_metadata = PluginRegistry.getInstance().getMetaData(plugin_id) if plugin_metadata: serialize_type = plugin_metadata["settings_container"]["type"] else: diff --git a/cura/Settings/MachineNameValidator.py b/cura/Settings/MachineNameValidator.py index 34b6351144..68782a2148 100644 --- a/cura/Settings/MachineNameValidator.py +++ b/cura/Settings/MachineNameValidator.py @@ -7,8 +7,8 @@ import os #For statvfs. import urllib #To escape machine names for how they're saved to file. import UM.Resources -import UM.Settings.ContainerRegistry -import UM.Settings.InstanceContainer +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.InstanceContainer import InstanceContainer ## Are machine names valid? # @@ -22,7 +22,7 @@ class MachineNameValidator(QObject): filename_max_length = os.statvfs(UM.Resources.getDataStoragePath()).f_namemax except AttributeError: #Doesn't support statvfs. Probably because it's not a Unix system. filename_max_length = 255 #Assume it's Windows on NTFS. - machine_name_max_length = filename_max_length - len("_current_settings.") - len(UM.Settings.ContainerRegistry.getMimeTypeForContainer(UM.Settings.InstanceContainer).preferredSuffix) + machine_name_max_length = filename_max_length - len("_current_settings.") - len(ContainerRegistry.getMimeTypeForContainer(InstanceContainer).preferredSuffix) # Characters that urllib.parse.quote_plus escapes count for 12! So now # we must devise a regex that allows only 12 normal characters or 1 # special character, and that up to [machine_name_max_length / 12] times. @@ -45,7 +45,7 @@ class MachineNameValidator(QObject): except AttributeError: #Doesn't support statvfs. Probably because it's not a Unix system. filename_max_length = 255 #Assume it's Windows on NTFS. escaped_name = urllib.parse.quote_plus(name) - current_settings_filename = escaped_name + "_current_settings." + UM.Settings.ContainerRegistry.getMimeTypeForContainer(UM.Settings.InstanceContainer).preferredSuffix + current_settings_filename = escaped_name + "_current_settings." + ContainerRegistry.getMimeTypeForContainer(InstanceContainer).preferredSuffix if len(current_settings_filename) > filename_max_length: return QValidator.Invalid diff --git a/cura/Settings/QualitySettingsModel.py b/cura/Settings/QualitySettingsModel.py index a00b47c12b..085c0f054c 100644 --- a/cura/Settings/QualitySettingsModel.py +++ b/cura/Settings/QualitySettingsModel.py @@ -88,7 +88,7 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): items = [] settings = collections.OrderedDict() - definition_container = UM.Application.getInstance().getGlobalContainerStack().getBottom() + definition_container = Application.getInstance().getGlobalContainerStack().getBottom() containers = self._container_registry.findInstanceContainers(id = self._quality_id) if not containers: @@ -116,7 +116,7 @@ class QualitySettingsModel(UM.Qt.ListModel.ListModel): quality_container = quality_container[0] quality_type = quality_container.getMetaDataEntry("quality_type") - definition_id = UM.Application.getInstance().getMachineManager().getQualityDefinitionId(quality_container.getDefinition()) + definition_id = Application.getInstance().getMachineManager().getQualityDefinitionId(quality_container.getDefinition()) criteria = {"type": "quality", "quality_type": quality_type, "definition": definition_id} diff --git a/cura/Settings/SettingInheritanceManager.py b/cura/Settings/SettingInheritanceManager.py index 4d1e60a739..49a465c37d 100644 --- a/cura/Settings/SettingInheritanceManager.py +++ b/cura/Settings/SettingInheritanceManager.py @@ -2,9 +2,7 @@ # Cura is released under the terms of the AGPLv3 or higher. from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal -import UM.Settings from UM.Application import Application -import cura.Settings from UM.Logger import Logger @@ -13,6 +11,12 @@ from UM.Logger import Logger # because some profiles tend to have 'hardcoded' values that break our inheritance. A good example of that are the # speed settings. If all the children of print_speed have a single value override, changing the speed won't # actually do anything, as only the 'leaf' settings are used by the engine. +from UM.Settings.ContainerStack import ContainerStack +from UM.Settings.SettingFunction import SettingFunction +from UM.Settings.SettingInstance import InstanceState + +from cura.Settings.ExtruderManager import ExtruderManager + class SettingInheritanceManager(QObject): def __init__(self, parent = None): super().__init__(parent) @@ -22,7 +26,7 @@ class SettingInheritanceManager(QObject): self._active_container_stack = None self._onGlobalContainerChanged() - cura.Settings.ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged) + ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged) self._onActiveExtruderChanged() settingsWithIntheritanceChanged = pyqtSignal() @@ -44,7 +48,7 @@ class SettingInheritanceManager(QObject): multi_extrusion = self._global_container_stack.getProperty("machine_extruder_count", "value") > 1 if not multi_extrusion: return self._settings_with_inheritance_warning - extruder = cura.Settings.ExtruderManager.getInstance().getExtruderStack(extruder_index) + extruder = ExtruderManager.getInstance().getExtruderStack(extruder_index) if not extruder: Logger.log("w", "Unable to find extruder for current machine with index %s", extruder_index) return [] @@ -70,7 +74,7 @@ class SettingInheritanceManager(QObject): self._update() def _onActiveExtruderChanged(self): - new_active_stack = cura.Settings.ExtruderManager.getInstance().getActiveExtruderStack() + new_active_stack = ExtruderManager.getInstance().getActiveExtruderStack() if not new_active_stack: new_active_stack = self._global_container_stack @@ -136,14 +140,14 @@ class SettingInheritanceManager(QObject): return self._settings_with_inheritance_warning ## Check if a setting has an inheritance function that is overwritten - def _settingIsOverwritingInheritance(self, key, stack = None): + def _settingIsOverwritingInheritance(self, key: str, stack: ContainerStack = None) -> bool: has_setting_function = False if not stack: stack = self._active_container_stack containers = [] ## Check if the setting has a user state. If not, it is never overwritten. - has_user_state = stack.getProperty(key, "state") == UM.Settings.InstanceState.User + has_user_state = stack.getProperty(key, "state") == InstanceState.User if not has_user_state: return False @@ -152,7 +156,7 @@ class SettingInheritanceManager(QObject): return False ## Also check if the top container is not a setting function (this happens if the inheritance is restored). - if isinstance(stack.getTop().getProperty(key, "value"), UM.Settings.SettingFunction): + if isinstance(stack.getTop().getProperty(key, "value"), SettingFunction): return False ## Mash all containers for all the stacks together. @@ -167,7 +171,7 @@ class SettingInheritanceManager(QObject): continue if value is not None: # If a setting doesn't use any keys, it won't change it's value, so treat it as if it's a fixed value - has_setting_function = isinstance(value, UM.Settings.SettingFunction) and len(value.getUsedSettingKeys()) > 0 + has_setting_function = isinstance(value, SettingFunction) and len(value.getUsedSettingKeys()) > 0 if has_setting_function is False: has_non_function_value = True continue diff --git a/cura/Settings/SettingOverrideDecorator.py b/cura/Settings/SettingOverrideDecorator.py index d38dac565b..d5f4ef7b14 100644 --- a/cura/Settings/SettingOverrideDecorator.py +++ b/cura/Settings/SettingOverrideDecorator.py @@ -10,10 +10,10 @@ from UM.Settings.InstanceContainer import InstanceContainer from UM.Settings.ContainerRegistry import ContainerRegistry import UM.Logger -import cura.Settings - from UM.Application import Application +from cura.Settings.ExtruderManager import ExtruderManager + ## A decorator that adds a container stack to a Node. This stack should be queried for all settings regarding # the linked node. The Stack in question will refer to the global stack (so that settings that are not defined by # this stack still resolve. @@ -29,8 +29,8 @@ class SettingOverrideDecorator(SceneNodeDecorator): self._instance = InstanceContainer(container_id = "SettingOverrideInstanceContainer") self._stack.addContainer(self._instance) - if cura.Settings.ExtruderManager.getInstance().extruderCount > 1: - self._extruder_stack = cura.Settings.ExtruderManager.getInstance().getExtruderStack(0).getId() + if ExtruderManager.getInstance().extruderCount > 1: + self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId() else: self._extruder_stack = None diff --git a/cura_app.py b/cura_app.py index 6c75e49fb7..c6f7e27065 100755 --- a/cura_app.py +++ b/cura_app.py @@ -55,5 +55,8 @@ if Platform.isWindows() and hasattr(sys, "frozen"): sys.stdout = open(os.path.join(dirpath, "stdout.log"), "w") sys.stderr = open(os.path.join(dirpath, "stderr.log"), "w") +# Force an instance of CuraContainerRegistry to be created and reused later. +cura.Settings.CuraContainerRegistry.CuraContainerRegistry.getInstance() + app = cura.CuraApplication.CuraApplication.getInstance() app.run() diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 2aa719018d..cd263b210f 100644 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -8,7 +8,6 @@ from UM.Math.Matrix import Matrix from UM.Math.Vector import Vector from UM.Scene.SceneNode import SceneNode from UM.Scene.GroupDecorator import GroupDecorator -import UM.Application from UM.Job import Job from cura.Settings.SettingOverrideDecorator import SettingOverrideDecorator from UM.Application import Application @@ -188,7 +187,7 @@ class ThreeMFReader(MeshReader): transform = build_item.get("transform") if transform is not None: build_item_node.setTransformation(self._createMatrixFromTransformationString(transform)) - global_container_stack = UM.Application.getInstance().getGlobalContainerStack() + global_container_stack = Application.getInstance().getGlobalContainerStack() # Create a transformation Matrix to convert from 3mf worldspace into ours. # First step: flip the y and z axis. diff --git a/plugins/CuraEngineBackend/CuraEngineBackend.py b/plugins/CuraEngineBackend/CuraEngineBackend.py index d7e1bce52b..6bf05b363c 100644 --- a/plugins/CuraEngineBackend/CuraEngineBackend.py +++ b/plugins/CuraEngineBackend/CuraEngineBackend.py @@ -13,12 +13,8 @@ from UM.Resources import Resources from UM.Settings.Validator import ValidatorState #To find if a setting is in an error state. We can't slice then. from UM.Platform import Platform -import cura.Settings - -from cura.OneAtATimeIterator import OneAtATimeIterator from cura.Settings.ExtruderManager import ExtruderManager from . import ProcessSlicedLayersJob -from . import ProcessGCodeJob from . import StartSliceJob import os @@ -82,7 +78,7 @@ class CuraEngineBackend(Backend): self._onGlobalStackChanged() self._active_extruder_stack = None - cura.Settings.ExtruderManager.ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged) + ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged) self._onActiveExtruderChanged() # When you update a setting and other settings get changed through inheritance, many propertyChanged signals are fired. @@ -484,7 +480,7 @@ class CuraEngineBackend(Backend): if self._active_extruder_stack: self._active_extruder_stack.containersChanged.disconnect(self._onChanged) - self._active_extruder_stack = cura.Settings.ExtruderManager.ExtruderManager.getInstance().getActiveExtruderStack() + self._active_extruder_stack = ExtruderManager.getInstance().getActiveExtruderStack() if self._active_extruder_stack: self._active_extruder_stack.containersChanged.connect(self._onChanged) diff --git a/plugins/CuraEngineBackend/StartSliceJob.py b/plugins/CuraEngineBackend/StartSliceJob.py index 0319186518..8efa50105f 100644 --- a/plugins/CuraEngineBackend/StartSliceJob.py +++ b/plugins/CuraEngineBackend/StartSliceJob.py @@ -16,8 +16,7 @@ from UM.Settings.Validator import ValidatorState from UM.Settings.SettingRelation import RelationType from cura.OneAtATimeIterator import OneAtATimeIterator - -import cura.Settings +from cura.Settings.ExtruderManager import ExtruderManager class StartJobResult(IntEnum): Finished = 1 @@ -84,7 +83,7 @@ class StartSliceJob(Job): self.setResult(StartJobResult.BuildPlateError) return - for extruder_stack in cura.Settings.ExtruderManager.getInstance().getMachineExtruders(stack.getId()): + for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()): material = extruder_stack.findContainer({"type": "material"}) if material: if material.getMetaDataEntry("compatible") == False: @@ -149,7 +148,7 @@ class StartSliceJob(Job): self._buildGlobalSettingsMessage(stack) self._buildGlobalInheritsStackMessage(stack) - for extruder_stack in cura.Settings.ExtruderManager.getInstance().getMachineExtruders(stack.getId()): + for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(stack.getId()): self._buildExtruderMessage(extruder_stack) for group in object_groups: diff --git a/plugins/GCodeWriter/GCodeWriter.py b/plugins/GCodeWriter/GCodeWriter.py index d503f547b0..162738f073 100644 --- a/plugins/GCodeWriter/GCodeWriter.py +++ b/plugins/GCodeWriter/GCodeWriter.py @@ -4,13 +4,10 @@ from UM.Mesh.MeshWriter import MeshWriter from UM.Logger import Logger from UM.Application import Application -import UM.Settings.ContainerRegistry - -from cura.CuraApplication import CuraApplication -from cura.Settings.ExtruderManager import ExtruderManager - from UM.Settings.InstanceContainer import InstanceContainer +from cura.Settings.ExtruderManager import ExtruderManager + import re #For escaping characters in the settings. import json import copy diff --git a/plugins/MachineSettingsAction/MachineSettingsAction.py b/plugins/MachineSettingsAction/MachineSettingsAction.py index 56206e010f..13b00b2fd7 100644 --- a/plugins/MachineSettingsAction/MachineSettingsAction.py +++ b/plugins/MachineSettingsAction/MachineSettingsAction.py @@ -4,13 +4,15 @@ from PyQt5.QtCore import pyqtSlot from cura.MachineAction import MachineAction -import cura.Settings.CuraContainerRegistry -import UM.Application -import UM.Settings.InstanceContainer -import UM.Settings.DefinitionContainer +from UM.Application import Application +from UM.Settings.InstanceContainer import InstanceContainer +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.DefinitionContainer import DefinitionContainer from UM.Logger import Logger +from cura.Settings.CuraContainerRegistry import CuraContainerRegistry + import UM.i18n catalog = UM.i18n.i18nCatalog("cura") @@ -19,10 +21,10 @@ class MachineSettingsAction(MachineAction): super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings")) self._qml_url = "MachineSettingsAction.qml" - cura.Settings.CuraContainerRegistry.CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) + CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) def _reset(self): - global_container_stack = UM.Application.Application.getInstance().getGlobalContainerStack() + global_container_stack = Application.Application.getInstance().getGlobalContainerStack() if global_container_stack: variant = global_container_stack.findContainer({"type": "variant"}) if variant and variant.getId() == "empty_variant": @@ -31,10 +33,10 @@ class MachineSettingsAction(MachineAction): def _createVariant(self, global_container_stack, variant_index): # Create and switch to a variant to store the settings in - new_variant = UM.Settings.InstanceContainer(global_container_stack.getName() + "_variant") + new_variant = InstanceContainer(global_container_stack.getName() + "_variant") new_variant.addMetaDataEntry("type", "variant") new_variant.setDefinition(global_container_stack.getBottom()) - UM.Settings.ContainerRegistry.getInstance().addContainer(new_variant) + ContainerRegistry.getInstance().addContainer(new_variant) global_container_stack.replaceContainer(variant_index, new_variant) def _onContainerAdded(self, container): @@ -49,13 +51,13 @@ class MachineSettingsAction(MachineAction): Logger.log("d", "Not attaching MachineSettingsAction to %s; Machines that use variants are not supported", container.getId()) return - UM.Application.Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) + Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) @pyqtSlot() def forceUpdate(self): # Force rebuilding the build volume by reloading the global container stack. # This is a bit of a hack, but it seems quick enough. - UM.Application.Application.getInstance().globalContainerStackChanged.emit() + Application.getInstance().globalContainerStackChanged.emit() @pyqtSlot() def updateHasMaterialsMetadata(self): @@ -78,7 +80,7 @@ class MachineSettingsAction(MachineAction): # Set the material container to a sane default if material_container.getId() == "empty_material": search_criteria = { "type": "material", "definition": "fdmprinter", "id": "*pla*" } - containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) + containers = ContainerRegistry.getInstance().findInstanceContainers(**search_criteria) if containers: global_container_stack.replaceContainer(material_index, containers[0]) else: @@ -87,7 +89,7 @@ class MachineSettingsAction(MachineAction): if "has_materials" in global_container_stack.getMetaData(): global_container_stack.removeMetaDataEntry("has_materials") - empty_material = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id = "empty_material")[0] + empty_material = ContainerRegistry.getInstance().findInstanceContainers(id = "empty_material")[0] global_container_stack.replaceContainer(material_index, empty_material) - UM.Application.getInstance().globalContainerStackChanged.emit() \ No newline at end of file + Application.getInstance().globalContainerStackChanged.emit() \ No newline at end of file diff --git a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py index 08532ef61b..b283608cb0 100644 --- a/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py +++ b/plugins/PerObjectSettingsTool/PerObjectSettingVisibilityHandler.py @@ -4,6 +4,7 @@ from PyQt5.QtCore import QObject, pyqtProperty, pyqtSignal from UM.Application import Application +from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.SettingInstance import SettingInstance from UM.Logger import Logger import UM.Settings.Models.SettingVisibilityHandler @@ -72,7 +73,7 @@ class PerObjectSettingVisibilityHandler(UM.Settings.Models.SettingVisibilityHand # Use the found stack number to get the right stack to copy the value from. if stack_nr in ExtruderManager.getInstance().extruderIds: - stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = ExtruderManager.getInstance().extruderIds[stack_nr])[0] + stack = ContainerRegistry.getInstance().findContainerStacks(id = ExtruderManager.getInstance().extruderIds[stack_nr])[0] # Use the raw property to set the value (so the inheritance doesn't break) if stack is not None: diff --git a/plugins/UltimakerMachineActions/UMOUpgradeSelection.py b/plugins/UltimakerMachineActions/UMOUpgradeSelection.py index b92dc30c68..87b2e42cd0 100644 --- a/plugins/UltimakerMachineActions/UMOUpgradeSelection.py +++ b/plugins/UltimakerMachineActions/UMOUpgradeSelection.py @@ -1,3 +1,5 @@ +from UM.Settings.ContainerRegistry import ContainerRegistry +from UM.Settings.InstanceContainer import InstanceContainer from cura.MachineAction import MachineAction from PyQt5.QtCore import pyqtSlot, pyqtSignal, pyqtProperty @@ -5,8 +7,6 @@ from UM.i18n import i18nCatalog from UM.Application import Application catalog = i18nCatalog("cura") -import UM.Settings.InstanceContainer - class UMOUpgradeSelection(MachineAction): def __init__(self): super().__init__("UMOUpgradeSelection", catalog.i18nc("@action", "Select upgrades")) @@ -37,9 +37,9 @@ class UMOUpgradeSelection(MachineAction): def _createVariant(self, global_container_stack, variant_index): # Create and switch to a variant to store the settings in - new_variant = UM.Settings.InstanceContainer(global_container_stack.getName() + "_variant") + new_variant = InstanceContainer(global_container_stack.getName() + "_variant") new_variant.addMetaDataEntry("type", "variant") new_variant.setDefinition(global_container_stack.getBottom()) - UM.Settings.ContainerRegistry.getInstance().addContainer(new_variant) + ContainerRegistry.getInstance().addContainer(new_variant) global_container_stack.replaceContainer(variant_index, new_variant) return new_variant \ No newline at end of file diff --git a/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py b/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py index 71d3f0b55b..838285969a 100644 --- a/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py +++ b/plugins/UltimakerMachineActions/UpgradeFirmwareMachineAction.py @@ -1,17 +1,18 @@ +from UM.Application import Application +from UM.Settings.DefinitionContainer import DefinitionContainer from cura.MachineAction import MachineAction from UM.i18n import i18nCatalog -import cura.Settings.CuraContainerRegistry -import UM.Settings.DefinitionContainer -catalog = i18nCatalog("cura") +from UM.Settings.ContainerRegistry import ContainerRegistry +catalog = i18nCatalog("cura") class UpgradeFirmwareMachineAction(MachineAction): def __init__(self): super().__init__("UpgradeFirmware", catalog.i18nc("@action", "Upgrade Firmware")) self._qml_url = "UpgradeFirmwareMachineAction.qml" - cura.Settings.CuraContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) + ContainerRegistry.getInstance().containerAdded.connect(self._onContainerAdded) def _onContainerAdded(self, container): # Add this action as a supported action to all machine definitions - if isinstance(container, UM.Settings.DefinitionContainer) and container.getMetaDataEntry("type") == "machine" and container.getMetaDataEntry("supports_usb_connection"): - UM.Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) + if isinstance(container, DefinitionContainer) and container.getMetaDataEntry("type") == "machine" and container.getMetaDataEntry("supports_usb_connection"): + Application.getInstance().getMachineActionManager().addSupportedAction(container.getId(), self.getKey()) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index d3a2b8deea..2ab9a58336 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -28,7 +28,7 @@ class XmlMaterialProfile(InstanceContainer): super().setReadOnly(read_only) basefile = self.getMetaDataEntry("base_file", self._id) # if basefile is self.id, this is a basefile. - for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): + for container in ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): container._read_only = read_only # prevent loop instead of calling setReadOnly ## Overridden from InstanceContainer @@ -44,7 +44,7 @@ class XmlMaterialProfile(InstanceContainer): basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is self.id, this is a basefile. # Update all containers that share GUID and basefile - for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): + for container in ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): container.setMetaDataEntry(key, value) ## Overridden from InstanceContainer, similar to setMetaDataEntry. From 61dcaf88116b7ec300fb4b00d0748cb206afff10 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Dec 2016 11:45:05 +0100 Subject: [PATCH 004/156] wip --- cura/CuraApplication.py | 4 + .../ProcessSlicedLayersJob.py | 6 + plugins/LayerView/layers.shader | 114 +++++++++++++++++- resources/shaders/overhang.shader | 53 ++++++-- 4 files changed, 164 insertions(+), 13 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 2ab7837352..17342edd7c 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -415,6 +415,8 @@ class CuraApplication(QtApplication): controller = self.getController() controller.setActiveView("SolidView") + # controller.setActiveView("LayerView") + controller.setCameraTool("CameraTool") controller.setSelectionTool("SelectionTool") @@ -455,6 +457,8 @@ class CuraApplication(QtApplication): self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles)) self.initializeEngine() + # self.callLater(controller.setActiveView, "LayerView") + if self._engine.rootObjects: self.closeSplash() diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index c4e9554b2c..d4d2ccf15e 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -85,6 +85,7 @@ class ProcessSlicedLayersJob(Job): min_layer_number = layer.id current_layer = 0 + all_normals = [] for layer in self._layers: abs_layer_number = layer.id + abs(min_layer_number) @@ -126,6 +127,9 @@ class ProcessSlicedLayersJob(Job): this_poly = LayerPolygon.LayerPolygon(layer_data, extruder, line_types, new_points, line_widths) this_poly.buildCache() + + normals = this_poly.getNormals() + all_normals.append(normals) this_layer.polygons.append(this_poly) @@ -143,7 +147,9 @@ class ProcessSlicedLayersJob(Job): if self._progress: self._progress.setProgress(progress) + # layer_data.calculateNormals() # We are done processing all the layers we got from the engine, now create a mesh out of the data + layer_data._normals = numpy.concatenate(all_normals) layer_mesh = layer_data.build() if self._abort_requested: diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 0e1f767e23..c48c56f1e7 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -1,35 +1,141 @@ [shaders] vertex = + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewProjectionMatrix; uniform highp mat4 u_modelViewProjectionMatrix; uniform lowp float u_active_extruder; uniform lowp float u_shade_factor; + uniform highp mat4 u_normalMatrix; attribute highp vec4 a_vertex; attribute lowp vec4 a_color; + attribute highp vec4 a_normal; + varying lowp vec4 v_color; + + varying highp vec3 v_vertex; + varying highp vec3 v_normal; + void main() { - gl_Position = u_modelViewProjectionMatrix * a_vertex; + vec4 world_space_vert = u_modelMatrix * a_vertex; + gl_Position = u_viewProjectionMatrix * world_space_vert; + // gl_Position = u_modelViewProjectionMatrix * a_vertex; // shade the color depending on the extruder index stored in the alpha component of the color v_color = (a_color.a == u_active_extruder) ? a_color : a_color * u_shade_factor; v_color.a = 1.0; + + v_vertex = world_space_vert.xyz; + v_normal = (u_normalMatrix * normalize(a_normal)).xyz; } -fragment = - varying lowp vec4 v_color; +geometry = + #version 410 + + layout(lines) in; + layout(triangle_strip, max_vertices = 6) out; + + in vec4 v_color[]; + in vec3 v_vertex[]; + in vec3 v_normal[]; + + out vec4 f_color; + out vec3 f_normal; + out vec3 f_vertex; void main() { - gl_FragColor = v_color; + int i; + vec4 delta; + vec3 g_normal; + vec3 g_offset; + + delta = vec4(gl_in[1].gl_Position.xy, 0.0, 0.0) - vec4(gl_in[0].gl_Position.xy, 0.0, 0.0); + g_normal = normalize(vec3(delta.y, -delta.x, delta.z)); + //g_offset = vec3(3.5, 3.5, 0.0); //5.0 * g_normal; // vec3(3.5, 3.5, 0.0); + g_offset = normalize(vec3(g_normal.x, g_normal.y, 0)); //5.0 * g_normal; // vec3(3.5, 3.5, 0.0); + f_vertex = v_vertex[0]; + + f_normal = v_normal[0]; + f_color = v_color[0]; + gl_Position = gl_in[0].gl_Position + g_offset; + EmitVertex(); + + f_normal = -v_normal[0]; + f_color = v_color[0]; + gl_Position = gl_in[0].gl_Position - g_offset; + EmitVertex(); + + f_normal = v_normal[0]; + f_color = v_color[1]; + gl_Position = gl_in[1].gl_Position + g_offset; + EmitVertex(); + + EndPrimitive(); + + + f_vertex = v_vertex[1]; + + f_normal = -v_normal[0]; + f_color = v_color[0]; + gl_Position = gl_in[0].gl_Position - g_offset; + EmitVertex(); + + f_normal = v_normal[0]; + f_color = v_color[1]; + gl_Position = gl_in[1].gl_Position + g_offset; + EmitVertex(); + + f_normal = -v_normal[0]; + f_color = v_color[1]; + gl_Position = gl_in[1].gl_Position - g_offset; + EmitVertex(); + + EndPrimitive(); + + } + +fragment = + varying lowp vec4 f_color; + varying lowp vec3 f_normal; + varying lowp vec3 f_vertex; + + uniform mediump vec4 u_diffuseColor; + //uniform highp vec3 u_lightPosition; + + void main() + { + mediump vec4 finalColor = vec4(0.0); + + finalColor += f_color; + + highp vec3 normal = normalize(f_normal); + highp vec3 lightDir = normalize(vec3(0.0, 100.0, -50.0) - f_vertex); + + // Diffuse Component + highp float NdotL = clamp(abs(dot(normal, lightDir)), 0.0, 1.0); + finalColor += (NdotL * u_diffuseColor); + + finalColor.a = 1.0; + gl_FragColor = finalColor; + + //gl_FragColor = f_color; + //gl_FragColor = vec4(f_normal, 1.0); } [defaults] u_active_extruder = 0.0 u_shade_factor = 0.60 +u_diffuseColor = [1.0, 0.79, 0.14, 1.0] +# u_lightPosition = light_0_position [bindings] u_modelViewProjectionMatrix = model_view_projection_matrix +u_modelMatrix = model_matrix +u_viewProjectionMatrix = view_projection_matrix +u_normalMatrix = normal_matrix [attributes] a_vertex = vertex a_color = color +a_normal = normal \ No newline at end of file diff --git a/resources/shaders/overhang.shader b/resources/shaders/overhang.shader index 99cbdf913d..0e8592f675 100644 --- a/resources/shaders/overhang.shader +++ b/resources/shaders/overhang.shader @@ -20,6 +20,40 @@ vertex = v_normal = (u_normalMatrix * normalize(a_normal)).xyz; } +geometry = + #version 410 + + layout(triangles) in; + layout(triangle_strip, max_vertices = 6) out; + + in vec3 v_normal[]; + in vec3 v_vertex[]; + + out vec3 f_normal; + out vec3 f_vertex; + + void main() + { + int i; + for(i = 0; i < 3; i++) + { + f_normal = v_normal[i]; + f_vertex = v_vertex[i]; + gl_Position = gl_in[i].gl_Position + vec4(-50, 0.0, 0.0, 0.0); + EmitVertex(); + } + EndPrimitive(); + + for(i = 0; i < 3; i++) + { + f_normal = v_normal[i]; + f_vertex = v_vertex[i]; + gl_Position = gl_in[i].gl_Position + vec4(50, 0.0, 0.0, 0.0); + EmitVertex(); + } + EndPrimitive(); + } + fragment = uniform mediump vec4 u_ambientColor; uniform mediump vec4 u_diffuseColor; @@ -31,27 +65,28 @@ fragment = uniform lowp float u_overhangAngle; uniform lowp vec4 u_overhangColor; - varying highp vec3 v_vertex; - varying highp vec3 v_normal; + varying highp vec3 f_vertex; + varying highp vec3 f_normal; void main() { + mediump vec4 finalColor = vec4(0.0); - /* Ambient Component */ + // Ambient Component finalColor += u_ambientColor; - highp vec3 normal = normalize(v_normal); - highp vec3 lightDir = normalize(u_lightPosition - v_vertex); + highp vec3 normal = normalize(f_normal); + highp vec3 lightDir = normalize(u_lightPosition - f_vertex); - /* Diffuse Component */ + // Diffuse Component highp float NdotL = clamp(abs(dot(normal, lightDir)), 0.0, 1.0); finalColor += (NdotL * u_diffuseColor); - /* Specular Component */ - /* TODO: We should not do specularity for fragments facing away from the light.*/ + // Specular Component + // TODO: We should not do specularity for fragments facing away from the light. highp vec3 reflectedLight = reflect(-lightDir, normal); - highp vec3 viewVector = normalize(u_viewPosition - v_vertex); + highp vec3 viewVector = normalize(u_viewPosition - f_vertex); highp float NdotR = clamp(dot(viewVector, reflectedLight), 0.0, 1.0); finalColor += pow(NdotR, u_shininess) * u_specularColor; From 57cec4ec59ae4558560db0ff970a2365dda10853 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Dec 2016 14:00:34 +0100 Subject: [PATCH 005/156] wip --- plugins/LayerView/layers.shader | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index c48c56f1e7..19f5c39e20 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -51,22 +51,31 @@ geometry = vec3 g_offset; delta = vec4(gl_in[1].gl_Position.xy, 0.0, 0.0) - vec4(gl_in[0].gl_Position.xy, 0.0, 0.0); - g_normal = normalize(vec3(delta.y, -delta.x, delta.z)); - //g_offset = vec3(3.5, 3.5, 0.0); //5.0 * g_normal; // vec3(3.5, 3.5, 0.0); - g_offset = normalize(vec3(g_normal.x, g_normal.y, 0)); //5.0 * g_normal; // vec3(3.5, 3.5, 0.0); - f_vertex = v_vertex[0]; + if (length(delta) > 0.1) { + g_normal = normalize(vec3(delta.y, -delta.x, delta.z)); + g_offset = vec3(g_normal.xy, 0); //5.0 * g_normal; // vec3(3.5, 3.5, 0.0); + } else { + g_normal = vec3(delta.y, -delta.x, delta.z); + g_offset = vec3(0.0, 0.0, 0.0); + } + //g_offset = vec3(3.5, 3.5, 0.0); //5.0 * g_normal; // vec3(3.5, 3.5, 0.0); + //g_normal = normalize(vec3(delta.y, -delta.x, delta.z)); + + f_vertex = v_vertex[0]; f_normal = v_normal[0]; f_color = v_color[0]; gl_Position = gl_in[0].gl_Position + g_offset; EmitVertex(); + f_vertex = v_vertex[0]; f_normal = -v_normal[0]; f_color = v_color[0]; gl_Position = gl_in[0].gl_Position - g_offset; EmitVertex(); - f_normal = v_normal[0]; + f_vertex = v_vertex[1]; + f_normal = v_normal[1]; f_color = v_color[1]; gl_Position = gl_in[1].gl_Position + g_offset; EmitVertex(); @@ -74,18 +83,19 @@ geometry = EndPrimitive(); - f_vertex = v_vertex[1]; - + f_vertex = v_vertex[0]; f_normal = -v_normal[0]; f_color = v_color[0]; gl_Position = gl_in[0].gl_Position - g_offset; EmitVertex(); + f_vertex = v_vertex[1]; f_normal = v_normal[0]; f_color = v_color[1]; gl_Position = gl_in[1].gl_Position + g_offset; EmitVertex(); + f_vertex = v_vertex[1]; f_normal = -v_normal[0]; f_color = v_color[1]; gl_Position = gl_in[1].gl_Position - g_offset; @@ -101,7 +111,7 @@ fragment = varying lowp vec3 f_vertex; uniform mediump vec4 u_diffuseColor; - //uniform highp vec3 u_lightPosition; + uniform highp vec3 u_lightPosition; void main() { @@ -110,10 +120,10 @@ fragment = finalColor += f_color; highp vec3 normal = normalize(f_normal); - highp vec3 lightDir = normalize(vec3(0.0, 100.0, -50.0) - f_vertex); + highp vec3 lightDir = normalize(u_lightPosition - f_vertex); // Diffuse Component - highp float NdotL = clamp(abs(dot(normal, lightDir)), 0.0, 1.0); + highp float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0); finalColor += (NdotL * u_diffuseColor); finalColor.a = 1.0; @@ -127,13 +137,13 @@ fragment = u_active_extruder = 0.0 u_shade_factor = 0.60 u_diffuseColor = [1.0, 0.79, 0.14, 1.0] -# u_lightPosition = light_0_position [bindings] u_modelViewProjectionMatrix = model_view_projection_matrix u_modelMatrix = model_matrix u_viewProjectionMatrix = view_projection_matrix u_normalMatrix = normal_matrix +u_lightPosition = light_0_position [attributes] a_vertex = vertex From 3d9bccb7c788b4c20d4a676b8ddd75003ff93ed2 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 20 Dec 2016 16:32:34 +0100 Subject: [PATCH 006/156] big tryout --- .../ProcessSlicedLayersJob.py | 20 +++- plugins/LayerView/layers.shader | 91 +++++++++++++++---- 2 files changed, 90 insertions(+), 21 deletions(-) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index d4d2ccf15e..64a55266e4 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -130,6 +130,8 @@ class ProcessSlicedLayersJob(Job): normals = this_poly.getNormals() all_normals.append(normals) + # insert last element twice - fake converting line normals to vertex normals + #all_normals.append(normals[-1:]) this_layer.polygons.append(this_poly) @@ -149,8 +151,24 @@ class ProcessSlicedLayersJob(Job): # layer_data.calculateNormals() # We are done processing all the layers we got from the engine, now create a mesh out of the data - layer_data._normals = numpy.concatenate(all_normals) + # layer_data._normals = numpy.concatenate(all_normals) layer_mesh = layer_data.build() + # normals = [] + # # quick and dirty normals calculation for 2d lines + # for line_idx in range(len(layer_mesh._indices) // 2 - 1): + # idx0 = layer_mesh._indices[line_idx] + # idx1 = layer_mesh._indices[line_idx + 1] + # x0 = layer_mesh._vertices[idx0][0] + # y0 = layer_mesh._vertices[idx0][2] + # x1 = layer_mesh._vertices[idx1][0] + # y1 = layer_mesh._vertices[idx1][2] + # dx = x1 - x0; + # dy = y1 - y0; + # normals.append([dy, 0, -dx]) + # normals.append([dy, 0, -dx]) + # layer_mesh._normals = numpy.array(normals) + #from UM.Mesh.MeshData import calculateNormalsFromIndexedVertices + #layer_mesh._normals = calculateNormalsFromIndexedVertices(layer_mesh._vertices, layer_mesh._indices, layer_mesh._face_count) if self._abort_requested: if self._progress: diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 19f5c39e20..7bed3df795 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -16,6 +16,8 @@ vertex = varying highp vec3 v_vertex; varying highp vec3 v_normal; + varying highp vec3 v_orig_vertex; + void main() { vec4 world_space_vert = u_modelMatrix * a_vertex; @@ -27,6 +29,8 @@ vertex = v_vertex = world_space_vert.xyz; v_normal = (u_normalMatrix * normalize(a_normal)).xyz; + + v_orig_vertex = a_vertex.xyz; } geometry = @@ -38,6 +42,7 @@ geometry = in vec4 v_color[]; in vec3 v_vertex[]; in vec3 v_normal[]; + in vec3 v_orig_vertex[]; out vec4 f_color; out vec3 f_normal; @@ -50,6 +55,12 @@ geometry = vec3 g_normal; vec3 g_offset; + vec3 g_vertex_delta; + vec3 g_vertex_normal; + + float size = 3; + + /* delta = vec4(gl_in[1].gl_Position.xy, 0.0, 0.0) - vec4(gl_in[0].gl_Position.xy, 0.0, 0.0); if (length(delta) > 0.1) { @@ -59,49 +70,71 @@ geometry = g_normal = vec3(delta.y, -delta.x, delta.z); g_offset = vec3(0.0, 0.0, 0.0); } - //g_offset = vec3(3.5, 3.5, 0.0); //5.0 * g_normal; // vec3(3.5, 3.5, 0.0); + g_offset = vec3(3.5, 3.5, 0.0); //5.0 * g_normal; // vec3(3.5, 3.5, 0.0); + */ //g_normal = normalize(vec3(delta.y, -delta.x, delta.z)); - f_vertex = v_vertex[0]; - f_normal = v_normal[0]; - f_color = v_color[0]; - gl_Position = gl_in[0].gl_Position + g_offset; - EmitVertex(); + g_vertex_delta = v_orig_vertex[1] - v_orig_vertex[0]; + g_vertex_normal = vec3(g_vertex_delta.z, 0.0, -g_vertex_delta.x); + if (length(g_vertex_normal) < 0.1) { + g_vertex_normal = vec3(1.0, 0.0, 0.0); + } else { + g_vertex_normal = normalize(g_vertex_normal); + } f_vertex = v_vertex[0]; - f_normal = -v_normal[0]; f_color = v_color[0]; - gl_Position = gl_in[0].gl_Position - g_offset; + + f_normal = g_vertex_normal; + gl_Position = gl_in[0].gl_Position + vec4(0.0, size, 0.0, 0.0); EmitVertex(); - f_vertex = v_vertex[1]; - f_normal = v_normal[1]; - f_color = v_color[1]; - gl_Position = gl_in[1].gl_Position + g_offset; + f_normal = g_vertex_normal; + gl_Position = gl_in[1].gl_Position + vec4(0.0, size, 0.0, 0.0); + EmitVertex(); + + f_normal = vec3(0.0); + gl_Position = gl_in[0].gl_Position + vec4(-size, 0.0, 0.0, 0.0); + EmitVertex(); + + //f_vertex = v_vertex[1]; + //f_color = v_color[1]; + + + f_normal = vec3(0.0); + gl_Position = gl_in[1].gl_Position + vec4(size, 0.0, 0.0, 0.0); + EmitVertex(); + + f_normal = -g_vertex_normal; + gl_Position = gl_in[0].gl_Position + vec4(0, -size, 0.0, 0.0); + EmitVertex(); + + f_normal = -g_vertex_normal; + gl_Position = gl_in[1].gl_Position + vec4(0.0, -size, 0.0, 0.0); EmitVertex(); EndPrimitive(); - + /* f_vertex = v_vertex[0]; - f_normal = -v_normal[0]; + f_normal = -g_vertex_normal; f_color = v_color[0]; gl_Position = gl_in[0].gl_Position - g_offset; EmitVertex(); f_vertex = v_vertex[1]; - f_normal = v_normal[0]; + f_normal = g_vertex_normal; f_color = v_color[1]; gl_Position = gl_in[1].gl_Position + g_offset; EmitVertex(); f_vertex = v_vertex[1]; - f_normal = -v_normal[0]; + f_normal = -g_vertex_normal; f_color = v_color[1]; gl_Position = gl_in[1].gl_Position - g_offset; EmitVertex(); + */ - EndPrimitive(); } @@ -110,21 +143,38 @@ fragment = varying lowp vec3 f_normal; varying lowp vec3 f_vertex; + uniform mediump vec4 u_ambientColor; uniform mediump vec4 u_diffuseColor; uniform highp vec3 u_lightPosition; + void Impostor(in float sphereRadius, in vec3 cameraSpherePos, in vec2 mapping, out vec3 cameraPos, out vec3 cameraNormal) + { + float lensqr = dot(mapping, mapping); + if(lensqr > 1.0) + discard; + + cameraNormal = vec3(mapping, sqrt(1.0 - lensqr)); + cameraPos = (cameraNormal * sphereRadius) + cameraSpherePos; + } + void main() { + vec3 cameraPos; + vec3 cameraNormal; + + Impostor(0.2, vec3(0.0, 0.0, 0.0), vec2(0.1, 0.0), cameraPos, cameraNormal); + mediump vec4 finalColor = vec4(0.0); - finalColor += f_color; + finalColor += u_ambientColor; - highp vec3 normal = normalize(f_normal); + //highp vec3 normal = normalize(f_normal); + highp vec3 normal = normalize(cameraNormal); highp vec3 lightDir = normalize(u_lightPosition - f_vertex); // Diffuse Component highp float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0); - finalColor += (NdotL * u_diffuseColor); + finalColor += (NdotL * f_color); finalColor.a = 1.0; gl_FragColor = finalColor; @@ -136,6 +186,7 @@ fragment = [defaults] u_active_extruder = 0.0 u_shade_factor = 0.60 +u_ambientColor = [0.3, 0.3, 0.3, 0.3] u_diffuseColor = [1.0, 0.79, 0.14, 1.0] [bindings] From 9e6c070ac64cd55981c998d48a9f75106e76580f Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Dec 2016 09:21:05 +0100 Subject: [PATCH 007/156] tryout --- plugins/LayerView/layers.shader | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 7bed3df795..24346e5c65 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -85,15 +85,15 @@ geometry = f_vertex = v_vertex[0]; f_color = v_color[0]; - f_normal = g_vertex_normal; + f_normal = g_vertex_normal + vec3(0.0, 0.0, 0.5); gl_Position = gl_in[0].gl_Position + vec4(0.0, size, 0.0, 0.0); EmitVertex(); - f_normal = g_vertex_normal; + f_normal = g_vertex_normal + vec3(0.0, 0.0, 0.5); gl_Position = gl_in[1].gl_Position + vec4(0.0, size, 0.0, 0.0); EmitVertex(); - f_normal = vec3(0.0); + f_normal = vec3(0.0, 0.0, 0.5); gl_Position = gl_in[0].gl_Position + vec4(-size, 0.0, 0.0, 0.0); EmitVertex(); @@ -101,15 +101,15 @@ geometry = //f_color = v_color[1]; - f_normal = vec3(0.0); + f_normal = vec3(0.0, 0.0, 0.5); gl_Position = gl_in[1].gl_Position + vec4(size, 0.0, 0.0, 0.0); EmitVertex(); - f_normal = -g_vertex_normal; + f_normal = -g_vertex_normal + vec3(0.0, 0.0, 0.5); gl_Position = gl_in[0].gl_Position + vec4(0, -size, 0.0, 0.0); EmitVertex(); - f_normal = -g_vertex_normal; + f_normal = -g_vertex_normal + vec3(0.0, 0.0, 0.5); gl_Position = gl_in[1].gl_Position + vec4(0.0, -size, 0.0, 0.0); EmitVertex(); @@ -162,14 +162,14 @@ fragment = vec3 cameraPos; vec3 cameraNormal; - Impostor(0.2, vec3(0.0, 0.0, 0.0), vec2(0.1, 0.0), cameraPos, cameraNormal); + //Impostor(0.2, vec3(0.0, 0.0, 0.0), vec2(0.1, 0.1), cameraPos, cameraNormal); mediump vec4 finalColor = vec4(0.0); finalColor += u_ambientColor; - //highp vec3 normal = normalize(f_normal); - highp vec3 normal = normalize(cameraNormal); + highp vec3 normal = normalize(f_normal); + //highp vec3 normal = normalize(cameraNormal); highp vec3 lightDir = normalize(u_lightPosition - f_vertex); // Diffuse Component From 0adb1a4c1c16ca6550a8450b1c516e79f5f7b53c Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Dec 2016 14:37:02 +0100 Subject: [PATCH 008/156] Finally got normals in --- cura/Layer.py | 4 +- cura/LayerDataBuilder.py | 4 +- .../ProcessSlicedLayersJob.py | 7 +- plugins/LayerView/LayerView.py | 6 +- plugins/LayerView/layers.shader | 206 ++++++++++++------ 5 files changed, 155 insertions(+), 72 deletions(-) diff --git a/cura/Layer.py b/cura/Layer.py index 4e38a6eba9..bc9f66e881 100644 --- a/cura/Layer.py +++ b/cura/Layer.py @@ -49,12 +49,14 @@ class Layer: return result - def build(self, vertex_offset, index_offset, vertices, colors, indices): + def build(self, vertex_offset, index_offset, vertices, colors, indices, normals): result_vertex_offset = vertex_offset result_index_offset = index_offset self._element_count = 0 for polygon in self._polygons: polygon.build(result_vertex_offset, result_index_offset, vertices, colors, indices) + polygon_normals = polygon.getNormals() # [numpy.where(numpy.logical_not(polygon.jumpMask))] + normals[result_vertex_offset:result_vertex_offset+polygon.lineMeshVertexCount()] = polygon_normals[:polygon.lineMeshVertexCount()] result_vertex_offset += polygon.lineMeshVertexCount() result_index_offset += polygon.lineMeshElementCount() self._element_count += polygon.elementCount diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index 2215ed5f27..f2ad6b55fa 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -56,18 +56,20 @@ class LayerDataBuilder(MeshBuilder): index_count += data.lineMeshElementCount() vertices = numpy.empty((vertex_count, 3), numpy.float32) + normals = numpy.empty((vertex_count, 3), numpy.float32) colors = numpy.empty((vertex_count, 4), numpy.float32) indices = numpy.empty((index_count, 2), numpy.int32) vertex_offset = 0 index_offset = 0 for layer, data in self._layers.items(): - ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, indices) + ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, indices, normals) self._element_counts[layer] = data.elementCount self.addVertices(vertices) self.addColors(colors) self.addIndices(indices.flatten()) + self._normals = normals return LayerData(vertices=self.getVertices(), normals=self.getNormals(), indices=self.getIndices(), colors=self.getColors(), uvs=self.getUVCoordinates(), file_name=self.getFileName(), diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 64a55266e4..d7863f07cb 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -129,9 +129,10 @@ class ProcessSlicedLayersJob(Job): this_poly.buildCache() normals = this_poly.getNormals() - all_normals.append(normals) + # normals = this_poly.getNormals()[numpy.where(numpy.logical_not(this_poly.jumpMask))] + # all_normals.append(normals) # insert last element twice - fake converting line normals to vertex normals - #all_normals.append(normals[-1:]) + # all_normals.append(normals[-1:]) this_layer.polygons.append(this_poly) @@ -155,7 +156,7 @@ class ProcessSlicedLayersJob(Job): layer_mesh = layer_data.build() # normals = [] # # quick and dirty normals calculation for 2d lines - # for line_idx in range(len(layer_mesh._indices) // 2 - 1): + # for line_idx in range(len(layer_mesh._indices) // 2): # idx0 = layer_mesh._indices[line_idx] # idx1 = layer_mesh._indices[line_idx + 1] # x0 = layer_mesh._vertices[idx0][0] diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 50c13194f7..cf2fbbc1d3 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -236,9 +236,9 @@ class LayerView(View): self.setBusy(True) - self._top_layers_job = _CreateTopLayersJob(self._controller.getScene(), self._current_layer_num, self._solid_layers) - self._top_layers_job.finished.connect(self._updateCurrentLayerMesh) - self._top_layers_job.start() + #self._top_layers_job = _CreateTopLayersJob(self._controller.getScene(), self._current_layer_num, self._solid_layers) + #self._top_layers_job.finished.connect(self._updateCurrentLayerMesh) + #self._top_layers_job.start() def _updateCurrentLayerMesh(self, job): self.setBusy(False) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 24346e5c65..88eb54cc36 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -1,8 +1,8 @@ [shaders] vertex = uniform highp mat4 u_modelMatrix; - uniform highp mat4 u_viewProjectionMatrix; - uniform highp mat4 u_modelViewProjectionMatrix; + //uniform highp mat4 u_viewProjectionMatrix; + //uniform highp mat4 u_modelViewProjectionMatrix; uniform lowp float u_active_extruder; uniform lowp float u_shade_factor; uniform highp mat4 u_normalMatrix; @@ -16,12 +16,17 @@ vertex = varying highp vec3 v_vertex; varying highp vec3 v_normal; - varying highp vec3 v_orig_vertex; + varying highp vec4 v_orig_vertex; + + varying lowp vec4 f_color; + varying highp vec3 f_vertex; + varying highp vec3 f_normal; void main() { vec4 world_space_vert = u_modelMatrix * a_vertex; - gl_Position = u_viewProjectionMatrix * world_space_vert; + // gl_Position = u_viewProjectionMatrix * world_space_vert; + gl_Position = world_space_vert; // gl_Position = u_modelViewProjectionMatrix * a_vertex; // shade the color depending on the extruder index stored in the alpha component of the color v_color = (a_color.a == u_active_extruder) ? a_color : a_color * u_shade_factor; @@ -30,14 +35,26 @@ vertex = v_vertex = world_space_vert.xyz; v_normal = (u_normalMatrix * normalize(a_normal)).xyz; - v_orig_vertex = a_vertex.xyz; + v_orig_vertex = a_vertex; + + // for testing without geometry shader + f_color = v_color; + f_vertex = v_vertex; + f_normal = v_normal; } geometry = #version 410 + //uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewProjectionMatrix; + //uniform highp mat4 u_modelViewProjectionMatrix; + layout(lines) in; - layout(triangle_strip, max_vertices = 6) out; + layout(triangle_strip, max_vertices = 4) out; + /*layout(std140) uniform Matrices { + mat4 u_modelViewProjectionMatrix; + };*/ in vec4 v_color[]; in vec3 v_vertex[]; @@ -48,6 +65,73 @@ geometry = out vec3 f_normal; out vec3 f_vertex; + void main() + { + //int i; + //vec3 g_normal; + //vec3 g_offset; + + //vec4 g_vertex_delta; + vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers + vec3 g_vertex_normal_vert; + vec3 g_vertex_offset_horz; + vec3 g_vertex_offset_vert; + + float size = 0.5; + + //g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; + g_vertex_normal_horz = normalize(v_normal[0]); //vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x); + g_vertex_offset_horz = vec3(0.5, 0.0, 0.0); //size * g_vertex_normal_horz; //size * g_vertex_normal_horz; + g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); + g_vertex_offset_vert = vec3(0.0, 0.5, 0.0); //size * g_vertex_normal_vert; + + f_vertex = v_vertex[0]; + f_normal = g_vertex_normal_horz; + f_color = vec4(g_vertex_normal_horz, 1.0); //v_color[0]; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + f_vertex = v_vertex[1]; + //f_color = v_color[1]; + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + f_vertex = v_vertex[0]; + //f_color = v_color[0]; + f_normal = g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); + EmitVertex(); + + f_vertex = v_vertex[1]; + //f_color = v_color[1]; + f_normal = g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); + EmitVertex(); + + EndPrimitive(); + } + + +poep = + #version 410 + + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewProjectionMatrix; + uniform highp mat4 u_modelViewProjectionMatrix; + + layout(lines) in; + layout(triangle_strip, max_vertices = 3) out; + + in vec4 v_color[]; + in vec3 v_vertex[]; + in vec3 v_normal[]; + in vec4 v_orig_vertex[]; + + out vec4 f_color; + out vec3 f_normal; + out vec3 f_vertex; + void main() { int i; @@ -55,85 +139,78 @@ geometry = vec3 g_normal; vec3 g_offset; - vec3 g_vertex_delta; - vec3 g_vertex_normal; + vec4 g_vertex_delta; + vec4 g_vertex_normal_horz; // horizontal and vertical in respect to layers + vec3 g_vertex_normal_vert; + vec3 g_vertex_offset_horz; + vec3 g_vertex_offset_vert; float size = 3; - /* - delta = vec4(gl_in[1].gl_Position.xy, 0.0, 0.0) - vec4(gl_in[0].gl_Position.xy, 0.0, 0.0); - - if (length(delta) > 0.1) { - g_normal = normalize(vec3(delta.y, -delta.x, delta.z)); - g_offset = vec3(g_normal.xy, 0); //5.0 * g_normal; // vec3(3.5, 3.5, 0.0); - } else { - g_normal = vec3(delta.y, -delta.x, delta.z); - g_offset = vec3(0.0, 0.0, 0.0); - } - g_offset = vec3(3.5, 3.5, 0.0); //5.0 * g_normal; // vec3(3.5, 3.5, 0.0); - */ - //g_normal = normalize(vec3(delta.y, -delta.x, delta.z)); - g_vertex_delta = v_orig_vertex[1] - v_orig_vertex[0]; - g_vertex_normal = vec3(g_vertex_delta.z, 0.0, -g_vertex_delta.x); - if (length(g_vertex_normal) < 0.1) { - g_vertex_normal = vec3(1.0, 0.0, 0.0); + g_vertex_normal_horz = vec4(g_vertex_delta.z, 0.0, -g_vertex_delta.x, g_vertex_delta.w); + if (length(g_vertex_normal_horz) < 0.1) { + g_vertex_normal_horz = vec4(1.0, 0.0, 0.0, 0.0); + g_vertex_offset_horz = vec3(0.0, 0.0, 0.0); + g_vertex_offset_vert = vec3(0.0, 0.0, 0.0); } else { - g_vertex_normal = normalize(g_vertex_normal); + g_vertex_normal_horz = normalize(g_vertex_normal_horz); + g_vertex_offset_horz = (u_viewProjectionMatrix * u_modelMatrix * size * g_vertex_normal_horz).xyz; + g_vertex_normal_vert = vec3(0.0, 0.0, 1.0); + g_vertex_offset_vert = (u_viewProjectionMatrix * u_modelMatrix * size * g_vertex_normal_vert).xyz; } f_vertex = v_vertex[0]; f_color = v_color[0]; - - f_normal = g_vertex_normal + vec3(0.0, 0.0, 0.5); - gl_Position = gl_in[0].gl_Position + vec4(0.0, size, 0.0, 0.0); + f_normal = g_vertex_normal_horz; + gl_Position = gl_in[0].gl_Position + g_vertex_offset_horz; EmitVertex(); - f_normal = g_vertex_normal + vec3(0.0, 0.0, 0.5); - gl_Position = gl_in[1].gl_Position + vec4(0.0, size, 0.0, 0.0); + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = g_vertex_normal_horz; + gl_Position = gl_in[1].gl_Position + g_vertex_offset_horz; EmitVertex(); - f_normal = vec3(0.0, 0.0, 0.5); - gl_Position = gl_in[0].gl_Position + vec4(-size, 0.0, 0.0, 0.0); + f_vertex = v_vertex[0]; + f_color = v_color[0]; + f_normal = g_vertex_offset_vert; + gl_Position = gl_in[0].gl_Position + g_vertex_offset_vert; EmitVertex(); - //f_vertex = v_vertex[1]; - //f_color = v_color[1]; - - - f_normal = vec3(0.0, 0.0, 0.5); - gl_Position = gl_in[1].gl_Position + vec4(size, 0.0, 0.0, 0.0); + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = g_vertex_offset_vert; + gl_Position = gl_in[1].gl_Position + g_vertex_offset_vert; EmitVertex(); - f_normal = -g_vertex_normal + vec3(0.0, 0.0, 0.5); - gl_Position = gl_in[0].gl_Position + vec4(0, -size, 0.0, 0.0); + f_vertex = v_vertex[0]; + f_color = v_color[0]; + f_normal = -g_vertex_normal_horz; + gl_Position = gl_in[0].gl_Position - g_vertex_offset_horz; EmitVertex(); - f_normal = -g_vertex_normal + vec3(0.0, 0.0, 0.5); - gl_Position = gl_in[1].gl_Position + vec4(0.0, -size, 0.0, 0.0); + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = -g_vertex_normal_horz; + gl_Position = gl_in[1].gl_Position - g_vertex_offset_horz; EmitVertex(); + f_vertex = v_vertex[0]; + f_color = v_color[0]; + f_normal = -g_vertex_offset_vert; + gl_Position = gl_in[0].gl_Position - g_vertex_offset_vert; + EmitVertex(); + + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = -g_vertex_offset_vert; + gl_Position = gl_in[1].gl_Position - g_vertex_offset_vert; + EmitVertex(); + + EndPrimitive(); - /* - f_vertex = v_vertex[0]; - f_normal = -g_vertex_normal; - f_color = v_color[0]; - gl_Position = gl_in[0].gl_Position - g_offset; - EmitVertex(); - - f_vertex = v_vertex[1]; - f_normal = g_vertex_normal; - f_color = v_color[1]; - gl_Position = gl_in[1].gl_Position + g_offset; - EmitVertex(); - - f_vertex = v_vertex[1]; - f_normal = -g_vertex_normal; - f_color = v_color[1]; - gl_Position = gl_in[1].gl_Position - g_offset; - EmitVertex(); - */ } @@ -166,7 +243,8 @@ fragment = mediump vec4 finalColor = vec4(0.0); - finalColor += u_ambientColor; + //finalColor += u_ambientColor; + finalColor = f_color; highp vec3 normal = normalize(f_normal); //highp vec3 normal = normalize(cameraNormal); @@ -174,7 +252,7 @@ fragment = // Diffuse Component highp float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0); - finalColor += (NdotL * f_color); + //finalColor += (NdotL * f_color); finalColor.a = 1.0; gl_FragColor = finalColor; From 47e204038fbef3041eac9f325cc00dbca8ab49dd Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 21 Dec 2016 15:44:01 +0100 Subject: [PATCH 009/156] Got cylinders --- plugins/LayerView/layers.shader | 66 ++++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 14 deletions(-) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 88eb54cc36..270d2daa50 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -51,7 +51,7 @@ geometry = //uniform highp mat4 u_modelViewProjectionMatrix; layout(lines) in; - layout(triangle_strip, max_vertices = 4) out; + layout(triangle_strip, max_vertices = 8) out; /*layout(std140) uniform Matrices { mat4 u_modelViewProjectionMatrix; };*/ @@ -73,42 +73,67 @@ geometry = //vec4 g_vertex_delta; vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers + vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position vec3 g_vertex_normal_vert; - vec3 g_vertex_offset_horz; - vec3 g_vertex_offset_vert; + vec4 g_vertex_offset_vert; - float size = 0.5; + const float size = 0.5; //g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; g_vertex_normal_horz = normalize(v_normal[0]); //vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x); - g_vertex_offset_horz = vec3(0.5, 0.0, 0.0); //size * g_vertex_normal_horz; //size * g_vertex_normal_horz; + g_vertex_offset_horz = vec4(g_vertex_normal_horz * size, 0.0); //size * g_vertex_normal_horz; g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); - g_vertex_offset_vert = vec3(0.0, 0.5, 0.0); //size * g_vertex_normal_vert; + //g_vertex_offset_vert = vec3(g_vertex_normal_vert.x * 0.5f, g_vertex_normal_vert.y * 0.5f, g_vertex_normal_vert.z * 0.5f); //size * g_vertex_normal_vert; + g_vertex_offset_vert = vec4(g_vertex_normal_vert * size, 0.0); f_vertex = v_vertex[0]; f_normal = g_vertex_normal_horz; - f_color = vec4(g_vertex_normal_horz, 1.0); //v_color[0]; + f_color = v_color[0]; gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[1]; - //f_color = v_color[1]; + f_color = v_color[1]; f_normal = g_vertex_normal_horz; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[0]; - //f_color = v_color[0]; + f_color = v_color[0]; f_normal = g_vertex_normal_vert; gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); EmitVertex(); f_vertex = v_vertex[1]; - //f_color = v_color[1]; + f_color = v_color[1]; f_normal = g_vertex_normal_vert; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); EmitVertex(); + f_vertex = v_vertex[0]; + f_normal = -g_vertex_normal_horz; + f_color = v_color[0]; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = -g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + f_vertex = v_vertex[0]; + f_color = v_color[0]; + f_normal = -g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); + EmitVertex(); + + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = -g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); + EmitVertex(); + EndPrimitive(); } @@ -222,6 +247,9 @@ fragment = uniform mediump vec4 u_ambientColor; uniform mediump vec4 u_diffuseColor; + //uniform mediump vec4 u_specularColor; + //uniform mediump float u_shininess; + uniform highp vec3 u_lightPosition; void Impostor(in float sphereRadius, in vec3 cameraSpherePos, in vec2 mapping, out vec3 cameraPos, out vec3 cameraNormal) @@ -241,18 +269,26 @@ fragment = //Impostor(0.2, vec3(0.0, 0.0, 0.0), vec2(0.1, 0.1), cameraPos, cameraNormal); + //gl_FrontFacing = .. + mediump vec4 finalColor = vec4(0.0); - //finalColor += u_ambientColor; - finalColor = f_color; + finalColor += u_ambientColor; + //finalColor = f_color; highp vec3 normal = normalize(f_normal); - //highp vec3 normal = normalize(cameraNormal); highp vec3 lightDir = normalize(u_lightPosition - f_vertex); // Diffuse Component highp float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0); - //finalColor += (NdotL * f_color); + finalColor += (NdotL * f_color); + + // Specular Component + // TODO: We should not do specularity for fragments facing away from the light. + /*highp vec3 reflectedLight = reflect(-lightDir, normal); + highp vec3 viewVector = normalize(u_viewPosition - f_vertex); + highp float NdotR = clamp(dot(viewVector, reflectedLight), 0.0, 1.0); + finalColor += pow(NdotR, u_shininess) * u_specularColor;*/ finalColor.a = 1.0; gl_FragColor = finalColor; @@ -264,8 +300,10 @@ fragment = [defaults] u_active_extruder = 0.0 u_shade_factor = 0.60 +u_specularColor = [0.4, 0.4, 0.4, 1.0] u_ambientColor = [0.3, 0.3, 0.3, 0.3] u_diffuseColor = [1.0, 0.79, 0.14, 1.0] +u_shininess = 20.0 [bindings] u_modelViewProjectionMatrix = model_view_projection_matrix From c6d56b60f69c7021b9f4aebfb4a0e97ce931ca33 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 22 Dec 2016 09:44:00 +0100 Subject: [PATCH 010/156] Working quite nicely --- cura/LayerDataBuilder.py | 1 + .../ProcessSlicedLayersJob.py | 25 --- plugins/LayerView/LayerPass.py | 4 +- plugins/LayerView/LayerView.py | 6 +- plugins/LayerView/layers.shader | 206 +++++++++--------- 5 files changed, 108 insertions(+), 134 deletions(-) diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index f2ad6b55fa..1bd26d1ddc 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -57,6 +57,7 @@ class LayerDataBuilder(MeshBuilder): vertices = numpy.empty((vertex_count, 3), numpy.float32) normals = numpy.empty((vertex_count, 3), numpy.float32) + # line_widths = numpy.empty((vertex_count, 3), numpy.float32) # strictly taken you need 1 less colors = numpy.empty((vertex_count, 4), numpy.float32) indices = numpy.empty((index_count, 2), numpy.int32) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index d7863f07cb..6a64cfd5d6 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -85,7 +85,6 @@ class ProcessSlicedLayersJob(Job): min_layer_number = layer.id current_layer = 0 - all_normals = [] for layer in self._layers: abs_layer_number = layer.id + abs(min_layer_number) @@ -128,12 +127,6 @@ class ProcessSlicedLayersJob(Job): this_poly = LayerPolygon.LayerPolygon(layer_data, extruder, line_types, new_points, line_widths) this_poly.buildCache() - normals = this_poly.getNormals() - # normals = this_poly.getNormals()[numpy.where(numpy.logical_not(this_poly.jumpMask))] - # all_normals.append(normals) - # insert last element twice - fake converting line normals to vertex normals - # all_normals.append(normals[-1:]) - this_layer.polygons.append(this_poly) Job.yieldThread() @@ -150,26 +143,8 @@ class ProcessSlicedLayersJob(Job): if self._progress: self._progress.setProgress(progress) - # layer_data.calculateNormals() # We are done processing all the layers we got from the engine, now create a mesh out of the data - # layer_data._normals = numpy.concatenate(all_normals) layer_mesh = layer_data.build() - # normals = [] - # # quick and dirty normals calculation for 2d lines - # for line_idx in range(len(layer_mesh._indices) // 2): - # idx0 = layer_mesh._indices[line_idx] - # idx1 = layer_mesh._indices[line_idx + 1] - # x0 = layer_mesh._vertices[idx0][0] - # y0 = layer_mesh._vertices[idx0][2] - # x1 = layer_mesh._vertices[idx1][0] - # y1 = layer_mesh._vertices[idx1][2] - # dx = x1 - x0; - # dy = y1 - y0; - # normals.append([dy, 0, -dx]) - # normals.append([dy, 0, -dx]) - # layer_mesh._normals = numpy.array(normals) - #from UM.Mesh.MeshData import calculateNormalsFromIndexedVertices - #layer_mesh._normals = calculateNormalsFromIndexedVertices(layer_mesh._vertices, layer_mesh._indices, layer_mesh._face_count) if self._abort_requested: if self._progress: diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index 8ff2eb16ec..378f7278c4 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -54,12 +54,12 @@ class LayerPass(RenderPass): continue # Render all layers below a certain number as line mesh instead of vertices. - if self._layerview._current_layer_num - self._layerview._solid_layers > -1 and not self._layerview._only_show_top_layers: + if self._layerview._current_layer_num > -1 and not self._layerview._only_show_top_layers: start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer, counts in element_counts.items(): - if layer + self._layerview._solid_layers > self._layerview._current_layer_num: + if layer > self._layerview._current_layer_num: break end += counts diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index cf2fbbc1d3..50c13194f7 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -236,9 +236,9 @@ class LayerView(View): self.setBusy(True) - #self._top_layers_job = _CreateTopLayersJob(self._controller.getScene(), self._current_layer_num, self._solid_layers) - #self._top_layers_job.finished.connect(self._updateCurrentLayerMesh) - #self._top_layers_job.start() + self._top_layers_job = _CreateTopLayersJob(self._controller.getScene(), self._current_layer_num, self._solid_layers) + self._top_layers_job.finished.connect(self._updateCurrentLayerMesh) + self._top_layers_job.start() def _updateCurrentLayerMesh(self, job): self.setBusy(False) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 270d2daa50..0e8791ef6a 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -16,8 +16,6 @@ vertex = varying highp vec3 v_vertex; varying highp vec3 v_normal; - varying highp vec4 v_orig_vertex; - varying lowp vec4 f_color; varying highp vec3 f_vertex; varying highp vec3 f_normal; @@ -29,14 +27,12 @@ vertex = gl_Position = world_space_vert; // gl_Position = u_modelViewProjectionMatrix * a_vertex; // shade the color depending on the extruder index stored in the alpha component of the color - v_color = (a_color.a == u_active_extruder) ? a_color : a_color * u_shade_factor; + v_color = (a_color.a == u_active_extruder) ? a_color : vec4(0.4, 0.4, 0.4, 1.0); //a_color * u_shade_factor; v_color.a = 1.0; v_vertex = world_space_vert.xyz; v_normal = (u_normalMatrix * normalize(a_normal)).xyz; - v_orig_vertex = a_vertex; - // for testing without geometry shader f_color = v_color; f_vertex = v_vertex; @@ -51,7 +47,7 @@ geometry = //uniform highp mat4 u_modelViewProjectionMatrix; layout(lines) in; - layout(triangle_strip, max_vertices = 8) out; + layout(triangle_strip, max_vertices = 28) out; /*layout(std140) uniform Matrices { mat4 u_modelViewProjectionMatrix; };*/ @@ -59,7 +55,6 @@ geometry = in vec4 v_color[]; in vec3 v_vertex[]; in vec3 v_normal[]; - in vec3 v_orig_vertex[]; out vec4 f_color; out vec3 f_normal; @@ -71,20 +66,28 @@ geometry = //vec3 g_normal; //vec3 g_offset; - //vec4 g_vertex_delta; + vec4 g_vertex_delta; vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position vec3 g_vertex_normal_vert; vec4 g_vertex_offset_vert; + vec3 g_vertex_normal_horz_head; + vec4 g_vertex_offset_horz_head; - const float size = 0.5; + const float size_x = 0.2; + const float size_y = 0.1; - //g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; - g_vertex_normal_horz = normalize(v_normal[0]); //vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x); - g_vertex_offset_horz = vec4(g_vertex_normal_horz * size, 0.0); //size * g_vertex_normal_horz; + //g_vertex_normal_horz = normalize(v_normal[0]); //vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x); + g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; + g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); + g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); + + g_vertex_normal_horz = normalize(vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x)); + + g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //size * g_vertex_normal_horz; g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); //g_vertex_offset_vert = vec3(g_vertex_normal_vert.x * 0.5f, g_vertex_normal_vert.y * 0.5f, g_vertex_normal_vert.z * 0.5f); //size * g_vertex_normal_vert; - g_vertex_offset_vert = vec4(g_vertex_normal_vert * size, 0.0); + g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); f_vertex = v_vertex[0]; f_normal = g_vertex_normal_horz; @@ -134,108 +137,101 @@ geometry = gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); EmitVertex(); - EndPrimitive(); - } - - -poep = - #version 410 - - uniform highp mat4 u_modelMatrix; - uniform highp mat4 u_viewProjectionMatrix; - uniform highp mat4 u_modelViewProjectionMatrix; - - layout(lines) in; - layout(triangle_strip, max_vertices = 3) out; - - in vec4 v_color[]; - in vec3 v_vertex[]; - in vec3 v_normal[]; - in vec4 v_orig_vertex[]; - - out vec4 f_color; - out vec3 f_normal; - out vec3 f_vertex; - - void main() - { - int i; - vec4 delta; - vec3 g_normal; - vec3 g_offset; - - vec4 g_vertex_delta; - vec4 g_vertex_normal_horz; // horizontal and vertical in respect to layers - vec3 g_vertex_normal_vert; - vec3 g_vertex_offset_horz; - vec3 g_vertex_offset_vert; - - float size = 3; - - g_vertex_delta = v_orig_vertex[1] - v_orig_vertex[0]; - g_vertex_normal_horz = vec4(g_vertex_delta.z, 0.0, -g_vertex_delta.x, g_vertex_delta.w); - if (length(g_vertex_normal_horz) < 0.1) { - g_vertex_normal_horz = vec4(1.0, 0.0, 0.0, 0.0); - g_vertex_offset_horz = vec3(0.0, 0.0, 0.0); - g_vertex_offset_vert = vec3(0.0, 0.0, 0.0); - } else { - g_vertex_normal_horz = normalize(g_vertex_normal_horz); - g_vertex_offset_horz = (u_viewProjectionMatrix * u_modelMatrix * size * g_vertex_normal_horz).xyz; - g_vertex_normal_vert = vec3(0.0, 0.0, 1.0); - g_vertex_offset_vert = (u_viewProjectionMatrix * u_modelMatrix * size * g_vertex_normal_vert).xyz; - } - f_vertex = v_vertex[0]; - f_color = v_color[0]; f_normal = g_vertex_normal_horz; - gl_Position = gl_in[0].gl_Position + g_vertex_offset_horz; + f_color = v_color[0]; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; f_normal = g_vertex_normal_horz; - gl_Position = gl_in[1].gl_Position + g_vertex_offset_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); EmitVertex(); - f_vertex = v_vertex[0]; - f_color = v_color[0]; - f_normal = g_vertex_offset_vert; - gl_Position = gl_in[0].gl_Position + g_vertex_offset_vert; - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = g_vertex_offset_vert; - gl_Position = gl_in[1].gl_Position + g_vertex_offset_vert; - EmitVertex(); - - f_vertex = v_vertex[0]; - f_color = v_color[0]; - f_normal = -g_vertex_normal_horz; - gl_Position = gl_in[0].gl_Position - g_vertex_offset_horz; - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = -g_vertex_normal_horz; - gl_Position = gl_in[1].gl_Position - g_vertex_offset_horz; - EmitVertex(); - - f_vertex = v_vertex[0]; - f_color = v_color[0]; - f_normal = -g_vertex_offset_vert; - gl_Position = gl_in[0].gl_Position - g_vertex_offset_vert; - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = -g_vertex_offset_vert; - gl_Position = gl_in[1].gl_Position - g_vertex_offset_vert; - EmitVertex(); - - EndPrimitive(); + // left side + f_vertex = v_vertex[0]; + f_color = v_color[0]; + + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + f_normal = g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); + EmitVertex(); + + f_normal = g_vertex_normal_horz_head; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); + EmitVertex(); + + f_normal = -g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + EndPrimitive(); + + f_normal = -g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + f_normal = -g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); + EmitVertex(); + + f_normal = g_vertex_normal_horz_head; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); + EmitVertex(); + + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + EndPrimitive(); + + // right side + f_vertex = v_vertex[1]; + f_color = v_color[1]; + + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + f_normal = g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); + EmitVertex(); + + f_normal = -g_vertex_normal_horz_head; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); + EmitVertex(); + + f_normal = -g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + EndPrimitive(); + + f_normal = -g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + f_normal = -g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); + EmitVertex(); + + f_normal = -g_vertex_normal_horz_head; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); + EmitVertex(); + + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + EndPrimitive(); + + } @@ -271,6 +267,8 @@ fragment = //gl_FrontFacing = .. + //if ((f_normal).z < 0) {discard; } + mediump vec4 finalColor = vec4(0.0); finalColor += u_ambientColor; From 2b37bde6302142ed24bfc32881e78cd59a61c38b Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 22 Dec 2016 10:46:19 +0100 Subject: [PATCH 011/156] Now with infill --- cura/LayerPolygon.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index cb00bd0c60..f37e6a2f5e 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -49,7 +49,8 @@ class LayerPolygon: def buildCache(self): # For the line mesh we do not draw Infill or Jumps. Therefore those lines are filtered out. - self._build_cache_line_mesh_mask = numpy.logical_not(numpy.logical_or(self._jump_mask, self._types == LayerPolygon.InfillType )) + # self._build_cache_line_mesh_mask = numpy.logical_not(numpy.logical_or(self._jump_mask, self._types == LayerPolygon.InfillType )) + self._build_cache_line_mesh_mask = numpy.logical_not(self._jump_mask) mesh_line_count = numpy.sum(self._build_cache_line_mesh_mask) self._index_begin = 0 self._index_end = mesh_line_count From c12e6da3ac5224ae72111ae21a1e648f321c5e2d Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 22 Dec 2016 14:41:50 +0100 Subject: [PATCH 012/156] Started setting layer height and line width in layer view --- cura/Layer.py | 6 ++-- cura/LayerDataBuilder.py | 6 ++-- cura/LayerPolygon.py | 2 +- .../ProcessSlicedLayersJob.py | 10 +++++++ plugins/LayerView/layers.shader | 28 +++++++++++++------ 5 files changed, 37 insertions(+), 15 deletions(-) diff --git a/cura/Layer.py b/cura/Layer.py index bc9f66e881..794d282a47 100644 --- a/cura/Layer.py +++ b/cura/Layer.py @@ -49,14 +49,14 @@ class Layer: return result - def build(self, vertex_offset, index_offset, vertices, colors, indices, normals): + def build(self, vertex_offset, index_offset, vertices, colors, indices): result_vertex_offset = vertex_offset result_index_offset = index_offset self._element_count = 0 for polygon in self._polygons: polygon.build(result_vertex_offset, result_index_offset, vertices, colors, indices) - polygon_normals = polygon.getNormals() # [numpy.where(numpy.logical_not(polygon.jumpMask))] - normals[result_vertex_offset:result_vertex_offset+polygon.lineMeshVertexCount()] = polygon_normals[:polygon.lineMeshVertexCount()] + #polygon_normals = polygon.getNormals() # [numpy.where(numpy.logical_not(polygon.jumpMask))] + #normals[result_vertex_offset:result_vertex_offset+polygon.lineMeshVertexCount()] = polygon_normals[:polygon.lineMeshVertexCount()] result_vertex_offset += polygon.lineMeshVertexCount() result_index_offset += polygon.lineMeshElementCount() self._element_count += polygon.elementCount diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index 1bd26d1ddc..e32e60efd3 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -56,7 +56,7 @@ class LayerDataBuilder(MeshBuilder): index_count += data.lineMeshElementCount() vertices = numpy.empty((vertex_count, 3), numpy.float32) - normals = numpy.empty((vertex_count, 3), numpy.float32) + # normals = numpy.empty((vertex_count, 3), numpy.float32) # line_widths = numpy.empty((vertex_count, 3), numpy.float32) # strictly taken you need 1 less colors = numpy.empty((vertex_count, 4), numpy.float32) indices = numpy.empty((index_count, 2), numpy.int32) @@ -64,13 +64,13 @@ class LayerDataBuilder(MeshBuilder): vertex_offset = 0 index_offset = 0 for layer, data in self._layers.items(): - ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, indices, normals) + ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, indices) self._element_counts[layer] = data.elementCount self.addVertices(vertices) self.addColors(colors) self.addIndices(indices.flatten()) - self._normals = normals + #self._normals = normals return LayerData(vertices=self.getVertices(), normals=self.getNormals(), indices=self.getIndices(), colors=self.getColors(), uvs=self.getUVCoordinates(), file_name=self.getFileName(), diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index f37e6a2f5e..27b9a9c11d 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -60,7 +60,7 @@ class LayerPolygon: self._build_cache_needed_points[1:, 0][:, numpy.newaxis] = self._types[1:] != self._types[:-1] # Mark points as unneeded if they are of types we don't want in the line mesh according to the calculated mask numpy.logical_and(self._build_cache_needed_points, self._build_cache_line_mesh_mask, self._build_cache_needed_points ) - + self._vertex_begin = 0 self._vertex_end = numpy.sum( self._build_cache_needed_points ) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 6a64cfd5d6..7a2fa6072f 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -145,6 +145,16 @@ class ProcessSlicedLayersJob(Job): # We are done processing all the layers we got from the engine, now create a mesh out of the data layer_mesh = layer_data.build() + # Hack for adding line widths and heights: misuse u, v coordinates. + uvs = numpy.zeros([layer_mesh.getVertexCount(), 2], dtype=numpy.float32) + uvs[:, 0] = 0.175 + uvs[:, 1] = 0.125 + + from UM.Math import NumPyUtil + layer_mesh._uvs = NumPyUtil.immutableNDArray(uvs) + # mesh._uvs = numpy.zeros([layer_mesh.getVertexCount(), 2]) + # mesh._uvs[:, 0] = 1.0 # width + # mesh._uvs[:, 1] = 0.1 # height if self._abort_requested: if self._progress: diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 0e8791ef6a..f6a96f1eeb 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -10,11 +10,13 @@ vertex = attribute highp vec4 a_vertex; attribute lowp vec4 a_color; attribute highp vec4 a_normal; + attribute highp vec2 a_uvs; // misused here for width and height varying lowp vec4 v_color; varying highp vec3 v_vertex; varying highp vec3 v_normal; + varying lowp vec2 v_uvs; varying lowp vec4 f_color; varying highp vec3 f_vertex; @@ -32,6 +34,7 @@ vertex = v_vertex = world_space_vert.xyz; v_normal = (u_normalMatrix * normalize(a_normal)).xyz; + v_uvs = a_uvs; // for testing without geometry shader f_color = v_color; @@ -47,14 +50,12 @@ geometry = //uniform highp mat4 u_modelViewProjectionMatrix; layout(lines) in; - layout(triangle_strip, max_vertices = 28) out; - /*layout(std140) uniform Matrices { - mat4 u_modelViewProjectionMatrix; - };*/ + layout(triangle_strip, max_vertices = 26) out; in vec4 v_color[]; in vec3 v_vertex[]; in vec3 v_normal[]; + in vec2 v_uvs[]; out vec4 f_color; out vec3 f_normal; @@ -74,8 +75,8 @@ geometry = vec3 g_vertex_normal_horz_head; vec4 g_vertex_offset_horz_head; - const float size_x = 0.2; - const float size_y = 0.1; + float size_x = v_uvs[0].x; + float size_y = v_uvs[0].y; //g_vertex_normal_horz = normalize(v_normal[0]); //vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x); g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; @@ -90,25 +91,29 @@ geometry = g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); f_vertex = v_vertex[0]; - f_normal = g_vertex_normal_horz; f_color = v_color[0]; + //f_color = vec4(v_uvs[0], 0.0, 1.0); + f_normal = g_vertex_normal_horz; gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; + //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = g_vertex_normal_horz; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[0]; f_color = v_color[0]; + //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = g_vertex_normal_vert; gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; + //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = g_vertex_normal_vert; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); EmitVertex(); @@ -116,23 +121,27 @@ geometry = f_vertex = v_vertex[0]; f_normal = -g_vertex_normal_horz; f_color = v_color[0]; + //f_color = vec4(v_uvs[0], 0.0, 1.0); gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; + //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = -g_vertex_normal_horz; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[0]; f_color = v_color[0]; + //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = -g_vertex_normal_vert; gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; + //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = -g_vertex_normal_vert; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); EmitVertex(); @@ -140,11 +149,13 @@ geometry = f_vertex = v_vertex[0]; f_normal = g_vertex_normal_horz; f_color = v_color[0]; + //f_color = vec4(v_uvs[0], 0.0, 1.0); gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; + //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = g_vertex_normal_horz; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); EmitVertex(); @@ -313,4 +324,5 @@ u_lightPosition = light_0_position [attributes] a_vertex = vertex a_color = color -a_normal = normal \ No newline at end of file +a_normal = normal +a_uvs = uv0 From 9904dad07b17aacdc7175d82f98a1ac161609ba4 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 28 Dec 2016 11:30:59 +0100 Subject: [PATCH 013/156] Added line thickness to layer view --- cura/Layer.py | 5 +++-- cura/LayerDataBuilder.py | 5 +++-- cura/LayerPolygon.py | 11 ++++++++--- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 10 +++++----- plugins/LayerView/layers.shader | 8 +++++--- 5 files changed, 24 insertions(+), 15 deletions(-) diff --git a/cura/Layer.py b/cura/Layer.py index 794d282a47..9fc744e9de 100644 --- a/cura/Layer.py +++ b/cura/Layer.py @@ -49,12 +49,13 @@ class Layer: return result - def build(self, vertex_offset, index_offset, vertices, colors, indices): + def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, indices): result_vertex_offset = vertex_offset result_index_offset = index_offset self._element_count = 0 + thickness = self._thickness / 1000 # micrometer to millimeter for polygon in self._polygons: - polygon.build(result_vertex_offset, result_index_offset, vertices, colors, indices) + polygon.build(result_vertex_offset, result_index_offset, vertices, colors, line_dimensions, indices, thickness) #polygon_normals = polygon.getNormals() # [numpy.where(numpy.logical_not(polygon.jumpMask))] #normals[result_vertex_offset:result_vertex_offset+polygon.lineMeshVertexCount()] = polygon_normals[:polygon.lineMeshVertexCount()] result_vertex_offset += polygon.lineMeshVertexCount() diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index e32e60efd3..7ff8a3737a 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -57,19 +57,20 @@ class LayerDataBuilder(MeshBuilder): vertices = numpy.empty((vertex_count, 3), numpy.float32) # normals = numpy.empty((vertex_count, 3), numpy.float32) - # line_widths = numpy.empty((vertex_count, 3), numpy.float32) # strictly taken you need 1 less + line_dimensions = numpy.empty((vertex_count, 2), numpy.float32) colors = numpy.empty((vertex_count, 4), numpy.float32) indices = numpy.empty((index_count, 2), numpy.int32) vertex_offset = 0 index_offset = 0 for layer, data in self._layers.items(): - ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, indices) + ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, line_dimensions, indices) self._element_counts[layer] = data.elementCount self.addVertices(vertices) self.addColors(colors) self.addIndices(indices.flatten()) + self._uvs = line_dimensions #self._normals = normals return LayerData(vertices=self.getVertices(), normals=self.getNormals(), indices=self.getIndices(), diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 27b9a9c11d..628fd78350 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -64,8 +64,9 @@ class LayerPolygon: self._vertex_begin = 0 self._vertex_end = numpy.sum( self._build_cache_needed_points ) - - def build(self, vertex_offset, index_offset, vertices, colors, indices): + ## build + # line_thicknesses: array with type as index and thickness as value + def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, indices, thickness): if (self._build_cache_line_mesh_mask is None) or (self._build_cache_needed_points is None ): self.buildCache() @@ -84,9 +85,13 @@ class LayerPolygon: # Points are picked based on the index list to get the vertices needed. vertices[self._vertex_begin:self._vertex_end, :] = self._data[index_list, :] # Create an array with colors for each vertex and remove the color data for the points that has been thrown away. - colors[self._vertex_begin:self._vertex_end, :] = numpy.tile(self._colors, (1, 2)).reshape((-1, 4))[needed_points_list.ravel()] + colors[self._vertex_begin:self._vertex_end, :] = numpy.tile(self._colors, (1, 2)).reshape((-1, 4))[needed_points_list.ravel()] colors[self._vertex_begin:self._vertex_end, :] *= numpy.array([[0.5, 0.5, 0.5, 1.0]], numpy.float32) + # Create an array with line widths for each vertex. + line_dimensions[self._vertex_begin:self._vertex_end, :] = numpy.tile(self._line_widths, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()] + line_dimensions[self._vertex_begin:self._vertex_end, 1] = thickness + # The relative values of begin and end indices have already been set in buildCache, so we only need to offset them to the parents offset. self._index_begin += index_offset self._index_end += index_offset diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 7a2fa6072f..f8b80e9da0 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -146,12 +146,12 @@ class ProcessSlicedLayersJob(Job): # We are done processing all the layers we got from the engine, now create a mesh out of the data layer_mesh = layer_data.build() # Hack for adding line widths and heights: misuse u, v coordinates. - uvs = numpy.zeros([layer_mesh.getVertexCount(), 2], dtype=numpy.float32) - uvs[:, 0] = 0.175 - uvs[:, 1] = 0.125 + #uvs = numpy.zeros([layer_mesh.getVertexCount(), 2], dtype=numpy.float32) + #uvs[:, 0] = 0.175 + #uvs[:, 1] = 0.125 - from UM.Math import NumPyUtil - layer_mesh._uvs = NumPyUtil.immutableNDArray(uvs) + #from UM.Math import NumPyUtil + #layer_mesh._uvs = NumPyUtil.immutableNDArray(uvs) # mesh._uvs = numpy.zeros([layer_mesh.getVertexCount(), 2]) # mesh._uvs[:, 0] = 1.0 # width # mesh._uvs[:, 1] = 0.1 # height diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index f6a96f1eeb..0cff84d233 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -24,7 +24,9 @@ vertex = void main() { - vec4 world_space_vert = u_modelMatrix * a_vertex; + vec4 v1_vertex = a_vertex; + v1_vertex.y -= a_uvs.y / 2; // half layer down + vec4 world_space_vert = u_modelMatrix * v1_vertex; // gl_Position = u_viewProjectionMatrix * world_space_vert; gl_Position = world_space_vert; // gl_Position = u_modelViewProjectionMatrix * a_vertex; @@ -75,8 +77,8 @@ geometry = vec3 g_vertex_normal_horz_head; vec4 g_vertex_offset_horz_head; - float size_x = v_uvs[0].x; - float size_y = v_uvs[0].y; + float size_x = v_uvs[0].x / 2 + 0.01; // radius, and make it nicely overlapping + float size_y = v_uvs[0].y / 2 + 0.01; //g_vertex_normal_horz = normalize(v_normal[0]); //vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x); g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; From 8d2b3654a4ff8d107b97fb2297cc27bd05315ed5 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 28 Dec 2016 13:15:42 +0100 Subject: [PATCH 014/156] Layer thickness now as array --- cura/LayerPolygon.py | 9 +++++---- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 10 +++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 628fd78350..858fa11c77 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -18,13 +18,14 @@ class LayerPolygon: __jump_map = numpy.logical_or(numpy.logical_or(numpy.arange(11) == NoneType, numpy.arange(11) == MoveCombingType), numpy.arange(11) == MoveRetractionType) - def __init__(self, mesh, extruder, line_types, data, line_widths): + def __init__(self, mesh, extruder, line_types, data, line_widths, line_thicknesses): self._mesh = mesh self._extruder = extruder self._types = line_types self._data = data self._line_widths = line_widths - + self._line_thicknesses = line_thicknesses + self._vertex_begin = 0 self._vertex_end = 0 self._index_begin = 0 @@ -89,8 +90,8 @@ class LayerPolygon: colors[self._vertex_begin:self._vertex_end, :] *= numpy.array([[0.5, 0.5, 0.5, 1.0]], numpy.float32) # Create an array with line widths for each vertex. - line_dimensions[self._vertex_begin:self._vertex_end, :] = numpy.tile(self._line_widths, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()] - line_dimensions[self._vertex_begin:self._vertex_end, 1] = thickness + line_dimensions[self._vertex_begin:self._vertex_end, 0] = numpy.tile(self._line_widths, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0] + line_dimensions[self._vertex_begin:self._vertex_end, 1] = numpy.tile(self._line_thicknesses, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0] # The relative values of begin and end indices have already been set in buildCache, so we only need to offset them to the parents offset. self._index_begin += index_offset diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index f8b80e9da0..7b814d99b4 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -92,7 +92,6 @@ class ProcessSlicedLayersJob(Job): layer_data.addLayer(abs_layer_number) this_layer = layer_data.getLayer(abs_layer_number) layer_data.setLayerHeight(abs_layer_number, layer.height) - layer_data.setLayerThickness(abs_layer_number, layer.thickness) for p in range(layer.repeatedMessageCount("path_segment")): polygon = layer.getRepeatedMessage("path_segment", p) @@ -110,7 +109,12 @@ class ProcessSlicedLayersJob(Job): line_widths = numpy.fromstring(polygon.line_width, dtype="f4") # Convert bytearray to numpy array line_widths = line_widths.reshape((-1,1)) # We get a linear list of pairs that make up the points, so make numpy interpret them correctly. - + + # In the future, line_thicknesses should be given by CuraEngine as well. + # Currently the infill layer thickness also translates to line width + line_thicknesses = numpy.zeros(line_widths.shape, dtype="f4") + line_thicknesses[:] = layer.thickness / 1000 # from micrometer to millimeter + # Create a new 3D-array, copy the 2D points over and insert the right height. # This uses manual array creation + copy rather than numpy.insert since this is # faster. @@ -124,7 +128,7 @@ class ProcessSlicedLayersJob(Job): new_points[:, 1] = points[:, 2] new_points[:, 2] = -points[:, 1] - this_poly = LayerPolygon.LayerPolygon(layer_data, extruder, line_types, new_points, line_widths) + this_poly = LayerPolygon.LayerPolygon(layer_data, extruder, line_types, new_points, line_widths, line_thicknesses) this_poly.buildCache() this_layer.polygons.append(this_poly) From 0f2fb86cd9872843eb73d86cbb5e001c75ad93dd Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 28 Dec 2016 15:20:14 +0100 Subject: [PATCH 015/156] Layer shader now uses own attribute for line dimensions instead of misusing uvs. --- cura/Layer.py | 5 +--- cura/LayerData.py | 4 +-- cura/LayerDataBuilder.py | 12 +++++--- cura/LayerPolygon.py | 3 +- .../ProcessSlicedLayersJob.py | 10 ------- plugins/LayerView/layers.shader | 28 ++++++------------- 6 files changed, 22 insertions(+), 40 deletions(-) diff --git a/cura/Layer.py b/cura/Layer.py index 9fc744e9de..3103d1772e 100644 --- a/cura/Layer.py +++ b/cura/Layer.py @@ -53,11 +53,8 @@ class Layer: result_vertex_offset = vertex_offset result_index_offset = index_offset self._element_count = 0 - thickness = self._thickness / 1000 # micrometer to millimeter for polygon in self._polygons: - polygon.build(result_vertex_offset, result_index_offset, vertices, colors, line_dimensions, indices, thickness) - #polygon_normals = polygon.getNormals() # [numpy.where(numpy.logical_not(polygon.jumpMask))] - #normals[result_vertex_offset:result_vertex_offset+polygon.lineMeshVertexCount()] = polygon_normals[:polygon.lineMeshVertexCount()] + polygon.build(result_vertex_offset, result_index_offset, vertices, colors, line_dimensions, indices) result_vertex_offset += polygon.lineMeshVertexCount() result_index_offset += polygon.lineMeshElementCount() self._element_count += polygon.elementCount diff --git a/cura/LayerData.py b/cura/LayerData.py index ad5326373e..3fe550c297 100644 --- a/cura/LayerData.py +++ b/cura/LayerData.py @@ -6,9 +6,9 @@ from UM.Mesh.MeshData import MeshData # Immutable, use LayerDataBuilder to create one of these. class LayerData(MeshData): def __init__(self, vertices = None, normals = None, indices = None, colors = None, uvs = None, file_name = None, - center_position = None, layers=None, element_counts=None): + center_position = None, layers=None, element_counts=None, attributes=None): super().__init__(vertices=vertices, normals=normals, indices=indices, colors=colors, uvs=uvs, - file_name=file_name, center_position=center_position) + file_name=file_name, center_position=center_position, attributes=attributes) self._layers = layers self._element_counts = element_counts diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index 7ff8a3737a..41c7790102 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -56,7 +56,6 @@ class LayerDataBuilder(MeshBuilder): index_count += data.lineMeshElementCount() vertices = numpy.empty((vertex_count, 3), numpy.float32) - # normals = numpy.empty((vertex_count, 3), numpy.float32) line_dimensions = numpy.empty((vertex_count, 2), numpy.float32) colors = numpy.empty((vertex_count, 4), numpy.float32) indices = numpy.empty((index_count, 2), numpy.int32) @@ -70,10 +69,15 @@ class LayerDataBuilder(MeshBuilder): self.addVertices(vertices) self.addColors(colors) self.addIndices(indices.flatten()) - self._uvs = line_dimensions - #self._normals = normals + # self._uvs = line_dimensions + attributes = { + "line_dimensions": { + "value": line_dimensions, + "opengl_name": "a_line_dim", + "opengl_type": "vector2f"} + } return LayerData(vertices=self.getVertices(), normals=self.getNormals(), indices=self.getIndices(), colors=self.getColors(), uvs=self.getUVCoordinates(), file_name=self.getFileName(), center_position=self.getCenterPosition(), layers=self._layers, - element_counts=self._element_counts) + element_counts=self._element_counts, attributes=attributes) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 858fa11c77..439146e6e2 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -67,7 +67,7 @@ class LayerPolygon: ## build # line_thicknesses: array with type as index and thickness as value - def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, indices, thickness): + def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, indices): if (self._build_cache_line_mesh_mask is None) or (self._build_cache_needed_points is None ): self.buildCache() @@ -85,6 +85,7 @@ class LayerPolygon: # Points are picked based on the index list to get the vertices needed. vertices[self._vertex_begin:self._vertex_end, :] = self._data[index_list, :] + # Create an array with colors for each vertex and remove the color data for the points that has been thrown away. colors[self._vertex_begin:self._vertex_end, :] = numpy.tile(self._colors, (1, 2)).reshape((-1, 4))[needed_points_list.ravel()] colors[self._vertex_begin:self._vertex_end, :] *= numpy.array([[0.5, 0.5, 0.5, 1.0]], numpy.float32) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 7b814d99b4..be148e41f6 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -149,16 +149,6 @@ class ProcessSlicedLayersJob(Job): # We are done processing all the layers we got from the engine, now create a mesh out of the data layer_mesh = layer_data.build() - # Hack for adding line widths and heights: misuse u, v coordinates. - #uvs = numpy.zeros([layer_mesh.getVertexCount(), 2], dtype=numpy.float32) - #uvs[:, 0] = 0.175 - #uvs[:, 1] = 0.125 - - #from UM.Math import NumPyUtil - #layer_mesh._uvs = NumPyUtil.immutableNDArray(uvs) - # mesh._uvs = numpy.zeros([layer_mesh.getVertexCount(), 2]) - # mesh._uvs[:, 0] = 1.0 # width - # mesh._uvs[:, 1] = 0.1 # height if self._abort_requested: if self._progress: diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 0cff84d233..cb34360226 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -10,13 +10,14 @@ vertex = attribute highp vec4 a_vertex; attribute lowp vec4 a_color; attribute highp vec4 a_normal; - attribute highp vec2 a_uvs; // misused here for width and height + attribute highp vec2 a_line_dim; // line width and thickness varying lowp vec4 v_color; varying highp vec3 v_vertex; varying highp vec3 v_normal; - varying lowp vec2 v_uvs; + //varying lowp vec2 v_uvs; + varying lowp vec2 v_line_dim; varying lowp vec4 f_color; varying highp vec3 f_vertex; @@ -25,7 +26,7 @@ vertex = void main() { vec4 v1_vertex = a_vertex; - v1_vertex.y -= a_uvs.y / 2; // half layer down + v1_vertex.y -= a_line_dim.y / 2; // half layer down vec4 world_space_vert = u_modelMatrix * v1_vertex; // gl_Position = u_viewProjectionMatrix * world_space_vert; gl_Position = world_space_vert; @@ -36,7 +37,7 @@ vertex = v_vertex = world_space_vert.xyz; v_normal = (u_normalMatrix * normalize(a_normal)).xyz; - v_uvs = a_uvs; + v_line_dim = a_line_dim; // for testing without geometry shader f_color = v_color; @@ -47,9 +48,7 @@ vertex = geometry = #version 410 - //uniform highp mat4 u_modelMatrix; uniform highp mat4 u_viewProjectionMatrix; - //uniform highp mat4 u_modelViewProjectionMatrix; layout(lines) in; layout(triangle_strip, max_vertices = 26) out; @@ -57,7 +56,7 @@ geometry = in vec4 v_color[]; in vec3 v_vertex[]; in vec3 v_normal[]; - in vec2 v_uvs[]; + in vec2 v_line_dim[]; out vec4 f_color; out vec3 f_normal; @@ -65,10 +64,6 @@ geometry = void main() { - //int i; - //vec3 g_normal; - //vec3 g_offset; - vec4 g_vertex_delta; vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position @@ -77,8 +72,8 @@ geometry = vec3 g_vertex_normal_horz_head; vec4 g_vertex_offset_horz_head; - float size_x = v_uvs[0].x / 2 + 0.01; // radius, and make it nicely overlapping - float size_y = v_uvs[0].y / 2 + 0.01; + float size_x = v_line_dim[0].x / 2 + 0.01; // radius, and make it nicely overlapping + float size_y = v_line_dim[0].y / 2 + 0.01; //g_vertex_normal_horz = normalize(v_normal[0]); //vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x); g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; @@ -89,7 +84,6 @@ geometry = g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //size * g_vertex_normal_horz; g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); - //g_vertex_offset_vert = vec3(g_vertex_normal_vert.x * 0.5f, g_vertex_normal_vert.y * 0.5f, g_vertex_normal_vert.z * 0.5f); //size * g_vertex_normal_vert; g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); f_vertex = v_vertex[0]; @@ -243,10 +237,6 @@ geometry = EmitVertex(); EndPrimitive(); - - - - } fragment = @@ -327,4 +317,4 @@ u_lightPosition = light_0_position a_vertex = vertex a_color = color a_normal = normal -a_uvs = uv0 +a_line_dim = line_dim From 1217281727d9496a7c31b1f36872eec88e91bbdd Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 29 Dec 2016 16:49:00 +0100 Subject: [PATCH 016/156] Busy with layer_view options --- cura/Layer.py | 4 +- cura/LayerDataBuilder.py | 27 ++++-- cura/LayerPolygon.py | 6 +- .../ProcessSlicedLayersJob.py | 34 +++++++- plugins/LayerView/LayerPass.py | 4 + plugins/LayerView/LayerView.qml | 72 +++++++++++++++ plugins/LayerView/layers.shader | 87 +++++++++++-------- 7 files changed, 187 insertions(+), 47 deletions(-) diff --git a/cura/Layer.py b/cura/Layer.py index 3103d1772e..8d35e9c6b2 100644 --- a/cura/Layer.py +++ b/cura/Layer.py @@ -49,12 +49,12 @@ class Layer: return result - def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, indices): + def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, indices): result_vertex_offset = vertex_offset result_index_offset = index_offset self._element_count = 0 for polygon in self._polygons: - polygon.build(result_vertex_offset, result_index_offset, vertices, colors, line_dimensions, indices) + polygon.build(result_vertex_offset, result_index_offset, vertices, colors, line_dimensions, extruders, indices) result_vertex_offset += polygon.lineMeshVertexCount() result_index_offset += polygon.lineMeshElementCount() self._element_count += polygon.elementCount diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index 41c7790102..2b46a604b7 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -48,7 +48,8 @@ class LayerDataBuilder(MeshBuilder): self._layers[layer].setThickness(thickness) - def build(self): + # material color map: [r, g, b, a] for each extruder row. + def build(self, material_color_map): vertex_count = 0 index_count = 0 for layer, data in self._layers.items(): @@ -59,23 +60,39 @@ class LayerDataBuilder(MeshBuilder): line_dimensions = numpy.empty((vertex_count, 2), numpy.float32) colors = numpy.empty((vertex_count, 4), numpy.float32) indices = numpy.empty((index_count, 2), numpy.int32) + extruders = numpy.empty((vertex_count), numpy.float32) vertex_offset = 0 index_offset = 0 for layer, data in self._layers.items(): - ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, line_dimensions, indices) + ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, indices) self._element_counts[layer] = data.elementCount self.addVertices(vertices) self.addColors(colors) self.addIndices(indices.flatten()) - # self._uvs = line_dimensions + + material_colors = numpy.zeros((line_dimensions.shape[0], 4), dtype=numpy.float32) + for extruder_nr in range(material_color_map.shape[0]): + material_colors[extruders == extruder_nr] = material_color_map[extruder_nr] + attributes = { "line_dimensions": { "value": line_dimensions, "opengl_name": "a_line_dim", - "opengl_type": "vector2f"} - } + "opengl_type": "vector2f" + }, + "extruders": { + "value": extruders, + "opengl_name": "a_extruder", + "opengl_type": "float" + }, + "colors": { + "value": material_colors, + "opengl_name": "a_material_color", + "opengl_type": "vector4f" + }, + } return LayerData(vertices=self.getVertices(), normals=self.getNormals(), indices=self.getIndices(), colors=self.getColors(), uvs=self.getUVCoordinates(), file_name=self.getFileName(), diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 439146e6e2..bb37d641bb 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -38,7 +38,7 @@ class LayerPolygon: # Buffering the colors shouldn't be necessary as it is not # re-used and can save alot of memory usage. - self._color_map = self.__color_map * [1, 1, 1, self._extruder] # The alpha component is used to store the extruder nr + self._color_map = self.__color_map # * [1, 1, 1, self._extruder] # The alpha component is used to store the extruder nr self._colors = self._color_map[self._types] # When type is used as index returns true if type == LayerPolygon.InfillType or type == LayerPolygon.SkinType or type == LayerPolygon.SupportInfillType @@ -67,7 +67,7 @@ class LayerPolygon: ## build # line_thicknesses: array with type as index and thickness as value - def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, indices): + def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, indices): if (self._build_cache_line_mesh_mask is None) or (self._build_cache_needed_points is None ): self.buildCache() @@ -94,6 +94,8 @@ class LayerPolygon: line_dimensions[self._vertex_begin:self._vertex_end, 0] = numpy.tile(self._line_widths, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0] line_dimensions[self._vertex_begin:self._vertex_end, 1] = numpy.tile(self._line_thicknesses, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0] + extruders[self._vertex_begin:self._vertex_end] = float(self._extruder) + # The relative values of begin and end indices have already been set in buildCache, so we only need to offset them to the parents offset. self._index_begin += index_offset self._index_end += index_offset diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index be148e41f6..d7be0f1a52 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -24,6 +24,14 @@ from time import time catalog = i18nCatalog("cura") +def colorCodeToRGBA(color_code): + return [ + int(color_code[1:3], 16) / 255, + int(color_code[3:5], 16) / 255, + int(color_code[5:7], 16) / 255, + 1.0] + + class ProcessSlicedLayersJob(Job): def __init__(self, layers): super().__init__() @@ -148,7 +156,31 @@ class ProcessSlicedLayersJob(Job): self._progress.setProgress(progress) # We are done processing all the layers we got from the engine, now create a mesh out of the data - layer_mesh = layer_data.build() + + # Find out colors per extruder + # TODO: move to a better place. Code is similar to code in ExtrudersModel + from cura.Settings.ExtruderManager import ExtruderManager + import UM + global_container_stack = UM.Application.getInstance().getGlobalContainerStack() + manager = ExtruderManager.getInstance() + extruders = list(manager.getMachineExtruders(global_container_stack.getId())) + if extruders: + material_color_map = numpy.zeros((len(extruders), 4), dtype=numpy.float32) + for extruder in extruders: + material = extruder.findContainer({"type": "material"}) + position = int(extruder.getMetaDataEntry("position", default="0")) # Get the position + color_code = material.getMetaDataEntry("color_code") + color = colorCodeToRGBA(color_code) + material_color_map[position, :] = color + else: + # Single extruder via global stack. + material_color_map = numpy.zeros((1, 4), dtype=numpy.float32) + material = global_container_stack.findContainer({"type": "material"}) + color_code = material.getMetaDataEntry("color_code") + color = colorCodeToRGBA(color_code) + material_color_map[0, :] = color + + layer_mesh = layer_data.build(material_color_map) if self._abort_requested: if self._progress: diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index 378f7278c4..dda35624ec 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -37,6 +37,10 @@ class LayerPass(RenderPass): self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("LayerView"), "layers.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))) + self._layer_shader.setUniformValue("u_layer_view_type", 0) + self._layer_shader.setUniformValue("u_only_color_active_extruder", 1) + self._layer_shader.setUniformValue("u_extruder_opacity", [1, 1, 1, 1]) + if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index fef0c52c12..68c51e5752 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -95,6 +95,7 @@ Item } Rectangle { + id: slider_background anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter z: slider.z - 1 @@ -113,4 +114,75 @@ Item } } } + + Rectangle { + anchors.left: parent.left + anchors.verticalCenter: parent.verticalCenter + anchors.top: slider_background.bottom + width: UM.Theme.getSize("slider_layerview_background").width * 3 + height: slider.height + UM.Theme.getSize("default_margin").height * 2 + color: UM.Theme.getColor("tool_panel_background"); + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + + ListModel + { + id: layerViewTypes + ListElement { + text: "Line type" + type_id: 0 // these ids match the switching in the shader + } + ListElement { + text: "Material color" + type_id: 1 + } + ListElement { + text: "Printing speed" + type_id: 2 + } + } + + ComboBox + { + id: layer_type_combobox + anchors.top: slider_background.bottom + model: layerViewTypes + onActivated: { + CuraApplication.log("Combobox" + String(index)); + CuraApplication.log(layerViewTypes.get(index).type_id); + } + } + + ColumnLayout { + anchors.top: layer_type_combobox.bottom + CheckBox { + checked: true + onClicked: { + CuraApplication.log("First"); + } + text: "Extruder 1" + } + CheckBox { + checked: true + onClicked: { + CuraApplication.log("First"); + } + text: "Extruder 2" + } + CheckBox { + onClicked: { + CuraApplication.log("First"); + } + text: "Travel moves" + } + CheckBox { + checked: true + onClicked: { + CuraApplication.log("First"); + } + text: "Only color active extruder" + } + } + + } } diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index cb34360226..869230e87d 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -4,24 +4,33 @@ vertex = //uniform highp mat4 u_viewProjectionMatrix; //uniform highp mat4 u_modelViewProjectionMatrix; uniform lowp float u_active_extruder; + uniform lowp int u_layer_view_type; + uniform lowp int u_only_color_active_extruder; + uniform lowp vec4 u_extruder_opacity; // currently only for max 4 extruders, others always visible + uniform lowp float u_shade_factor; uniform highp mat4 u_normalMatrix; attribute highp vec4 a_vertex; attribute lowp vec4 a_color; + attribute lowp vec4 a_material_color; attribute highp vec4 a_normal; attribute highp vec2 a_line_dim; // line width and thickness + attribute highp int a_extruder; varying lowp vec4 v_color; + //varying lowp vec4 v_material_color; varying highp vec3 v_vertex; varying highp vec3 v_normal; //varying lowp vec2 v_uvs; varying lowp vec2 v_line_dim; + varying highp int v_extruder; varying lowp vec4 f_color; varying highp vec3 f_vertex; varying highp vec3 f_normal; + varying highp int f_extruder; void main() { @@ -32,17 +41,38 @@ vertex = gl_Position = world_space_vert; // gl_Position = u_modelViewProjectionMatrix * a_vertex; // shade the color depending on the extruder index stored in the alpha component of the color - v_color = (a_color.a == u_active_extruder) ? a_color : vec4(0.4, 0.4, 0.4, 1.0); //a_color * u_shade_factor; - v_color.a = 1.0; + + switch (u_layer_view_type) { + case 0: // "Line type" + v_color = a_color; + break; + case 1: // "Material color" + v_color = a_material_color; + break; + case 2: // "Speed" + v_color = a_color; + break; + } + if (u_only_color_active_extruder == 1) { + v_color = (a_extruder == u_active_extruder) ? v_color : vec4(0.4, 0.4, 0.4, 1.0); + } else { + v_color = (a_extruder == u_active_extruder) ? v_color : v_color * u_shade_factor; + } + if (a_extruder < 4) { + v_color.a *= u_extruder_opacity[a_extruder]; // make it (in)visible + } v_vertex = world_space_vert.xyz; v_normal = (u_normalMatrix * normalize(a_normal)).xyz; v_line_dim = a_line_dim; + v_extruder = a_extruder; + //v_material_color = a_material_color; // for testing without geometry shader f_color = v_color; f_vertex = v_vertex; f_normal = v_normal; + f_extruder = v_extruder; } geometry = @@ -57,10 +87,14 @@ geometry = in vec3 v_vertex[]; in vec3 v_normal[]; in vec2 v_line_dim[]; + in int v_extruder[]; + //in vec4 v_material_color[]; out vec4 f_color; out vec3 f_normal; out vec3 f_vertex; + out uint f_extruder; + //out vec4 f_material_color; void main() { @@ -75,6 +109,9 @@ geometry = float size_x = v_line_dim[0].x / 2 + 0.01; // radius, and make it nicely overlapping float size_y = v_line_dim[0].y / 2 + 0.01; + f_extruder = v_extruder[0]; + //f_material_color = v_material_color[0]; + //g_vertex_normal_horz = normalize(v_normal[0]); //vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x); g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); @@ -241,41 +278,19 @@ geometry = fragment = varying lowp vec4 f_color; + //varying lowp vec4 f_material_color; varying lowp vec3 f_normal; varying lowp vec3 f_vertex; + //flat varying lowp uint f_extruder; uniform mediump vec4 u_ambientColor; - uniform mediump vec4 u_diffuseColor; - //uniform mediump vec4 u_specularColor; - //uniform mediump float u_shininess; - uniform highp vec3 u_lightPosition; - void Impostor(in float sphereRadius, in vec3 cameraSpherePos, in vec2 mapping, out vec3 cameraPos, out vec3 cameraNormal) - { - float lensqr = dot(mapping, mapping); - if(lensqr > 1.0) - discard; - - cameraNormal = vec3(mapping, sqrt(1.0 - lensqr)); - cameraPos = (cameraNormal * sphereRadius) + cameraSpherePos; - } - void main() { - vec3 cameraPos; - vec3 cameraNormal; - - //Impostor(0.2, vec3(0.0, 0.0, 0.0), vec2(0.1, 0.1), cameraPos, cameraNormal); - - //gl_FrontFacing = .. - - //if ((f_normal).z < 0) {discard; } - mediump vec4 finalColor = vec4(0.0); finalColor += u_ambientColor; - //finalColor = f_color; highp vec3 normal = normalize(f_normal); highp vec3 lightDir = normalize(u_lightPosition - f_vertex); @@ -283,23 +298,19 @@ fragment = // Diffuse Component highp float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0); finalColor += (NdotL * f_color); + //finalColor += (NdotL * f_material_color); + //finalColor.a = 1.0; - // Specular Component - // TODO: We should not do specularity for fragments facing away from the light. - /*highp vec3 reflectedLight = reflect(-lightDir, normal); - highp vec3 viewVector = normalize(u_viewPosition - f_vertex); - highp float NdotR = clamp(dot(viewVector, reflectedLight), 0.0, 1.0); - finalColor += pow(NdotR, u_shininess) * u_specularColor;*/ - - finalColor.a = 1.0; gl_FragColor = finalColor; - - //gl_FragColor = f_color; - //gl_FragColor = vec4(f_normal, 1.0); } + [defaults] u_active_extruder = 0.0 +u_layer_view_type = 0 +u_only_color_active_extruder = 1 +u_extruder_opacity = [1.0, 1.0] + u_shade_factor = 0.60 u_specularColor = [0.4, 0.4, 0.4, 1.0] u_ambientColor = [0.3, 0.3, 0.3, 0.3] @@ -318,3 +329,5 @@ a_vertex = vertex a_color = color a_normal = normal a_line_dim = line_dim +a_extruder = extruders +a_material_color = material_color From fc4c60b0dcfe8198831915ebf2d1de2dda653dfb Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Fri, 30 Dec 2016 14:31:53 +0100 Subject: [PATCH 017/156] Added layer view options --- cura/Layer.py | 4 +- cura/LayerDataBuilder.py | 12 +++++- cura/LayerPolygon.py | 11 ++++-- plugins/LayerView/LayerPass.py | 28 +++++++++----- plugins/LayerView/LayerView.py | 34 +++++++++++++++++ plugins/LayerView/LayerView.qml | 18 +++++---- plugins/LayerView/LayerViewProxy.py | 25 ++++++++++++ plugins/LayerView/layers.shader | 59 ++++++++++++++++------------- resources/shaders/overhang.shader | 42 ++------------------ 9 files changed, 143 insertions(+), 90 deletions(-) diff --git a/cura/Layer.py b/cura/Layer.py index 8d35e9c6b2..869b84ed90 100644 --- a/cura/Layer.py +++ b/cura/Layer.py @@ -49,12 +49,12 @@ class Layer: return result - def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, indices): + def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, line_types, indices): result_vertex_offset = vertex_offset result_index_offset = index_offset self._element_count = 0 for polygon in self._polygons: - polygon.build(result_vertex_offset, result_index_offset, vertices, colors, line_dimensions, extruders, indices) + polygon.build(result_vertex_offset, result_index_offset, vertices, colors, line_dimensions, extruders, line_types, indices) result_vertex_offset += polygon.lineMeshVertexCount() result_index_offset += polygon.lineMeshElementCount() self._element_count += polygon.elementCount diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index 2b46a604b7..6750b60d53 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -60,12 +60,13 @@ class LayerDataBuilder(MeshBuilder): line_dimensions = numpy.empty((vertex_count, 2), numpy.float32) colors = numpy.empty((vertex_count, 4), numpy.float32) indices = numpy.empty((index_count, 2), numpy.int32) - extruders = numpy.empty((vertex_count), numpy.float32) + extruders = numpy.empty((vertex_count), numpy.int32) + line_types = numpy.empty((vertex_count), numpy.int32) vertex_offset = 0 index_offset = 0 for layer, data in self._layers.items(): - ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, indices) + ( vertex_offset, index_offset ) = data.build( vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, line_types, indices) self._element_counts[layer] = data.elementCount self.addVertices(vertices) @@ -75,6 +76,8 @@ class LayerDataBuilder(MeshBuilder): material_colors = numpy.zeros((line_dimensions.shape[0], 4), dtype=numpy.float32) for extruder_nr in range(material_color_map.shape[0]): material_colors[extruders == extruder_nr] = material_color_map[extruder_nr] + material_colors[line_types == LayerPolygon.MoveCombingType] = [0.0, 0.0, 0.8, 1.0] + material_colors[line_types == LayerPolygon.MoveRetractionType] = [0.0, 0.0, 0.8, 1.0] attributes = { "line_dimensions": { @@ -92,6 +95,11 @@ class LayerDataBuilder(MeshBuilder): "opengl_name": "a_material_color", "opengl_type": "vector4f" }, + "line_types": { + "value": line_types, + "opengl_name": "a_line_type", + "opengl_type": "float" + } } return LayerData(vertices=self.getVertices(), normals=self.getNormals(), indices=self.getIndices(), diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index bb37d641bb..f7acc62286 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -51,7 +51,7 @@ class LayerPolygon: def buildCache(self): # For the line mesh we do not draw Infill or Jumps. Therefore those lines are filtered out. # self._build_cache_line_mesh_mask = numpy.logical_not(numpy.logical_or(self._jump_mask, self._types == LayerPolygon.InfillType )) - self._build_cache_line_mesh_mask = numpy.logical_not(self._jump_mask) + self._build_cache_line_mesh_mask = numpy.ones(self._jump_mask.shape, dtype=bool) # numpy.logical_not(self._jump_mask) mesh_line_count = numpy.sum(self._build_cache_line_mesh_mask) self._index_begin = 0 self._index_end = mesh_line_count @@ -60,14 +60,14 @@ class LayerPolygon: # Only if the type of line segment changes do we need to add an extra vertex to change colors self._build_cache_needed_points[1:, 0][:, numpy.newaxis] = self._types[1:] != self._types[:-1] # Mark points as unneeded if they are of types we don't want in the line mesh according to the calculated mask - numpy.logical_and(self._build_cache_needed_points, self._build_cache_line_mesh_mask, self._build_cache_needed_points ) + numpy.logical_and(self._build_cache_needed_points, self._build_cache_line_mesh_mask ) self._vertex_begin = 0 self._vertex_end = numpy.sum( self._build_cache_needed_points ) ## build # line_thicknesses: array with type as index and thickness as value - def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, indices): + def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, line_types, indices): if (self._build_cache_line_mesh_mask is None) or (self._build_cache_needed_points is None ): self.buildCache() @@ -94,7 +94,10 @@ class LayerPolygon: line_dimensions[self._vertex_begin:self._vertex_end, 0] = numpy.tile(self._line_widths, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0] line_dimensions[self._vertex_begin:self._vertex_end, 1] = numpy.tile(self._line_thicknesses, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0] - extruders[self._vertex_begin:self._vertex_end] = float(self._extruder) + extruders[self._vertex_begin:self._vertex_end] = self._extruder + + # Convert type per vertex to type per line + line_types[self._vertex_begin:self._vertex_end] = numpy.tile(self._types, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0] # The relative values of begin and end indices have already been set in buildCache, so we only need to offset them to the parents offset. self._index_begin += index_offset diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index dda35624ec..545abd04f2 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -30,16 +30,24 @@ class LayerPass(RenderPass): self._layer_view = None def setLayerView(self, layerview): - self._layerview = layerview + self._layer_view = layerview def render(self): if not self._layer_shader: self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("LayerView"), "layers.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))) - self._layer_shader.setUniformValue("u_layer_view_type", 0) - self._layer_shader.setUniformValue("u_only_color_active_extruder", 1) - self._layer_shader.setUniformValue("u_extruder_opacity", [1, 1, 1, 1]) + if self._layer_view: + self._layer_shader.setUniformValue("u_layer_view_type", self._layer_view.getLayerViewType()) + self._layer_shader.setUniformValue("u_only_color_active_extruder", (1 if self._layer_view.getOnlyColorActiveExtruder() else 0)) + self._layer_shader.setUniformValue("u_extruder_opacity", self._layer_view.getExtruderOpacities()) + self._layer_shader.setUniformValue("u_show_travel_moves", self._layer_view.getShowTravelMoves()) + else: + #defaults + self._layer_shader.setUniformValue("u_layer_view_type", 1) + self._layer_shader.setUniformValue("u_only_color_active_extruder", 1) + self._layer_shader.setUniformValue("u_extruder_opacity", [1, 1, 1, 1]) + self._layer_shader.setUniformValue("u_show_travel_moves", 0) if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) @@ -58,12 +66,12 @@ class LayerPass(RenderPass): continue # Render all layers below a certain number as line mesh instead of vertices. - if self._layerview._current_layer_num > -1 and not self._layerview._only_show_top_layers: + if self._layer_view._current_layer_num > -1 and not self._layer_view._only_show_top_layers: start = 0 end = 0 element_counts = layer_data.getElementCounts() for layer, counts in element_counts.items(): - if layer > self._layerview._current_layer_num: + if layer > self._layer_view._current_layer_num: break end += counts @@ -75,11 +83,11 @@ class LayerPass(RenderPass): # Create a new batch that is not range-limited batch = RenderBatch(self._layer_shader, type = RenderBatch.RenderType.Solid) - if self._layerview._current_layer_mesh: - batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_mesh) + if self._layer_view._current_layer_mesh: + batch.addItem(node.getWorldTransformation(), self._layer_view._current_layer_mesh) - if self._layerview._current_layer_jumps: - batch.addItem(node.getWorldTransformation(), self._layerview._current_layer_jumps) + if self._layer_view._current_layer_jumps: + batch.addItem(node.getWorldTransformation(), self._layer_view._current_layer_jumps) if len(batch.items) > 0: batch.render(self._scene.getActiveCamera()) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 50c13194f7..16dced8a6e 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -60,8 +60,14 @@ class LayerView(View): self._proxy = LayerViewProxy.LayerViewProxy() self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged) + self._layer_view_type = 0 # 0 is material color, 1 is color by linetype, 2 is speed + self._only_color_active_extruder = True + self._extruder_opacity = [1.0, 1.0, 1.0, 1.0] + self._show_travel_moves = 0 + Preferences.getInstance().addPreference("view/top_layer_count", 5) Preferences.getInstance().addPreference("view/only_show_top_layers", False) + Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) @@ -134,6 +140,34 @@ class LayerView(View): self.currentLayerNumChanged.emit() + def setLayerViewType(self, layer_view_type): + self._layer_view_type = layer_view_type + self.currentLayerNumChanged.emit() + + def getLayerViewType(self): + return self._layer_view_type + + def setOnlyColorActiveExtruder(self, only_color_active_extruder): + self._only_color_active_extruder = only_color_active_extruder + self.currentLayerNumChanged.emit() + + def getOnlyColorActiveExtruder(self): + return self._only_color_active_extruder + + def setExtruderOpacity(self, extruder_nr, opacity): + self._extruder_opacity[extruder_nr] = opacity + self.currentLayerNumChanged.emit() + + def getExtruderOpacities(self): + return self._extruder_opacity + + def setShowTravelMoves(self, show): + self._show_travel_moves = show + self.currentLayerNumChanged.emit() + + def getShowTravelMoves(self): + return self._show_travel_moves + def calculateMaxLayers(self): scene = self.getController().getScene() self._activity = True diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index 68c51e5752..500e0d12c1 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -129,12 +129,12 @@ Item { id: layerViewTypes ListElement { - text: "Line type" - type_id: 0 // these ids match the switching in the shader + text: "Material color" + type_id: 0 } ListElement { - text: "Material color" - type_id: 1 + text: "Line type" + type_id: 1 // these ids match the switching in the shader } ListElement { text: "Printing speed" @@ -150,6 +150,7 @@ Item onActivated: { CuraApplication.log("Combobox" + String(index)); CuraApplication.log(layerViewTypes.get(index).type_id); + UM.LayerView.setLayerViewType(layerViewTypes.get(index).type_id); } } @@ -158,27 +159,28 @@ Item CheckBox { checked: true onClicked: { - CuraApplication.log("First"); + UM.LayerView.setExtruderOpacity(0, checked ? 1.0 : 0.0); } text: "Extruder 1" } CheckBox { checked: true onClicked: { - CuraApplication.log("First"); + UM.LayerView.setExtruderOpacity(1, checked ? 1.0 : 0.0); } text: "Extruder 2" } CheckBox { onClicked: { - CuraApplication.log("First"); + UM.LayerView.setShowTravelMoves(checked ? 1 : 0); } text: "Travel moves" } CheckBox { checked: true onClicked: { - CuraApplication.log("First"); + CuraApplication.log("First" + checked); + UM.LayerView.setOnlyColorActiveExtruder(checked); } text: "Only color active extruder" } diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index e9319ef6e1..5555f7358a 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -50,6 +50,31 @@ class LayerViewProxy(QObject): if type(active_view) == LayerView.LayerView.LayerView: active_view.setLayer(layer_num) + @pyqtSlot(int) + def setLayerViewType(self, layer_view_type): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.setLayerViewType(layer_view_type) + + @pyqtSlot(bool) + def setOnlyColorActiveExtruder(self, only_color_active_extruder): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.setOnlyColorActiveExtruder(only_color_active_extruder) + + # Opacity 0..1 + @pyqtSlot(int, float) + def setExtruderOpacity(self, extruder_nr, opacity): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.setExtruderOpacity(extruder_nr, opacity) + + @pyqtSlot(bool) + def setShowTravelMoves(self, show): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.setShowTravelMoves(show) + def _layerActivityChanged(self): self.activityChanged.emit() diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 869230e87d..c086aa3575 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -17,6 +17,7 @@ vertex = attribute highp vec4 a_normal; attribute highp vec2 a_line_dim; // line width and thickness attribute highp int a_extruder; + attribute highp int a_line_type; varying lowp vec4 v_color; //varying lowp vec4 v_material_color; @@ -26,6 +27,7 @@ vertex = //varying lowp vec2 v_uvs; varying lowp vec2 v_line_dim; varying highp int v_extruder; + varying int v_line_type; varying lowp vec4 f_color; varying highp vec3 f_vertex; @@ -44,19 +46,19 @@ vertex = switch (u_layer_view_type) { case 0: // "Line type" - v_color = a_color; + v_color = a_material_color; break; case 1: // "Material color" - v_color = a_material_color; + v_color = a_color; break; case 2: // "Speed" v_color = a_color; break; } if (u_only_color_active_extruder == 1) { - v_color = (a_extruder == u_active_extruder) ? v_color : vec4(0.4, 0.4, 0.4, 1.0); + v_color = (a_extruder == u_active_extruder) ? v_color : vec4(0.4, 0.4, 0.4, v_color.a); } else { - v_color = (a_extruder == u_active_extruder) ? v_color : v_color * u_shade_factor; + v_color = (a_extruder == u_active_extruder) ? v_color : vec4((v_color * u_shade_factor).rgb, v_color.a); } if (a_extruder < 4) { v_color.a *= u_extruder_opacity[a_extruder]; // make it (in)visible @@ -66,19 +68,20 @@ vertex = v_normal = (u_normalMatrix * normalize(a_normal)).xyz; v_line_dim = a_line_dim; v_extruder = a_extruder; - //v_material_color = a_material_color; + v_line_type = a_line_type; // for testing without geometry shader - f_color = v_color; + /*f_color = v_color; f_vertex = v_vertex; f_normal = v_normal; - f_extruder = v_extruder; + f_extruder = v_extruder; */ } geometry = #version 410 uniform highp mat4 u_viewProjectionMatrix; + uniform int u_show_travel_moves; layout(lines) in; layout(triangle_strip, max_vertices = 26) out; @@ -88,7 +91,7 @@ geometry = in vec3 v_normal[]; in vec2 v_line_dim[]; in int v_extruder[]; - //in vec4 v_material_color[]; + in int v_line_type[]; out vec4 f_color; out vec3 f_normal; @@ -106,13 +109,24 @@ geometry = vec3 g_vertex_normal_horz_head; vec4 g_vertex_offset_horz_head; - float size_x = v_line_dim[0].x / 2 + 0.01; // radius, and make it nicely overlapping - float size_y = v_line_dim[0].y / 2 + 0.01; + float size_x; + float size_y; + + // See LayerPolygon; 8 is MoveCombingType, 9 is RetractionType + if (((v_line_type[0] == 8) || (v_line_type[0] == 9)) && (u_show_travel_moves == 0)) { + return; + } + if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { + // fixed size for movements + size_x = 0.1; + size_y = 0.1; + } else { + size_x = v_line_dim[0].x / 2 + 0.01; // radius, and make it nicely overlapping + size_y = v_line_dim[0].y / 2 + 0.01; + } f_extruder = v_extruder[0]; - //f_material_color = v_material_color[0]; - //g_vertex_normal_horz = normalize(v_normal[0]); //vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x); g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); @@ -125,28 +139,24 @@ geometry = f_vertex = v_vertex[0]; f_color = v_color[0]; - //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = g_vertex_normal_horz; gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; - //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = g_vertex_normal_horz; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[0]; f_color = v_color[0]; - //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = g_vertex_normal_vert; gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; - //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = g_vertex_normal_vert; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); EmitVertex(); @@ -154,27 +164,23 @@ geometry = f_vertex = v_vertex[0]; f_normal = -g_vertex_normal_horz; f_color = v_color[0]; - //f_color = vec4(v_uvs[0], 0.0, 1.0); gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; - //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = -g_vertex_normal_horz; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[0]; f_color = v_color[0]; - //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = -g_vertex_normal_vert; gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; - //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = -g_vertex_normal_vert; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); EmitVertex(); @@ -182,13 +188,11 @@ geometry = f_vertex = v_vertex[0]; f_normal = g_vertex_normal_horz; f_color = v_color[0]; - //f_color = vec4(v_uvs[0], 0.0, 1.0); gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); EmitVertex(); f_vertex = v_vertex[1]; f_color = v_color[1]; - //f_color = vec4(v_uvs[0], 0.0, 1.0); f_normal = g_vertex_normal_horz; gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); EmitVertex(); @@ -289,8 +293,9 @@ fragment = void main() { mediump vec4 finalColor = vec4(0.0); + float alpha = f_color.a; - finalColor += u_ambientColor; + finalColor.rgb += f_color.rgb * 0.3; highp vec3 normal = normalize(f_normal); highp vec3 lightDir = normalize(u_lightPosition - f_vertex); @@ -298,8 +303,7 @@ fragment = // Diffuse Component highp float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0); finalColor += (NdotL * f_color); - //finalColor += (NdotL * f_material_color); - //finalColor.a = 1.0; + finalColor.a = alpha; // Do not change alpha in any way gl_FragColor = finalColor; } @@ -313,10 +317,12 @@ u_extruder_opacity = [1.0, 1.0] u_shade_factor = 0.60 u_specularColor = [0.4, 0.4, 0.4, 1.0] -u_ambientColor = [0.3, 0.3, 0.3, 0.3] +u_ambientColor = [0.3, 0.3, 0.3, 0.0] u_diffuseColor = [1.0, 0.79, 0.14, 1.0] u_shininess = 20.0 +u_show_travel_moves = 0 + [bindings] u_modelViewProjectionMatrix = model_view_projection_matrix u_modelMatrix = model_matrix @@ -331,3 +337,4 @@ a_normal = normal a_line_dim = line_dim a_extruder = extruders a_material_color = material_color +a_line_type = line_type diff --git a/resources/shaders/overhang.shader b/resources/shaders/overhang.shader index 0e8592f675..4e5999a693 100644 --- a/resources/shaders/overhang.shader +++ b/resources/shaders/overhang.shader @@ -8,50 +8,16 @@ vertex = attribute highp vec4 a_normal; attribute highp vec2 a_uvs; - varying highp vec3 v_vertex; - varying highp vec3 v_normal; + varying highp vec3 f_vertex; + varying highp vec3 f_normal; void main() { vec4 world_space_vert = u_modelMatrix * a_vertex; gl_Position = u_viewProjectionMatrix * world_space_vert; - v_vertex = world_space_vert.xyz; - v_normal = (u_normalMatrix * normalize(a_normal)).xyz; - } - -geometry = - #version 410 - - layout(triangles) in; - layout(triangle_strip, max_vertices = 6) out; - - in vec3 v_normal[]; - in vec3 v_vertex[]; - - out vec3 f_normal; - out vec3 f_vertex; - - void main() - { - int i; - for(i = 0; i < 3; i++) - { - f_normal = v_normal[i]; - f_vertex = v_vertex[i]; - gl_Position = gl_in[i].gl_Position + vec4(-50, 0.0, 0.0, 0.0); - EmitVertex(); - } - EndPrimitive(); - - for(i = 0; i < 3; i++) - { - f_normal = v_normal[i]; - f_vertex = v_vertex[i]; - gl_Position = gl_in[i].gl_Position + vec4(50, 0.0, 0.0, 0.0); - EmitVertex(); - } - EndPrimitive(); + f_vertex = world_space_vert.xyz; + f_normal = (u_normalMatrix * normalize(a_normal)).xyz; } fragment = From 6271774528688a5fb0af46a39eefd4586a238136 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Fri, 30 Dec 2016 15:32:06 +0100 Subject: [PATCH 018/156] Added all kinds of options to layer view --- cura/LayerDataBuilder.py | 4 +- cura/LayerPolygon.py | 1 - .../ProcessSlicedLayersJob.py | 1 + plugins/LayerView/LayerPass.py | 8 ++++ plugins/LayerView/LayerView.py | 32 ++++++++++++++++ plugins/LayerView/LayerView.qml | 38 +++++++++++++++---- plugins/LayerView/LayerViewProxy.py | 26 ++++++++++++- plugins/LayerView/layers.shader | 34 ++++++++++++----- 8 files changed, 122 insertions(+), 22 deletions(-) diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index 6750b60d53..72dac319cd 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -76,8 +76,8 @@ class LayerDataBuilder(MeshBuilder): material_colors = numpy.zeros((line_dimensions.shape[0], 4), dtype=numpy.float32) for extruder_nr in range(material_color_map.shape[0]): material_colors[extruders == extruder_nr] = material_color_map[extruder_nr] - material_colors[line_types == LayerPolygon.MoveCombingType] = [0.0, 0.0, 0.8, 1.0] - material_colors[line_types == LayerPolygon.MoveRetractionType] = [0.0, 0.0, 0.8, 1.0] + material_colors[line_types == LayerPolygon.MoveCombingType] = colors[line_types == LayerPolygon.MoveCombingType] + material_colors[line_types == LayerPolygon.MoveRetractionType] = colors[line_types == LayerPolygon.MoveRetractionType] attributes = { "line_dimensions": { diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index f7acc62286..4509ba7d26 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -88,7 +88,6 @@ class LayerPolygon: # Create an array with colors for each vertex and remove the color data for the points that has been thrown away. colors[self._vertex_begin:self._vertex_end, :] = numpy.tile(self._colors, (1, 2)).reshape((-1, 4))[needed_points_list.ravel()] - colors[self._vertex_begin:self._vertex_end, :] *= numpy.array([[0.5, 0.5, 0.5, 1.0]], numpy.float32) # Create an array with line widths for each vertex. line_dimensions[self._vertex_begin:self._vertex_end, 0] = numpy.tile(self._line_widths, (1, 2)).reshape((-1, 1))[needed_points_list.ravel()][:, 0] diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index d7be0f1a52..70398ff867 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -105,6 +105,7 @@ class ProcessSlicedLayersJob(Job): polygon = layer.getRepeatedMessage("path_segment", p) extruder = polygon.extruder + x = dir(polygon) line_types = numpy.fromstring(polygon.line_type, dtype="u1") # Convert bytearray to numpy array line_types = line_types.reshape((-1,1)) diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index 545abd04f2..2ff4b14ec6 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -42,12 +42,20 @@ class LayerPass(RenderPass): self._layer_shader.setUniformValue("u_only_color_active_extruder", (1 if self._layer_view.getOnlyColorActiveExtruder() else 0)) 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_support", self._layer_view.getShowSupport()) + self._layer_shader.setUniformValue("u_show_adhesion", self._layer_view.getShowAdhesion()) + self._layer_shader.setUniformValue("u_show_skin", self._layer_view.getShowSkin()) + self._layer_shader.setUniformValue("u_show_infill", self._layer_view.getShowInfill()) else: #defaults self._layer_shader.setUniformValue("u_layer_view_type", 1) self._layer_shader.setUniformValue("u_only_color_active_extruder", 1) self._layer_shader.setUniformValue("u_extruder_opacity", [1, 1, 1, 1]) self._layer_shader.setUniformValue("u_show_travel_moves", 0) + self._layer_shader.setUniformValue("u_show_support", 1) + self._layer_shader.setUniformValue("u_show_adhesion", 1) + self._layer_shader.setUniformValue("u_show_skin", 1) + self._layer_shader.setUniformValue("u_show_infill", 1) if not self._tool_handle_shader: self._tool_handle_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "toolhandle.shader")) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 16dced8a6e..a1e48ee3a6 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -64,6 +64,10 @@ class LayerView(View): self._only_color_active_extruder = True self._extruder_opacity = [1.0, 1.0, 1.0, 1.0] self._show_travel_moves = 0 + self._show_support = 1 + self._show_adhesion = 1 + self._show_skin = 1 + self._show_infill = 1 Preferences.getInstance().addPreference("view/top_layer_count", 5) Preferences.getInstance().addPreference("view/only_show_top_layers", False) @@ -168,6 +172,34 @@ class LayerView(View): def getShowTravelMoves(self): return self._show_travel_moves + def setShowSupport(self, show): + self._show_support = show + self.currentLayerNumChanged.emit() + + def getShowSupport(self): + return self._show_support + + def setShowAdhesion(self, show): + self._show_adhesion = show + self.currentLayerNumChanged.emit() + + def getShowAdhesion(self): + return self._show_adhesion + + def setShowSkin(self, show): + self._show_skin = show + self.currentLayerNumChanged.emit() + + def getShowSkin(self): + return self._show_skin + + def setShowInfill(self, show): + self._show_infill = show + self.currentLayerNumChanged.emit() + + def getShowInfill(self): + return self._show_infill + def calculateMaxLayers(self): scene = self.getController().getScene() self._activity = True diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index 500e0d12c1..ad02aade19 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -136,20 +136,15 @@ Item text: "Line type" type_id: 1 // these ids match the switching in the shader } - ListElement { - text: "Printing speed" - type_id: 2 - } } ComboBox { id: layer_type_combobox anchors.top: slider_background.bottom + anchors.left: parent.left model: layerViewTypes onActivated: { - CuraApplication.log("Combobox" + String(index)); - CuraApplication.log(layerViewTypes.get(index).type_id); UM.LayerView.setLayerViewType(layerViewTypes.get(index).type_id); } } @@ -174,12 +169,39 @@ Item onClicked: { UM.LayerView.setShowTravelMoves(checked ? 1 : 0); } - text: "Travel moves" + text: "Show travel moves" + } + CheckBox { + checked: true + onClicked: { + UM.LayerView.setShowSupport(checked ? 1 : 0); + } + text: "Show support" + } + CheckBox { + checked: true + onClicked: { + UM.LayerView.setShowAdhesion(checked ? 1 : 0); + } + text: "Show adhesion" + } + CheckBox { + checked: true + onClicked: { + UM.LayerView.setShowSkin(checked ? 1 : 0); + } + text: "Show skin" + } + CheckBox { + checked: true + onClicked: { + UM.LayerView.setShowInfill(checked ? 1 : 0); + } + text: "Show infill" } CheckBox { checked: true onClicked: { - CuraApplication.log("First" + checked); UM.LayerView.setOnlyColorActiveExtruder(checked); } text: "Only color active extruder" diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index 5555f7358a..c7a0d4a918 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -69,12 +69,36 @@ class LayerViewProxy(QObject): if type(active_view) == LayerView.LayerView.LayerView: active_view.setExtruderOpacity(extruder_nr, opacity) - @pyqtSlot(bool) + @pyqtSlot(int) def setShowTravelMoves(self, show): active_view = self._controller.getActiveView() if type(active_view) == LayerView.LayerView.LayerView: active_view.setShowTravelMoves(show) + @pyqtSlot(int) + def setShowSupport(self, show): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.setShowSupport(show) + + @pyqtSlot(int) + def setShowAdhesion(self, show): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.setShowAdhesion(show) + + @pyqtSlot(int) + def setShowSkin(self, show): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.setShowSkin(show) + + @pyqtSlot(int) + def setShowInfill(self, show): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.setShowInfill(show) + def _layerActivityChanged(self): self.activityChanged.emit() diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index c086aa3575..a667ecc370 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -8,7 +8,6 @@ vertex = uniform lowp int u_only_color_active_extruder; uniform lowp vec4 u_extruder_opacity; // currently only for max 4 extruders, others always visible - uniform lowp float u_shade_factor; uniform highp mat4 u_normalMatrix; attribute highp vec4 a_vertex; @@ -45,20 +44,15 @@ vertex = // shade the color depending on the extruder index stored in the alpha component of the color switch (u_layer_view_type) { - case 0: // "Line type" + case 0: // "Material color" v_color = a_material_color; break; - case 1: // "Material color" - v_color = a_color; - break; - case 2: // "Speed" + case 1: // "Line type" v_color = a_color; break; } if (u_only_color_active_extruder == 1) { v_color = (a_extruder == u_active_extruder) ? v_color : vec4(0.4, 0.4, 0.4, v_color.a); - } else { - v_color = (a_extruder == u_active_extruder) ? v_color : vec4((v_color * u_shade_factor).rgb, v_color.a); } if (a_extruder < 4) { v_color.a *= u_extruder_opacity[a_extruder]; // make it (in)visible @@ -82,6 +76,10 @@ geometry = uniform highp mat4 u_viewProjectionMatrix; uniform int u_show_travel_moves; + uniform int u_show_support; + uniform int u_show_adhesion; + uniform int u_show_skin; + uniform int u_show_infill; layout(lines) in; layout(triangle_strip, max_vertices = 26) out; @@ -113,9 +111,22 @@ geometry = float size_y; // See LayerPolygon; 8 is MoveCombingType, 9 is RetractionType - if (((v_line_type[0] == 8) || (v_line_type[0] == 9)) && (u_show_travel_moves == 0)) { + if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9))) { return; } + if ((u_show_support == 0) && ((v_line_type[0] == 4) || (v_line_type[0] == 7) || (v_line_type[0] == 10))) { + return; + } + if ((u_show_adhesion == 0) && (v_line_type[0] == 5)) { + return; + } + if ((u_show_skin == 0) && ((v_line_type[0] == 1) || (v_line_type[0] == 2) || (v_line_type[0] == 3))) { + return; + } + if ((u_show_infill == 0) && (v_line_type[0] == 6)) { + return; + } + if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { // fixed size for movements size_x = 0.1; @@ -315,13 +326,16 @@ u_layer_view_type = 0 u_only_color_active_extruder = 1 u_extruder_opacity = [1.0, 1.0] -u_shade_factor = 0.60 u_specularColor = [0.4, 0.4, 0.4, 1.0] u_ambientColor = [0.3, 0.3, 0.3, 0.0] u_diffuseColor = [1.0, 0.79, 0.14, 1.0] u_shininess = 20.0 u_show_travel_moves = 0 +u_show_support = 1 +u_show_adhesion = 1 +u_show_skin = 1 +u_show_infill = 1 [bindings] u_modelViewProjectionMatrix = model_view_projection_matrix From e3d77de6df0a30df96965210922ea00fa4c0bbd6 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Fri, 30 Dec 2016 15:43:32 +0100 Subject: [PATCH 019/156] Working quite well --- plugins/LayerView/layers.shader | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index a667ecc370..96ef72e7fd 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -26,6 +26,7 @@ vertex = //varying lowp vec2 v_uvs; varying lowp vec2 v_line_dim; varying highp int v_extruder; + varying highp vec4 v_extruder_opacity; varying int v_line_type; varying lowp vec4 f_color; @@ -51,18 +52,19 @@ vertex = v_color = a_color; break; } - if (u_only_color_active_extruder == 1) { + if ((u_only_color_active_extruder == 1) && (a_line_type != 8) && (a_line_type != 9)) { v_color = (a_extruder == u_active_extruder) ? v_color : vec4(0.4, 0.4, 0.4, v_color.a); } - if (a_extruder < 4) { + /*if (a_extruder < 4) { v_color.a *= u_extruder_opacity[a_extruder]; // make it (in)visible - } + }*/ v_vertex = world_space_vert.xyz; v_normal = (u_normalMatrix * normalize(a_normal)).xyz; v_line_dim = a_line_dim; v_extruder = a_extruder; v_line_type = a_line_type; + v_extruder_opacity = u_extruder_opacity; // for testing without geometry shader /*f_color = v_color; @@ -89,6 +91,7 @@ geometry = in vec3 v_normal[]; in vec2 v_line_dim[]; in int v_extruder[]; + in vec4 v_extruder_opacity[]; in int v_line_type[]; out vec4 f_color; @@ -110,6 +113,9 @@ geometry = float size_x; float size_y; + if ((v_extruder_opacity[0][v_extruder[0]] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) { + return; + } // See LayerPolygon; 8 is MoveCombingType, 9 is RetractionType if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9))) { return; From 73a8859b0e46fc69a77e9e8535b03c2edc68fa81 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 2 Jan 2017 09:20:27 +0100 Subject: [PATCH 020/156] WIP second slider LayerView --- plugins/LayerView/LayerPass.py | 2 ++ plugins/LayerView/LayerView.py | 16 ++++++++++++++++ plugins/LayerView/LayerView.qml | 22 +++++++++++++++++++++- plugins/LayerView/LayerViewProxy.py | 12 ++++++++++++ 4 files changed, 51 insertions(+), 1 deletion(-) diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index 2ff4b14ec6..2fce95b18b 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -81,6 +81,8 @@ class LayerPass(RenderPass): for layer, counts in element_counts.items(): if layer > self._layer_view._current_layer_num: break + if self._layer_view._minimum_layer_num > layer: + start += counts end += counts # This uses glDrawRangeElements internally to only draw a certain range of lines. diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index a1e48ee3a6..d39fb38d58 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -41,6 +41,7 @@ class LayerView(View): self._max_layers = 0 self._current_layer_num = 0 + self._minimum_layer_num = 0 self._current_layer_mesh = None self._current_layer_jumps = None self._top_layers_job = None @@ -94,6 +95,9 @@ class LayerView(View): def getCurrentLayer(self): return self._current_layer_num + def getMinimumLayer(self): + return self._minimum_layer_num + def _onSceneChanged(self, node): self.calculateMaxLayers() @@ -144,6 +148,18 @@ class LayerView(View): self.currentLayerNumChanged.emit() + def setMinimumLayer(self, value): + if self._minimum_layer_num != value: + self._minimum_layer_num = value + if self._minimum_layer_num < 0: + self._minimum_layer_num = 0 + if self._minimum_layer_num > self._current_layer_num: + self._minimum_layer_num = self._current_layer_num + + self._startUpdateTopLayers() + + self.currentLayerNumChanged.emit() + def setLayerViewType(self, layer_view_type): self._layer_view_type = layer_view_type self.currentLayerNumChanged.emit() diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index ad02aade19..dd0b311c6d 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -13,13 +13,33 @@ Item width: UM.Theme.getSize("button").width height: UM.Theme.getSize("slider_layerview_size").height + Slider + { + id: slider2 + width: UM.Theme.getSize("slider_layerview_size").width + height: UM.Theme.getSize("slider_layerview_size").height + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("slider_layerview_margin").width * 0.2 + orientation: Qt.Vertical + minimumValue: 0; + maximumValue: UM.LayerView.numLayers; + stepSize: 1 + + property real pixelsPerStep: ((height - UM.Theme.getSize("slider_handle").height) / (maximumValue - minimumValue)) * stepSize; + + value: UM.LayerView.minimumLayer + onValueChanged: UM.LayerView.setMinimumLayer(value) + + style: UM.Theme.styles.slider; + } + Slider { id: slider width: UM.Theme.getSize("slider_layerview_size").width height: UM.Theme.getSize("slider_layerview_size").height anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("slider_layerview_margin").width/2 + anchors.leftMargin: UM.Theme.getSize("slider_layerview_margin").width * 0.8 orientation: Qt.Vertical minimumValue: 0; maximumValue: UM.LayerView.numLayers; diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index c7a0d4a918..28acdce4a5 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -35,6 +35,12 @@ class LayerViewProxy(QObject): if type(active_view) == LayerView.LayerView.LayerView: return active_view.getCurrentLayer() + @pyqtProperty(int, notify = currentLayerChanged) + def minimumLayer(self): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + return active_view.getMinimumLayer() + busyChanged = pyqtSignal() @pyqtProperty(bool, notify = busyChanged) def busy(self): @@ -50,6 +56,12 @@ class LayerViewProxy(QObject): if type(active_view) == LayerView.LayerView.LayerView: active_view.setLayer(layer_num) + @pyqtSlot(int) + def setMinimumLayer(self, layer_num): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.setMinimumLayer(layer_num) + @pyqtSlot(int) def setLayerViewType(self, layer_view_type): active_view = self._controller.getActiveView() From 93137fcc91ced8b08fab66ce41a95d44568e9cf7 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 2 Jan 2017 12:56:18 +0100 Subject: [PATCH 021/156] Added compatibility mode - old layer view is now also available --- cura/CuraApplication.py | 3 - plugins/LayerView/LayerPass.py | 8 +- plugins/LayerView/LayerView.py | 11 +- plugins/LayerView/LayerView.qml | 5 + plugins/LayerView/LayerViewProxy.py | 10 +- plugins/LayerView/layers.shader | 353 +-------------------- plugins/LayerView/layers3d.shader | 355 ++++++++++++++++++++++ resources/qml/Preferences/GeneralPage.qml | 19 +- 8 files changed, 418 insertions(+), 346 deletions(-) create mode 100644 plugins/LayerView/layers3d.shader diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 17342edd7c..3f4e0963d1 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -415,7 +415,6 @@ class CuraApplication(QtApplication): controller = self.getController() controller.setActiveView("SolidView") - # controller.setActiveView("LayerView") controller.setCameraTool("CameraTool") controller.setSelectionTool("SelectionTool") @@ -457,8 +456,6 @@ class CuraApplication(QtApplication): self._qml_import_paths.append(Resources.getPath(self.ResourceTypes.QmlFiles)) self.initializeEngine() - # self.callLater(controller.setActiveView, "LayerView") - if self._engine.rootObjects: self.closeSplash() diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index 2fce95b18b..6d0c49e0f9 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -28,13 +28,19 @@ class LayerPass(RenderPass): self._extruder_manager = ExtruderManager.getInstance() self._layer_view = None + self._compatibility_mode = None def setLayerView(self, layerview): self._layer_view = layerview + self._compatibility_mode = layerview.getCompatibilityMode() def render(self): if not self._layer_shader: - self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("LayerView"), "layers.shader")) + if self._compatibility_mode: + shader_filename = "layers.shader" + else: + shader_filename = "layers3d.shader" + self._layer_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("LayerView"), shader_filename)) # 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 self._layer_view: diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index d39fb38d58..4e5d7da23e 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -72,11 +72,13 @@ class LayerView(View): Preferences.getInstance().addPreference("view/top_layer_count", 5) Preferences.getInstance().addPreference("view/only_show_top_layers", False) + Preferences.getInstance().addPreference("view/compatibility_mode", True) # Default True for now, needs testing of different computers Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) + self._compatibility_mode = bool(Preferences.getInstance().getValue("view/compatibility_mode")) self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled")) @@ -216,6 +218,9 @@ class LayerView(View): def getShowInfill(self): return self._show_infill + def getCompatibilityMode(self): + return self._compatibility_mode + def calculateMaxLayers(self): scene = self.getController().getScene() self._activity = True @@ -312,6 +317,9 @@ class LayerView(View): self._wireprint_warning_message.hide() def _startUpdateTopLayers(self): + if not self._compatibility_mode: + return + if self._top_layers_job: self._top_layers_job.finished.disconnect(self._updateCurrentLayerMesh) self._top_layers_job.cancel() @@ -335,11 +343,12 @@ class LayerView(View): self._top_layers_job = None def _onPreferencesChanged(self, preference): - if preference != "view/top_layer_count" and preference != "view/only_show_top_layers": + if preference not in {"view/top_layer_count", "view/only_show_top_layers", "view/compatibility_mode"}: return self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) + self._compatibility_mode = bool(Preferences.getInstance().getValue("view/compatibility_mode")) self._startUpdateTopLayers() diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index dd0b311c6d..9306b4f5f5 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -139,11 +139,14 @@ Item anchors.left: parent.left anchors.verticalCenter: parent.verticalCenter anchors.top: slider_background.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + //anchors.leftMargin: UM.Theme.getSize("default_margin").width width: UM.Theme.getSize("slider_layerview_background").width * 3 height: slider.height + UM.Theme.getSize("default_margin").height * 2 color: UM.Theme.getColor("tool_panel_background"); border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") + visible: !UM.LayerView.compatibilityMode ListModel { @@ -171,6 +174,8 @@ Item ColumnLayout { anchors.top: layer_type_combobox.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + CheckBox { checked: true onClicked: { diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index 28acdce4a5..8b9a9b7d38 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -49,7 +49,15 @@ class LayerViewProxy(QObject): return active_view.isBusy() return False - + + @pyqtProperty(bool) + def compatibilityMode(self): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + return active_view.getCompatibilityMode() + + return False + @pyqtSlot(int) def setCurrentLayer(self, layer_num): active_view = self._controller.getActiveView() diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 96ef72e7fd..f360e57121 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -1,360 +1,37 @@ [shaders] vertex = - uniform highp mat4 u_modelMatrix; - //uniform highp mat4 u_viewProjectionMatrix; - //uniform highp mat4 u_modelViewProjectionMatrix; + uniform highp mat4 u_modelViewProjectionMatrix; uniform lowp float u_active_extruder; - uniform lowp int u_layer_view_type; - uniform lowp int u_only_color_active_extruder; - uniform lowp vec4 u_extruder_opacity; // currently only for max 4 extruders, others always visible - - uniform highp mat4 u_normalMatrix; + uniform lowp float u_shade_factor; + attribute highp int a_extruder; attribute highp vec4 a_vertex; attribute lowp vec4 a_color; - attribute lowp vec4 a_material_color; - attribute highp vec4 a_normal; - attribute highp vec2 a_line_dim; // line width and thickness - attribute highp int a_extruder; - attribute highp int a_line_type; - varying lowp vec4 v_color; - //varying lowp vec4 v_material_color; - - varying highp vec3 v_vertex; - varying highp vec3 v_normal; - //varying lowp vec2 v_uvs; - varying lowp vec2 v_line_dim; - varying highp int v_extruder; - varying highp vec4 v_extruder_opacity; - varying int v_line_type; - - varying lowp vec4 f_color; - varying highp vec3 f_vertex; - varying highp vec3 f_normal; - varying highp int f_extruder; - - void main() - { - vec4 v1_vertex = a_vertex; - v1_vertex.y -= a_line_dim.y / 2; // half layer down - vec4 world_space_vert = u_modelMatrix * v1_vertex; - // gl_Position = u_viewProjectionMatrix * world_space_vert; - gl_Position = world_space_vert; - // gl_Position = u_modelViewProjectionMatrix * a_vertex; - // shade the color depending on the extruder index stored in the alpha component of the color - - switch (u_layer_view_type) { - case 0: // "Material color" - v_color = a_material_color; - break; - case 1: // "Line type" - v_color = a_color; - break; + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + // shade the color depending on the extruder index stored in the alpha component of the color + v_color = (a_color.a == u_active_extruder) ? a_color * 1.5 : a_color * 1.5 * u_shade_factor; + v_color.a = 1.0; } - if ((u_only_color_active_extruder == 1) && (a_line_type != 8) && (a_line_type != 9)) { - v_color = (a_extruder == u_active_extruder) ? v_color : vec4(0.4, 0.4, 0.4, v_color.a); - } - /*if (a_extruder < 4) { - v_color.a *= u_extruder_opacity[a_extruder]; // make it (in)visible - }*/ - - v_vertex = world_space_vert.xyz; - v_normal = (u_normalMatrix * normalize(a_normal)).xyz; - v_line_dim = a_line_dim; - v_extruder = a_extruder; - v_line_type = a_line_type; - v_extruder_opacity = u_extruder_opacity; - - // for testing without geometry shader - /*f_color = v_color; - f_vertex = v_vertex; - f_normal = v_normal; - f_extruder = v_extruder; */ - } - -geometry = - #version 410 - - uniform highp mat4 u_viewProjectionMatrix; - uniform int u_show_travel_moves; - uniform int u_show_support; - uniform int u_show_adhesion; - uniform int u_show_skin; - uniform int u_show_infill; - - layout(lines) in; - layout(triangle_strip, max_vertices = 26) out; - - in vec4 v_color[]; - in vec3 v_vertex[]; - in vec3 v_normal[]; - in vec2 v_line_dim[]; - in int v_extruder[]; - in vec4 v_extruder_opacity[]; - in int v_line_type[]; - - out vec4 f_color; - out vec3 f_normal; - out vec3 f_vertex; - out uint f_extruder; - //out vec4 f_material_color; - - void main() - { - vec4 g_vertex_delta; - vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers - vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position - vec3 g_vertex_normal_vert; - vec4 g_vertex_offset_vert; - vec3 g_vertex_normal_horz_head; - vec4 g_vertex_offset_horz_head; - - float size_x; - float size_y; - - if ((v_extruder_opacity[0][v_extruder[0]] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) { - return; - } - // See LayerPolygon; 8 is MoveCombingType, 9 is RetractionType - if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9))) { - return; - } - if ((u_show_support == 0) && ((v_line_type[0] == 4) || (v_line_type[0] == 7) || (v_line_type[0] == 10))) { - return; - } - if ((u_show_adhesion == 0) && (v_line_type[0] == 5)) { - return; - } - if ((u_show_skin == 0) && ((v_line_type[0] == 1) || (v_line_type[0] == 2) || (v_line_type[0] == 3))) { - return; - } - if ((u_show_infill == 0) && (v_line_type[0] == 6)) { - return; - } - - if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { - // fixed size for movements - size_x = 0.1; - size_y = 0.1; - } else { - size_x = v_line_dim[0].x / 2 + 0.01; // radius, and make it nicely overlapping - size_y = v_line_dim[0].y / 2 + 0.01; - } - - f_extruder = v_extruder[0]; - - g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; - g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); - g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); - - g_vertex_normal_horz = normalize(vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x)); - - g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //size * g_vertex_normal_horz; - g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); - g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); - - f_vertex = v_vertex[0]; - f_color = v_color[0]; - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - f_vertex = v_vertex[0]; - f_color = v_color[0]; - f_normal = g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); - EmitVertex(); - - f_vertex = v_vertex[0]; - f_normal = -g_vertex_normal_horz; - f_color = v_color[0]; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = -g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); - EmitVertex(); - - f_vertex = v_vertex[0]; - f_color = v_color[0]; - f_normal = -g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = -g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); - EmitVertex(); - - f_vertex = v_vertex[0]; - f_normal = g_vertex_normal_horz; - f_color = v_color[0]; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - EndPrimitive(); - - // left side - f_vertex = v_vertex[0]; - f_color = v_color[0]; - - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - f_normal = g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); - EmitVertex(); - - f_normal = g_vertex_normal_horz_head; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); - EmitVertex(); - - f_normal = -g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); - EmitVertex(); - - EndPrimitive(); - - f_normal = -g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); - EmitVertex(); - - f_normal = -g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); - EmitVertex(); - - f_normal = g_vertex_normal_horz_head; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); - EmitVertex(); - - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - EndPrimitive(); - - // right side - f_vertex = v_vertex[1]; - f_color = v_color[1]; - - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - f_normal = g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); - EmitVertex(); - - f_normal = -g_vertex_normal_horz_head; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); - EmitVertex(); - - f_normal = -g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); - EmitVertex(); - - EndPrimitive(); - - f_normal = -g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); - EmitVertex(); - - f_normal = -g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); - EmitVertex(); - - f_normal = -g_vertex_normal_horz_head; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); - EmitVertex(); - - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - EndPrimitive(); - } fragment = - varying lowp vec4 f_color; - //varying lowp vec4 f_material_color; - varying lowp vec3 f_normal; - varying lowp vec3 f_vertex; - //flat varying lowp uint f_extruder; - - uniform mediump vec4 u_ambientColor; - uniform highp vec3 u_lightPosition; + varying lowp vec4 v_color; void main() - { - mediump vec4 finalColor = vec4(0.0); - float alpha = f_color.a; - - finalColor.rgb += f_color.rgb * 0.3; - - highp vec3 normal = normalize(f_normal); - highp vec3 lightDir = normalize(u_lightPosition - f_vertex); - - // Diffuse Component - highp float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0); - finalColor += (NdotL * f_color); - finalColor.a = alpha; // Do not change alpha in any way - - gl_FragColor = finalColor; - } - + { + gl_FragColor = v_color; + } [defaults] u_active_extruder = 0.0 -u_layer_view_type = 0 -u_only_color_active_extruder = 1 -u_extruder_opacity = [1.0, 1.0] - -u_specularColor = [0.4, 0.4, 0.4, 1.0] -u_ambientColor = [0.3, 0.3, 0.3, 0.0] -u_diffuseColor = [1.0, 0.79, 0.14, 1.0] -u_shininess = 20.0 - -u_show_travel_moves = 0 -u_show_support = 1 -u_show_adhesion = 1 -u_show_skin = 1 -u_show_infill = 1 +u_shade_factor = 0.60 [bindings] u_modelViewProjectionMatrix = model_view_projection_matrix -u_modelMatrix = model_matrix -u_viewProjectionMatrix = view_projection_matrix -u_normalMatrix = normal_matrix -u_lightPosition = light_0_position [attributes] a_vertex = vertex a_color = color -a_normal = normal -a_line_dim = line_dim -a_extruder = extruders -a_material_color = material_color -a_line_type = line_type +a_extruder = extruder diff --git a/plugins/LayerView/layers3d.shader b/plugins/LayerView/layers3d.shader new file mode 100644 index 0000000000..76813915b8 --- /dev/null +++ b/plugins/LayerView/layers3d.shader @@ -0,0 +1,355 @@ +[shaders] +vertex = + #version 410 + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewProjectionMatrix; + //uniform highp mat4 u_modelViewProjectionMatrix; + uniform lowp float u_active_extruder; + uniform lowp int u_layer_view_type; + uniform lowp int u_only_color_active_extruder; + uniform lowp vec4 u_extruder_opacity; // currently only for max 4 extruders, others always visible + + uniform highp mat4 u_normalMatrix; + + attribute highp vec4 a_vertex; + attribute lowp vec4 a_color; + attribute lowp vec4 a_material_color; + attribute highp vec4 a_normal; + attribute highp vec2 a_line_dim; // line width and thickness + attribute highp int a_extruder; + attribute highp int a_line_type; + + varying lowp vec4 v_color; + //varying lowp vec4 v_material_color; + + varying highp vec3 v_vertex; + varying highp vec3 v_normal; + //varying lowp vec2 v_uvs; + varying lowp vec2 v_line_dim; + varying highp int v_extruder; + varying highp vec4 v_extruder_opacity; + varying int v_line_type; + + varying lowp vec4 f_color; + varying highp vec3 f_vertex; + varying highp vec3 f_normal; + varying highp int f_extruder; + + void main() + { + vec4 v1_vertex = a_vertex; + v1_vertex.y -= a_line_dim.y / 2; // half layer down + + vec4 world_space_vert = u_modelMatrix * v1_vertex; + gl_Position = world_space_vert; + // shade the color depending on the extruder index stored in the alpha component of the color + + switch (u_layer_view_type) { + case 0: // "Material color" + v_color = a_material_color; + break; + case 1: // "Line type" + v_color = a_color; + break; + } + if ((u_only_color_active_extruder == 1) && (a_line_type != 8) && (a_line_type != 9)) { + v_color = (a_extruder == u_active_extruder) ? v_color : vec4(0.4, 0.4, 0.4, v_color.a); + } + + v_vertex = world_space_vert.xyz; + v_normal = (u_normalMatrix * normalize(a_normal)).xyz; + v_line_dim = a_line_dim; + v_extruder = a_extruder; + v_line_type = a_line_type; + v_extruder_opacity = u_extruder_opacity; + + // for testing and backwards compatibility without geometry shader + /*f_color = v_color; + f_vertex = v_vertex; + f_normal = v_normal;*/ + } + +geometry = + #version 410 + + uniform highp mat4 u_viewProjectionMatrix; + uniform int u_show_travel_moves; + uniform int u_show_support; + uniform int u_show_adhesion; + uniform int u_show_skin; + uniform int u_show_infill; + + layout(lines) in; + layout(triangle_strip, max_vertices = 26) out; + + in vec4 v_color[]; + in vec3 v_vertex[]; + in vec3 v_normal[]; + in vec2 v_line_dim[]; + in int v_extruder[]; + in vec4 v_extruder_opacity[]; + in int v_line_type[]; + + out vec4 f_color; + out vec3 f_normal; + out vec3 f_vertex; + out uint f_extruder; + //out vec4 f_material_color; + + void main() + { + vec4 g_vertex_delta; + vec3 g_vertex_normal_horz; // horizontal and vertical in respect to layers + vec4 g_vertex_offset_horz; // vec4 to match gl_in[x].gl_Position + vec3 g_vertex_normal_vert; + vec4 g_vertex_offset_vert; + vec3 g_vertex_normal_horz_head; + vec4 g_vertex_offset_horz_head; + + float size_x; + float size_y; + + if ((v_extruder_opacity[0][v_extruder[0]] == 0.0) && (v_line_type[0] != 8) && (v_line_type[0] != 9)) { + return; + } + // See LayerPolygon; 8 is MoveCombingType, 9 is RetractionType + if ((u_show_travel_moves == 0) && ((v_line_type[0] == 8) || (v_line_type[0] == 9))) { + return; + } + if ((u_show_support == 0) && ((v_line_type[0] == 4) || (v_line_type[0] == 7) || (v_line_type[0] == 10))) { + return; + } + if ((u_show_adhesion == 0) && (v_line_type[0] == 5)) { + return; + } + if ((u_show_skin == 0) && ((v_line_type[0] == 1) || (v_line_type[0] == 2) || (v_line_type[0] == 3))) { + return; + } + if ((u_show_infill == 0) && (v_line_type[0] == 6)) { + return; + } + + if ((v_line_type[0] == 8) || (v_line_type[0] == 9)) { + // fixed size for movements + size_x = 0.1; + size_y = 0.1; + } else { + size_x = v_line_dim[0].x / 2 + 0.01; // radius, and make it nicely overlapping + size_y = v_line_dim[0].y / 2 + 0.01; + } + + f_extruder = v_extruder[0]; + + g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; + g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); + g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); + + g_vertex_normal_horz = normalize(vec3(g_vertex_delta.z, g_vertex_delta.y, -g_vertex_delta.x)); + + g_vertex_offset_horz = vec4(g_vertex_normal_horz * size_x, 0.0); //size * g_vertex_normal_horz; + g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); + g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); + + f_vertex = v_vertex[0]; + f_color = v_color[0]; + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + f_vertex = v_vertex[0]; + f_color = v_color[0]; + f_normal = g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); + EmitVertex(); + + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); + EmitVertex(); + + f_vertex = v_vertex[0]; + f_normal = -g_vertex_normal_horz; + f_color = v_color[0]; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = -g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + f_vertex = v_vertex[0]; + f_color = v_color[0]; + f_normal = -g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); + EmitVertex(); + + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = -g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); + EmitVertex(); + + f_vertex = v_vertex[0]; + f_normal = g_vertex_normal_horz; + f_color = v_color[0]; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + f_vertex = v_vertex[1]; + f_color = v_color[1]; + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + EndPrimitive(); + + // left side + f_vertex = v_vertex[0]; + f_color = v_color[0]; + + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + f_normal = g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); + EmitVertex(); + + f_normal = g_vertex_normal_horz_head; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); + EmitVertex(); + + f_normal = -g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + EndPrimitive(); + + f_normal = -g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + f_normal = -g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); + EmitVertex(); + + f_normal = g_vertex_normal_horz_head; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); + EmitVertex(); + + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + EndPrimitive(); + + // right side + f_vertex = v_vertex[1]; + f_color = v_color[1]; + + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + f_normal = g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); + EmitVertex(); + + f_normal = -g_vertex_normal_horz_head; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); + EmitVertex(); + + f_normal = -g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + EndPrimitive(); + + f_normal = -g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); + EmitVertex(); + + f_normal = -g_vertex_normal_vert; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); + EmitVertex(); + + f_normal = -g_vertex_normal_horz_head; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); + EmitVertex(); + + f_normal = g_vertex_normal_horz; + gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); + EmitVertex(); + + EndPrimitive(); + } + +fragment = + #version 410 + varying lowp vec4 f_color; + varying lowp vec3 f_normal; + varying lowp vec3 f_vertex; + + uniform mediump vec4 u_ambientColor; + uniform highp vec3 u_lightPosition; + + void main() + { + mediump vec4 finalColor = vec4(0.0); + float alpha = f_color.a; + + finalColor.rgb += f_color.rgb * 0.3; + + highp vec3 normal = normalize(f_normal); + highp vec3 lightDir = normalize(u_lightPosition - f_vertex); + + // Diffuse Component + highp float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0); + finalColor += (NdotL * f_color); + finalColor.a = alpha; // Do not change alpha in any way + + gl_FragColor = finalColor; + } + + +[defaults] +u_active_extruder = 0.0 +u_layer_view_type = 0 +u_only_color_active_extruder = 1 +u_extruder_opacity = [1.0, 1.0] + +u_specularColor = [0.4, 0.4, 0.4, 1.0] +u_ambientColor = [0.3, 0.3, 0.3, 0.0] +u_diffuseColor = [1.0, 0.79, 0.14, 1.0] +u_shininess = 20.0 + +u_show_travel_moves = 0 +u_show_support = 1 +u_show_adhesion = 1 +u_show_skin = 1 +u_show_infill = 1 + +[bindings] +u_modelViewProjectionMatrix = model_view_projection_matrix +u_modelMatrix = model_matrix +u_viewProjectionMatrix = view_projection_matrix +u_normalMatrix = normal_matrix +u_lightPosition = light_0_position + +[attributes] +a_vertex = vertex +a_color = color +a_normal = normal +a_line_dim = line_dim +a_extruder = extruder +a_material_color = material_color +a_line_type = line_type diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index eab5dbe938..bf6e1aa0f0 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -212,6 +212,20 @@ UM.PreferencesPage } } + UM.TooltipArea { + width: childrenRect.width + height: childrenRect.height + text: catalog.i18nc("@info:tooltip", "Compatibility mode in layerview?") + + CheckBox + { + id: topLayerViewCompatibilityCheckbox + text: catalog.i18nc("@option:check", "Layer view compatibility mode (for OpenGL <= 4.0, restart required)") + checked: boolCheck(UM.Preferences.getValue("view/compatibility_mode")) + onCheckedChanged: UM.Preferences.setValue("view/compatibility_mode", checked) + } + } + UM.TooltipArea { width: childrenRect.width; height: childrenRect.height; @@ -220,7 +234,7 @@ UM.PreferencesPage CheckBox { id: topLayerCountCheckbox - text: catalog.i18nc("@action:button","Display five top layers in layer view"); + text: catalog.i18nc("@action:button","Display five top layers in layer view (only for compatibility mode)"); checked: UM.Preferences.getValue("view/top_layer_count") == 5 onClicked: { @@ -235,6 +249,7 @@ UM.PreferencesPage } } } + UM.TooltipArea { width: childrenRect.width height: childrenRect.height @@ -243,7 +258,7 @@ UM.PreferencesPage CheckBox { id: topLayersOnlyCheckbox - text: catalog.i18nc("@option:check", "Only display top layer(s) in layer view") + text: catalog.i18nc("@option:check", "Only display top layer(s) in layer view (only for compatibility mode)") checked: boolCheck(UM.Preferences.getValue("view/only_show_top_layers")) onCheckedChanged: UM.Preferences.setValue("view/only_show_top_layers", checked) } From f0e0d65635fbf0f2170631ce04a475757122fc0f Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 2 Jan 2017 14:56:31 +0100 Subject: [PATCH 022/156] Finishing up compatibility mode --- cura/LayerDataBuilder.py | 4 +- .../ProcessSlicedLayersJob.py | 9 ++- plugins/LayerView/LayerView.qml | 12 ++- plugins/LayerView/layers.shader | 78 ++++++++++++++++--- plugins/LayerView/layers3d.shader | 3 +- 5 files changed, 91 insertions(+), 15 deletions(-) diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index 72dac319cd..dcc3991833 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -49,7 +49,8 @@ class LayerDataBuilder(MeshBuilder): self._layers[layer].setThickness(thickness) # material color map: [r, g, b, a] for each extruder row. - def build(self, material_color_map): + # line_type_brightness: compatibility layer view uses line type brightness of 0.5 + def build(self, material_color_map, line_type_brightness = 1.0): vertex_count = 0 index_count = 0 for layer, data in self._layers.items(): @@ -70,6 +71,7 @@ class LayerDataBuilder(MeshBuilder): self._element_counts[layer] = data.elementCount self.addVertices(vertices) + colors[:, 0:3] *= line_type_brightness self.addColors(colors) self.addIndices(indices.flatten()) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 70398ff867..028c51b3ed 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -8,6 +8,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.SceneNode import SceneNode from UM.Application import Application from UM.Mesh.MeshData import MeshData +from UM.Preferences import Preferences from UM.Message import Message from UM.i18n import i18nCatalog @@ -105,7 +106,6 @@ class ProcessSlicedLayersJob(Job): polygon = layer.getRepeatedMessage("path_segment", p) extruder = polygon.extruder - x = dir(polygon) line_types = numpy.fromstring(polygon.line_type, dtype="u1") # Convert bytearray to numpy array line_types = line_types.reshape((-1,1)) @@ -162,6 +162,7 @@ class ProcessSlicedLayersJob(Job): # TODO: move to a better place. Code is similar to code in ExtrudersModel from cura.Settings.ExtruderManager import ExtruderManager import UM + global_container_stack = UM.Application.getInstance().getGlobalContainerStack() manager = ExtruderManager.getInstance() extruders = list(manager.getMachineExtruders(global_container_stack.getId())) @@ -181,7 +182,11 @@ class ProcessSlicedLayersJob(Job): color = colorCodeToRGBA(color_code) material_color_map[0, :] = color - layer_mesh = layer_data.build(material_color_map) + if bool(Preferences.getInstance().getValue("view/compatibility_mode")): + line_type_brightness = 0.5 + else: + line_type_brightness = 1.0 + layer_mesh = layer_data.build(material_color_map, line_type_brightness) if self._abort_requested: if self._progress: diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index 9306b4f5f5..73c34520d6 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -146,7 +146,6 @@ Item color: UM.Theme.getColor("tool_panel_background"); border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") - visible: !UM.LayerView.compatibilityMode ListModel { @@ -167,11 +166,20 @@ Item anchors.top: slider_background.bottom anchors.left: parent.left model: layerViewTypes + visible: !UM.LayerView.compatibilityMode onActivated: { UM.LayerView.setLayerViewType(layerViewTypes.get(index).type_id); } } + Label + { + anchors.top: slider_background.bottom + anchors.left: parent.left + text: catalog.i18nc("@label","Compatibility mode") + visible: UM.LayerView.compatibilityMode + } + ColumnLayout { anchors.top: layer_type_combobox.bottom anchors.topMargin: UM.Theme.getSize("default_margin").height @@ -182,6 +190,7 @@ Item UM.LayerView.setExtruderOpacity(0, checked ? 1.0 : 0.0); } text: "Extruder 1" + visible: !UM.LayerView.compatibilityMode } CheckBox { checked: true @@ -189,6 +198,7 @@ Item UM.LayerView.setExtruderOpacity(1, checked ? 1.0 : 0.0); } text: "Extruder 2" + visible: !UM.LayerView.compatibilityMode } CheckBox { onClicked: { diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index f360e57121..b58d11da0c 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -3,30 +3,88 @@ vertex = uniform highp mat4 u_modelViewProjectionMatrix; uniform lowp float u_active_extruder; uniform lowp float u_shade_factor; + uniform highp int u_layer_view_type; + uniform highp int u_only_color_active_extruder; attribute highp int a_extruder; + attribute highp int a_line_type; attribute highp vec4 a_vertex; attribute lowp vec4 a_color; + attribute lowp vec4 a_material_color; + varying lowp vec4 v_color; - void main() - { - gl_Position = u_modelViewProjectionMatrix * a_vertex; - // shade the color depending on the extruder index stored in the alpha component of the color - v_color = (a_color.a == u_active_extruder) ? a_color * 1.5 : a_color * 1.5 * u_shade_factor; - v_color.a = 1.0; + varying float v_line_type; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + v_color = a_color; + if ((u_only_color_active_extruder == 1) && (a_line_type != 8) && (a_line_type != 9)) { + v_color = (a_extruder == u_active_extruder) ? v_color : vec4(0.4, 0.4, 0.4, v_color.a); } + if ((u_only_color_active_extruder == 0) && (a_line_type != 8) && (a_line_type != 9)) { + v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a); + } + + v_line_type = a_line_type; + } fragment = varying lowp vec4 v_color; + varying float v_line_type; + + uniform int u_show_travel_moves; + uniform int u_show_support; + uniform int u_show_adhesion; + uniform int u_show_skin; + uniform int u_show_infill; void main() - { - gl_FragColor = v_color; - } + { + if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9 + // discard movements + discard; + } + // support: 4, 7, 10 + if ((u_show_support == 0) && ( + ((v_line_type >= 3.5) && (v_line_type <= 4.5)) || + ((v_line_type >= 6.5) && (v_line_type <= 7.5)) || + ((v_line_type >= 9.5) && (v_line_type <= 10.5)) + )) { + discard; + } + // skin: 1, 2, 3 + if ((u_show_skin == 0) && ( + (v_line_type >= 0.5) && (v_line_type <= 3.5) + )) { + discard; + } + // adhesion: + if ((u_show_adhesion == 0) && (v_line_type >= 4.5) && (v_line_type <= 5.5)) { + // discard movements + discard; + } + // infill: + if ((u_show_infill == 0) && (v_line_type >= 5.5) && (v_line_type <= 6.5)) { + // discard movements + discard; + } + + gl_FragColor = v_color; + } [defaults] u_active_extruder = 0.0 u_shade_factor = 0.60 +u_layer_view_type = 0 +u_only_color_active_extruder = 1 +u_extruder_opacity = [1.0, 1.0, 1.0, 1.0] + +u_show_travel_moves = 0 +u_show_support = 1 +u_show_adhesion = 1 +u_show_skin = 1 +u_show_infill = 1 [bindings] u_modelViewProjectionMatrix = model_view_projection_matrix @@ -35,3 +93,5 @@ u_modelViewProjectionMatrix = model_view_projection_matrix a_vertex = vertex a_color = color a_extruder = extruder +a_line_type = line_type +a_material_color = material_color diff --git a/plugins/LayerView/layers3d.shader b/plugins/LayerView/layers3d.shader index 76813915b8..03a4015b3c 100644 --- a/plugins/LayerView/layers3d.shader +++ b/plugins/LayerView/layers3d.shader @@ -94,7 +94,6 @@ geometry = out vec3 f_normal; out vec3 f_vertex; out uint f_extruder; - //out vec4 f_material_color; void main() { @@ -325,7 +324,7 @@ fragment = u_active_extruder = 0.0 u_layer_view_type = 0 u_only_color_active_extruder = 1 -u_extruder_opacity = [1.0, 1.0] +u_extruder_opacity = [1.0, 1.0, 1.0, 1.0] u_specularColor = [0.4, 0.4, 0.4, 1.0] u_ambientColor = [0.3, 0.3, 0.3, 0.0] From 55dd08eff81cd5e20b5f07c9590dc6679f326d67 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 3 Jan 2017 09:18:26 +0100 Subject: [PATCH 023/156] Somewhat better layout, added legend --- .../ProcessSlicedLayersJob.py | 8 +-- plugins/LayerView/LayerView.qml | 57 +++++++++++++++++++ plugins/LayerView/LayerViewProxy.py | 7 +++ 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 028c51b3ed..49c306ea77 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -16,6 +16,7 @@ from UM.Logger import Logger from UM.Math.Vector import Vector +from cura.Settings.ExtruderManager import ExtruderManager from cura import LayerDataBuilder from cura import LayerDataDecorator from cura import LayerPolygon @@ -159,11 +160,7 @@ class ProcessSlicedLayersJob(Job): # We are done processing all the layers we got from the engine, now create a mesh out of the data # Find out colors per extruder - # TODO: move to a better place. Code is similar to code in ExtrudersModel - from cura.Settings.ExtruderManager import ExtruderManager - import UM - - global_container_stack = UM.Application.getInstance().getGlobalContainerStack() + global_container_stack = Application.getInstance().getGlobalContainerStack() manager = ExtruderManager.getInstance() extruders = list(manager.getMachineExtruders(global_container_stack.getId())) if extruders: @@ -182,6 +179,7 @@ class ProcessSlicedLayersJob(Job): color = colorCodeToRGBA(color_code) material_color_map[0, :] = color + # We have to scale the colors for compatibility mode if bool(Preferences.getInstance().getValue("view/compatibility_mode")): line_type_brightness = 0.5 else: diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index 73c34520d6..0e9a2cd7c9 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -181,8 +181,10 @@ Item } ColumnLayout { + id: view_settings anchors.top: layer_type_combobox.bottom anchors.topMargin: UM.Theme.getSize("default_margin").height + x: UM.Theme.getSize("default_margin").width CheckBox { checked: true @@ -243,5 +245,60 @@ Item } } + // legend + ListView { + + visible: (UM.LayerView.getLayerViewType() == 1) // line type + anchors.top: view_settings.bottom + anchors.topMargin: UM.Theme.getSize("default_margin").height + //width: parent.width + //height: childrenRect.height + + delegate: Row + { + Rectangle + { + id: rect + + x: UM.Theme.getSize("default_margin").width + y: index * UM.Theme.getSize("section_icon").height + + //width: UM.Theme.getSize("section_icon").width + //height: 0.5 * UM.Theme.getSize("section_icon").height + width: UM.Theme.getSize("setting_control").height / 2 + height: UM.Theme.getSize("setting_control").height / 2 + //Behavior on height { NumberAnimation { duration: 50; } } + + border.width: UM.Theme.getSize("default_lining").width; + border.color: UM.Theme.getColor("slider_groove_border"); + + color: model.color; + } + + Label + { + anchors.left: rect.right + anchors.verticalCenter: rect.verticalCenter + anchors.leftMargin: UM.Theme.getSize("default_margin").width + text: model.label + } + } + model: ListModel + { + id: legendModel + } + Component.onCompleted: + { + // see LayerPolygon + legendModel.append({ label:catalog.i18nc("@label", "Inset0"), color: "#ff0000" }); + legendModel.append({ label:catalog.i18nc("@label", "InsetX"), color: "#00ff00" }); + legendModel.append({ label:catalog.i18nc("@label", "Skin"), color: "#ffff00" }); + legendModel.append({ label:catalog.i18nc("@label", "Support, Skirt, SupportInfill"), color: "#00ffff" }); + legendModel.append({ label:catalog.i18nc("@label", "Infill"), color: "#ffbf00" }); + legendModel.append({ label:catalog.i18nc("@label", "MoveCombing"), color: "#0000ff" }); + legendModel.append({ label:catalog.i18nc("@label", "MoveRetraction"), color: "#8080ff" }); + legendModel.append({ label:catalog.i18nc("@label", "SupportInterface"), color: "#3fbfff" }); + } + } } } diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index 8b9a9b7d38..4cf1668ca3 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -76,6 +76,13 @@ class LayerViewProxy(QObject): if type(active_view) == LayerView.LayerView.LayerView: active_view.setLayerViewType(layer_view_type) + @pyqtProperty(bool) + def getLayerViewType(self): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + return active_view.getLayerViewType() + return 0 + @pyqtSlot(bool) def setOnlyColorActiveExtruder(self, only_color_active_extruder): active_view = self._controller.getActiveView() From e57de296e70d66d978f867dcd79289fb04ff7910 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 3 Jan 2017 10:14:34 +0100 Subject: [PATCH 024/156] Readded accidently removed stuff --- cura/LayerPolygon.py | 2 +- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 4509ba7d26..959ac9ad84 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -60,7 +60,7 @@ class LayerPolygon: # Only if the type of line segment changes do we need to add an extra vertex to change colors self._build_cache_needed_points[1:, 0][:, numpy.newaxis] = self._types[1:] != self._types[:-1] # Mark points as unneeded if they are of types we don't want in the line mesh according to the calculated mask - numpy.logical_and(self._build_cache_needed_points, self._build_cache_line_mesh_mask ) + numpy.logical_and(self._build_cache_needed_points, self._build_cache_line_mesh_mask, self._build_cache_needed_points ) self._vertex_begin = 0 self._vertex_end = numpy.sum( self._build_cache_needed_points ) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 49c306ea77..a00ab69d67 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -131,7 +131,7 @@ class ProcessSlicedLayersJob(Job): new_points = numpy.empty((len(points), 3), numpy.float32) if polygon.point_type == 0: # Point2D new_points[:, 0] = points[:, 0] - new_points[:, 1] = layer.height / 1000 # layer height value is in backend representation + new_points[:, 1] = layer.height / 1000 # layer height value is in backend representation new_points[:, 2] = -points[:, 1] else: # Point3D new_points[:, 0] = points[:, 0] From cd8eaf77599f9e3cb12113771f6669ff7d44eea9 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 3 Jan 2017 15:58:35 +0100 Subject: [PATCH 025/156] minimum layer slider now works --- plugins/LayerView/LayerPass.py | 2 +- plugins/LayerView/LayerView.py | 2 -- plugins/LayerView/LayerView.qml | 16 +++++++++++++--- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index 6d0c49e0f9..dba6f10930 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -80,7 +80,7 @@ class LayerPass(RenderPass): 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: + 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() diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 4e5d7da23e..d7bcb03f93 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -155,8 +155,6 @@ class LayerView(View): self._minimum_layer_num = value if self._minimum_layer_num < 0: self._minimum_layer_num = 0 - if self._minimum_layer_num > self._current_layer_num: - self._minimum_layer_num = self._current_layer_num self._startUpdateTopLayers() diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index 0e9a2cd7c9..de6327e066 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -22,13 +22,18 @@ Item anchors.leftMargin: UM.Theme.getSize("slider_layerview_margin").width * 0.2 orientation: Qt.Vertical minimumValue: 0; - maximumValue: UM.LayerView.numLayers; + maximumValue: UM.LayerView.numLayers-1; stepSize: 1 property real pixelsPerStep: ((height - UM.Theme.getSize("slider_handle").height) / (maximumValue - minimumValue)) * stepSize; value: UM.LayerView.minimumLayer - onValueChanged: UM.LayerView.setMinimumLayer(value) + onValueChanged: { + UM.LayerView.setMinimumLayer(value) + if (value > UM.LayerView.currentLayer) { + UM.LayerView.setCurrentLayer(value); + } + } style: UM.Theme.styles.slider; } @@ -48,7 +53,12 @@ Item property real pixelsPerStep: ((height - UM.Theme.getSize("slider_handle").height) / (maximumValue - minimumValue)) * stepSize; value: UM.LayerView.currentLayer - onValueChanged: UM.LayerView.setCurrentLayer(value) + onValueChanged: { + UM.LayerView.setCurrentLayer(value); + if (value < UM.LayerView.minimumLayer) { + UM.LayerView.setMinimumLayer(value); + } + } style: UM.Theme.styles.slider; From 38a7ffa7da151501028350d94ab82c45d57112ae Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Mon, 16 Jan 2017 21:35:28 +0100 Subject: [PATCH 026/156] Some fixes regarding submodules and imports. --- .../VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py | 2 +- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py b/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py index dce2b311bb..031e6c16f3 100644 --- a/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py +++ b/plugins/VersionUpgrade/VersionUpgrade22to24/VersionUpgrade.py @@ -6,7 +6,7 @@ import os import os.path import io -from UM import Resources +from UM.Resources import Resources from UM.VersionUpgrade import VersionUpgrade # Superclass of the plugin. class VersionUpgrade22to24(VersionUpgrade): diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 6be8d45b0a..5d5561f7aa 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -72,7 +72,7 @@ class XmlMaterialProfile(InstanceContainer): super().setDirty(dirty) base_file = self.getMetaDataEntry("base_file", None) if base_file is not None and base_file != self._id: - containers = UM.Settings.ContainerRegistry.getInstance().findContainers(id=base_file) + containers = ContainerRegistry.getInstance().findContainers(id=base_file) if containers: base_container = containers[0] if not base_container.isReadOnly(): @@ -479,7 +479,7 @@ class XmlMaterialProfile(InstanceContainer): new_material_id = self.id + "_" + machine_id # It could be that we are overwriting, so check if the ID already exists. - materials = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id=new_material_id) + materials = ContainerRegistry.getInstance().findInstanceContainers(id=new_material_id) if materials: new_material = materials[0] new_material.clearData() @@ -533,7 +533,7 @@ class XmlMaterialProfile(InstanceContainer): # It could be that we are overwriting, so check if the ID already exists. new_hotend_id = self.id + "_" + machine_id + "_" + hotend_id.replace(" ", "_") - materials = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(id=new_hotend_id) + materials = ContainerRegistry.getInstance().findInstanceContainers(id=new_hotend_id) if materials: new_hotend_material = materials[0] new_hotend_material.clearData() From 1b43e4981ed4b6623c9f0553d9269bf07c36ed9e Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Tue, 17 Jan 2017 16:57:37 +0100 Subject: [PATCH 027/156] Fixes for all of the plugins. Added a script to invoke mypy. (I'm stiiiick of .bat files. They are just broken.) --- cura/CrashHandler.py | 12 ++++--- plugins/3MFReader/ThreeMFReader.py | 4 ++- plugins/3MFReader/__init__.py | 8 ++--- plugins/3MFWriter/ThreeMFWriter.py | 4 ++- .../WindowsRemovableDrivePlugin.py | 2 +- plugins/SliceInfoPlugin/SliceInfo.py | 5 +-- .../NetworkPrinterOutputDevicePlugin.py | 2 +- plugins/USBPrinting/USBPrinterOutputDevice.py | 2 +- .../USBPrinterOutputDeviceManager.py | 4 +-- plugins/USBPrinting/avr_isp/stk500v2.py | 4 +-- plugins/X3DReader/X3DReader.py | 4 ++- run_mypy.py | 31 +++++++++++++++++++ 12 files changed, 62 insertions(+), 20 deletions(-) create mode 100644 run_mypy.py diff --git a/cura/CrashHandler.py b/cura/CrashHandler.py index ba8499d4f2..b658f88824 100644 --- a/cura/CrashHandler.py +++ b/cura/CrashHandler.py @@ -12,10 +12,14 @@ from UM.Logger import Logger from UM.i18n import i18nCatalog catalog = i18nCatalog("cura") -try: - from cura.CuraVersion import CuraDebugMode -except ImportError: - CuraDebugMode = False # [CodeStyle: Reflecting imported value] +MYPY = False +if MYPY: + CuraDebugMode = False +else: + try: + from cura.CuraVersion import CuraDebugMode + except ImportError: + CuraDebugMode = False # [CodeStyle: Reflecting imported value] # List of exceptions that should be considered "fatal" and abort the program. # These are primarily some exception types that we simply cannot really recover from diff --git a/plugins/3MFReader/ThreeMFReader.py b/plugins/3MFReader/ThreeMFReader.py index 976f54ba25..5638ce551c 100644 --- a/plugins/3MFReader/ThreeMFReader.py +++ b/plugins/3MFReader/ThreeMFReader.py @@ -17,8 +17,10 @@ from cura.Settings.ExtruderManager import ExtruderManager from cura.QualityManager import QualityManager from UM.Scene.SceneNode import SceneNode +MYPY = False try: - import xml.etree.cElementTree as ET + if not MYPY: + import xml.etree.cElementTree as ET except ImportError: Logger.log("w", "Unable to load cElementTree, switching to slower version") import xml.etree.ElementTree as ET diff --git a/plugins/3MFReader/__init__.py b/plugins/3MFReader/__init__.py index 3e05cb8dc7..cb4f9b9761 100644 --- a/plugins/3MFReader/__init__.py +++ b/plugins/3MFReader/__init__.py @@ -1,16 +1,16 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. +from typing import Dict from . import ThreeMFReader from . import ThreeMFWorkspaceReader from UM.i18n import i18nCatalog -import UM.Platform +from UM.Platform import Platform catalog = i18nCatalog("cura") - -def getMetaData(): +def getMetaData() -> Dict: # Workarround for osx not supporting double file extensions correclty. - if UM.Platform.isOSX(): + if Platform.isOSX(): workspace_extension = "3mf" else: workspace_extension = "curaproject.3mf" diff --git a/plugins/3MFWriter/ThreeMFWriter.py b/plugins/3MFWriter/ThreeMFWriter.py index 882740c4ed..361cf796d0 100644 --- a/plugins/3MFWriter/ThreeMFWriter.py +++ b/plugins/3MFWriter/ThreeMFWriter.py @@ -7,8 +7,10 @@ from UM.Logger import Logger from UM.Math.Matrix import Matrix from UM.Application import Application +MYPY = False try: - import xml.etree.cElementTree as ET + if not MYPY: + import xml.etree.cElementTree as ET except ImportError: Logger.log("w", "Unable to load cElementTree, switching to slower version") import xml.etree.ElementTree as ET diff --git a/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py b/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py index 14a4681bc3..42f3935f65 100644 --- a/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py +++ b/plugins/RemovableDriveOutputDevice/WindowsRemovableDrivePlugin.py @@ -8,7 +8,7 @@ catalog = i18nCatalog("cura") from . import RemovableDrivePlugin import string -import ctypes +import ctypes # type: ignore from ctypes import wintypes # Using ctypes.wintypes in the code below does not seem to work from UM.i18n import i18nCatalog diff --git a/plugins/SliceInfoPlugin/SliceInfo.py b/plugins/SliceInfoPlugin/SliceInfo.py index 4f39fd4818..05f7c0e6f5 100644 --- a/plugins/SliceInfoPlugin/SliceInfo.py +++ b/plugins/SliceInfoPlugin/SliceInfo.py @@ -1,5 +1,6 @@ # Copyright (c) 2015 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. +from typing import Any from cura.CuraApplication import CuraApplication @@ -26,8 +27,8 @@ import json catalog = i18nCatalog("cura") class SliceInfoJob(Job): - data = None - url = None + data = None # type: Any + url = None # type: str def __init__(self, url, data): super().__init__() diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevicePlugin.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevicePlugin.py index 2725fa8d17..fe35b60de5 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevicePlugin.py @@ -1,7 +1,7 @@ from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin from . import NetworkPrinterOutputDevice -from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo +from zeroconf import Zeroconf, ServiceBrowser, ServiceStateChange, ServiceInfo # type: ignore from UM.Logger import Logger from UM.Signal import Signal, signalemitter from UM.Application import Application diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index e344caee1d..7adb0b0d08 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -2,7 +2,7 @@ # Cura is released under the terms of the AGPLv3 or higher. from .avr_isp import stk500v2, ispBase, intelHex -import serial +import serial # type: ignore import threading import time import queue diff --git a/plugins/USBPrinting/USBPrinterOutputDeviceManager.py b/plugins/USBPrinting/USBPrinterOutputDeviceManager.py index 4dec2e3a06..ed97076df6 100644 --- a/plugins/USBPrinting/USBPrinterOutputDeviceManager.py +++ b/plugins/USBPrinting/USBPrinterOutputDeviceManager.py @@ -258,7 +258,7 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension): def getSerialPortList(self, only_list_usb = False): base_list = [] if platform.system() == "Windows": - import winreg #@UnresolvedImport + import winreg # type: ignore @UnresolvedImport try: key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM") i = 0 @@ -277,4 +277,4 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension): base_list = base_list + glob.glob("/dev/ttyUSB*") + glob.glob("/dev/ttyACM*") + glob.glob("/dev/cu.*") + glob.glob("/dev/tty.usb*") + glob.glob("/dev/rfcomm*") + glob.glob("/dev/serial/by-id/*") return list(base_list) - _instance = None + _instance = None # type: "USBPrinterOutputDeviceManager" diff --git a/plugins/USBPrinting/avr_isp/stk500v2.py b/plugins/USBPrinting/avr_isp/stk500v2.py index 91bef53875..dbfc8dc756 100644 --- a/plugins/USBPrinting/avr_isp/stk500v2.py +++ b/plugins/USBPrinting/avr_isp/stk500v2.py @@ -7,7 +7,7 @@ import struct import sys import time -from serial import Serial +from serial import Serial # type: ignore from serial import SerialException from serial import SerialTimeoutException from UM.Logger import Logger @@ -184,7 +184,7 @@ class Stk500v2(ispBase.IspBase): def portList(): ret = [] - import _winreg + import _winreg # type: ignore key=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,"HARDWARE\\DEVICEMAP\\SERIALCOMM") #@UndefinedVariable i=0 while True: diff --git a/plugins/X3DReader/X3DReader.py b/plugins/X3DReader/X3DReader.py index 0a81e98d0d..f78023dfab 100644 --- a/plugins/X3DReader/X3DReader.py +++ b/plugins/X3DReader/X3DReader.py @@ -13,8 +13,10 @@ from UM.Mesh.MeshBuilder import MeshBuilder from UM.Mesh.MeshReader import MeshReader from UM.Scene.SceneNode import SceneNode +MYPY = False try: - import xml.etree.cElementTree as ET + if not MYPY: + import xml.etree.cElementTree as ET except ImportError: import xml.etree.ElementTree as ET diff --git a/run_mypy.py b/run_mypy.py new file mode 100644 index 0000000000..7c203f87d9 --- /dev/null +++ b/run_mypy.py @@ -0,0 +1,31 @@ +#!env python +import os +import subprocess + +os.putenv("MYPYPATH", r".;.\plugins;..\Uranium_hint\;..\Uranium_hint\stubs\\" ) + +def findModules(path): + result = [] + for entry in os.scandir(path): + if entry.is_dir() and os.path.exists(os.path.join(path, entry.name, "__init__.py")): + result.append(entry.name) + return result + +plugins = findModules("plugins") +plugins.sort() + +mods = ["cura"] + plugins + +for mod in mods: + print("------------- Checking module {mod}".format(**locals())) + result = subprocess.run(["python", r"c:\python35\Scripts\mypy", "-p", mod]) + if result.returncode != 0: + print(""" +Module {mod} failed checking. :( +""".format(**locals())) + break +else: + print(""" + +Done checking. All is good. +""") From cf85831d87daee40cf9b7cd8c66931a0558ecfd5 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Tue, 17 Jan 2017 20:56:28 +0100 Subject: [PATCH 028/156] Also check the upgrade plugins. --- plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py | 8 ++++---- run_mypy.py | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py b/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py index 5897524e93..3bff7c1bf5 100644 --- a/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py +++ b/plugins/VersionUpgrade/VersionUpgrade21to22/Profile.py @@ -26,7 +26,7 @@ class Profile: # # \param serialised A string with the contents of a profile. # \param filename The supposed filename of the profile, without extension. - def __init__(self, serialised: str, filename: str): + def __init__(self, serialised: str, filename: str) -> None: self._filename = filename parser = configparser.ConfigParser(interpolation = None) @@ -58,17 +58,17 @@ class Profile: self._material_name = None # Parse the settings. - self._settings = {} + self._settings = {} # type: Dict[str,str] if parser.has_section("settings"): for key, value in parser["settings"].items(): self._settings[key] = value # Parse the defaults and the disabled defaults. - self._changed_settings_defaults = {} + self._changed_settings_defaults = {} # type: Dict[str,str] if parser.has_section("defaults"): for key, value in parser["defaults"].items(): self._changed_settings_defaults[key] = value - self._disabled_settings_defaults = [] + self._disabled_settings_defaults = [] # type: List[str] if parser.has_section("disabled_defaults"): disabled_defaults_string = parser.get("disabled_defaults", "values") self._disabled_settings_defaults = [item for item in disabled_defaults_string.split(",") if item != ""] # Split by comma. diff --git a/run_mypy.py b/run_mypy.py index 7c203f87d9..c5dfb23802 100644 --- a/run_mypy.py +++ b/run_mypy.py @@ -2,7 +2,7 @@ import os import subprocess -os.putenv("MYPYPATH", r".;.\plugins;..\Uranium_hint\;..\Uranium_hint\stubs\\" ) +os.putenv("MYPYPATH", r".;.\plugins;.\plugins\VersionUpgrade;..\Uranium_hint\;..\Uranium_hint\stubs\\" ) def findModules(path): result = [] @@ -14,7 +14,7 @@ def findModules(path): plugins = findModules("plugins") plugins.sort() -mods = ["cura"] + plugins +mods = ["cura"] + plugins + findModules("plugins/VersionUpgrade") for mod in mods: print("------------- Checking module {mod}".format(**locals())) From 4fecf55b3b0e64e4f6720d8d628ba209c20a65a3 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Tue, 17 Jan 2017 20:56:50 +0100 Subject: [PATCH 029/156] Use double quotes instead of singles. --- cura/QualityManager.py | 2 +- cura/Settings/ContainerManager.py | 2 +- cura/Settings/ExtruderManager.py | 2 +- cura/Settings/ProfilesModel.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cura/QualityManager.py b/cura/QualityManager.py index 8aa3c3a097..d7b2c7d705 100644 --- a/cura/QualityManager.py +++ b/cura/QualityManager.py @@ -22,7 +22,7 @@ class QualityManager: QualityManager.__instance = cls() return QualityManager.__instance - __instance = None # type: 'QualityManager' + __instance = None # type: "QualityManager" ## Find a quality by name for a specific machine definition and materials. # diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index 061f0f9b79..4e4fc36784 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -697,7 +697,7 @@ class ContainerManager(QObject): ContainerManager.__instance = cls() return ContainerManager.__instance - __instance = None # type: 'ContainerManager' + __instance = None # type: "ContainerManager" # Factory function, used by QML @staticmethod diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 52a2a9c694..add906c166 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -89,7 +89,7 @@ class ExtruderManager(QObject): # # \return The extruder manager. @classmethod - def getInstance(cls) -> 'ExtruderManager': + def getInstance(cls) -> "ExtruderManager": if not cls.__instance: cls.__instance = ExtruderManager() return cls.__instance diff --git a/cura/Settings/ProfilesModel.py b/cura/Settings/ProfilesModel.py index d60a633549..404bb569a5 100644 --- a/cura/Settings/ProfilesModel.py +++ b/cura/Settings/ProfilesModel.py @@ -38,7 +38,7 @@ class ProfilesModel(InstanceContainersModel): ProfilesModel.__instance = cls() return ProfilesModel.__instance - __instance = None # type: 'ProfilesModel' + __instance = None # type: "ProfilesModel" ## Fetch the list of containers to display. # From d5c96c1aaee119b96596c820bb636e254eb9643c Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Wed, 18 Jan 2017 13:49:18 +0100 Subject: [PATCH 030/156] Removed a line of debug. --- cura/Settings/MachineManager.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 8c14c7b007..fec31094ce 100644 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -378,7 +378,6 @@ class MachineManager(QObject): # \param fallback_name \type{string} Name to use when (stripped) new_name is empty # \return \type{string} Name that is unique for the specified type and name/id def _createUniqueName(self, container_type: str, current_name: str, new_name: str, fallback_name: str) -> str: - Logger.log('d', str(ContainerRegistry.getInstance())) return ContainerRegistry.getInstance().createUniqueName(container_type, current_name, new_name, fallback_name) def _checkStacksHaveErrors(self): From f80a04cbc3101db38b9d6346b47709d4aa6a1c10 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 24 Jan 2017 16:31:57 +0100 Subject: [PATCH 031/156] Auto detect compatibility mode for layer view. --- plugins/LayerView/LayerView.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 6aa85c3e3c..21854fb295 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -13,15 +13,13 @@ from UM.Mesh.MeshBuilder import MeshBuilder from UM.Job import Job from UM.Preferences import Preferences from UM.Logger import Logger -from UM.Scene.SceneNode import SceneNode -from UM.View.RenderBatch import RenderBatch from UM.View.GL.OpenGL import OpenGL from UM.Message import Message from UM.Application import Application from cura.ConvexHullNode import ConvexHullNode -from PyQt5.QtCore import Qt, QTimer +from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication from . import LayerViewProxy @@ -78,7 +76,10 @@ class LayerView(View): self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) - self._compatibility_mode = bool(Preferences.getInstance().getValue("view/compatibility_mode")) + self._compatibility_mode = True # for safety + #self._compatibility_mode = bool(Preferences.getInstance().getValue("view/compatibility_mode")) + #self._compatibility_mode = not self.getRenderer().getSupportsGeometryShader() + #Logger.log("d", "OpenGL Compatibility mode: %s" % self._compatibility_mode) self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled")) @@ -90,6 +91,7 @@ class LayerView(View): # Currently the RenderPass constructor requires a size > 0 # This should be fixed in RenderPass's constructor. self._layer_pass = LayerPass.LayerPass(1, 1) + self._compatibility_mode = not self.getRenderer().getSupportsGeometryShader() self._layer_pass.setLayerView(self) self.getRenderer().addRenderPass(self._layer_pass) return self._layer_pass @@ -346,7 +348,7 @@ class LayerView(View): self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) - self._compatibility_mode = bool(Preferences.getInstance().getValue("view/compatibility_mode")) + # self._compatibility_mode = bool(Preferences.getInstance().getValue("view/compatibility_mode")) self._startUpdateTopLayers() From e21a6ed62a0e6018c717c5ce0e331c9496d5a85b Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 24 Jan 2017 16:52:47 +0100 Subject: [PATCH 032/156] Cleanup --- plugins/LayerView/LayerView.py | 4 ---- resources/qml/Preferences/GeneralPage.qml | 18 ++---------------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 21854fb295..0d38e89026 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -77,9 +77,6 @@ class LayerView(View): self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) self._compatibility_mode = True # for safety - #self._compatibility_mode = bool(Preferences.getInstance().getValue("view/compatibility_mode")) - #self._compatibility_mode = not self.getRenderer().getSupportsGeometryShader() - #Logger.log("d", "OpenGL Compatibility mode: %s" % self._compatibility_mode) self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled")) @@ -348,7 +345,6 @@ class LayerView(View): self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) - # self._compatibility_mode = bool(Preferences.getInstance().getValue("view/compatibility_mode")) self._startUpdateTopLayers() diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index db0b372fd9..57a35943d9 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -213,20 +213,6 @@ UM.PreferencesPage } } - UM.TooltipArea { - width: childrenRect.width - height: childrenRect.height - text: catalog.i18nc("@info:tooltip", "Compatibility mode in layerview?") - - CheckBox - { - id: topLayerViewCompatibilityCheckbox - text: catalog.i18nc("@option:check", "Layer view compatibility mode (for OpenGL <= 4.0, restart required)") - checked: boolCheck(UM.Preferences.getValue("view/compatibility_mode")) - onCheckedChanged: UM.Preferences.setValue("view/compatibility_mode", checked) - } - } - UM.TooltipArea { width: childrenRect.width; height: childrenRect.height; @@ -235,7 +221,7 @@ UM.PreferencesPage CheckBox { id: topLayerCountCheckbox - text: catalog.i18nc("@action:button","Display five top layers in layer view (only for compatibility mode)"); + text: catalog.i18nc("@action:button","Display five top layers in layer view compatibility mode"); checked: UM.Preferences.getValue("view/top_layer_count") == 5 onClicked: { @@ -259,7 +245,7 @@ UM.PreferencesPage CheckBox { id: topLayersOnlyCheckbox - text: catalog.i18nc("@option:check", "Only display top layer(s) in layer view (only for compatibility mode)") + text: catalog.i18nc("@option:check", "Only display top layer(s) in layer view compatibility mode") checked: boolCheck(UM.Preferences.getValue("view/only_show_top_layers")) onCheckedChanged: UM.Preferences.setValue("view/only_show_top_layers", checked) } From 6625938a2b7d0590e099d398acad2c4fa3b29ec6 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 25 Jan 2017 09:24:40 +0100 Subject: [PATCH 033/156] Cleanup __color_map in LayerPolygon --- cura/LayerPolygon.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 959ac9ad84..c1ec3a6978 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -38,7 +38,6 @@ class LayerPolygon: # Buffering the colors shouldn't be necessary as it is not # re-used and can save alot of memory usage. - self._color_map = self.__color_map # * [1, 1, 1, self._extruder] # The alpha component is used to store the extruder nr self._colors = self._color_map[self._types] # When type is used as index returns true if type == LayerPolygon.InfillType or type == LayerPolygon.SkinType or type == LayerPolygon.SupportInfillType @@ -185,7 +184,7 @@ class LayerPolygon: return normals # Should be generated in better way, not hardcoded. - __color_map = numpy.array([ + _color_map = numpy.array([ [1.0, 1.0, 1.0, 1.0], # NoneType [1.0, 0.0, 0.0, 1.0], # Inset0Type [0.0, 1.0, 0.0, 1.0], # InsetXType From 5fff1f665763904f8b9ccaf4138555391396a333 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 25 Jan 2017 09:27:22 +0100 Subject: [PATCH 034/156] Cleanup --- cura/LayerPolygon.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index c1ec3a6978..287caa69f9 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -49,8 +49,7 @@ class LayerPolygon: def buildCache(self): # For the line mesh we do not draw Infill or Jumps. Therefore those lines are filtered out. - # self._build_cache_line_mesh_mask = numpy.logical_not(numpy.logical_or(self._jump_mask, self._types == LayerPolygon.InfillType )) - self._build_cache_line_mesh_mask = numpy.ones(self._jump_mask.shape, dtype=bool) # numpy.logical_not(self._jump_mask) + self._build_cache_line_mesh_mask = numpy.ones(self._jump_mask.shape, dtype=bool) mesh_line_count = numpy.sum(self._build_cache_line_mesh_mask) self._index_begin = 0 self._index_end = mesh_line_count From a52cb2fa636c2af1f70fedfd3a3af2cbdfb74180 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 25 Jan 2017 09:48:36 +0100 Subject: [PATCH 035/156] Compatibility mode scale line type colors --- cura/LayerPolygon.py | 4 ++-- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 287caa69f9..34bb38249a 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -18,6 +18,8 @@ class LayerPolygon: __jump_map = numpy.logical_or(numpy.logical_or(numpy.arange(11) == NoneType, numpy.arange(11) == MoveCombingType), numpy.arange(11) == MoveRetractionType) + ## LayerPolygon + # line_thicknesses: array with type as index and thickness as value def __init__(self, mesh, extruder, line_types, data, line_widths, line_thicknesses): self._mesh = mesh self._extruder = extruder @@ -63,8 +65,6 @@ class LayerPolygon: self._vertex_begin = 0 self._vertex_end = numpy.sum( self._build_cache_needed_points ) - ## build - # line_thicknesses: array with type as index and thickness as value def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, line_types, indices): if (self._build_cache_line_mesh_mask is None) or (self._build_cache_needed_points is None ): self.buildCache() diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index a00ab69d67..1dbcbdb3b7 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -180,10 +180,10 @@ class ProcessSlicedLayersJob(Job): material_color_map[0, :] = color # We have to scale the colors for compatibility mode - if bool(Preferences.getInstance().getValue("view/compatibility_mode")): - line_type_brightness = 0.5 - else: + if Application.getInstance().getRenderer().getSupportsGeometryShader(): line_type_brightness = 1.0 + else: + line_type_brightness = 0.5 # for compatibility mode layer_mesh = layer_data.build(material_color_map, line_type_brightness) if self._abort_requested: From 5f6ed488d1693f8f422364d2537b46b38fcdf258 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 30 Jan 2017 11:39:59 +0100 Subject: [PATCH 036/156] Layerview removed Color Only Selected Extruder, cleanup 3d shader. CURA-3273 --- plugins/LayerView/LayerPass.py | 2 -- plugins/LayerView/LayerView.py | 8 -------- plugins/LayerView/LayerView.qml | 7 ------- plugins/LayerView/LayerViewProxy.py | 6 ------ plugins/LayerView/layers3d.shader | 8 -------- 5 files changed, 31 deletions(-) diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index f01e4b56c2..7ae024181d 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -45,7 +45,6 @@ class LayerPass(RenderPass): self._layer_shader.setUniformValue("u_active_extruder", float(max(0, self._extruder_manager.activeExtruderIndex))) if self._layer_view: self._layer_shader.setUniformValue("u_layer_view_type", self._layer_view.getLayerViewType()) - self._layer_shader.setUniformValue("u_only_color_active_extruder", (1 if self._layer_view.getOnlyColorActiveExtruder() else 0)) 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_support", self._layer_view.getShowSupport()) @@ -55,7 +54,6 @@ class LayerPass(RenderPass): else: #defaults self._layer_shader.setUniformValue("u_layer_view_type", 1) - self._layer_shader.setUniformValue("u_only_color_active_extruder", 1) self._layer_shader.setUniformValue("u_extruder_opacity", [1, 1, 1, 1]) self._layer_shader.setUniformValue("u_show_travel_moves", 0) self._layer_shader.setUniformValue("u_show_support", 1) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 15a79c4412..8f8d9dbd0a 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -60,7 +60,6 @@ class LayerView(View): self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged) self._layer_view_type = 0 # 0 is material color, 1 is color by linetype, 2 is speed - self._only_color_active_extruder = True self._extruder_opacity = [1.0, 1.0, 1.0, 1.0] self._show_travel_moves = 0 self._show_support = 1 @@ -167,13 +166,6 @@ class LayerView(View): def getLayerViewType(self): return self._layer_view_type - def setOnlyColorActiveExtruder(self, only_color_active_extruder): - self._only_color_active_extruder = only_color_active_extruder - self.currentLayerNumChanged.emit() - - def getOnlyColorActiveExtruder(self): - return self._only_color_active_extruder - def setExtruderOpacity(self, extruder_nr, opacity): self._extruder_opacity[extruder_nr] = opacity self.currentLayerNumChanged.emit() diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index d7ea4282d2..aeb163855e 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -247,13 +247,6 @@ Item } text: "Show infill" } - CheckBox { - checked: true - onClicked: { - UM.LayerView.setOnlyColorActiveExtruder(checked); - } - text: "Only color active extruder" - } } } } diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index ac87ca904d..3de360306a 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -84,12 +84,6 @@ class LayerViewProxy(QObject): return active_view.getLayerViewType() return 0 - @pyqtSlot(bool) - def setOnlyColorActiveExtruder(self, only_color_active_extruder): - active_view = self._controller.getActiveView() - if type(active_view) == LayerView.LayerView.LayerView: - active_view.setOnlyColorActiveExtruder(only_color_active_extruder) - # Opacity 0..1 @pyqtSlot(int, float) def setExtruderOpacity(self, extruder_nr, opacity): diff --git a/plugins/LayerView/layers3d.shader b/plugins/LayerView/layers3d.shader index 03a4015b3c..943e9bd64e 100644 --- a/plugins/LayerView/layers3d.shader +++ b/plugins/LayerView/layers3d.shader @@ -3,10 +3,8 @@ vertex = #version 410 uniform highp mat4 u_modelMatrix; uniform highp mat4 u_viewProjectionMatrix; - //uniform highp mat4 u_modelViewProjectionMatrix; uniform lowp float u_active_extruder; uniform lowp int u_layer_view_type; - uniform lowp int u_only_color_active_extruder; uniform lowp vec4 u_extruder_opacity; // currently only for max 4 extruders, others always visible uniform highp mat4 u_normalMatrix; @@ -20,11 +18,9 @@ vertex = attribute highp int a_line_type; varying lowp vec4 v_color; - //varying lowp vec4 v_material_color; varying highp vec3 v_vertex; varying highp vec3 v_normal; - //varying lowp vec2 v_uvs; varying lowp vec2 v_line_dim; varying highp int v_extruder; varying highp vec4 v_extruder_opacity; @@ -52,9 +48,6 @@ vertex = v_color = a_color; break; } - if ((u_only_color_active_extruder == 1) && (a_line_type != 8) && (a_line_type != 9)) { - v_color = (a_extruder == u_active_extruder) ? v_color : vec4(0.4, 0.4, 0.4, v_color.a); - } v_vertex = world_space_vert.xyz; v_normal = (u_normalMatrix * normalize(a_normal)).xyz; @@ -323,7 +316,6 @@ fragment = [defaults] u_active_extruder = 0.0 u_layer_view_type = 0 -u_only_color_active_extruder = 1 u_extruder_opacity = [1.0, 1.0, 1.0, 1.0] u_specularColor = [0.4, 0.4, 0.4, 1.0] From 5a2aa8846b7c0afcdbb4e18314ed2e5cdcc63b40 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 30 Jan 2017 13:29:35 +0100 Subject: [PATCH 037/156] Added extruder count detection to layer view. CURA-3273 --- cura/Settings/ExtruderManager.py | 1 + plugins/LayerView/LayerView.py | 25 ++++++++++++++++++------- plugins/LayerView/LayerView.qml | 24 ++++++++++++++++++++++-- plugins/LayerView/LayerViewProxy.py | 14 +++++++++++++- 4 files changed, 54 insertions(+), 10 deletions(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 81579f74d0..4e59df9597 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -50,6 +50,7 @@ class ExtruderManager(QObject): except KeyError: # Extruder index could be -1 if the global tab is selected, or the entry doesn't exist if the machine definition is wrong. return None + ## Return extruder count according to extruder trains. @pyqtProperty(int, notify = extrudersChanged) def extruderCount(self): if not UM.Application.getInstance().getGlobalContainerStack(): diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 8f8d9dbd0a..922966854d 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -18,6 +18,7 @@ from UM.Message import Message from UM.Application import Application from cura.ConvexHullNode import ConvexHullNode +from cura.Settings.ExtruderManager import ExtruderManager from PyQt5.QtCore import Qt from PyQt5.QtWidgets import QApplication @@ -59,13 +60,7 @@ class LayerView(View): self._proxy = LayerViewProxy.LayerViewProxy() self._controller.getScene().getRoot().childrenChanged.connect(self._onSceneChanged) - self._layer_view_type = 0 # 0 is material color, 1 is color by linetype, 2 is speed - self._extruder_opacity = [1.0, 1.0, 1.0, 1.0] - self._show_travel_moves = 0 - self._show_support = 1 - self._show_adhesion = 1 - self._show_skin = 1 - self._show_infill = 1 + self._resetSettings() self._legend_items = None Preferences.getInstance().addPreference("view/top_layer_count", 5) @@ -80,6 +75,16 @@ class LayerView(View): self._wireprint_warning_message = Message(catalog.i18nc("@info:status", "Cura does not accurately display layers when Wire Printing is enabled")) + def _resetSettings(self): + self._layer_view_type = 0 # 0 is material color, 1 is color by linetype, 2 is speed + self._extruder_count = 0 + self._extruder_opacity = [1.0, 1.0, 1.0, 1.0] + self._show_travel_moves = 0 + self._show_support = 1 + self._show_adhesion = 1 + self._show_skin = 1 + self._show_infill = 1 + def getActivity(self): return self._activity @@ -211,6 +216,9 @@ class LayerView(View): def getCompatibilityMode(self): return self._compatibility_mode + def getExtruderCount(self): + return self._extruder_count + def calculateMaxLayers(self): scene = self.getController().getScene() self._activity = True @@ -242,6 +250,7 @@ class LayerView(View): maxLayersChanged = Signal() currentLayerNumChanged = Signal() + globalStackChanged = Signal() ## Hackish way to ensure the proxy is already created, which ensures that the layerview.qml is already created # as this caused some issues. @@ -302,7 +311,9 @@ class LayerView(View): self._global_container_stack = Application.getInstance().getGlobalContainerStack() if self._global_container_stack: self._global_container_stack.propertyChanged.connect(self._onPropertyChanged) + self._extruder_count = self._global_container_stack.getProperty("machine_extruder_count", "value") self._onPropertyChanged("wireframe_enabled", "value") + self.globalStackChanged.emit() else: self._wireprint_warning_message.hide() diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index aeb163855e..b60f158e3b 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -203,7 +203,7 @@ Item UM.LayerView.setExtruderOpacity(0, checked ? 1.0 : 0.0); } text: "Extruder 1" - visible: !UM.LayerView.compatibilityMode + visible: !UM.LayerView.compatibilityMode && (UM.LayerView.getExtruderCount >= 1) } CheckBox { checked: true @@ -211,7 +211,27 @@ Item UM.LayerView.setExtruderOpacity(1, checked ? 1.0 : 0.0); } text: "Extruder 2" - visible: !UM.LayerView.compatibilityMode + visible: !UM.LayerView.compatibilityMode && (UM.LayerView.getExtruderCount >= 2) + } + CheckBox { + checked: true + onClicked: { + UM.LayerView.setExtruderOpacity(2, checked ? 1.0 : 0.0); + } + text: "Extruder 3" + visible: !UM.LayerView.compatibilityMode && (UM.LayerView.getExtruderCount >= 3) + } + CheckBox { + checked: true + onClicked: { + UM.LayerView.setExtruderOpacity(3, checked ? 1.0 : 0.0); + } + text: "Extruder 4" + visible: !UM.LayerView.compatibilityMode && (UM.LayerView.getExtruderCount >= 4) + } + Label { + text: "Other extruders always visible" + visible: !UM.LayerView.compatibilityMode && (UM.LayerView.getExtruderCount >= 5) } CheckBox { onClicked: { diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index 3de360306a..7eb4cc65da 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -16,6 +16,7 @@ class LayerViewProxy(QObject): currentLayerChanged = pyqtSignal() maxLayersChanged = pyqtSignal() activityChanged = pyqtSignal() + globalStackChanged = pyqtSignal() @pyqtProperty(bool, notify = activityChanged) def getLayerActivity(self): @@ -121,6 +122,13 @@ class LayerViewProxy(QObject): if type(active_view) == LayerView.LayerView.LayerView: active_view.setShowInfill(show) + @pyqtProperty(int, notify = globalStackChanged) + def getExtruderCount(self): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + return active_view.getExtruderCount() + return 0 + def _layerActivityChanged(self): self.activityChanged.emit() @@ -133,10 +141,14 @@ class LayerViewProxy(QObject): def _onBusyChanged(self): self.busyChanged.emit() - + + def _onGlobalStackChanged(self): + self.globalStackChanged.emit() + def _onActiveViewChanged(self): active_view = self._controller.getActiveView() if type(active_view) == LayerView.LayerView.LayerView: active_view.currentLayerNumChanged.connect(self._onLayerChanged) active_view.maxLayersChanged.connect(self._onMaxLayersChanged) active_view.busyChanged.connect(self._onBusyChanged) + active_view.globalStackChanged.connect(self._onGlobalStackChanged) From aa923321f80aafa6ed473746f73f2d9e98fd7121 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 31 Jan 2017 09:19:18 +0100 Subject: [PATCH 038/156] Fix compatibility mode layout. CURA-3273 --- plugins/LayerView/LayerView.qml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index b60f158e3b..9c877769bc 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -173,7 +173,7 @@ Item ComboBox { - id: layer_type_combobox + id: layerTypeCombobox anchors.top: slider_background.bottom anchors.left: parent.left model: layerViewTypes @@ -185,6 +185,7 @@ Item Label { + id: compatibilityModeLabel anchors.top: slider_background.bottom anchors.left: parent.left text: catalog.i18nc("@label","Compatibility mode") @@ -193,7 +194,7 @@ Item ColumnLayout { id: view_settings - anchors.top: layer_type_combobox.bottom + anchors.top: UM.LayerView.compatibilityMode ? compatibilityModeLabel.bottom : layerTypeCombobox.bottom anchors.topMargin: UM.Theme.getSize("default_margin").height x: UM.Theme.getSize("default_margin").width From e31a6950614e5fa8a031fb8a68c037fb685581a9 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 31 Jan 2017 17:05:00 +0100 Subject: [PATCH 039/156] WIP OpenGL 4.1 core profile. CURA-3273 --- resources/shaders/grid.shader | 31 ++++++++++ resources/shaders/overhang.shader | 67 ++++++++++++++++++++ resources/shaders/striped.shader | 68 +++++++++++++++++++++ resources/shaders/transparent_object.shader | 53 ++++++++++++++++ 4 files changed, 219 insertions(+) diff --git a/resources/shaders/grid.shader b/resources/shaders/grid.shader index c05b9ba15c..74eed544fd 100644 --- a/resources/shaders/grid.shader +++ b/resources/shaders/grid.shader @@ -27,6 +27,37 @@ fragment = gl_FragColor = u_gridColor1; } +vertex41core = + #version 410 + uniform highp mat4 u_modelViewProjectionMatrix; + + in highp vec4 a_vertex; + in lowp vec2 a_uvs; + + out lowp vec2 v_uvs; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + v_uvs = a_uvs; + } + +fragment41core = + #version 410 + uniform lowp vec4 u_gridColor0; + uniform lowp vec4 u_gridColor1; + + in lowp vec2 v_uvs; + out vec4 frag_color; + + void main() + { + if (mod(floor(v_uvs.x / 10.0) - floor(v_uvs.y / 10.0), 2.0) < 1.0) + frag_color = u_gridColor0; + else + frag_color = u_gridColor1; + } + [defaults] u_gridColor0 = [0.96, 0.96, 0.96, 1.0] u_gridColor1 = [0.8, 0.8, 0.8, 1.0] diff --git a/resources/shaders/overhang.shader b/resources/shaders/overhang.shader index 4e5999a693..b9cf53f8b7 100644 --- a/resources/shaders/overhang.shader +++ b/resources/shaders/overhang.shader @@ -62,6 +62,73 @@ fragment = gl_FragColor.a = 1.0; } +vertex41core = + #version 410 + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewProjectionMatrix; + uniform highp mat4 u_normalMatrix; + + in highp vec4 a_vertex; + in highp vec4 a_normal; + in highp vec2 a_uvs; + + out highp vec3 f_vertex; + out highp vec3 f_normal; + + void main() + { + vec4 world_space_vert = u_modelMatrix * a_vertex; + gl_Position = u_viewProjectionMatrix * world_space_vert; + + f_vertex = world_space_vert.xyz; + f_normal = (u_normalMatrix * normalize(a_normal)).xyz; + } + +fragment41core = + #version 410 + uniform mediump vec4 u_ambientColor; + uniform mediump vec4 u_diffuseColor; + uniform mediump vec4 u_specularColor; + uniform highp vec3 u_lightPosition; + uniform mediump float u_shininess; + uniform highp vec3 u_viewPosition; + + uniform lowp float u_overhangAngle; + uniform lowp vec4 u_overhangColor; + + in highp vec3 f_vertex; + in highp vec3 f_normal; + + out vec4 frag_color; + + void main() + { + + mediump vec4 finalColor = vec4(0.0); + + // Ambient Component + finalColor += u_ambientColor; + + highp vec3 normal = normalize(f_normal); + highp vec3 lightDir = normalize(u_lightPosition - f_vertex); + + // Diffuse Component + highp float NdotL = clamp(abs(dot(normal, lightDir)), 0.0, 1.0); + finalColor += (NdotL * u_diffuseColor); + + // Specular Component + // TODO: We should not do specularity for fragments facing away from the light. + highp vec3 reflectedLight = reflect(-lightDir, normal); + highp vec3 viewVector = normalize(u_viewPosition - f_vertex); + highp float NdotR = clamp(dot(viewVector, reflectedLight), 0.0, 1.0); + finalColor += pow(NdotR, u_shininess) * u_specularColor; + + finalColor = (-normal.y > u_overhangAngle) ? u_overhangColor : finalColor; + + frag_color = finalColor; + frag_color.a = 1.0; + } + [defaults] u_ambientColor = [0.3, 0.3, 0.3, 1.0] u_diffuseColor = [1.0, 0.79, 0.14, 1.0] diff --git a/resources/shaders/striped.shader b/resources/shaders/striped.shader index 0114f0b2cb..ce7d14e39e 100644 --- a/resources/shaders/striped.shader +++ b/resources/shaders/striped.shader @@ -63,6 +63,74 @@ fragment = gl_FragColor.a = 1.0; } +vertex41core = + #version 410 + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewProjectionMatrix; + uniform highp mat4 u_normalMatrix; + + in highp vec4 a_vertex; + in highp vec4 a_normal; + in highp vec2 a_uvs; + + out highp vec3 v_position; + out highp vec3 v_vertex; + out highp vec3 v_normal; + + void main() + { + vec4 world_space_vert = u_modelMatrix * a_vertex; + gl_Position = u_viewProjectionMatrix * world_space_vert; + + v_position = gl_Position.xyz; + v_vertex = world_space_vert.xyz; + v_normal = (u_normalMatrix * normalize(a_normal)).xyz; + } + +fragment41core = + #version 410 + uniform mediump vec4 u_ambientColor; + uniform mediump vec4 u_diffuseColor1; + uniform mediump vec4 u_diffuseColor2; + uniform mediump vec4 u_specularColor; + uniform highp vec3 u_lightPosition; + uniform mediump float u_shininess; + uniform highp vec3 u_viewPosition; + + uniform mediump float u_width; + + in highp vec3 v_position; + in highp vec3 v_vertex; + in highp vec3 v_normal; + + out vec4 frag_color; + + void main() + { + mediump vec4 finalColor = vec4(0.0); + mediump vec4 diffuseColor = (mod((-v_position.x + v_position.y), u_width) < (u_width / 2.)) ? u_diffuseColor1 : u_diffuseColor2; + + /* Ambient Component */ + finalColor += u_ambientColor; + + highp vec3 normal = normalize(v_normal); + highp vec3 lightDir = normalize(u_lightPosition - v_vertex); + + /* Diffuse Component */ + highp float NdotL = clamp(abs(dot(normal, lightDir)), 0.0, 1.0); + finalColor += (NdotL * diffuseColor); + + /* Specular Component */ + /* TODO: We should not do specularity for fragments facing away from the light.*/ + highp vec3 reflectedLight = reflect(-lightDir, normal); + highp vec3 viewVector = normalize(u_viewPosition - v_vertex); + highp float NdotR = clamp(dot(viewVector, reflectedLight), 0.0, 1.0); + finalColor += pow(NdotR, u_shininess) * u_specularColor; + + frag_color = finalColor; + frag_color.a = 1.0; + } + [defaults] u_ambientColor = [0.3, 0.3, 0.3, 1.0] u_diffuseColor1 = [1.0, 0.5, 0.5, 1.0] diff --git a/resources/shaders/transparent_object.shader b/resources/shaders/transparent_object.shader index cd27a40769..faa43bb46c 100644 --- a/resources/shaders/transparent_object.shader +++ b/resources/shaders/transparent_object.shader @@ -48,6 +48,59 @@ fragment = gl_FragColor.a = u_opacity; } +vertex41core = + #version 410 + uniform highp mat4 u_modelMatrix; + uniform highp mat4 u_viewProjectionMatrix; + uniform highp mat4 u_normalMatrix; + + in highp vec4 a_vertex; + in highp vec4 a_normal; + in highp vec2 a_uvs; + + out highp vec3 v_vertex; + out highp vec3 v_normal; + + void main() + { + vec4 world_space_vert = u_modelMatrix * a_vertex; + gl_Position = u_viewProjectionMatrix * world_space_vert; + + v_vertex = world_space_vert.xyz; + v_normal = (u_normalMatrix * normalize(a_normal)).xyz; + } + +fragment41core = + #version 410 + uniform mediump vec4 u_ambientColor; + uniform mediump vec4 u_diffuseColor; + uniform highp vec3 u_lightPosition; + + uniform mediump float u_opacity; + + in highp vec3 v_vertex; + in highp vec3 v_normal; + + out vec4 frag_color; + + void main() + { + mediump vec4 finalColor = vec4(0.0); + + /* Ambient Component */ + finalColor += u_ambientColor; + + highp vec3 normal = normalize(v_normal); + highp vec3 lightDir = normalize(u_lightPosition - v_vertex); + + /* Diffuse Component */ + highp float NdotL = clamp(abs(dot(normal, lightDir)), 0.0, 1.0); + finalColor += (NdotL * u_diffuseColor); + + frag_color = finalColor; + frag_color.a = u_opacity; + } + [defaults] u_ambientColor = [0.1, 0.1, 0.1, 1.0] u_diffuseColor = [0.4, 0.4, 0.4, 1.0] From 4715afdad60097b972914724809fd17bea26a5a2 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Wed, 1 Feb 2017 14:53:22 +0100 Subject: [PATCH 040/156] Fixed one new class variable. Updated the script to run mypy. --- cura/LayerPolygon.py | 4 ++-- run_mypy.py | 48 ++++++++++++++++++++++++++++++-------------- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 70b17cff75..81fe66a80d 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -1,6 +1,6 @@ from UM.Math.Color import Color from UM.Application import Application - +from typing import Any import numpy @@ -173,7 +173,7 @@ class LayerPolygon: return normals - __color_map = None + __color_map = None # type: numpy.ndarray[Any] ## Gets the instance of the VersionUpgradeManager, or creates one. @classmethod diff --git a/run_mypy.py b/run_mypy.py index c5dfb23802..24c9d3ae31 100644 --- a/run_mypy.py +++ b/run_mypy.py @@ -1,8 +1,17 @@ #!env python import os +import sys import subprocess -os.putenv("MYPYPATH", r".;.\plugins;.\plugins\VersionUpgrade;..\Uranium_hint\;..\Uranium_hint\stubs\\" ) +# A quick Python implementation of unix 'where' command. +def where(exeName): + searchPath = os.getenv("PATH") + paths = searchPath.split(";" if sys.platform == "win32" else ":") + for path in paths: + candidatePath = os.path.join(path, exeName) + if os.path.exists(candidatePath): + return candidatePath + return None def findModules(path): result = [] @@ -11,21 +20,30 @@ def findModules(path): result.append(entry.name) return result -plugins = findModules("plugins") -plugins.sort() +def main(): + os.putenv("MYPYPATH", r".;.\plugins;.\plugins\VersionUpgrade;..\Uranium_hint\;..\Uranium_hint\stubs\\" ) -mods = ["cura"] + plugins + findModules("plugins/VersionUpgrade") + # Mypy really needs to be run via its Python script otherwise it can't find its data files. + mypyExe = where("mypy.bat" if sys.platform == "win32" else "mypy") + mypyModule = os.path.join(os.path.dirname(mypyExe), "mypy") -for mod in mods: - print("------------- Checking module {mod}".format(**locals())) - result = subprocess.run(["python", r"c:\python35\Scripts\mypy", "-p", mod]) - if result.returncode != 0: + plugins = findModules("plugins") + plugins.sort() + + mods = ["cura"] + plugins + findModules("plugins/VersionUpgrade") + + for mod in mods: + print("------------- Checking module {mod}".format(**locals())) + result = subprocess.run([sys.executable, mypyModule, "-p", mod]) + if result.returncode != 0: + print(""" + Module {mod} failed checking. :( + """.format(**locals())) + break + else: print(""" -Module {mod} failed checking. :( -""".format(**locals())) - break -else: - print(""" -Done checking. All is good. -""") + Done checking. All is good. + """) + return 0 +sys.exit(main()) From 4bb8e1b0252b5d9bf1974d3a55366292ad1ecf61 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 1 Feb 2017 16:10:52 +0100 Subject: [PATCH 041/156] Converted layers3d.shader to 41core spec. Contributes to CURA-3273 --- plugins/LayerView/layers3d.shader | 52 ++++++++++++++++--------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/plugins/LayerView/layers3d.shader b/plugins/LayerView/layers3d.shader index 943e9bd64e..c066c7cc6f 100644 --- a/plugins/LayerView/layers3d.shader +++ b/plugins/LayerView/layers3d.shader @@ -1,5 +1,5 @@ [shaders] -vertex = +vertex41core = #version 410 uniform highp mat4 u_modelMatrix; uniform highp mat4 u_viewProjectionMatrix; @@ -9,27 +9,27 @@ vertex = uniform highp mat4 u_normalMatrix; - attribute highp vec4 a_vertex; - attribute lowp vec4 a_color; - attribute lowp vec4 a_material_color; - attribute highp vec4 a_normal; - attribute highp vec2 a_line_dim; // line width and thickness - attribute highp int a_extruder; - attribute highp int a_line_type; + in highp vec4 a_vertex; + in lowp vec4 a_color; + in lowp vec4 a_material_color; + in highp vec4 a_normal; + in highp vec2 a_line_dim; // line width and thickness + in highp int a_extruder; + in highp int a_line_type; - varying lowp vec4 v_color; + out lowp vec4 v_color; - varying highp vec3 v_vertex; - varying highp vec3 v_normal; - varying lowp vec2 v_line_dim; - varying highp int v_extruder; - varying highp vec4 v_extruder_opacity; - varying int v_line_type; + out highp vec3 v_vertex; + out highp vec3 v_normal; + out lowp vec2 v_line_dim; + out highp int v_extruder; + out highp vec4 v_extruder_opacity; + out int v_line_type; - varying lowp vec4 f_color; - varying highp vec3 f_vertex; - varying highp vec3 f_normal; - varying highp int f_extruder; + out lowp vec4 f_color; + out highp vec3 f_vertex; + out highp vec3 f_normal; + out highp int f_extruder; void main() { @@ -62,7 +62,7 @@ vertex = f_normal = v_normal;*/ } -geometry = +geometry41core = #version 410 uniform highp mat4 u_viewProjectionMatrix; @@ -285,11 +285,13 @@ geometry = EndPrimitive(); } -fragment = +fragment41core = #version 410 - varying lowp vec4 f_color; - varying lowp vec3 f_normal; - varying lowp vec3 f_vertex; + in lowp vec4 f_color; + in lowp vec3 f_normal; + in lowp vec3 f_vertex; + + out vec4 frag_color; uniform mediump vec4 u_ambientColor; uniform highp vec3 u_lightPosition; @@ -309,7 +311,7 @@ fragment = finalColor += (NdotL * f_color); finalColor.a = alpha; // Do not change alpha in any way - gl_FragColor = finalColor; + frag_color = finalColor; } From 4659d8616eacf3d78b76903d0080f476a45ec13f Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 1 Feb 2017 16:29:21 +0100 Subject: [PATCH 042/156] Fixed some opengl 4.1 core vertex and fragment shaders, layerview anchor. CURA-3273 --- plugins/LayerView/LayerView.qml | 4 +- plugins/LayerView/layerview_composite.shader | 68 ++++++++++++++++++++ plugins/XRayView/xray.shader | 22 +++++++ 3 files changed, 92 insertions(+), 2 deletions(-) diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index 9c877769bc..ee109b7f04 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -174,7 +174,7 @@ Item ComboBox { id: layerTypeCombobox - anchors.top: slider_background.bottom + anchors.top: parent.top anchors.left: parent.left model: layerViewTypes visible: !UM.LayerView.compatibilityMode @@ -186,7 +186,7 @@ Item Label { id: compatibilityModeLabel - anchors.top: slider_background.bottom + anchors.top: parent.top anchors.left: parent.left text: catalog.i18nc("@label","Compatibility mode") visible: UM.LayerView.compatibilityMode diff --git a/plugins/LayerView/layerview_composite.shader b/plugins/LayerView/layerview_composite.shader index 61d61bb901..f203650ce6 100644 --- a/plugins/LayerView/layerview_composite.shader +++ b/plugins/LayerView/layerview_composite.shader @@ -63,6 +63,74 @@ fragment = } } +vertex41core = + #version 410 + uniform highp mat4 u_modelViewProjectionMatrix; + in highp vec4 a_vertex; + in highp vec2 a_uvs; + + out highp vec2 v_uvs; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + v_uvs = a_uvs; + } + +fragment41core = + #version 410 + uniform sampler2D u_layer0; + uniform sampler2D u_layer1; + uniform sampler2D u_layer2; + + uniform vec2 u_offset[9]; + + uniform vec4 u_background_color; + uniform float u_outline_strength; + uniform vec4 u_outline_color; + + in vec2 v_uvs; + + float kernel[9]; + + const vec3 x_axis = vec3(1.0, 0.0, 0.0); + const vec3 y_axis = vec3(0.0, 1.0, 0.0); + const vec3 z_axis = vec3(0.0, 0.0, 1.0); + + out vec4 frag_color; + + void main() + { + kernel[0] = 0.0; kernel[1] = 1.0; kernel[2] = 0.0; + kernel[3] = 1.0; kernel[4] = -4.0; kernel[5] = 1.0; + kernel[6] = 0.0; kernel[7] = 1.0; kernel[8] = 0.0; + + vec4 result = u_background_color; + + vec4 main_layer = texture(u_layer0, v_uvs); + vec4 selection_layer = texture(u_layer1, v_uvs); + vec4 layerview_layer = texture(u_layer2, v_uvs); + + result = main_layer * main_layer.a + result * (1.0 - main_layer.a); + result = layerview_layer * layerview_layer.a + result * (1.0 - layerview_layer.a); + + vec4 sum = vec4(0.0); + for (int i = 0; i < 9; i++) + { + vec4 color = vec4(texture(u_layer1, v_uvs.xy + u_offset[i]).a); + sum += color * (kernel[i] / u_outline_strength); + } + + if((selection_layer.rgb == x_axis || selection_layer.rgb == y_axis || selection_layer.rgb == z_axis)) + { + frag_color = result; + } + else + { + frag_color = mix(result, u_outline_color, abs(sum.a)); + } + } + [defaults] u_layer0 = 0 u_layer1 = 1 diff --git a/plugins/XRayView/xray.shader b/plugins/XRayView/xray.shader index b42b3e056a..41b00154ea 100644 --- a/plugins/XRayView/xray.shader +++ b/plugins/XRayView/xray.shader @@ -17,6 +17,28 @@ fragment = gl_FragColor = u_color; } +vertex41core = + #version 410 + uniform highp mat4 u_modelViewProjectionMatrix; + + in highp vec4 a_vertex; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + } + +fragment41core = + #version 410 + uniform lowp vec4 u_color; + + out vec4 frag_color; + + void main() + { + frag_color = u_color; + } + [defaults] u_color = [0.02, 0.02, 0.02, 1.0] From 5c2f1a935a4a95dd842d3b4392f84cb53406dcfe Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 1 Feb 2017 17:31:36 +0100 Subject: [PATCH 043/156] Move monitorLabel into PrintMonitor.qml It's a label that belongs to the print monitor after all. Let the print monitor file decide how it's going to look. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 13 ++++++++++++- resources/qml/Sidebar.qml | 17 ++--------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index cd2f2a7376..887c70f457 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2016 Ultimaker B.V. +// Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the AGPLv3 or higher. import QtQuick 2.2 @@ -20,6 +20,17 @@ Column simpleNames: true } + Label { + id: monitorLabel + text: catalog.i18nc("@label","Printer Monitor"); + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width; + width: parent.width * 0.45 + font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text") + visible: monitoringPrint + } + Item { width: base.width - 2 * UM.Theme.getSize("default_margin").width diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index 148606679f..45dc49d076 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -1,4 +1,4 @@ -// Copyright (c) 2015 Ultimaker B.V. +// Copyright (c) 2017 Ultimaker B.V. // Cura is released under the terms of the AGPLv3 or higher. import QtQuick 2.2 @@ -455,19 +455,6 @@ Rectangle } } - Label { - id: monitorLabel - text: catalog.i18nc("@label","Printer Monitor"); - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width; - anchors.top: headerSeparator.bottom - anchors.topMargin: UM.Theme.getSize("default_margin").height - width: parent.width * 0.45 - font: UM.Theme.getFont("large") - color: UM.Theme.getColor("text") - visible: monitoringPrint - } - StackView { id: sidebarContents @@ -511,7 +498,7 @@ Rectangle Loader { anchors.bottom: footerSeparator.top - anchors.top: monitorLabel.bottom + anchors.top: headerSeparator.bottom anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.left: base.left anchors.leftMargin: UM.Theme.getSize("default_margin").width From cda5ee1dca80daa5072b071467e45204b57d1bec Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 2 Feb 2017 14:27:49 +0100 Subject: [PATCH 044/156] Separate name from address in properties This way we can display them separately. Contributes to issue CURA-3161. --- .../NetworkPrinterOutputDevice.py | 9 +++++++-- .../NetworkPrinterOutputDevicePlugin.py | 19 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 549c0905d6..c1e75e6181 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016 Ultimaker B.V. +# Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. from UM.i18n import i18nCatalog @@ -100,7 +100,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): self.setPriority(2) # Make sure the output device gets selected above local file output self.setName(key) - self.setShortDescription(i18n_catalog.i18nc("@action:button Preceded by 'Ready to'.", "Print over network")) + 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.setIconName("print") @@ -220,6 +220,11 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): def getKey(self): return self._key + ## The IP address of the printer. + @pyqtProperty(str, constant = True) + def address(self): + return self._properties.get(b"address", b"0.0.0.0").decode("utf-8") + ## Name of the printer (as returned from the zeroConf properties) @pyqtProperty(str, constant = True) def name(self): diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevicePlugin.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevicePlugin.py index 2725fa8d17..9165bd5273 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevicePlugin.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevicePlugin.py @@ -1,3 +1,6 @@ +# Copyright (c) 2017 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + from UM.OutputDevice.OutputDevicePlugin import OutputDevicePlugin from . import NetworkPrinterOutputDevice @@ -75,9 +78,13 @@ class NetworkPrinterOutputDevicePlugin(OutputDevicePlugin): self._manual_instances.append(address) self._preferences.setValue("um3networkprinting/manual_instances", ",".join(self._manual_instances)) - name = address instance_name = "manual:%s" % address - properties = { b"name": name.encode("utf-8"), b"manual": b"true", b"incomplete": b"true" } + properties = { + b"name": address.encode("utf-8"), + b"address": address.encode("utf-8"), + b"manual": b"true", + b"incomplete": b"true" + } if instance_name not in self._printers: # Add a preliminary printer instance @@ -112,10 +119,14 @@ class NetworkPrinterOutputDevicePlugin(OutputDevicePlugin): if status_code == 200: system_info = json.loads(bytes(reply.readAll()).decode("utf-8")) address = reply.url().host() - name = ("%s (%s)" % (system_info["name"], address)) instance_name = "manual:%s" % address - properties = { b"name": name.encode("utf-8"), b"firmware_version": system_info["firmware"].encode("utf-8"), b"manual": b"true" } + properties = { + b"name": system_info["name"].encode("utf-8"), + b"address": address.encode("utf-8"), + b"firmware_version": system_info["firmware"].encode("utf-8"), + b"manual": b"true" + } if instance_name in self._printers: # Only replace the printer if it is still in the list of (manual) printers self.removePrinter(instance_name) From 1f0bcc1abdb601ebb5355c7f0d4aba9fd8f481bf Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 2 Feb 2017 14:34:40 +0100 Subject: [PATCH 045/156] Add header bar for print monitor It lists the name of the printer it is connected to, and the address on the right side. This won't work for USB printing (it'll give errors there). I'll solve that later. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 36 ++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 887c70f457..e4d9d84ac7 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -20,6 +20,42 @@ Column simpleNames: true } + Rectangle + { + id: connectedPrinterHeader + width: parent.width + height: UM.Theme.getSize("sidebar_header").height + color: UM.Theme.getColor("setting_category") + + Label + { + id: connectedPrinterNameLabel + text: printerConnected ? connectedPrinter.name : catalog.i18nc("@info:status", "No printer connected") + font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text") + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + } + Label + { + id: connectedPrinterAddressLabel + text: printerConnected ? connectedPrinter.address : "" + font: UM.Theme.getFont("small") + color: UM.Theme.getColor("text_inactive") + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + horizontalAlignment: Text.AlignRight + } + } + Label { id: monitorLabel text: catalog.i18nc("@label","Printer Monitor"); From c7a91f07d25128b6484c0367b936df666b454c00 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 2 Feb 2017 14:45:44 +0100 Subject: [PATCH 046/156] Add label for printer connection text to header Also fixed the indenting of the previous two labels to use spaces instead of tabs. I knew I was going to forget putting it back to spaces after working on a different project that uses tabs. The information is duplicated now. I'll remove the old one promptly. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 68 ++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 28 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index e4d9d84ac7..c5bf160657 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -24,36 +24,48 @@ Column { id: connectedPrinterHeader width: parent.width - height: UM.Theme.getSize("sidebar_header").height + height: childrenRect.height + UM.Theme.getSize("default_margin").height * 2 color: UM.Theme.getColor("setting_category") - Label - { - id: connectedPrinterNameLabel - text: printerConnected ? connectedPrinter.name : catalog.i18nc("@info:status", "No printer connected") - font: UM.Theme.getFont("large") - color: UM.Theme.getColor("text") - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width - } - Label - { - id: connectedPrinterAddressLabel - text: printerConnected ? connectedPrinter.address : "" - font: UM.Theme.getFont("small") - color: UM.Theme.getColor("text_inactive") - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width - horizontalAlignment: Text.AlignRight - } + Label + { + id: connectedPrinterNameLabel + text: printerConnected ? connectedPrinter.name : catalog.i18nc("@info:status", "No printer connected") + font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text") + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + } + Label + { + id: connectedPrinterAddressLabel + text: printerConnected ? connectedPrinter.address : "" + font: UM.Theme.getFont("small") + color: UM.Theme.getColor("text_inactive") + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + horizontalAlignment: Text.AlignRight + } + Label + { + text: printerConnected ? connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.") + color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") + font: UM.Theme.getFont("default") + wrapMode: Text.WordWrap + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.top: connectedPrinterNameLabel.bottom + } } Label { From 7b8d41cb8f956bdb175dd5dfef81949166dc841c Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 2 Feb 2017 14:48:06 +0100 Subject: [PATCH 047/156] Remove old connected printer header It has been replaced by a nicer header. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index c5bf160657..97ecfeb46a 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -68,34 +68,6 @@ Column } } - Label { - id: monitorLabel - text: catalog.i18nc("@label","Printer Monitor"); - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width; - width: parent.width * 0.45 - font: UM.Theme.getFont("large") - color: UM.Theme.getColor("text") - visible: monitoringPrint - } - - Item - { - width: base.width - 2 * UM.Theme.getSize("default_margin").width - height: childrenRect.height + UM.Theme.getSize("default_margin").height - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - - Label - { - text: printerConnected ? connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.") - color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") - font: UM.Theme.getFont("default") - wrapMode: Text.WordWrap - width: parent.width - } - } - Loader { sourceComponent: monitorSection From 7b41e844cc6f0832d8ff9496761a38a771de38cd Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 2 Feb 2017 15:19:56 +0100 Subject: [PATCH 048/156] Fix name and address for USB printing devices As address it uses the serial port, which would be COM# for Windows and /dev/ttyUSB# for Linux. I don't know what it would display there on OSX, probably a drive directory. Contributes to issue CURA-3161. --- plugins/USBPrinting/USBPrinterOutputDevice.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index e344caee1d..e30ba613bc 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -124,6 +124,16 @@ class USBPrinterOutputDevice(PrinterOutputDevice): def _homeBed(self): self._sendCommand("G28 Z") + ## A name for the device. + @pyqtProperty(str, constant = True) + def name(self): + return self.getName() + + ## The address of the device. + @pyqtProperty(str, constant = True) + def address(self): + return self._serial_port + def startPrint(self): self.writeStarted.emit(self) gcode_list = getattr( Application.getInstance().getController().getScene(), "gcode_list") From 0889722350ac9bfe981e93dbb22efe6dcd451280 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 2 Feb 2017 17:08:20 +0100 Subject: [PATCH 049/156] Finishing up opengl 4.1 core profile things, it all works. CURA-3273 --- plugins/LayerView/LayerPass.py | 1 + plugins/LayerView/layers.shader | 88 +++++++++++++++++++++++--- plugins/LayerView/layers3d.shader | 13 ++-- plugins/XRayView/xray_composite.shader | 71 +++++++++++++++++++++ 4 files changed, 157 insertions(+), 16 deletions(-) diff --git a/plugins/LayerView/LayerPass.py b/plugins/LayerView/LayerPass.py index 7ae024181d..9ba245489a 100644 --- a/plugins/LayerView/LayerPass.py +++ b/plugins/LayerView/LayerPass.py @@ -14,6 +14,7 @@ from UM.View.GL.OpenGL import OpenGL from cura.Settings.ExtruderManager import ExtruderManager + import os.path ## RenderPass used to display g-code paths. diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index b58d11da0c..0999e07e8c 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -4,7 +4,6 @@ vertex = uniform lowp float u_active_extruder; uniform lowp float u_shade_factor; uniform highp int u_layer_view_type; - uniform highp int u_only_color_active_extruder; attribute highp int a_extruder; attribute highp int a_line_type; @@ -19,10 +18,7 @@ vertex = { gl_Position = u_modelViewProjectionMatrix * a_vertex; v_color = a_color; - if ((u_only_color_active_extruder == 1) && (a_line_type != 8) && (a_line_type != 9)) { - v_color = (a_extruder == u_active_extruder) ? v_color : vec4(0.4, 0.4, 0.4, v_color.a); - } - if ((u_only_color_active_extruder == 0) && (a_line_type != 8) && (a_line_type != 9)) { + if ((a_line_type != 8) && (a_line_type != 9)) { v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a); } @@ -30,8 +26,10 @@ vertex = } fragment = - varying lowp vec4 v_color; - varying float v_line_type; + in lowp vec4 v_color; + in float v_line_type; + + out vec4 frag_color; uniform int u_show_travel_moves; uniform int u_show_support; @@ -70,14 +68,86 @@ fragment = discard; } - gl_FragColor = v_color; + frag_color = v_color; + } + +vertex41core = + #version 410 + uniform highp mat4 u_modelViewProjectionMatrix; + uniform lowp float u_active_extruder; + uniform lowp float u_shade_factor; + uniform highp int u_layer_view_type; + + in highp int a_extruder; + in highp int a_line_type; + in highp vec4 a_vertex; + in lowp vec4 a_color; + in lowp vec4 a_material_color; + + out lowp vec4 v_color; + out float v_line_type; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + v_color = a_color; + if ((a_line_type != 8) && (a_line_type != 9)) { + v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a); + } + + v_line_type = a_line_type; + } + +fragment41core = + #version 410 + in lowp vec4 v_color; + in float v_line_type; + out vec4 frag_color; + + uniform int u_show_travel_moves; + uniform int u_show_support; + uniform int u_show_adhesion; + uniform int u_show_skin; + uniform int u_show_infill; + + void main() + { + if ((u_show_travel_moves == 0) && (v_line_type >= 7.5) && (v_line_type <= 9.5)) { // actually, 8 and 9 + // discard movements + discard; + } + // support: 4, 7, 10 + if ((u_show_support == 0) && ( + ((v_line_type >= 3.5) && (v_line_type <= 4.5)) || + ((v_line_type >= 6.5) && (v_line_type <= 7.5)) || + ((v_line_type >= 9.5) && (v_line_type <= 10.5)) + )) { + discard; + } + // skin: 1, 2, 3 + if ((u_show_skin == 0) && ( + (v_line_type >= 0.5) && (v_line_type <= 3.5) + )) { + discard; + } + // adhesion: + if ((u_show_adhesion == 0) && (v_line_type >= 4.5) && (v_line_type <= 5.5)) { + // discard movements + discard; + } + // infill: + if ((u_show_infill == 0) && (v_line_type >= 5.5) && (v_line_type <= 6.5)) { + // discard movements + discard; + } + + frag_color = v_color; } [defaults] u_active_extruder = 0.0 u_shade_factor = 0.60 u_layer_view_type = 0 -u_only_color_active_extruder = 1 u_extruder_opacity = [1.0, 1.0, 1.0, 1.0] u_show_travel_moves = 0 diff --git a/plugins/LayerView/layers3d.shader b/plugins/LayerView/layers3d.shader index c066c7cc6f..a1e412debb 100644 --- a/plugins/LayerView/layers3d.shader +++ b/plugins/LayerView/layers3d.shader @@ -1,6 +1,8 @@ [shaders] vertex41core = #version 410 + uniform highp mat4 u_modelViewProjectionMatrix; + uniform highp mat4 u_modelMatrix; uniform highp mat4 u_viewProjectionMatrix; uniform lowp float u_active_extruder; @@ -29,7 +31,6 @@ vertex41core = out lowp vec4 f_color; out highp vec3 f_vertex; out highp vec3 f_normal; - out highp int f_extruder; void main() { @@ -37,6 +38,7 @@ vertex41core = v1_vertex.y -= a_line_dim.y / 2; // half layer down vec4 world_space_vert = u_modelMatrix * v1_vertex; + //gl_Position = u_modelViewProjectionMatrix * a_vertex; //world_space_vert; gl_Position = world_space_vert; // shade the color depending on the extruder index stored in the alpha component of the color @@ -56,10 +58,10 @@ vertex41core = v_line_type = a_line_type; v_extruder_opacity = u_extruder_opacity; - // for testing and backwards compatibility without geometry shader - /*f_color = v_color; + // for testing without geometry shader + f_color = v_color; f_vertex = v_vertex; - f_normal = v_normal;*/ + f_normal = v_normal; } geometry41core = @@ -86,7 +88,6 @@ geometry41core = out vec4 f_color; out vec3 f_normal; out vec3 f_vertex; - out uint f_extruder; void main() { @@ -130,8 +131,6 @@ geometry41core = size_y = v_line_dim[0].y / 2 + 0.01; } - f_extruder = v_extruder[0]; - g_vertex_delta = gl_in[1].gl_Position - gl_in[0].gl_Position; g_vertex_normal_horz_head = normalize(vec3(-g_vertex_delta.x, -g_vertex_delta.y, -g_vertex_delta.z)); g_vertex_offset_horz_head = vec4(g_vertex_normal_horz_head * size_x, 0.0); diff --git a/plugins/XRayView/xray_composite.shader b/plugins/XRayView/xray_composite.shader index e7a38950bf..82dca52cf9 100644 --- a/plugins/XRayView/xray_composite.shader +++ b/plugins/XRayView/xray_composite.shader @@ -67,6 +67,77 @@ fragment = } } +vertex41core = + #version 410 + uniform highp mat4 u_modelViewProjectionMatrix; + in highp vec4 a_vertex; + in highp vec2 a_uvs; + + out highp vec2 v_uvs; + + void main() + { + gl_Position = u_modelViewProjectionMatrix * a_vertex; + v_uvs = a_uvs; + } + +fragment41core = + #version 410 + uniform sampler2D u_layer0; + uniform sampler2D u_layer1; + uniform sampler2D u_layer2; + + uniform vec2 u_offset[9]; + + uniform float u_outline_strength; + uniform vec4 u_outline_color; + uniform vec4 u_error_color; + uniform vec4 u_background_color; + + const vec3 x_axis = vec3(1.0, 0.0, 0.0); + const vec3 y_axis = vec3(0.0, 1.0, 0.0); + const vec3 z_axis = vec3(0.0, 0.0, 1.0); + + in vec2 v_uvs; + out vec4 frag_color; + + float kernel[9]; + + void main() + { + kernel[0] = 0.0; kernel[1] = 1.0; kernel[2] = 0.0; + kernel[3] = 1.0; kernel[4] = -4.0; kernel[5] = 1.0; + kernel[6] = 0.0; kernel[7] = 1.0; kernel[8] = 0.0; + + vec4 result = u_background_color; + vec4 layer0 = texture(u_layer0, v_uvs); + + result = layer0 * layer0.a + result * (1.0 - layer0.a); + + float intersection_count = (texture(u_layer2, v_uvs).r * 255.0) / 5.0; + if(mod(intersection_count, 2.0) == 1.0) + { + result = u_error_color; + } + + vec4 sum = vec4(0.0); + for (int i = 0; i < 9; i++) + { + vec4 color = vec4(texture(u_layer1, v_uvs.xy + u_offset[i]).a); + sum += color * (kernel[i] / u_outline_strength); + } + + vec4 layer1 = texture(u_layer1, v_uvs); + if((layer1.rgb == x_axis || layer1.rgb == y_axis || layer1.rgb == z_axis)) + { + frag_color = result; + } + else + { + frag_color = mix(result, vec4(abs(sum.a)) * u_outline_color, abs(sum.a)); + } + } + [defaults] u_layer0 = 0 u_layer1 = 1 From 9546c85967492ef46c73a277748238a190fc68e0 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 3 Feb 2017 13:50:17 +0100 Subject: [PATCH 050/156] Add boxes containing information on extruders These are meant to eventually replace the bullet-list of information we currently have. Contributes to issue CURA-3161. --- .../NetworkPrinterOutputDevice.py | 2 +- resources/qml/PrintMonitor.qml | 42 ++++++++++++++++++- resources/themes/cura/theme.json | 6 +++ 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index c1e75e6181..32ebd354ee 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -100,7 +100,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): self.setPriority(2) # Make sure the output device gets selected above local file output self.setName(key) - self.setShortDescription(i18n_catalog.i18nc("@action:button Preceded by 'Ready to'.", "print over network")) + 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.setIconName("print") diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 97ecfeb46a..556f500348 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -58,7 +58,7 @@ Column { text: printerConnected ? connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.") color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") - font: UM.Theme.getFont("default") + font: UM.Theme.getFont("very_small") wrapMode: Text.WordWrap anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width @@ -68,6 +68,46 @@ Column } } + GridLayout + { + id: extrudersGrid + columns: 2 + columnSpacing: UM.Theme.getSize("sidebar_lining_thin").width + rowSpacing: UM.Theme.getSize("sidebar_lining_thin").height + width: parent.width + + Repeater + { + model: machineExtruderCount.properties.value + delegate: Rectangle + { + id: extruderRectangle + color: UM.Theme.getColor("sidebar") + width: extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2 + height: UM.Theme.getSize("sidebar_extruder_box").height + + Text //Extruder name. + { + text: machineExtruderCount.properties.value > 1 ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") + color: UM.Theme.getColor("text") + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + } + Text //Temperature indication. + { + text: printerConnected ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" + font: UM.Theme.getFont("large") + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + } + } + } + } + Loader { sourceComponent: monitorSection diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index 23ebacd7f9..80fe6a3236 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -24,6 +24,10 @@ "bold": true, "family": "Open Sans" }, + "very_small": { + "size": 1.0, + "family": "Open Sans" + }, "button_tooltip": { "size": 1.0, "family": "Open Sans" @@ -247,9 +251,11 @@ "sidebar_header_mode_toggle": [0.0, 2.0], "sidebar_header_mode_tabs": [0.0, 3.0], "sidebar_lining": [0.5, 0.5], + "sidebar_lining_thin": [0.2, 0.2], "sidebar_setup": [0.0, 2.0], "sidebar_tabs": [0.0, 3.5], "sidebar_inputfields": [0.0, 2.0], + "sidebar_extruder_box": [0.0, 4.0], "simple_mode_infill_caption": [0.0, 5.0], "simple_mode_infill_height": [0.0, 8.0], From 687cdcc30ea4c74dc02e5012f82c445c105b87e7 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 3 Feb 2017 13:54:37 +0100 Subject: [PATCH 051/156] Add grey border between extruder boxes This is done by fitting tightly a rectangle around the grid of boxes. The boxes themselves have a white background but there is spacing between the boxes, which results in the little border. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 65 +++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 556f500348..2db524a794 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -68,41 +68,48 @@ Column } } - GridLayout + Rectangle { - id: extrudersGrid - columns: 2 - columnSpacing: UM.Theme.getSize("sidebar_lining_thin").width - rowSpacing: UM.Theme.getSize("sidebar_lining_thin").height + color: UM.Theme.getColor("sidebar_lining") width: parent.width + height: childrenRect.height - Repeater + GridLayout { - model: machineExtruderCount.properties.value - delegate: Rectangle - { - id: extruderRectangle - color: UM.Theme.getColor("sidebar") - width: extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2 - height: UM.Theme.getSize("sidebar_extruder_box").height + id: extrudersGrid + columns: 2 + columnSpacing: UM.Theme.getSize("sidebar_lining_thin").width + rowSpacing: UM.Theme.getSize("sidebar_lining_thin").height + width: parent.width - Text //Extruder name. + Repeater + { + model: machineExtruderCount.properties.value + delegate: Rectangle { - text: machineExtruderCount.properties.value > 1 ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") - color: UM.Theme.getColor("text") - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width - anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height - } - Text //Temperature indication. - { - text: printerConnected ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" - font: UM.Theme.getFont("large") - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width - anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height + id: extruderRectangle + color: UM.Theme.getColor("sidebar") + width: extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2 + height: UM.Theme.getSize("sidebar_extruder_box").height + + Text //Extruder name. + { + text: machineExtruderCount.properties.value > 1 ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") + color: UM.Theme.getColor("text") + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + } + Text //Temperature indication. + { + text: printerConnected ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" + font: UM.Theme.getFont("large") + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + } } } } From ee3e0ba6abb659cd1a1b5322b6da6ab3d75ba18b Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 3 Feb 2017 14:52:09 +0100 Subject: [PATCH 052/156] Add material indication to extruder boxes Only if a material is known of course. But the case where it is unknown is not tested. Contributes to issue CURA-3161. --- cura/PrinterOutputDevice.py | 22 ++++++++++++++++++++++ resources/qml/PrintMonitor.qml | 24 ++++++++++++++++++++++++ resources/themes/cura/theme.json | 2 +- 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index 6e7305b27b..ed67bbb1ca 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -323,6 +323,28 @@ class PrinterOutputDevice(QObject, OutputDevice): result.append(i18n_catalog.i18nc("@item:material", "Unknown material")) return result + ## List of the colours of the currently loaded materials. + # + # The list is in order of extruders. If there is no material in an + # extruder, the colour is shown as transparent. + # + # The colours are returned in hex-format AARRGGBB or RRGGBB + # (e.g. #800000ff for transparent blue or #00ff00 for pure green). + @pyqtProperty("QVariantList", notify = materialIdChanged) + def materialColors(self): + result = [] + for material_id in self._material_ids: + if material_id is None: + result.append("#800000FF") #No material. + continue + + containers = self._container_registry.findInstanceContainers(type = "material", GUID = material_id) + if containers: + result.append(containers[0].getMetaDataEntry("color_code")) + else: + result.append("#800000FF") #Unknown material. + return result + ## Protected setter for the current material id. # /param index Index of the extruder # /param material_id id of the material diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 2db524a794..537adc53e5 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -110,6 +110,30 @@ Column anchors.top: parent.top anchors.topMargin: UM.Theme.getSize("default_margin").height } + Rectangle //Material colour indication. + { + id: materialColor + width: materialName.height * 0.75 + height: materialName.height * 0.75 + color: printerConnected ? connectedPrinter.materialColors[index] : [0, 0, 0, 0] //Need to check for printerConnected or materialColors[index] gives an error. + border.width: UM.Theme.getSize("default_lining").width + border.color: UM.Theme.getColor("lining") + visible: printerConnected + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.verticalCenter: materialName.verticalCenter + } + Text //Material name. + { + id: materialName + text: printerConnected ? connectedPrinter.materialNames[index] : "" + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + anchors.left: materialColor.right + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.bottom: parent.bottom + anchors.bottomMargin: UM.Theme.getSize("default_margin").height + } } } } diff --git a/resources/themes/cura/theme.json b/resources/themes/cura/theme.json index 80fe6a3236..acce27b74e 100644 --- a/resources/themes/cura/theme.json +++ b/resources/themes/cura/theme.json @@ -255,7 +255,7 @@ "sidebar_setup": [0.0, 2.0], "sidebar_tabs": [0.0, 3.5], "sidebar_inputfields": [0.0, 2.0], - "sidebar_extruder_box": [0.0, 4.0], + "sidebar_extruder_box": [0.0, 6.0], "simple_mode_infill_caption": [0.0, 5.0], "simple_mode_infill_height": [0.0, 8.0], From 41c94fd247cd5400e39a66961fab560fefe53cb3 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 3 Feb 2017 15:03:24 +0100 Subject: [PATCH 053/156] Add variant names to extruder boxes In the bottom-right corner. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 537adc53e5..c23d732d62 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -134,6 +134,16 @@ Column anchors.bottom: parent.bottom anchors.bottomMargin: UM.Theme.getSize("default_margin").height } + Text //Variant name. + { + text: printerConnected ? connectedPrinter.hotendIds[index] : "" + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.bottom: parent.bottom + anchors.bottomMargin: UM.Theme.getSize("default_margin").height + } } } } From a6c244f969aaab248e5b20865d068b8faf0c339b Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 3 Feb 2017 15:06:21 +0100 Subject: [PATCH 054/156] Use setting separator margin between material colour and name It's a bit smaller. Looks like it belongs together now. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index c23d732d62..debc7657f8 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -130,7 +130,7 @@ Column font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") anchors.left: materialColor.right - anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width anchors.bottom: parent.bottom anchors.bottomMargin: UM.Theme.getSize("default_margin").height } From 1305dd88d74909e28a1aaf34014d025e0708002e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 3 Feb 2017 15:20:24 +0100 Subject: [PATCH 055/156] Remove old extruder monitoring code It has been replaced by these fancy new boxes. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index debc7657f8..616b90fe72 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -149,21 +149,6 @@ Column } } - Loader - { - sourceComponent: monitorSection - property string label: catalog.i18nc("@label", "Temperatures") - } - Repeater - { - model: machineExtruderCount.properties.value - delegate: Loader - { - sourceComponent: monitorItem - property string label: machineExtruderCount.properties.value > 1 ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") - property string value: printerConnected ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" - } - } Repeater { model: machineHeatedBed.properties.value == "True" ? 1 : 0 From 03e16b53982a5efba061043a42ab431391bb97be Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 3 Feb 2017 15:49:18 +0100 Subject: [PATCH 056/156] Fix material colour when no printer is selected It's invisible anyway, but the hex colour gives no errors at least. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 616b90fe72..d74f769fd5 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -115,7 +115,7 @@ Column id: materialColor width: materialName.height * 0.75 height: materialName.height * 0.75 - color: printerConnected ? connectedPrinter.materialColors[index] : [0, 0, 0, 0] //Need to check for printerConnected or materialColors[index] gives an error. + color: printerConnected ? connectedPrinter.materialColors[index] : "#00000000" //Need to check for printerConnected or materialColors[index] gives an error. border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") visible: printerConnected From abb9b8d7f09174a73ae4ec4609427299cbaee325 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 3 Feb 2017 15:52:14 +0100 Subject: [PATCH 057/156] Add box for build plate monitoring This one's a bit bigger. It is supposed to contain the pre-heat button. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 41 +++++++++++++++++++++++++++++----- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index d74f769fd5..e0c1d7ceca 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -149,14 +149,43 @@ Column } } - Repeater + Rectangle { - model: machineHeatedBed.properties.value == "True" ? 1 : 0 - delegate: Loader + color: UM.Theme.getColor("sidebar") + width: parent.width + height: machineHeatedBed.properties.value == "True" ? UM.Theme.getSize("sidebar_extruder_box").height : 0 + visible: machineHeatedBed.properties.value == "True" + + Label //Build plate label. { - sourceComponent: monitorItem - property string label: catalog.i18nc("@label", "Build plate") - property string value: printerConnected ? Math.round(connectedPrinter.bedTemperature) + "°C" : "" + text: catalog.i18nc("@label", "Build plate") + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height + } + Text //Target temperature. + { + id: bedTargetTemperature + text: printerConnected ? connectedPrinter.targetBedTemperature + "°C" : "" + font: UM.Theme.getFont("small") + color: UM.Theme.getColor("text_inactive") + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.bottom: bedCurrentTemperature.bottom + } + Text //Current temperature. + { + id: bedCurrentTemperature + text: printerConnected ? connectedPrinter.bedTemperature + "°C" : "" + font: UM.Theme.getFont("large") + color: UM.Theme.getColor("text") + anchors.right: bedTargetTemperature.left + anchors.rightMargin: UM.Theme.getSize("setting_unit_margin").width + anchors.top: parent.top + anchors.topMargin: UM.Theme.getSize("default_margin").height } } From 3fb625109e0ec75ae26e2f1453765cdf5c1d5c1f Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 3 Feb 2017 17:04:31 +0100 Subject: [PATCH 058/156] Add text field for target pre-heat temperature I'm sure it's quite buggy on all sides though. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 75 ++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index e0c1d7ceca..56f16ed7c2 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -187,6 +187,81 @@ Column anchors.top: parent.top anchors.topMargin: UM.Theme.getSize("default_margin").height } + Rectangle //Input field for pre-heat temperature. + { + id: preheatTemperatureControl + color: UM.Theme.getColor("setting_validation_ok") + border.width: UM.Theme.getSize("default_lining").width + border.color: hovered ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border") + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width + anchors.bottom: parent.bottom + anchors.bottomMargin: UM.Theme.getSize("default_margin").height + width: UM.Theme.getSize("setting_control").width + height: UM.Theme.getSize("setting_control").height + + Rectangle //Highlight of input field. + { + anchors.fill: parent + anchors.margins: UM.Theme.getSize("default_lining").width + color: UM.Theme.getColor("setting_control_highlight") + opacity: preheatTemperatureControl.hovered ? 1.0 : 0 + } + Label //Maximum temperature indication. + { + text: "MAXTEMP" //TODO: Placeholder! + color: UM.Theme.getColor("setting_unit") + font: UM.Theme.getFont("default") + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("setting_unit_margin").width + anchors.verticalCenter: parent.verticalCenter + } + MouseArea //Change cursor on hovering. + { + id: mouseArea + anchors.fill: parent + cursorShape: Qt.IBeamCursor + } + TextInput + { + id: preheatTemperatureInput + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("setting_control_text") + selectByMouse: true + maximumLength: 10 + validator: RegExpValidator { regExp: /^-?[0-9]{0,9}[.,]?[0-9]{0,10}$/ } //Floating point regex. + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + + text: "60" //TODO: Bind this to the default. + /*Binding + { + target: preheatTemperatureInput + property: "text" + value: { + // Stacklevels + // 0: user -> unsaved change + // 1: quality changes -> saved change + // 2: quality + // 3: material -> user changed material in materialspage + // 4: variant + // 5: machine_changes + // 6: machine + if ((base.resolve != "None" && base.resolve) && (stackLevel != 0) && (stackLevel != 1)) { + // We have a resolve function. Indicates that the setting is not settable per extruder and that + // we have to choose between the resolved value (default) and the global value + // (if user has explicitly set this). + return base.resolve; + } else { + return propertyProvider.properties.value; + } + } + when: !preheatTemperatureInput.activeFocus + }*/ + } + } } Loader From 7c964045dbb5ae799119661de04cbbf8eac7a456 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 6 Feb 2017 13:16:47 +0100 Subject: [PATCH 059/156] Removed unused line in shader. CURA-3273 --- plugins/LayerView/layers3d.shader | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/LayerView/layers3d.shader b/plugins/LayerView/layers3d.shader index a1e412debb..c7c7628a92 100644 --- a/plugins/LayerView/layers3d.shader +++ b/plugins/LayerView/layers3d.shader @@ -38,7 +38,6 @@ vertex41core = v1_vertex.y -= a_line_dim.y / 2; // half layer down vec4 world_space_vert = u_modelMatrix * v1_vertex; - //gl_Position = u_modelViewProjectionMatrix * a_vertex; //world_space_vert; gl_Position = world_space_vert; // shade the color depending on the extruder index stored in the alpha component of the color From 27ff55d75b6ee2cfce95e1b9d5adb4dc49f0bdbb Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 6 Feb 2017 15:09:18 +0100 Subject: [PATCH 060/156] Add binding to current maximum bed temperature Instead of the MAXTEMP placeholder. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 56f16ed7c2..b61d56feec 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -209,7 +209,7 @@ Column } Label //Maximum temperature indication. { - text: "MAXTEMP" //TODO: Placeholder! + text: bedTemperature.properties.maximum_value color: UM.Theme.getColor("setting_unit") font: UM.Theme.getFont("default") anchors.right: parent.right @@ -264,6 +264,15 @@ Column } } + UM.SettingPropertyProvider + { + id: bedTemperature + containerStackId: Cura.MachineManager.activeMachineId + key: "material_bed_temperature" + watchedProperties: ["value", "minimum_value", "maximum_value", "minimum_value_warning", "maximum_value_warning"] + storeIndex: 0 + } + Loader { sourceComponent: monitorSection From 78fed0531dc39dfb228c99153493e11b5b9a1538 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 6 Feb 2017 15:17:59 +0100 Subject: [PATCH 061/156] Fix hovering the setting box The 'hovered' property was taken from the example of the setting item, but that doesn't exist apparently. I looked up how it is normally done in QML. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index b61d56feec..b28944f008 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -192,7 +192,7 @@ Column id: preheatTemperatureControl color: UM.Theme.getColor("setting_validation_ok") border.width: UM.Theme.getSize("default_lining").width - border.color: hovered ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border") + border.color: mouseArea.containsMouse ? UM.Theme.getColor("setting_control_border_highlight") : UM.Theme.getColor("setting_control_border") anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.bottom: parent.bottom @@ -219,6 +219,7 @@ Column MouseArea //Change cursor on hovering. { id: mouseArea + hoverEnabled: true anchors.fill: parent cursorShape: Qt.IBeamCursor } From b1a8b28e87415c4f71d43a7c39dd79d027a252d4 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 6 Feb 2017 15:44:40 +0100 Subject: [PATCH 062/156] Bind default pre-heat temperature to current build plate temperature Currently the setting 'resets' when you go out of the print monitor mode. That wasn't the original intention but it works kind of nicely. We'll bring it up in a meeting whether this needs to be changed. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index b28944f008..49f49502a6 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -236,12 +236,12 @@ Column anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter - text: "60" //TODO: Bind this to the default. - /*Binding + Binding { target: preheatTemperatureInput property: "text" - value: { + value: + { // Stacklevels // 0: user -> unsaved change // 1: quality changes -> saved change @@ -250,17 +250,20 @@ Column // 4: variant // 5: machine_changes // 6: machine - if ((base.resolve != "None" && base.resolve) && (stackLevel != 0) && (stackLevel != 1)) { + if ((bedTemperature.resolve != "None" && bedTemperature.resolve) && (bedTemperature.stackLevels[0] != 0) && (bedTemperature.stackLevels[0] != 1)) + { // We have a resolve function. Indicates that the setting is not settable per extruder and that // we have to choose between the resolved value (default) and the global value // (if user has explicitly set this). - return base.resolve; - } else { - return propertyProvider.properties.value; + return bedTemperature.resolve; + } + else + { + return bedTemperature.properties.value; } } when: !preheatTemperatureInput.activeFocus - }*/ + } } } } @@ -270,8 +273,10 @@ Column id: bedTemperature containerStackId: Cura.MachineManager.activeMachineId key: "material_bed_temperature" - watchedProperties: ["value", "minimum_value", "maximum_value", "minimum_value_warning", "maximum_value_warning"] + watchedProperties: ["value", "minimum_value", "maximum_value", "minimum_value_warning", "maximum_value_warning", "resolve"] storeIndex: 0 + + property var resolve: Cura.MachineManager.activeStackId != Cura.MachineManager.activeMachineId ? properties.resolve : "None" } Loader From b1448887ba05a5e6dae8230f0cc73a96b7b6bf4c Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 6 Feb 2017 16:45:52 +0100 Subject: [PATCH 063/156] Add button to pre-heat build plate This is the one. The actual commit that implements the issue. It doesn't do anything yet, this button, but it's how it should look. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 98 ++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 49f49502a6..ee7fb1a692 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -266,6 +266,104 @@ Column } } } + + Button //The pre-heat button. + { + text: catalog.i18nc("@button", "Pre-heat") + tooltip: catalog.i18nc("@tooltip of pre-heat", "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print.") + height: UM.Theme.getSize("setting_control").height + anchors.right: parent.right + anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.bottom: parent.bottom + anchors.bottomMargin: UM.Theme.getSize("default_margin").height + style: ButtonStyle { + background: Rectangle + { + border.width: UM.Theme.getSize("default_lining").width + implicitWidth: actualLabel.contentWidth + (UM.Theme.getSize("default_margin").width * 2) + border.color: + { + if(!control.enabled) + { + return UM.Theme.getColor("action_button_disabled_border"); + } + else if(control.pressed) + { + return UM.Theme.getColor("action_button_active_border"); + } + else if(control.hovered) + { + return UM.Theme.getColor("action_button_hovered_border"); + } + else + { + return UM.Theme.getColor("action_button_border"); + } + } + color: + { + if(!control.enabled) + { + return UM.Theme.getColor("action_button_disabled"); + } + else if(control.pressed) + { + return UM.Theme.getColor("action_button_active"); + } + else if(control.hovered) + { + return UM.Theme.getColor("action_button_hovered"); + } + else + { + return UM.Theme.getColor("action_button"); + } + } + Behavior on color + { + ColorAnimation + { + duration: 50 + } + } + + Label + { + id: actualLabel + anchors.centerIn: parent + color: + { + if(!control.enabled) + { + return UM.Theme.getColor("action_button_disabled_text"); + } + else if(control.pressed) + { + return UM.Theme.getColor("action_button_active_text"); + } + else if(control.hovered) + { + return UM.Theme.getColor("action_button_hovered_text"); + } + else + { + return UM.Theme.getColor("action_button_text"); + } + } + font: UM.Theme.getFont("action_button") + text: control.text; + } + } + label: Item + { + } + } + + onClicked: + { + print("Click!"); + } + } } UM.SettingPropertyProvider From 1d778649154112cb138f9c20aba41b869c7fb3dd Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 7 Feb 2017 09:36:21 +0100 Subject: [PATCH 064/156] Added force layer view compatibility mode. CURA-3273 --- cura/CuraApplication.py | 1 + plugins/LayerView/LayerView.py | 3 +-- resources/qml/Preferences/GeneralPage.qml | 14 ++++++++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index e6e1d08afb..720f5b8fb7 100644 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -223,6 +223,7 @@ class CuraApplication(QtApplication): Preferences.getInstance().addPreference("mesh/scale_tiny_meshes", True) Preferences.getInstance().addPreference("cura/dialog_on_project_save", True) Preferences.getInstance().addPreference("cura/asked_dialog_on_project_save", False) + Preferences.getInstance().addPreference("view/force_layer_view_compatibility_mode", False) Preferences.getInstance().addPreference("cura/currency", "€") Preferences.getInstance().addPreference("cura/material_settings", "{}") diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 922966854d..a5e07513a7 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -65,7 +65,6 @@ class LayerView(View): Preferences.getInstance().addPreference("view/top_layer_count", 5) Preferences.getInstance().addPreference("view/only_show_top_layers", False) - Preferences.getInstance().addPreference("view/compatibility_mode", True) # Default True for now, needs testing of different computers Preferences.getInstance().preferenceChanged.connect(self._onPreferencesChanged) @@ -93,7 +92,7 @@ class LayerView(View): # Currently the RenderPass constructor requires a size > 0 # This should be fixed in RenderPass's constructor. self._layer_pass = LayerPass.LayerPass(1, 1) - self._compatibility_mode = not self.getRenderer().getSupportsGeometryShader() + self._compatibility_mode = not self.getRenderer().getSupportsGeometryShader() or bool(Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode")) self._layer_pass.setLayerView(self) self.getRenderer().addRenderPass(self._layer_pass) return self._layer_pass diff --git a/resources/qml/Preferences/GeneralPage.qml b/resources/qml/Preferences/GeneralPage.qml index ee300989a4..9b6f32f114 100644 --- a/resources/qml/Preferences/GeneralPage.qml +++ b/resources/qml/Preferences/GeneralPage.qml @@ -265,6 +265,20 @@ UM.PreferencesPage } } + UM.TooltipArea { + width: childrenRect.width + height: childrenRect.height + text: catalog.i18nc("@info:tooltip", "Should layer be forced into compatibility mode?") + + CheckBox + { + id: forceLayerViewCompatibilityModeCheckbox + text: catalog.i18nc("@option:check", "Force layer view compatibility mode (restart required)") + checked: boolCheck(UM.Preferences.getValue("view/force_layer_view_compatibility_mode")) + onCheckedChanged: UM.Preferences.setValue("view/force_layer_view_compatibility_mode", checked) + } + } + Item { //: Spacer From 4b02a425d8a8fc11423cbb2cafc0ed3e19e22309 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 7 Feb 2017 11:55:51 +0100 Subject: [PATCH 065/156] Let Layer View compatibility mode depend on OpenGL version we asked for (may be different than actual). CURA-3273 --- plugins/LayerView/LayerView.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index a5e07513a7..468fc01ec3 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -16,6 +16,7 @@ from UM.Logger import Logger from UM.View.GL.OpenGL import OpenGL from UM.Message import Message from UM.Application import Application +from UM.View.GL.OpenGLContext import OpenGLContext from cura.ConvexHullNode import ConvexHullNode from cura.Settings.ExtruderManager import ExtruderManager @@ -92,7 +93,7 @@ class LayerView(View): # Currently the RenderPass constructor requires a size > 0 # This should be fixed in RenderPass's constructor. self._layer_pass = LayerPass.LayerPass(1, 1) - self._compatibility_mode = not self.getRenderer().getSupportsGeometryShader() or bool(Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode")) + self._compatibility_mode = OpenGLContext.isLegacyOpenGL() or bool(Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode")) self._layer_pass.setLayerView(self) self.getRenderer().addRenderPass(self._layer_pass) return self._layer_pass From f24d778cc5269fe8e4fef61c9610e65d03f644b0 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 12:51:02 +0100 Subject: [PATCH 066/156] Disable pre-heat button when not connected This covers the case when there is no printer added as well as the case where a printer is added but not connected. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index ee7fb1a692..c1fbdef983 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -272,6 +272,7 @@ Column text: catalog.i18nc("@button", "Pre-heat") tooltip: catalog.i18nc("@tooltip of pre-heat", "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print.") height: UM.Theme.getSize("setting_control").height + enabled: printerConnected anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("default_margin").width anchors.bottom: parent.bottom From cfbcf567399449beff2e9db8b22ab0f2c289c0e5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 13:18:41 +0100 Subject: [PATCH 067/156] Add function to pre-head bed This makes a PUT-request to the printer with the new API function call. Contributes to issue CURA-3161. --- .../UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 32ebd354ee..99d07a8b81 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -240,6 +240,18 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): def ipAddress(self): return self._address + ## Pre-heats the heated bed of the printer. + # + # \param temperature The temperature to heat the bed to, in degrees + # Celsius. + # \param duration How long the bed should stay warm, in seconds. + def preheatBed(self, temperature, duration): + url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") + data = """{"temperature": "{temperature}", "timeout": "{timeout}"}""".format(temperature=temperature, timeout=duration) + put_request = QNetworkRequest(url) + put_request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") + self._manager.put(put_request, data.encode()) + def _stopCamera(self): self._camera_timer.stop() if self._image_reply: From ed1fea2d3eb44e3ad7d52d6168ad3eb105697844 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 7 Feb 2017 13:20:26 +0100 Subject: [PATCH 068/156] Fix colors of compatibility mode. CURA-3273 --- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 1dbcbdb3b7..21227e7a8b 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -9,6 +9,7 @@ from UM.Scene.SceneNode import SceneNode from UM.Application import Application from UM.Mesh.MeshData import MeshData from UM.Preferences import Preferences +from UM.View.GL.OpenGLContext import OpenGLContext from UM.Message import Message from UM.i18n import i18nCatalog @@ -180,10 +181,10 @@ class ProcessSlicedLayersJob(Job): material_color_map[0, :] = color # We have to scale the colors for compatibility mode - if Application.getInstance().getRenderer().getSupportsGeometryShader(): - line_type_brightness = 1.0 - else: + if OpenGLContext.isLegacyOpenGL() or bool(Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode")): line_type_brightness = 0.5 # for compatibility mode + else: + line_type_brightness = 1.0 layer_mesh = layer_data.build(material_color_map, line_type_brightness) if self._abort_requested: From 9d8034d14fcc4dc1665226ccb480ff7dc79a24ce Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 13:22:21 +0100 Subject: [PATCH 069/156] Add default for duration parameter of preheatBed It defaults to 15 minutes. Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 99d07a8b81..5ac06e7154 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -244,8 +244,9 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): # # \param temperature The temperature to heat the bed to, in degrees # Celsius. - # \param duration How long the bed should stay warm, in seconds. - def preheatBed(self, temperature, duration): + # \param duration How long the bed should stay warm, in seconds. Defaults + # to a quarter hour. + def preheatBed(self, temperature, duration=900): url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") data = """{"temperature": "{temperature}", "timeout": "{timeout}"}""".format(temperature=temperature, timeout=duration) put_request = QNetworkRequest(url) From d7bf23ca21616788cb0345bf3da71432ede3bec5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 13:23:56 +0100 Subject: [PATCH 070/156] Add function to cancel pre-heating the bed You could also do this by calling preheatBed with a temperature of 0. In fact, that's what this function does. Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 5ac06e7154..470d0efa0a 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -253,6 +253,12 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): put_request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") self._manager.put(put_request, data.encode()) + ## Cancels pre-heating the heated bed of the printer. + # + # If the bed is not pre-heated, nothing happens. + def cancelPreheatBed(self): + self.preheatBed(temperature=0) + def _stopCamera(self): self._camera_timer.stop() if self._image_reply: From 0df4afff33a823cfaebcf2b1538791c37abaa5f5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 13:26:10 +0100 Subject: [PATCH 071/156] Convert parameters to string before including them This way you can provide normal floating point values instead of providing strings with numbers in them. Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 470d0efa0a..e43e522c0c 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -248,7 +248,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): # to a quarter hour. def preheatBed(self, temperature, duration=900): url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") - data = """{"temperature": "{temperature}", "timeout": "{timeout}"}""".format(temperature=temperature, timeout=duration) + data = """{"temperature": "{temperature}", "timeout": "{timeout}"}""".format(temperature=str(temperature), timeout=str(duration)) put_request = QNetworkRequest(url) put_request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") self._manager.put(put_request, data.encode()) From 559b40867ef88c37379244fed2947743058f7da2 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 13:29:57 +0100 Subject: [PATCH 072/156] Call pre-heat if pre-heat button is pressed Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 2 ++ resources/qml/PrintMonitor.qml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index e43e522c0c..59c04dd822 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -246,6 +246,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): # Celsius. # \param duration How long the bed should stay warm, in seconds. Defaults # to a quarter hour. + @pyqtSlot(float, float) def preheatBed(self, temperature, duration=900): url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") data = """{"temperature": "{temperature}", "timeout": "{timeout}"}""".format(temperature=str(temperature), timeout=str(duration)) @@ -256,6 +257,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): ## Cancels pre-heating the heated bed of the printer. # # If the bed is not pre-heated, nothing happens. + @pyqtSlot() def cancelPreheatBed(self): self.preheatBed(temperature=0) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index c1fbdef983..4ff6d02c54 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -362,7 +362,7 @@ Column onClicked: { - print("Click!"); + connectedPrinter.preheatBed(preheatTemperatureInput.text, 900) } } } From 3618ae0d4f9e9435ac7ba093927f9ac7de83b862 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 13:35:09 +0100 Subject: [PATCH 073/156] Properly float-format input of preheatBed It rounds to 3 digits. The specification of the feature in the API doesn't mention how detailed the temperature and duration can go, but thousands seems more than enough. This also eliminates pesky problems with the JSON brackets in the format function. Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 59c04dd822..87986afbf3 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -249,7 +249,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): @pyqtSlot(float, float) def preheatBed(self, temperature, duration=900): url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") - data = """{"temperature": "{temperature}", "timeout": "{timeout}"}""".format(temperature=str(temperature), timeout=str(duration)) + data = """{"temperature": "%0.3f", "timeout": "%0.3f"}""" % (temperature, duration) put_request = QNetworkRequest(url) put_request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") self._manager.put(put_request, data.encode()) From b27a9e65352db035de78edddb01797ef6b5600ba Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 13:52:44 +0100 Subject: [PATCH 074/156] Implement tracking target bed temperature I had already assumed it was tracking this but apparently it wasn't. This works though. Contributes to issue CURA-3161. --- .../UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 87986afbf3..c4177953fe 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -97,6 +97,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): self._material_ids = [""] * self._num_extruders self._hotend_ids = [""] * self._num_extruders + self._target_bed_temperature = 0 self.setPriority(2) # Make sure the output device gets selected above local file output self.setName(key) @@ -261,6 +262,15 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): def cancelPreheatBed(self): self.preheatBed(temperature=0) + ## Changes the target bed temperature and makes sure that its signal is + # emitted. + # + # /param temperature The new target temperature of the bed. + def _setTargetBedTemperature(self, temperature): + if self._target_bed_temperature != temperature: + self._target_bed_temperature = temperature + self.targetBedTemperatureChanged.emit() + def _stopCamera(self): self._camera_timer.stop() if self._image_reply: @@ -492,6 +502,8 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): bed_temperature = self._json_printer_state["bed"]["temperature"]["current"] self._setBedTemperature(bed_temperature) + target_bed_temperature = self._json_printer_state["bed"]["temperature"]["target"] + self._setTargetBedTemperature(target_bed_temperature) head_x = self._json_printer_state["heads"][0]["position"]["x"] head_y = self._json_printer_state["heads"][0]["position"]["y"] From 4057996e2395b6c1736bb9781d09a5a866585dc0 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Tue, 7 Feb 2017 14:28:22 +0100 Subject: [PATCH 075/156] Made layers.shader compatibility shader compatible. CURA-3273 --- plugins/LayerView/layers.shader | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 0999e07e8c..88717e8774 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -26,10 +26,8 @@ vertex = } fragment = - in lowp vec4 v_color; - in float v_line_type; - - out vec4 frag_color; + varying lowp vec4 v_color; + varying float v_line_type; uniform int u_show_travel_moves; uniform int u_show_support; @@ -68,7 +66,7 @@ fragment = discard; } - frag_color = v_color; + gl_FragColor = u_color; } vertex41core = From d751285713b57177f79e007133e4d4c4cb1f03d4 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 14:39:56 +0100 Subject: [PATCH 076/156] Provide pre-heat command with integer parameters The firmware only accepts integers, apparently. Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index c4177953fe..3d2d4bbc07 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -247,10 +247,10 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): # Celsius. # \param duration How long the bed should stay warm, in seconds. Defaults # to a quarter hour. - @pyqtSlot(float, float) + @pyqtSlot(int, int) def preheatBed(self, temperature, duration=900): url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") - data = """{"temperature": "%0.3f", "timeout": "%0.3f"}""" % (temperature, duration) + data = """{"temperature": "%i", "timeout": "%i"}""" % (temperature, duration) put_request = QNetworkRequest(url) put_request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") self._manager.put(put_request, data.encode()) From d3d36d47ebbb2e3d31f2a11ffc08df4ea6e7ac75 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 16:22:47 +0100 Subject: [PATCH 077/156] Add countdown timer for pre-heat time Not happy with how there is '900' in multiple places in the code. I might do something about that later. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 47 +++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 4ff6d02c54..9bc30f324e 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -267,8 +267,47 @@ Column } } + Timer + { + id: preheatCountdownTimer + interval: 100 //Update every 100ms. You want to update every 1s, but then you have one timer for the updating running out of sync with the actual date timer and you might skip seconds. + running: false + repeat: true + onTriggered: update() + property var endTime: new Date() + function update() + { + var now = new Date(); + if (now.getTime() < endTime.getTime()) + { + var remaining = endTime - now; //This is in milliseconds. + var minutes = Math.floor(remaining / 60 / 1000); + var seconds = Math.floor((remaining / 1000) % 60); + preheatCountdown.text = minutes + ":" + (seconds < 10 ? "0" + seconds : seconds); + preheatCountdown.visible = true; + } + else + { + preheatCountdown.visible = false; + running = false; + } + } + } + Text + { + id: preheatCountdown + text: "0:00" + visible: false //It only becomes visible when the timer is running. + font: UM.Theme.getFont("default") + color: UM.Theme.getColor("text") + anchors.right: preheatButton.left + anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.verticalCenter: preheatButton.verticalCenter + } + Button //The pre-heat button. { + id: preheatButton text: catalog.i18nc("@button", "Pre-heat") tooltip: catalog.i18nc("@tooltip of pre-heat", "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print.") height: UM.Theme.getSize("setting_control").height @@ -362,7 +401,13 @@ Column onClicked: { - connectedPrinter.preheatBed(preheatTemperatureInput.text, 900) + connectedPrinter.preheatBed(preheatTemperatureInput.text, 900); + var now = new Date(); + var end_time = new Date(); + end_time.setTime(now.getTime() + 900 * 1000); //*1000 because time is in milliseconds here. + preheatCountdownTimer.endTime = end_time; + preheatCountdownTimer.start(); + preheatCountdownTimer.update(); //Update once before the first timer is triggered. } } } From d705fb1d763e3f1065c7774cb4ed74d35927d3d4 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 16:24:28 +0100 Subject: [PATCH 078/156] Document why we set endTime to the current date initially Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 9bc30f324e..0a34eb8f31 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -274,7 +274,7 @@ Column running: false repeat: true onTriggered: update() - property var endTime: new Date() + property var endTime: new Date() //Set initial endTime to be the current date, so that the endTime has initially already passed and the timer text becomes invisible if you were to update. function update() { var now = new Date(); From 1a902b21bb8704dca2fea80a2199a8fe2c699a86 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 16:29:41 +0100 Subject: [PATCH 079/156] Store default pre-heat time in central location Its default is 900s or 15 minutes. QML now requests the time-out time and sends it on to the printer. Contributes to issue CURA-3161. --- cura/PrinterOutputDevice.py | 6 ++++++ plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 4 ++-- resources/qml/PrintMonitor.qml | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index ed67bbb1ca..56ae34b6f4 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -45,6 +45,7 @@ class PrinterOutputDevice(QObject, OutputDevice): self._job_name = "" self._error_text = "" self._accepts_commands = True + self._preheat_bed_timeout = 900 #Default time-out for pre-heating the bed, in seconds. self._printer_state = "" self._printer_type = "unknown" @@ -199,6 +200,11 @@ class PrinterOutputDevice(QObject, OutputDevice): self._target_bed_temperature = temperature self.targetBedTemperatureChanged.emit() + ## + @pyqtProperty(int) + def preheatBedTimeout(self): + return self._preheat_bed_timeout + ## Time the print has been printing. # Note that timeTotal - timeElapsed should give time remaining. @pyqtProperty(float, notify = timeElapsedChanged) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 3d2d4bbc07..bf708f23d7 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -248,7 +248,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): # \param duration How long the bed should stay warm, in seconds. Defaults # to a quarter hour. @pyqtSlot(int, int) - def preheatBed(self, temperature, duration=900): + def preheatBed(self, temperature, duration): url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") data = """{"temperature": "%i", "timeout": "%i"}""" % (temperature, duration) put_request = QNetworkRequest(url) @@ -260,7 +260,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): # If the bed is not pre-heated, nothing happens. @pyqtSlot() def cancelPreheatBed(self): - self.preheatBed(temperature=0) + self.preheatBed(temperature = 0, duration = 0) ## Changes the target bed temperature and makes sure that its signal is # emitted. diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 0a34eb8f31..65a56b3441 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -404,7 +404,7 @@ Column connectedPrinter.preheatBed(preheatTemperatureInput.text, 900); var now = new Date(); var end_time = new Date(); - end_time.setTime(now.getTime() + 900 * 1000); //*1000 because time is in milliseconds here. + end_time.setTime(now.getTime() + connectedPrinter.preheatBedTimeout * 1000); //*1000 because time is in milliseconds here. preheatCountdownTimer.endTime = end_time; preheatCountdownTimer.start(); preheatCountdownTimer.update(); //Update once before the first timer is triggered. From 8e25a1c73fbc7430b0f2e2a3c7b682eb2c882668 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 16:32:36 +0100 Subject: [PATCH 080/156] Also use central pre-heat time when sending time to printer Oops. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 65a56b3441..277ae9b325 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -401,7 +401,7 @@ Column onClicked: { - connectedPrinter.preheatBed(preheatTemperatureInput.text, 900); + connectedPrinter.preheatBed(preheatTemperatureInput.text, connectedPrinter.preheatBedTimeout); var now = new Date(); var end_time = new Date(); end_time.setTime(now.getTime() + connectedPrinter.preheatBedTimeout * 1000); //*1000 because time is in milliseconds here. From 9b235aebf2cf829ec89413f57a1bab1a1804a0f1 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 16:38:28 +0100 Subject: [PATCH 081/156] Add clock icon to pre-heat countdown It's aligned left of the pre-heat countdown and only visible if the countdown is visible. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 277ae9b325..30f021675b 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -267,6 +267,21 @@ Column } } + UM.RecolorImage + { + id: preheatCountdownIcon + width: UM.Theme.getSize("save_button_specs_icons").width + height: UM.Theme.getSize("save_button_specs_icons").height + sourceSize.width: width + sourceSize.height: height + color: UM.Theme.getColor("text") + visible: preheatCountdown.visible + source: UM.Theme.getIcon("print_time") + anchors.right: preheatCountdown.left + anchors.rightMargin: UM.Theme.getSize("default_margin").width / 2 + anchors.verticalCenter: preheatCountdown.verticalCenter + } + Timer { id: preheatCountdownTimer From 8d09c538967e5cf841064e38cd4a80526a443da8 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 16:46:22 +0100 Subject: [PATCH 082/156] Make pre-heat button cancel if currently heating This is based on the timer, which is locally. Eventually we'd want to make the timer update every now and then or so. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 30f021675b..848aa5f9a5 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -323,7 +323,7 @@ Column Button //The pre-heat button. { id: preheatButton - text: catalog.i18nc("@button", "Pre-heat") + text: preheatCountdownTimer.running ? catalog.i18nc("@button Cancel pre-heating", "Cancel") : catalog.i18nc("@button", "Pre-heat") tooltip: catalog.i18nc("@tooltip of pre-heat", "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print.") height: UM.Theme.getSize("setting_control").height enabled: printerConnected @@ -416,13 +416,22 @@ Column onClicked: { - connectedPrinter.preheatBed(preheatTemperatureInput.text, connectedPrinter.preheatBedTimeout); - var now = new Date(); - var end_time = new Date(); - end_time.setTime(now.getTime() + connectedPrinter.preheatBedTimeout * 1000); //*1000 because time is in milliseconds here. - preheatCountdownTimer.endTime = end_time; - preheatCountdownTimer.start(); - preheatCountdownTimer.update(); //Update once before the first timer is triggered. + if (!preheatCountdownTimer.running) + { + connectedPrinter.preheatBed(preheatTemperatureInput.text, connectedPrinter.preheatBedTimeout); + var now = new Date(); + var end_time = new Date(); + end_time.setTime(now.getTime() + connectedPrinter.preheatBedTimeout * 1000); //*1000 because time is in milliseconds here. + preheatCountdownTimer.endTime = end_time; + preheatCountdownTimer.start(); + preheatCountdownTimer.update(); //Update once before the first timer is triggered. + } + else + { + connectedPrinter.cancelPreheatBed(); + preheatCountdownTimer.endTime = new Date(); + preheatCountdownTimer.update(); + } } } } From 785f10966efaf2e3e584384d41f185e96bf0f794 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 16:48:27 +0100 Subject: [PATCH 083/156] Don't send a time-out for preheat if timeout is 0 The printer doesn't accept 0. Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index bf708f23d7..074bc92cda 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -250,7 +250,10 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): @pyqtSlot(int, int) def preheatBed(self, temperature, duration): url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") - data = """{"temperature": "%i", "timeout": "%i"}""" % (temperature, duration) + if duration > 0: + data = """{"temperature": "%i", "timeout": "%i"}""" % (temperature, duration) + else: + data = """{"temperature": "%i"}""" % temperature put_request = QNetworkRequest(url) put_request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") self._manager.put(put_request, data.encode()) From 4ccadc6208796ea98aa5611621deaa6877e58c98 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 16:57:20 +0100 Subject: [PATCH 084/156] Round pre-heat temperature and duration to integer but allow floats We want to allow floats in the interface since the interface needs to be agnostic of what device it is connected to. But the UM3 API only allows integers, so we still need to round it to the nearest integer. Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 074bc92cda..3694ada361 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -247,8 +247,10 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): # Celsius. # \param duration How long the bed should stay warm, in seconds. Defaults # to a quarter hour. - @pyqtSlot(int, int) + @pyqtSlot(float, float) def preheatBed(self, temperature, duration): + temperature = round(temperature) #The API doesn't allow floating point. + duration = round(duration) url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") if duration > 0: data = """{"temperature": "%i", "timeout": "%i"}""" % (temperature, duration) From 57ec987cd9a350db4b08998695d26a9fcf3667ca Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 17:13:36 +0100 Subject: [PATCH 085/156] Disable pre-heat if temperature is invalid Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 848aa5f9a5..598b9489d9 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -326,7 +326,7 @@ Column text: preheatCountdownTimer.running ? catalog.i18nc("@button Cancel pre-heating", "Cancel") : catalog.i18nc("@button", "Pre-heat") tooltip: catalog.i18nc("@tooltip of pre-heat", "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print.") height: UM.Theme.getSize("setting_control").height - enabled: printerConnected + enabled: printerConnected && (preheatCountdownTimer.running || (parseInt(preheatTemperatureInput.text) >= parseInt(bedTemperature.properties.minimum_value) && parseInt(preheatTemperatureInput.text) <= parseInt(bedTemperature.properties.maximum_value))) anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("default_margin").width anchors.bottom: parent.bottom From d30430381f5e37094aea9a4743861132e4675092 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 17:16:19 +0100 Subject: [PATCH 086/156] Add default implementations for preheatBed and cancelPreheatBed It is a no-op implementation that gives a warning. I'd rather give an exception and have that handled by whatever calls it, but this is how the other methods here do it. Contributes to issue CURA-3161. --- cura/PrinterOutputDevice.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index 56ae34b6f4..f7b5ccbe05 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -260,6 +260,23 @@ class PrinterOutputDevice(QObject, OutputDevice): def _setTargetBedTemperature(self, temperature): Logger.log("w", "_setTargetBedTemperature is not implemented by this output device") + ## Pre-heats the heated bed of the printer. + # + # \param temperature The temperature to heat the bed to, in degrees + # Celsius. + # \param duration How long the bed should stay warm, in seconds. Defaults + # to a quarter hour. + @pyqtSlot(float, float) + def preheatBed(self, temperature, duration): + Logger.log("w", "preheatBed is not implemented by this output device.") + + ## Cancels pre-heating the heated bed of the printer. + # + # If the bed is not pre-heated, nothing happens. + @pyqtSlot() + def cancelPreheatBed(self): + Logger.log("w", "cancelPreheatBed is not implemented by this output device.") + ## Protected setter for the current bed temperature. # This simply sets the bed temperature, but ensures that a signal is emitted. # /param temperature temperature of the bed. From 9354a80504a03bf4e265468539be9416994fe03e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 17:17:45 +0100 Subject: [PATCH 087/156] Document no longer that pre-heating defaults to 15m Because that was removed. Contributes to issue CURA-3161. --- cura/PrinterOutputDevice.py | 3 +-- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index f7b5ccbe05..3cba132f9a 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -264,8 +264,7 @@ class PrinterOutputDevice(QObject, OutputDevice): # # \param temperature The temperature to heat the bed to, in degrees # Celsius. - # \param duration How long the bed should stay warm, in seconds. Defaults - # to a quarter hour. + # \param duration How long the bed should stay warm, in seconds. @pyqtSlot(float, float) def preheatBed(self, temperature, duration): Logger.log("w", "preheatBed is not implemented by this output device.") diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 3694ada361..6ce3a4fcc5 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -245,8 +245,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): # # \param temperature The temperature to heat the bed to, in degrees # Celsius. - # \param duration How long the bed should stay warm, in seconds. Defaults - # to a quarter hour. + # \param duration How long the bed should stay warm, in seconds. @pyqtSlot(float, float) def preheatBed(self, temperature, duration): temperature = round(temperature) #The API doesn't allow floating point. From b05697b0d57b3dc9d5ca93fceb39eb61834a44c0 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 17:21:14 +0100 Subject: [PATCH 088/156] Also cancel pre-heating bed from Cura after time-out Printers that don't automatically turn off their heated bed will get the task to do so by Cura then. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 598b9489d9..f52ea86312 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -305,6 +305,10 @@ Column { preheatCountdown.visible = false; running = false; + if (printerConnected) + { + connectedPrinter.cancelPreheatBed() + } } } } From 7cf81412ae4cc46e94013c3e9706069764601424 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 17:26:44 +0100 Subject: [PATCH 089/156] Implement bed pre-heating via USB It just calls the bed heating command without implementing the time-out. Implementing the time-out is impossible via just g-code. Contributes to issue CURA-3161. --- plugins/USBPrinting/USBPrinterOutputDevice.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/plugins/USBPrinting/USBPrinterOutputDevice.py b/plugins/USBPrinting/USBPrinterOutputDevice.py index e30ba613bc..9fd5bf02e0 100644 --- a/plugins/USBPrinting/USBPrinterOutputDevice.py +++ b/plugins/USBPrinting/USBPrinterOutputDevice.py @@ -641,3 +641,20 @@ class USBPrinterOutputDevice(PrinterOutputDevice): self._update_firmware_thread.daemon = True self.connect() + + ## Pre-heats the heated bed of the printer, if it has one. + # + # \param temperature The temperature to heat the bed to, in degrees + # Celsius. + # \param duration How long the bed should stay warm, in seconds. This is + # ignored because there is no g-code to set this. + @pyqtSlot(float, float) + def preheatBed(self, temperature, duration): + self._setTargetBedTemperature(temperature) + + ## Cancels pre-heating the heated bed of the printer. + # + # If the bed is not pre-heated, nothing happens. + @pyqtSlot() + def cancelPreheatBed(self): + self._setTargetBedTemperature(0) \ No newline at end of file From e9b30daad6b6ba079a739dd9c9d0b182adc21db5 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 17:30:15 +0100 Subject: [PATCH 090/156] Write out pre-heat button enabled condition It should be equivalent. This needs to be done because the line is getting long and I need to add additional checks for if the properties are even set. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index f52ea86312..ee3f68ad17 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -330,7 +330,26 @@ Column text: preheatCountdownTimer.running ? catalog.i18nc("@button Cancel pre-heating", "Cancel") : catalog.i18nc("@button", "Pre-heat") tooltip: catalog.i18nc("@tooltip of pre-heat", "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print.") height: UM.Theme.getSize("setting_control").height - enabled: printerConnected && (preheatCountdownTimer.running || (parseInt(preheatTemperatureInput.text) >= parseInt(bedTemperature.properties.minimum_value) && parseInt(preheatTemperatureInput.text) <= parseInt(bedTemperature.properties.maximum_value))) + enabled: + { + if (!printerConnected) + { + return false; //Can't preheat if not connected. + } + if (preheatCountdownTimer.running) + { + return true; //Can always cancel if the timer is running. + } + if (parseInt(preheatTemperatureInput.text) < parseInt(bedTemperature.properties.minimum_value)) + { + return false; //Target temperature too low. + } + if (parseInt(preheatTemperatureInput.text) > parseInt(bedTemperature.properties.maximum_value)) + { + return false; //Target temperature too high. + } + return true; //Preconditions are met. + } anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("default_margin").width anchors.bottom: parent.bottom From 0b10df01b01d06b3c7b75d23211cd4705bb70b2e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 17:33:59 +0100 Subject: [PATCH 091/156] Don't check for min/max temperature if we have no min/max If we have no minimum/maximum bed temperature, the property returns 'None'. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index ee3f68ad17..2d989aeb43 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -340,11 +340,11 @@ Column { return true; //Can always cancel if the timer is running. } - if (parseInt(preheatTemperatureInput.text) < parseInt(bedTemperature.properties.minimum_value)) + if (bedTemperature.properties.minimum_value != "None" && parseInt(preheatTemperatureInput.text) < parseInt(bedTemperature.properties.minimum_value)) { return false; //Target temperature too low. } - if (parseInt(preheatTemperatureInput.text) > parseInt(bedTemperature.properties.maximum_value)) + if (bedTemperature.properties.maximum_value != "None" && parseInt(preheatTemperatureInput.text) > parseInt(bedTemperature.properties.maximum_value)) { return false; //Target temperature too high. } From 74bef2ff951ef2a29fb4db72f1eed2667f58e234 Mon Sep 17 00:00:00 2001 From: Arjen Hiemstra Date: Tue, 7 Feb 2017 17:34:02 +0100 Subject: [PATCH 092/156] Fix OpenGL 2.0 fallback shader for Layer View --- plugins/LayerView/layers.shader | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 88717e8774..81d5c94dff 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -5,8 +5,8 @@ vertex = uniform lowp float u_shade_factor; uniform highp int u_layer_view_type; - attribute highp int a_extruder; - attribute highp int a_line_type; + attribute highp float a_extruder; + attribute highp float a_line_type; attribute highp vec4 a_vertex; attribute lowp vec4 a_color; attribute lowp vec4 a_material_color; @@ -18,7 +18,7 @@ vertex = { gl_Position = u_modelViewProjectionMatrix * a_vertex; v_color = a_color; - if ((a_line_type != 8) && (a_line_type != 9)) { + if ((a_line_type != 8.0) && (a_line_type != 9.0)) { v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a); } @@ -66,7 +66,7 @@ fragment = discard; } - gl_FragColor = u_color; + gl_FragColor = v_color; } vertex41core = From be9823e94fe07123bda7d4f588fe0ec7023eb288 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 7 Feb 2017 17:39:45 +0100 Subject: [PATCH 093/156] Hide maximum bed temperature if there is no maximum Instead of the ugly 'None' it would display. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 2d989aeb43..34cb3d438a 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -210,6 +210,7 @@ Column Label //Maximum temperature indication. { text: bedTemperature.properties.maximum_value + visible: bedTemperature.properties.maximum_value != "None" color: UM.Theme.getColor("setting_unit") font: UM.Theme.getFont("default") anchors.right: parent.right From 2cdf06413bb48628449594bc3c3ef8d2ef89d632 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 09:41:42 +0100 Subject: [PATCH 094/156] Remove margin on the left of print monitor For the other side bar objects this margin was applied doubly, so that makes it very easy to remove. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- resources/qml/Sidebar.qml | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 34cb3d438a..ea33dad592 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -533,7 +533,7 @@ Column Rectangle { color: UM.Theme.getColor("setting_category") - width: base.width - 2 * UM.Theme.getSize("default_margin").width + width: base.width height: UM.Theme.getSize("section").height Label diff --git a/resources/qml/Sidebar.qml b/resources/qml/Sidebar.qml index 45dc49d076..ab3032e7f1 100644 --- a/resources/qml/Sidebar.qml +++ b/resources/qml/Sidebar.qml @@ -499,9 +499,7 @@ Rectangle { anchors.bottom: footerSeparator.top anchors.top: headerSeparator.bottom - anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.left: base.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.right: base.right source: monitoringPrint ? "PrintMonitor.qml": "SidebarContents.qml" } From 34f929c9df3ce7ebf49d1dc826feffd3f3e2549d Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 10:18:21 +0100 Subject: [PATCH 095/156] Disable preheat button if printer is busy It is allowed to preheat the bed if the printer is waiting for the bed to clean up or for stuff to cool down after a print. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index ea33dad592..861b6d2bc1 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -337,6 +337,10 @@ Column { return false; //Can't preheat if not connected. } + if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "pre_print" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline") + { + return false; //Printer is in a state where it can't react to pre-heating. + } if (preheatCountdownTimer.running) { return true; //Can always cancel if the timer is running. From 98e3e2a25a8774c9c48a943fd017d67d9c7f4546 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 10:19:20 +0100 Subject: [PATCH 096/156] Allow pre-heating bed while pausing It is allowed during the pause. So it should also be allowed when transitioning towards the pause. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 861b6d2bc1..8bf3d41322 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -337,7 +337,7 @@ Column { return false; //Can't preheat if not connected. } - if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "pre_print" || connectedPrinter.jobState == "pausing" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline") + if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "pre_print" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline") { return false; //Printer is in a state where it can't react to pre-heating. } From 1d6ef4bc3cdcf42714e61b1eb69836a348de4c33 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 8 Feb 2017 10:40:17 +0100 Subject: [PATCH 097/156] Default color if no material color is available. CURA-3273 --- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 21227e7a8b..7648307de5 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -177,6 +177,8 @@ class ProcessSlicedLayersJob(Job): material_color_map = numpy.zeros((1, 4), dtype=numpy.float32) material = global_container_stack.findContainer({"type": "material"}) color_code = material.getMetaDataEntry("color_code") + if color_code is None: # not all stacks have a material color + color_code = "#e0e000" color = colorCodeToRGBA(color_code) material_color_map[0, :] = color From 6c19bc1c16c15329539c9275581c80842f516cb1 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 8 Feb 2017 11:08:59 +0100 Subject: [PATCH 098/156] Only show legend in color: line_type --- plugins/LayerView/LayerView.py | 15 +++++++++++++-- plugins/LayerView/LayerView.qml | 11 +++++++++-- plugins/LayerView/LayerViewProxy.py | 12 ++++++++++++ 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 468fc01ec3..6217ebdad2 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -36,6 +36,10 @@ import os.path ## View used to display g-code paths. class LayerView(View): + # Must match LayerView.qml + LAYER_VIEW_TYPE_MATERIAL_TYPE = 0 + LAYER_VIEW_TYPE_LINE_TYPE = 1 + def __init__(self): super().__init__() @@ -260,6 +264,12 @@ class LayerView(View): def endRendering(self): pass + def enableLegend(self): + Application.getInstance().setViewLegendItems(self._getLegendItems()) + + def disableLegend(self): + Application.getInstance().setViewLegendItems([]) + def event(self, event): modifiers = QApplication.keyboardModifiers() ctrl_is_active = modifiers == Qt.ControlModifier @@ -292,7 +302,8 @@ class LayerView(View): self._old_composite_shader = self._composite_pass.getCompositeShader() self._composite_pass.setCompositeShader(self._layerview_composite_shader) - Application.getInstance().setViewLegendItems(self._getLegendItems()) + if self.getLayerViewType() == self.LAYER_VIEW_TYPE_LINE_TYPE: + self.enableLegend() elif event.type == Event.ViewDeactivateEvent: self._wireprint_warning_message.hide() @@ -303,7 +314,7 @@ class LayerView(View): self._composite_pass.setLayerBindings(self._old_layer_bindings) self._composite_pass.setCompositeShader(self._old_composite_shader) - Application.getInstance().setViewLegendItems([]) + self.disableLegend() def _onGlobalStackChanged(self): if self._global_container_stack: diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index ee109b7f04..c2b2fb3559 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -158,7 +158,7 @@ Item border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") - ListModel + ListModel // matches LayerView.py { id: layerViewTypes ListElement { @@ -179,7 +179,14 @@ Item model: layerViewTypes visible: !UM.LayerView.compatibilityMode onActivated: { - UM.LayerView.setLayerViewType(layerViewTypes.get(index).type_id); + var type_id = layerViewTypes.get(index).type_id; + UM.LayerView.setLayerViewType(type_id); + if (type_id == 1) { + // Line type + UM.LayerView.enableLegend(); + } else { + UM.LayerView.disableLegend(); + } } } diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index 7eb4cc65da..d386b53d01 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -129,6 +129,18 @@ class LayerViewProxy(QObject): return active_view.getExtruderCount() return 0 + @pyqtSlot() + def enableLegend(self): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.enableLegend() + + @pyqtSlot() + def disableLegend(self): + active_view = self._controller.getActiveView() + if type(active_view) == LayerView.LayerView.LayerView: + active_view.disableLegend() + def _layerActivityChanged(self): self.activityChanged.emit() From 50ba236e660ac7df92e3070585de59a6d25374b0 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 8 Feb 2017 11:24:41 +0100 Subject: [PATCH 099/156] Removed unused option in LayerPolygon, added comments --- cura/LayerDataBuilder.py | 9 +++++++-- cura/LayerPolygon.py | 11 +++++++---- plugins/CuraEngineBackend/ProcessSlicedLayersJob.py | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index dcc3991833..1de2302f77 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -48,8 +48,10 @@ class LayerDataBuilder(MeshBuilder): self._layers[layer].setThickness(thickness) - # material color map: [r, g, b, a] for each extruder row. - # line_type_brightness: compatibility layer view uses line type brightness of 0.5 + ## Return the layer data as LayerData. + # + # \param material_color_map: [r, g, b, a] for each extruder row. + # \param line_type_brightness: compatibility layer view uses line type brightness of 0.5 def build(self, material_color_map, line_type_brightness = 1.0): vertex_count = 0 index_count = 0 @@ -75,9 +77,12 @@ class LayerDataBuilder(MeshBuilder): self.addColors(colors) self.addIndices(indices.flatten()) + # Note: we're using numpy indexing here. + # See also: https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html material_colors = numpy.zeros((line_dimensions.shape[0], 4), dtype=numpy.float32) for extruder_nr in range(material_color_map.shape[0]): material_colors[extruders == extruder_nr] = material_color_map[extruder_nr] + # Set material_colors with indices where line_types (also numpy array) == MoveCombingType material_colors[line_types == LayerPolygon.MoveCombingType] = colors[line_types == LayerPolygon.MoveCombingType] material_colors[line_types == LayerPolygon.MoveRetractionType] = colors[line_types == LayerPolygon.MoveRetractionType] diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 90bc123548..577de9e40b 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -19,10 +19,13 @@ class LayerPolygon: __jump_map = numpy.logical_or(numpy.logical_or(numpy.arange(11) == NoneType, numpy.arange(11) == MoveCombingType), numpy.arange(11) == MoveRetractionType) - ## LayerPolygon - # line_thicknesses: array with type as index and thickness as value - def __init__(self, mesh, extruder, line_types, data, line_widths, line_thicknesses): - self._mesh = mesh + ## LayerPolygon, used in ProcessSlicedLayersJob + # \param extruder + # \param line_types array with line_types + # \param data new_points + # \param line_widths array with line widths + # \param line_thicknesses: array with type as index and thickness as value + def __init__(self, extruder, line_types, data, line_widths, line_thicknesses): self._extruder = extruder self._types = line_types self._data = data diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 7648307de5..0f46cc96bf 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -139,7 +139,7 @@ class ProcessSlicedLayersJob(Job): new_points[:, 1] = points[:, 2] new_points[:, 2] = -points[:, 1] - this_poly = LayerPolygon.LayerPolygon(layer_data, extruder, line_types, new_points, line_widths, line_thicknesses) + this_poly = LayerPolygon.LayerPolygon(extruder, line_types, new_points, line_widths, line_thicknesses) this_poly.buildCache() this_layer.polygons.append(this_poly) From 28e488dad712a5e5b3ce01d1e457e80b1c809263 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 11:37:04 +0100 Subject: [PATCH 100/156] Fix setting target bed temperature The previous implementation just emitted the signal twice, once in setTargetBedTemperature and once in _setTargetBedTemperature. I've made the private one actually set the temperature. Contributes to issue CURA-3161. --- .../NetworkPrinterOutputDevice.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 6ce3a4fcc5..5f7a36f316 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -266,14 +266,17 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): def cancelPreheatBed(self): self.preheatBed(temperature = 0, duration = 0) - ## Changes the target bed temperature and makes sure that its signal is - # emitted. + ## Changes the target bed temperature on the printer. # # /param temperature The new target temperature of the bed. def _setTargetBedTemperature(self, temperature): - if self._target_bed_temperature != temperature: - self._target_bed_temperature = temperature - self.targetBedTemperatureChanged.emit() + if self._target_bed_temperature == temperature: + return + url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/temperature") + data = """{"target": "%i"}""" % temperature + put_request = QNetworkRequest(url) + put_request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") + self._manager.put(put_request, data.encode()) def _stopCamera(self): self._camera_timer.stop() From da4574cb32d78a169b000b5edb79d9affb7d63bb Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 11:38:03 +0100 Subject: [PATCH 101/156] Use fallback without time-out if preheating bed on old firmware It manually sets the temperature just like what happens when you print via USB. Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 5f7a36f316..44aead8e5b 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -9,6 +9,7 @@ from UM.Signal import signalemitter from UM.Message import Message import UM.Settings +import UM.Version #To compare firmware version numbers. from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState import cura.Settings.ExtruderManager @@ -250,6 +251,9 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): def preheatBed(self, temperature, duration): temperature = round(temperature) #The API doesn't allow floating point. duration = round(duration) + if UM.Version(self.firmwareVersion) < UM.Version("3.5.92"): #Real bed pre-heating support is implemented from 3.5.92 and up. + self.setTargetBedTemperature(temperature = temperature) #No firmware-side duration support then. + return url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") if duration > 0: data = """{"temperature": "%i", "timeout": "%i"}""" % (temperature, duration) From 9f66ad1132e213fdd0c50a4e2a40e3259b3c32f8 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 11:40:40 +0100 Subject: [PATCH 102/156] Remove superfluous empty item Don't know where that came from. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 3 --- 1 file changed, 3 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 8bf3d41322..4b811f1806 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -437,9 +437,6 @@ Column text: control.text; } } - label: Item - { - } } onClicked: From 47ab49795f732886d223f61f32a04d3239185458 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 8 Feb 2017 11:48:00 +0100 Subject: [PATCH 103/156] Added comments, changed small layout and id thing. CURA-3273 --- cura/LayerPolygon.py | 15 +++++++++++++-- .../CuraEngineBackend/ProcessSlicedLayersJob.py | 3 +++ plugins/LayerView/LayerView.py | 8 ++++++++ plugins/LayerView/LayerView.qml | 6 +++--- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/cura/LayerPolygon.py b/cura/LayerPolygon.py index 577de9e40b..242bb25d56 100644 --- a/cura/LayerPolygon.py +++ b/cura/LayerPolygon.py @@ -69,9 +69,20 @@ class LayerPolygon: self._vertex_begin = 0 self._vertex_end = numpy.sum( self._build_cache_needed_points ) - + + ## Set all the arrays provided by the function caller, representing the LayerPolygon + # The arrays are either by vertex or by indices. + # + # \param vertex_offset : determines where to start and end filling the arrays + # \param index_offset : determines where to start and end filling the arrays + # \param vertices : vertex numpy array to be filled + # \param colors : vertex numpy array to be filled + # \param line_dimensions : vertex numpy array to be filled + # \param extruders : vertex numpy array to be filled + # \param line_types : vertex numpy array to be filled + # \param indices : index numpy array to be filled def build(self, vertex_offset, index_offset, vertices, colors, line_dimensions, extruders, line_types, indices): - if (self._build_cache_line_mesh_mask is None) or (self._build_cache_needed_points is None ): + if self._build_cache_line_mesh_mask is None or self._build_cache_needed_points is None: self.buildCache() line_mesh_mask = self._build_cache_line_mesh_mask diff --git a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py index 0f46cc96bf..0d706f59b8 100644 --- a/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py +++ b/plugins/CuraEngineBackend/ProcessSlicedLayersJob.py @@ -27,6 +27,9 @@ from time import time catalog = i18nCatalog("cura") +## Return a 4-tuple with floats 0-1 representing the html color code +# +# \param color_code html color code, i.e. "#FF0000" -> red def colorCodeToRGBA(color_code): return [ int(color_code[1:3], 16) / 255, diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index 6217ebdad2..c75c2eac0c 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -168,13 +168,21 @@ class LayerView(View): self.currentLayerNumChanged.emit() + ## Set the layer view type + # + # \param layer_view_type integer as in LayerView.qml and this class def setLayerViewType(self, layer_view_type): self._layer_view_type = layer_view_type self.currentLayerNumChanged.emit() + ## Return the layer view type, integer as in LayerView.qml and this class def getLayerViewType(self): return self._layer_view_type + ## Set the extruder opacity + # + # \param extruder_nr 0..3 + # \param opacity 0.0 .. 1.0 def setExtruderOpacity(self, extruder_nr, opacity): self._extruder_opacity[extruder_nr] = opacity self.currentLayerNumChanged.emit() diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index c2b2fb3559..ac85d6ccb2 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -15,7 +15,7 @@ Item Slider { - id: slider2 + id: sliderMinimumLayer width: UM.Theme.getSize("slider_layerview_size").width height: UM.Theme.getSize("slider_layerview_size").height anchors.left: parent.left @@ -151,7 +151,6 @@ Item anchors.verticalCenter: parent.verticalCenter anchors.top: slider_background.bottom anchors.topMargin: UM.Theme.getSize("default_margin").height - //anchors.leftMargin: UM.Theme.getSize("default_margin").width width: UM.Theme.getSize("slider_layerview_background").width * 3 height: slider.height + UM.Theme.getSize("default_margin").height * 2 color: UM.Theme.getColor("tool_panel_background"); @@ -203,7 +202,8 @@ Item id: view_settings anchors.top: UM.LayerView.compatibilityMode ? compatibilityModeLabel.bottom : layerTypeCombobox.bottom anchors.topMargin: UM.Theme.getSize("default_margin").height - x: UM.Theme.getSize("default_margin").width + anchors.left: parent.left + anchors.leftMargin: UM.Theme.getSize("default_margin").width CheckBox { checked: true From cc950732b63fa3d34a7f4b040fcb7162b72be236 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 8 Feb 2017 11:57:59 +0100 Subject: [PATCH 104/156] Added comment. CURA-3273 --- plugins/LayerView/layers.shader | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 81d5c94dff..1b1c62e21f 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -17,6 +17,7 @@ vertex = void main() { gl_Position = u_modelViewProjectionMatrix * a_vertex; + // shade the color depending on the extruder index v_color = a_color; if ((a_line_type != 8.0) && (a_line_type != 9.0)) { v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a); From 2a114f1e533bef64e8b48a001e12998e63937275 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 11:59:19 +0100 Subject: [PATCH 105/156] Display last item with double width if there's room on the right side If it's on the left side and it's the last item, it gets the entire width. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 4b811f1806..b707b41151 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -91,6 +91,7 @@ Column color: UM.Theme.getColor("sidebar") width: extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2 height: UM.Theme.getSize("sidebar_extruder_box").height + Layout.fillWidth: index == machineExtruderCount.properties.value - 1 && index % 2 == 0 Text //Extruder name. { From d7b0336c2411711acf944c4f2bb296caf80c34be Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 12:42:40 +0100 Subject: [PATCH 106/156] Fix colour of unknown material The other colour was just used for debugging. Contributes to issue CURA-3161. --- cura/PrinterOutputDevice.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index 3cba132f9a..f989bf26cd 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -1,3 +1,6 @@ +# Copyright (c) 2017 Ultimaker B.V. +# Cura is released under the terms of the AGPLv3 or higher. + from UM.i18n import i18nCatalog from UM.OutputDevice.OutputDevice import OutputDevice from PyQt5.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject @@ -357,14 +360,14 @@ class PrinterOutputDevice(QObject, OutputDevice): result = [] for material_id in self._material_ids: if material_id is None: - result.append("#800000FF") #No material. + result.append("#00000000") #No material. continue containers = self._container_registry.findInstanceContainers(type = "material", GUID = material_id) if containers: result.append(containers[0].getMetaDataEntry("color_code")) else: - result.append("#800000FF") #Unknown material. + result.append("#00000000") #Unknown material. return result ## Protected setter for the current material id. From 1395735ecef792e50a886231d13d43197f0086cb Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 12:53:54 +0100 Subject: [PATCH 107/156] No longer mention printer name in status The printer name is displayed right above it, so mentioning the name again is double. Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 44aead8e5b..69d5c8abc2 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -318,14 +318,14 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): if auth_state == AuthState.AuthenticationRequested: Logger.log("d", "Authentication state changed to authentication requested.") self.setAcceptsCommands(False) - self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network to {0}. Please approve the access request on the printer.").format(self.name)) + self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network. Please approve the access request on the printer.")) self._authentication_requested_message.show() self._authentication_request_active = True self._authentication_timer.start() # Start timer so auth will fail after a while. elif auth_state == AuthState.Authenticated: Logger.log("d", "Authentication state changed to authenticated") self.setAcceptsCommands(True) - self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network to {0}.").format(self.name)) + self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network.")) self._authentication_requested_message.hide() if self._authentication_request_active: self._authentication_succeeded_message.show() @@ -338,7 +338,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): self.sendMaterialProfiles() elif auth_state == AuthState.AuthenticationDenied: self.setAcceptsCommands(False) - self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network to {0}. No access to control the printer.").format(self.name)) + self.setConnectionText(i18n_catalog.i18nc("@info:status", "Connected over the network. No access to control the printer.")) self._authentication_requested_message.hide() if self._authentication_request_active: if self._authentication_timer.remainingTime() > 0: From 8e80593232140b62bf3b21890122834205f8b064 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 8 Feb 2017 13:03:48 +0100 Subject: [PATCH 108/156] Added comment. CURA-3273 --- plugins/LayerView/layers.shader | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index 1b1c62e21f..cc25134216 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -19,6 +19,7 @@ vertex = gl_Position = u_modelViewProjectionMatrix * a_vertex; // shade the color depending on the extruder index v_color = a_color; + // 8 and 9 are travel moves if ((a_line_type != 8.0) && (a_line_type != 9.0)) { v_color = (a_extruder == u_active_extruder) ? v_color : vec4(u_shade_factor * v_color.rgb, v_color.a); } From 0d444298bcffef2f19e1771ee950908f9dea059d Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 8 Feb 2017 13:29:24 +0100 Subject: [PATCH 109/156] Added myEmitVertex function in layers3d.shader. CURA-3273 --- plugins/LayerView/layers3d.shader | 160 +++++++----------------------- 1 file changed, 35 insertions(+), 125 deletions(-) diff --git a/plugins/LayerView/layers3d.shader b/plugins/LayerView/layers3d.shader index c7c7628a92..16572356db 100644 --- a/plugins/LayerView/layers3d.shader +++ b/plugins/LayerView/layers3d.shader @@ -88,6 +88,15 @@ geometry41core = out vec3 f_normal; out vec3 f_vertex; + // Set the set of variables and EmitVertex + void myEmitVertex(vec3 vertex, vec4 color, vec3 normal, vec4 pos) { + f_vertex = vertex; + f_color = color; + f_normal = normal; + gl_Position = pos; + EmitVertex(); + } + void main() { vec4 g_vertex_delta; @@ -140,145 +149,46 @@ geometry41core = g_vertex_normal_vert = vec3(0.0, 1.0, 0.0); g_vertex_offset_vert = vec4(g_vertex_normal_vert * size_y, 0.0); - f_vertex = v_vertex[0]; - f_color = v_color[0]; - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - f_vertex = v_vertex[0]; - f_color = v_color[0]; - f_normal = g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); - EmitVertex(); - - f_vertex = v_vertex[0]; - f_normal = -g_vertex_normal_horz; - f_color = v_color[0]; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = -g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); - EmitVertex(); - - f_vertex = v_vertex[0]; - f_color = v_color[0]; - f_normal = -g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = -g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); - EmitVertex(); - - f_vertex = v_vertex[0]; - f_normal = g_vertex_normal_horz; - f_color = v_color[0]; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - f_vertex = v_vertex[1]; - f_color = v_color[1]; - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); - EmitVertex(); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert)); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert)); + myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz)); + myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz)); + myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert)); + myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz)); EndPrimitive(); // left side - f_vertex = v_vertex[0]; - f_color = v_color[0]; - - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - f_normal = g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert); - EmitVertex(); - - f_normal = g_vertex_normal_horz_head; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); - EmitVertex(); - - f_normal = -g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); - EmitVertex(); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head)); + myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz)); EndPrimitive(); - f_normal = -g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz); - EmitVertex(); - - f_normal = -g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert); - EmitVertex(); - - f_normal = g_vertex_normal_horz_head; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head); - EmitVertex(); - - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz); - EmitVertex(); + myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz)); + myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_vert)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); EndPrimitive(); // right side - f_vertex = v_vertex[1]; - f_color = v_color[1]; - - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); - EmitVertex(); - - f_normal = g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert); - EmitVertex(); - - f_normal = -g_vertex_normal_horz_head; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); - EmitVertex(); - - f_normal = -g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); - EmitVertex(); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz)); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_vert)); + myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head)); + myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz)); EndPrimitive(); - f_normal = -g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz); - EmitVertex(); - - f_normal = -g_vertex_normal_vert; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert); - EmitVertex(); - - f_normal = -g_vertex_normal_horz_head; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head); - EmitVertex(); - - f_normal = g_vertex_normal_horz; - gl_Position = u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz); - EmitVertex(); + myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz)); + myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert)); + myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head)); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz)); EndPrimitive(); } From 811f40d294b2ef5afba56b20591976d1ff3da9bf Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 8 Feb 2017 13:34:54 +0100 Subject: [PATCH 110/156] Renamed lightDir to light_dir. CURA-3273 --- plugins/LayerView/layers3d.shader | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/LayerView/layers3d.shader b/plugins/LayerView/layers3d.shader index 16572356db..c63bdac7d9 100644 --- a/plugins/LayerView/layers3d.shader +++ b/plugins/LayerView/layers3d.shader @@ -212,10 +212,10 @@ fragment41core = finalColor.rgb += f_color.rgb * 0.3; highp vec3 normal = normalize(f_normal); - highp vec3 lightDir = normalize(u_lightPosition - f_vertex); + highp vec3 light_dir = normalize(u_lightPosition - f_vertex); // Diffuse Component - highp float NdotL = clamp(dot(normal, lightDir), 0.0, 1.0); + highp float NdotL = clamp(dot(normal, light_dir), 0.0, 1.0); finalColor += (NdotL * f_color); finalColor.a = alpha; // Do not change alpha in any way From 81e575da31dee0f1ab77a88c743929fd3a56a86b Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 8 Feb 2017 13:39:19 +0100 Subject: [PATCH 111/156] Added comment. CURA-3273 --- plugins/LayerView/layerview_composite.shader | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/LayerView/layerview_composite.shader b/plugins/LayerView/layerview_composite.shader index f203650ce6..dcc02acc84 100644 --- a/plugins/LayerView/layerview_composite.shader +++ b/plugins/LayerView/layerview_composite.shader @@ -33,6 +33,7 @@ fragment = void main() { + // blur kernel kernel[0] = 0.0; kernel[1] = 1.0; kernel[2] = 0.0; kernel[3] = 1.0; kernel[4] = -4.0; kernel[5] = 1.0; kernel[6] = 0.0; kernel[7] = 1.0; kernel[8] = 0.0; @@ -101,6 +102,7 @@ fragment41core = void main() { + // blur kernel kernel[0] = 0.0; kernel[1] = 1.0; kernel[2] = 0.0; kernel[3] = 1.0; kernel[4] = -4.0; kernel[5] = 1.0; kernel[6] = 0.0; kernel[7] = 1.0; kernel[8] = 0.0; From bcab0d7be90d54da310901b69f318d284908b2ad Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 14:00:06 +0100 Subject: [PATCH 112/156] Add unit to maximum temperature indication Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index b707b41151..90111265f0 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -210,8 +210,7 @@ Column } Label //Maximum temperature indication. { - text: bedTemperature.properties.maximum_value - visible: bedTemperature.properties.maximum_value != "None" + text: (bedTemperature.properties.maximum_value != "None" ? bedTemperature.properties.maximum_value : "") + "°C" color: UM.Theme.getColor("setting_unit") font: UM.Theme.getFont("default") anchors.right: parent.right From 4013b500632f1cca1342910ec9ecba9afacdc484 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Wed, 8 Feb 2017 14:01:07 +0100 Subject: [PATCH 113/156] Only allow pre-heating if authenticated Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 90111265f0..b34d1af252 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -337,6 +337,10 @@ Column { return false; //Can't preheat if not connected. } + if (!connectedPrinter.acceptsCommands) + { + return false; //Not allowed to do anything. + } if (connectedPrinter.jobState == "printing" || connectedPrinter.jobState == "pre_print" || connectedPrinter.jobState == "resuming" || connectedPrinter.jobState == "error" || connectedPrinter.jobState == "offline") { return false; //Printer is in a state where it can't react to pre-heating. From c5655d4d8c1a3d1c02fd5092202803bae806fc91 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 9 Feb 2017 09:32:14 +0100 Subject: [PATCH 114/156] Document preheatBedTimeout Must've slipped through the cracks. Contributes to issue CURA-3161. --- cura/PrinterOutputDevice.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index f989bf26cd..c6bc3e8f3d 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -203,7 +203,9 @@ class PrinterOutputDevice(QObject, OutputDevice): self._target_bed_temperature = temperature self.targetBedTemperatureChanged.emit() - ## + ## The duration of the time-out to pre-heat the bed, in seconds. + # + # \return The duration of the time-out to pre-heat the bed, in seconds. @pyqtProperty(int) def preheatBedTimeout(self): return self._preheat_bed_timeout From e37d8b949e5427d7564da6e3c1af4cc9cbf04bcc Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 9 Feb 2017 10:31:35 +0100 Subject: [PATCH 115/156] Add fallback in PrinterOutputDevice for getting address The fallback gives a warning that it's not implemented. Contributes to issue CURA-3161. --- cura/PrinterOutputDevice.py | 5 +++++ resources/qml/PrintMonitor.qml | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index c6bc3e8f3d..8f03bdff79 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -165,6 +165,11 @@ class PrinterOutputDevice(QObject, OutputDevice): self._job_name = name self.jobNameChanged.emit() + ## Gives a human-readable address where the device can be found. + @pyqtProperty(str, constant = True) + def address(self): + Logger.log("w", "address is not implemented by this output device.") + @pyqtProperty(str, notify = errorTextChanged) def errorText(self): return self._error_text diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index b34d1af252..8ce094cbd3 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -43,7 +43,7 @@ Column Label { id: connectedPrinterAddressLabel - text: printerConnected ? connectedPrinter.address : "" + text: (printerConnected && connectedPrinter.address != null) ? connectedPrinter.address : "" font: UM.Theme.getFont("small") color: UM.Theme.getColor("text_inactive") anchors.left: parent.left From 27c30006da20b8cf1e849c2f5adfa1e4535c179e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 9 Feb 2017 10:33:14 +0100 Subject: [PATCH 116/156] Give no address instead of a wrong address if unknown Contributes to issue CURA-3161. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 69d5c8abc2..5790cdab77 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -225,7 +225,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): ## The IP address of the printer. @pyqtProperty(str, constant = True) def address(self): - return self._properties.get(b"address", b"0.0.0.0").decode("utf-8") + return self._properties.get(b"address", b"").decode("utf-8") ## Name of the printer (as returned from the zeroConf properties) @pyqtProperty(str, constant = True) From 30af908e2919f83bf04a21bca625a9d9b0ddcba6 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Thu, 9 Feb 2017 15:27:53 +0100 Subject: [PATCH 117/156] Fixed GCodeReader. CURA-3273 --- plugins/GCodeReader/GCodeReader.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/GCodeReader/GCodeReader.py b/plugins/GCodeReader/GCodeReader.py index 34ea91a727..290b66343e 100644 --- a/plugins/GCodeReader/GCodeReader.py +++ b/plugins/GCodeReader/GCodeReader.py @@ -99,8 +99,11 @@ class GCodeReader(MeshReader): count = len(path) line_types = numpy.empty((count - 1, 1), numpy.int32) line_widths = numpy.empty((count - 1, 1), numpy.float32) + line_thicknesses = numpy.empty((count - 1, 1), numpy.float32) # TODO: need to calculate actual line width based on E values line_widths[:, 0] = 0.4 + # TODO: need to calculate actual line heights + line_thicknesses[:, 0] = 0.2 points = numpy.empty((count, 3), numpy.float32) i = 0 for point in path: @@ -113,7 +116,7 @@ class GCodeReader(MeshReader): line_widths[i - 1] = 0.2 i += 1 - this_poly = LayerPolygon(self._layer_data_builder, self._extruder, line_types, points, line_widths) + this_poly = LayerPolygon(self._extruder, line_types, points, line_widths, line_thicknesses) this_poly.buildCache() this_layer.polygons.append(this_poly) @@ -276,7 +279,10 @@ class GCodeReader(MeshReader): self._layer += 1 current_path.clear() - layer_mesh = self._layer_data_builder.build() + material_color_map = numpy.zeros((10, 4), dtype = numpy.float32) + material_color_map[0, :] = [0.0, 0.7, 0.9, 1.0] + material_color_map[1, :] = [0.7, 0.9, 0.0, 1.0] + layer_mesh = self._layer_data_builder.build(material_color_map) decorator = LayerDataDecorator.LayerDataDecorator() decorator.setLayerData(layer_mesh) scene_node.addDecorator(decorator) From 0c9b9a3033cfe7e110103db15ce9acd7ec5a5b8a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Thu, 9 Feb 2017 17:34:51 +0100 Subject: [PATCH 118/156] Add fallback name property in PrinterOutputDevice It'll call this property, which gives an empty string, if the device doesn't implement giving a name. Contributes to issue CURA-3161. --- cura/PrinterOutputDevice.py | 6 ++++++ plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/cura/PrinterOutputDevice.py b/cura/PrinterOutputDevice.py index 8f03bdff79..8a95748cf1 100644 --- a/cura/PrinterOutputDevice.py +++ b/cura/PrinterOutputDevice.py @@ -170,6 +170,12 @@ class PrinterOutputDevice(QObject, OutputDevice): def address(self): Logger.log("w", "address is not implemented by this output device.") + ## A human-readable name for the device. + @pyqtProperty(str, constant = True) + def name(self): + Logger.log("w", "name is not implemented by this output device.") + return "" + @pyqtProperty(str, notify = errorTextChanged) def errorText(self): return self._error_text diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 5790cdab77..7df3c7bf23 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -227,12 +227,12 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): def address(self): return self._properties.get(b"address", b"").decode("utf-8") - ## Name of the printer (as returned from the zeroConf properties) + ## Name of the printer (as returned from the ZeroConf properties) @pyqtProperty(str, constant = True) def name(self): return self._properties.get(b"name", b"").decode("utf-8") - ## Firmware version (as returned from the zeroConf properties) + ## Firmware version (as returned from the ZeroConf properties) @pyqtProperty(str, constant=True) def firmwareVersion(self): return self._properties.get(b"firmware_version", b"").decode("utf-8") From 45c045131baccacee688adf46ab366cc768b801e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 09:38:38 +0100 Subject: [PATCH 119/156] Fix rendering pre-heat button text twice It was rendered by the button and again by the style for the button. I'm just using the style since it has the proper styling. Thanks, fieldOfView. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 8ce094cbd3..db58927cfa 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -328,7 +328,6 @@ Column Button //The pre-heat button. { id: preheatButton - text: preheatCountdownTimer.running ? catalog.i18nc("@button Cancel pre-heating", "Cancel") : catalog.i18nc("@button", "Pre-heat") tooltip: catalog.i18nc("@tooltip of pre-heat", "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print.") height: UM.Theme.getSize("setting_control").height enabled: @@ -438,7 +437,7 @@ Column } } font: UM.Theme.getFont("action_button") - text: control.text; + text: preheatCountdownTimer.running ? catalog.i18nc("@button Cancel pre-heating", "Cancel") : catalog.i18nc("@button", "Pre-heat") } } } From 4ce755021abb5b18053878ab32e626d7efa73fb6 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 11:11:39 +0100 Subject: [PATCH 120/156] Don't use printerConnected from Sidebar.qml We don't need it if we just check for connectedPrinter to not be null each time. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 38 +++++++++++++++++----------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index db58927cfa..b39cec34b2 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -12,7 +12,7 @@ import Cura 1.0 as Cura Column { id: printMonitor - property var connectedPrinter: printerConnected ? Cura.MachineManager.printerOutputDevices[0] : null + property var connectedPrinter: Cura.MachineManager.printerOutputDevices.length >= 1 ? Cura.MachineManager.printerOutputDevices[0] : null Cura.ExtrudersModel { @@ -30,7 +30,7 @@ Column Label { id: connectedPrinterNameLabel - text: printerConnected ? connectedPrinter.name : catalog.i18nc("@info:status", "No printer connected") + text: connectedPrinter != null ? connectedPrinter.name : catalog.i18nc("@info:status", "No printer connected") font: UM.Theme.getFont("large") color: UM.Theme.getColor("text") anchors.left: parent.left @@ -43,7 +43,7 @@ Column Label { id: connectedPrinterAddressLabel - text: (printerConnected && connectedPrinter.address != null) ? connectedPrinter.address : "" + text: (connectedPrinter != null && connectedPrinter.address != null) ? connectedPrinter.address : "" font: UM.Theme.getFont("small") color: UM.Theme.getColor("text_inactive") anchors.left: parent.left @@ -56,8 +56,8 @@ Column } Label { - text: printerConnected ? connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.") - color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") + text: connectedPrinter != null ? connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.") + color: connectedPrinter != null && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") font: UM.Theme.getFont("very_small") wrapMode: Text.WordWrap anchors.left: parent.left @@ -104,7 +104,7 @@ Column } Text //Temperature indication. { - text: printerConnected ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" + text: connectedPrinter != null ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" font: UM.Theme.getFont("large") anchors.right: parent.right anchors.rightMargin: UM.Theme.getSize("default_margin").width @@ -116,10 +116,10 @@ Column id: materialColor width: materialName.height * 0.75 height: materialName.height * 0.75 - color: printerConnected ? connectedPrinter.materialColors[index] : "#00000000" //Need to check for printerConnected or materialColors[index] gives an error. + color: connectedPrinter != null ? connectedPrinter.materialColors[index] : "#00000000" border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") - visible: printerConnected + visible: connectedPrinter != null anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.verticalCenter: materialName.verticalCenter @@ -127,7 +127,7 @@ Column Text //Material name. { id: materialName - text: printerConnected ? connectedPrinter.materialNames[index] : "" + text: connectedPrinter != null ? connectedPrinter.materialNames[index] : "" font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") anchors.left: materialColor.right @@ -137,7 +137,7 @@ Column } Text //Variant name. { - text: printerConnected ? connectedPrinter.hotendIds[index] : "" + text: connectedPrinter != null ? connectedPrinter.hotendIds[index] : "" font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") anchors.right: parent.right @@ -170,7 +170,7 @@ Column Text //Target temperature. { id: bedTargetTemperature - text: printerConnected ? connectedPrinter.targetBedTemperature + "°C" : "" + text: connectedPrinter != null ? connectedPrinter.targetBedTemperature + "°C" : "" font: UM.Theme.getFont("small") color: UM.Theme.getColor("text_inactive") anchors.right: parent.right @@ -180,7 +180,7 @@ Column Text //Current temperature. { id: bedCurrentTemperature - text: printerConnected ? connectedPrinter.bedTemperature + "°C" : "" + text: connectedPrinter != null ? connectedPrinter.bedTemperature + "°C" : "" font: UM.Theme.getFont("large") color: UM.Theme.getColor("text") anchors.right: bedTargetTemperature.left @@ -306,7 +306,7 @@ Column { preheatCountdown.visible = false; running = false; - if (printerConnected) + if (connectedPrinter != null) { connectedPrinter.cancelPreheatBed() } @@ -332,7 +332,7 @@ Column height: UM.Theme.getSize("setting_control").height enabled: { - if (!printerConnected) + if (!connectedPrinter != null) { return false; //Can't preheat if not connected. } @@ -484,19 +484,19 @@ Column { sourceComponent: monitorItem property string label: catalog.i18nc("@label", "Job Name") - property string value: printerConnected ? connectedPrinter.jobName : "" + property string value: connectedPrinter != null ? connectedPrinter.jobName : "" } Loader { sourceComponent: monitorItem property string label: catalog.i18nc("@label", "Printing Time") - property string value: printerConnected ? getPrettyTime(connectedPrinter.timeTotal) : "" + property string value: connectedPrinter != null ? getPrettyTime(connectedPrinter.timeTotal) : "" } Loader { sourceComponent: monitorItem property string label: catalog.i18nc("@label", "Estimated time left") - property string value: printerConnected ? getPrettyTime(connectedPrinter.timeTotal - connectedPrinter.timeElapsed) : "" + property string value: connectedPrinter != null ? getPrettyTime(connectedPrinter.timeTotal - connectedPrinter.timeElapsed) : "" } Component @@ -515,7 +515,7 @@ Column width: parent.width * 0.4 anchors.verticalCenter: parent.verticalCenter text: label - color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") + color: connectedPrinter != null && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") font: UM.Theme.getFont("default") elide: Text.ElideRight } @@ -524,7 +524,7 @@ Column width: parent.width * 0.6 anchors.verticalCenter: parent.verticalCenter text: value - color: printerConnected && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") + color: connectedPrinter != null && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") font: UM.Theme.getFont("default") elide: Text.ElideRight } From 17a03d777ca01dd0b0e69b15770c64f629c7ee8d Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 11:14:28 +0100 Subject: [PATCH 121/156] No longer use printerAcceptsCommands It's an external variable we don't need. Just ask the currently connected printer. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index b39cec34b2..7984cd59c5 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -57,7 +57,7 @@ Column Label { text: connectedPrinter != null ? connectedPrinter.connectionText : catalog.i18nc("@info:status", "The printer is not connected.") - color: connectedPrinter != null && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") + color: connectedPrinter != null && connectedPrinter.acceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") font: UM.Theme.getFont("very_small") wrapMode: Text.WordWrap anchors.left: parent.left @@ -515,7 +515,7 @@ Column width: parent.width * 0.4 anchors.verticalCenter: parent.verticalCenter text: label - color: connectedPrinter != null && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") + color: connectedPrinter != null && connectedPrinter.acceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") font: UM.Theme.getFont("default") elide: Text.ElideRight } @@ -524,7 +524,7 @@ Column width: parent.width * 0.6 anchors.verticalCenter: parent.verticalCenter text: value - color: connectedPrinter != null && printerAcceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") + color: connectedPrinter != null && connectedPrinter.acceptsCommands ? UM.Theme.getColor("setting_control_text") : UM.Theme.getColor("setting_control_disabled_text") font: UM.Theme.getFont("default") elide: Text.ElideRight } From 60812139b78c927b52b91c8264adaa8ff4bb7989 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 11:27:45 +0100 Subject: [PATCH 122/156] Use global margins instead of specific per cardinal direction Makes it a bit shorter. But also makes it use the width of the margins for vertical margin, which is unintuitive. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 31 +++++++++---------------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 7984cd59c5..6a78a23348 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -34,11 +34,8 @@ Column font: UM.Theme.getFont("large") color: UM.Theme.getColor("text") anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height - anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.margins: UM.Theme.getSize("default_margin").width } Label { @@ -46,12 +43,9 @@ Column text: (connectedPrinter != null && connectedPrinter.address != null) ? connectedPrinter.address : "" font: UM.Theme.getFont("small") color: UM.Theme.getColor("text_inactive") - anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width + anchors.margins: UM.Theme.getSize("default_margin").width horizontalAlignment: Text.AlignRight } Label @@ -98,18 +92,16 @@ Column text: machineExtruderCount.properties.value > 1 ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") color: UM.Theme.getColor("text") anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.margins: UM.Theme.getSize("default_margin").width } Text //Temperature indication. { text: connectedPrinter != null ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" font: UM.Theme.getFont("large") anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.margins: UM.Theme.getSize("default_margin").width } Rectangle //Material colour indication. { @@ -131,9 +123,8 @@ Column font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") anchors.left: materialColor.right - anchors.leftMargin: UM.Theme.getSize("setting_unit_margin").width anchors.bottom: parent.bottom - anchors.bottomMargin: UM.Theme.getSize("default_margin").height + anchors.margins: UM.Theme.getSize("default_margin").width } Text //Variant name. { @@ -141,9 +132,8 @@ Column font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width anchors.bottom: parent.bottom - anchors.bottomMargin: UM.Theme.getSize("default_margin").height + anchors.margins: UM.Theme.getSize("default_margin").width } } } @@ -163,9 +153,8 @@ Column font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") anchors.left: parent.left - anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.margins: UM.Theme.getSize("default_margin").width } Text //Target temperature. { @@ -184,9 +173,8 @@ Column font: UM.Theme.getFont("large") color: UM.Theme.getColor("text") anchors.right: bedTargetTemperature.left - anchors.rightMargin: UM.Theme.getSize("setting_unit_margin").width anchors.top: parent.top - anchors.topMargin: UM.Theme.getSize("default_margin").height + anchors.margins: UM.Theme.getSize("default_margin").width } Rectangle //Input field for pre-heat temperature. { @@ -359,9 +347,8 @@ Column return true; //Preconditions are met. } anchors.right: parent.right - anchors.rightMargin: UM.Theme.getSize("default_margin").width anchors.bottom: parent.bottom - anchors.bottomMargin: UM.Theme.getSize("default_margin").height + anchors.margins: UM.Theme.getSize("default_margin").width style: ButtonStyle { background: Rectangle { From 6ed0e81492c46f8c9291df0bd805aabcaf5e1d88 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 11:30:05 +0100 Subject: [PATCH 123/156] Remove unnecessary alignment It is single-line text and already aligned to the right side via the anchors. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 6a78a23348..29f3210c2d 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -46,7 +46,6 @@ Column anchors.top: parent.top anchors.right: parent.right anchors.margins: UM.Theme.getSize("default_margin").width - horizontalAlignment: Text.AlignRight } Label { From f6fe4f9fd306c10332854b19abaff46fed6b86bd Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 11:56:37 +0100 Subject: [PATCH 124/156] Use Label for all text, not just labels The fonts use better fallbacks if they fail to load for labels. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 29f3210c2d..7666c175d2 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -86,7 +86,7 @@ Column height: UM.Theme.getSize("sidebar_extruder_box").height Layout.fillWidth: index == machineExtruderCount.properties.value - 1 && index % 2 == 0 - Text //Extruder name. + Label //Extruder name. { text: machineExtruderCount.properties.value > 1 ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") color: UM.Theme.getColor("text") @@ -94,7 +94,7 @@ Column anchors.top: parent.top anchors.margins: UM.Theme.getSize("default_margin").width } - Text //Temperature indication. + Label //Temperature indication. { text: connectedPrinter != null ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" font: UM.Theme.getFont("large") @@ -115,7 +115,7 @@ Column anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.verticalCenter: materialName.verticalCenter } - Text //Material name. + Label //Material name. { id: materialName text: connectedPrinter != null ? connectedPrinter.materialNames[index] : "" @@ -125,7 +125,7 @@ Column anchors.bottom: parent.bottom anchors.margins: UM.Theme.getSize("default_margin").width } - Text //Variant name. + Label //Variant name. { text: connectedPrinter != null ? connectedPrinter.hotendIds[index] : "" font: UM.Theme.getFont("default") @@ -155,7 +155,7 @@ Column anchors.top: parent.top anchors.margins: UM.Theme.getSize("default_margin").width } - Text //Target temperature. + Label //Target temperature. { id: bedTargetTemperature text: connectedPrinter != null ? connectedPrinter.targetBedTemperature + "°C" : "" @@ -165,7 +165,7 @@ Column anchors.rightMargin: UM.Theme.getSize("default_margin").width anchors.bottom: bedCurrentTemperature.bottom } - Text //Current temperature. + Label //Current temperature. { id: bedCurrentTemperature text: connectedPrinter != null ? connectedPrinter.bedTemperature + "°C" : "" @@ -300,7 +300,7 @@ Column } } } - Text + Label { id: preheatCountdown text: "0:00" From be5b656ef7139309e2de662d7917ccafc2f96255 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 13:28:59 +0100 Subject: [PATCH 125/156] Hide extruder information when hotend/material is not provided This happens when there is no extruder in the machine or the machine simply doesn't provide enough information. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 7666c175d2..cf15973c11 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -96,7 +96,7 @@ Column } Label //Temperature indication. { - text: connectedPrinter != null ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" + text: (connectedPrinter != null && connectedPrinter.hotendTemperatures[index] != null) ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" font: UM.Theme.getFont("large") anchors.right: parent.right anchors.top: parent.top @@ -107,10 +107,10 @@ Column id: materialColor width: materialName.height * 0.75 height: materialName.height * 0.75 - color: connectedPrinter != null ? connectedPrinter.materialColors[index] : "#00000000" + color: (connectedPrinter != null && connectedPrinter.materialColors[index] != null) ? connectedPrinter.materialColors[index] : "#00000000" border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") - visible: connectedPrinter != null + visible: (connectedPrinter != null && connectedPrinter.materialColors[index] != null) anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.verticalCenter: materialName.verticalCenter @@ -118,7 +118,7 @@ Column Label //Material name. { id: materialName - text: connectedPrinter != null ? connectedPrinter.materialNames[index] : "" + text: (connectedPrinter != null && connectedPrinter.materialNames[index] != null) ? connectedPrinter.materialNames[index] : "" font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") anchors.left: materialColor.right @@ -127,7 +127,7 @@ Column } Label //Variant name. { - text: connectedPrinter != null ? connectedPrinter.hotendIds[index] : "" + text: (connectedPrinter != null && connectedPrinter.hotendIds[index] != null) ? connectedPrinter.hotendIds[index] : "" font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") anchors.right: parent.right From b3bd488c07bffec191a96dfdab564d176e2188ab Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 14:40:31 +0100 Subject: [PATCH 126/156] Use stylised tooltip for pre-heat button Took some figuring out, this one... But it works. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index cf15973c11..bead30d85b 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -315,7 +315,6 @@ Column Button //The pre-heat button. { id: preheatButton - tooltip: catalog.i18nc("@tooltip of pre-heat", "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print.") height: UM.Theme.getSize("setting_control").height enabled: { @@ -447,6 +446,22 @@ Column preheatCountdownTimer.update(); } } + + onHoveredChanged: + { + if (hovered) + { + base.showTooltip( + base, + {x: 0, y: preheatButton.mapToItem(base, 0, 0).y}, + catalog.i18nc("@tooltip of pre-heat", "Heat the bed in advance before printing. You can continue adjusting your print while it is heating, and you won't have to wait for the bed to heat up when you're ready to print.") + ); + } + else + { + base.hideTooltip(); + } + } } } From 2f8fc0518157065ecdac1c83411478015fcc7b9f Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 14:43:31 +0100 Subject: [PATCH 127/156] Fix button enabled state depending on printer connection I think I made a mistake when I removed one of the global variables here. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index bead30d85b..6e9eafaf78 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -318,7 +318,7 @@ Column height: UM.Theme.getSize("setting_control").height enabled: { - if (!connectedPrinter != null) + if (connectedPrinter == null) { return false; //Can't preheat if not connected. } From b69ec56f66fd0050f7d4bf60578887df97f9294a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 14:55:06 +0100 Subject: [PATCH 128/156] Make extruder name recover if it returns null If it returns null, you'd get an error that it can't assign [undefined] to a text field. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 6e9eafaf78..f088e49c85 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -88,7 +88,7 @@ Column Label //Extruder name. { - text: machineExtruderCount.properties.value > 1 ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") + text: (machineExtruderCount.properties.value > 1 && extrudersModel.getItem(index).name != null) ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") color: UM.Theme.getColor("text") anchors.left: parent.left anchors.top: parent.top From 6629c8d0cf3cbf296d237f65675877718cc147e3 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 15:27:32 +0100 Subject: [PATCH 129/156] Anchor last-row extruder box to left and right to stretch it Layout.fillwidth seems to only stretch the box to full width on the first row, but without it the entire thing doesn't stretch. Leaving the width out will make the entire left column stretch so that the right column is no longer visible. It's all a bit weird, this QML stuff. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index f088e49c85..8abc5ec2c4 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -85,6 +85,8 @@ Column width: extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2 height: UM.Theme.getSize("sidebar_extruder_box").height Layout.fillWidth: index == machineExtruderCount.properties.value - 1 && index % 2 == 0 + anchors.right: (index == machineExtruderCount.properties.value - 1 && index % 2 == 0) ? parent.right : undefined + anchors.left: (index == machineExtruderCount.properties.value - 1 && index % 2 == 0) ? parent.left : undefined Label //Extruder name. { From 440508f0025d2f35b01964b95294eb332034d4de Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 16:05:18 +0100 Subject: [PATCH 130/156] Don't display material if an unknown material is given This makes it more clear for the cases other than UM3. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 8abc5ec2c4..6f8345aae7 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -109,10 +109,10 @@ Column id: materialColor width: materialName.height * 0.75 height: materialName.height * 0.75 - color: (connectedPrinter != null && connectedPrinter.materialColors[index] != null) ? connectedPrinter.materialColors[index] : "#00000000" + color: (connectedPrinter != null && connectedPrinter.materialColors[index] != null && connectedPrinter.materialIds[index] != "") ? connectedPrinter.materialColors[index] : "#00000000" border.width: UM.Theme.getSize("default_lining").width border.color: UM.Theme.getColor("lining") - visible: (connectedPrinter != null && connectedPrinter.materialColors[index] != null) + visible: connectedPrinter != null && connectedPrinter.materialColors[index] != null && connectedPrinter.materialIds[index] != "" anchors.left: parent.left anchors.leftMargin: UM.Theme.getSize("default_margin").width anchors.verticalCenter: materialName.verticalCenter @@ -120,7 +120,7 @@ Column Label //Material name. { id: materialName - text: (connectedPrinter != null && connectedPrinter.materialNames[index] != null) ? connectedPrinter.materialNames[index] : "" + text: (connectedPrinter != null && connectedPrinter.materialNames[index] != null && connectedPrinter.materialIds[index] != "") ? connectedPrinter.materialNames[index] : "" font: UM.Theme.getFont("default") color: UM.Theme.getColor("text") anchors.left: materialColor.right From d3147a6e97f1bbc6b64d177e841b458734127264 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Fri, 10 Feb 2017 16:07:16 +0100 Subject: [PATCH 131/156] Add font for extruder name label This allows it to get stylised. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 6f8345aae7..686dd11e3a 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -92,6 +92,7 @@ Column { text: (machineExtruderCount.properties.value > 1 && extrudersModel.getItem(index).name != null) ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") color: UM.Theme.getColor("text") + font: UM.Them.getFont("default") anchors.left: parent.left anchors.top: parent.top anchors.margins: UM.Theme.getSize("default_margin").width From a3170041f8b70a3144e2cd676baf166dbad6aa70 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 13 Feb 2017 09:15:58 +0100 Subject: [PATCH 132/156] Fix typo of theme This was giving a warning that we couldn't get a font from undefined. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 686dd11e3a..7e3c4e4b45 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -92,7 +92,7 @@ Column { text: (machineExtruderCount.properties.value > 1 && extrudersModel.getItem(index).name != null) ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") color: UM.Theme.getColor("text") - font: UM.Them.getFont("default") + font: UM.Theme.getFont("default") anchors.left: parent.left anchors.top: parent.top anchors.margins: UM.Theme.getSize("default_margin").width From 2722ac5a8f93f50529bed24bb8931c9a13f2ee27 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 13 Feb 2017 09:32:16 +0100 Subject: [PATCH 133/156] Re-use repeater count instead of listening to machineExtruderCount everywhere Might be slightly more efficient and/or update stuff in the correct order. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 7e3c4e4b45..43f771296a 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -77,6 +77,7 @@ Column Repeater { + id: extrudersRepeater model: machineExtruderCount.properties.value delegate: Rectangle { @@ -84,13 +85,13 @@ Column color: UM.Theme.getColor("sidebar") width: extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2 height: UM.Theme.getSize("sidebar_extruder_box").height - Layout.fillWidth: index == machineExtruderCount.properties.value - 1 && index % 2 == 0 - anchors.right: (index == machineExtruderCount.properties.value - 1 && index % 2 == 0) ? parent.right : undefined - anchors.left: (index == machineExtruderCount.properties.value - 1 && index % 2 == 0) ? parent.left : undefined + Layout.fillWidth: index == extrudersRepeater.count - 1 && index % 2 == 0 + anchors.right: (index == extrudersRepeater.count - 1 && index % 2 == 0) ? parent.right : undefined + anchors.left: (index == extrudersRepeater.count - 1 && index % 2 == 0) ? parent.left : undefined Label //Extruder name. { - text: (machineExtruderCount.properties.value > 1 && extrudersModel.getItem(index).name != null) ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") + text: (extrudersRepeater.count > 1 && extrudersModel.getItem(index).name != null) ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") color: UM.Theme.getColor("text") font: UM.Theme.getFont("default") anchors.left: parent.left From c2c61c4331f3861225d0db5790ca1af30002c616 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 13 Feb 2017 09:35:09 +0100 Subject: [PATCH 134/156] Improve condition for extruder name fallback In effect this has no change. But semantically it is better: If there are no extruders or the extruders have no name, use 'hotend'. Otherwise use the available name. It has nothing to do with the amount of extruders. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 43f771296a..9865f94232 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -91,7 +91,7 @@ Column Label //Extruder name. { - text: (extrudersRepeater.count > 1 && extrudersModel.getItem(index).name != null) ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") + text: (extrudersModel.getItem(index) != null && extrudersModel.getItem(index).name != null) ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") color: UM.Theme.getColor("text") font: UM.Theme.getFont("default") anchors.left: parent.left From 40f32449c6d3747755b3d3193fa59174d694116e Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 13 Feb 2017 09:38:02 +0100 Subject: [PATCH 135/156] Remove unnecessary watched properties from machineExtruderCount Since we don't change the colour of the input box right now, we won't need the warning values. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 9865f94232..c10fd03464 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -474,7 +474,7 @@ Column id: bedTemperature containerStackId: Cura.MachineManager.activeMachineId key: "material_bed_temperature" - watchedProperties: ["value", "minimum_value", "maximum_value", "minimum_value_warning", "maximum_value_warning", "resolve"] + watchedProperties: ["value", "minimum_value", "maximum_value", "resolve"] storeIndex: 0 property var resolve: Cura.MachineManager.activeStackId != Cura.MachineManager.activeMachineId ? properties.resolve : "None" From 7000717f6e2f5a6cd1c061d59bdffae3baaf152e Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 13 Feb 2017 09:58:33 +0100 Subject: [PATCH 136/156] Fixed warning non-NOTIFYable properties, added signals for propertiesChanged. CURA-3273 --- plugins/LayerView/LayerView.py | 6 +++++- plugins/LayerView/LayerViewProxy.py | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/LayerView/LayerView.py b/plugins/LayerView/LayerView.py index c75c2eac0c..77c17a0aea 100644 --- a/plugins/LayerView/LayerView.py +++ b/plugins/LayerView/LayerView.py @@ -263,6 +263,7 @@ class LayerView(View): maxLayersChanged = Signal() currentLayerNumChanged = Signal() globalStackChanged = Signal() + preferencesChanged = Signal() ## Hackish way to ensure the proxy is already created, which ensures that the layerview.qml is already created # as this caused some issues. @@ -370,13 +371,16 @@ class LayerView(View): self._top_layers_job = None def _onPreferencesChanged(self, preference): - if preference not in {"view/top_layer_count", "view/only_show_top_layers", "view/compatibility_mode"}: + if preference not in {"view/top_layer_count", "view/only_show_top_layers", "view/force_layer_view_compatibility_mode"}: return self._solid_layers = int(Preferences.getInstance().getValue("view/top_layer_count")) self._only_show_top_layers = bool(Preferences.getInstance().getValue("view/only_show_top_layers")) + self._compatibility_mode = OpenGLContext.isLegacyOpenGL() or bool( + Preferences.getInstance().getValue("view/force_layer_view_compatibility_mode")) self._startUpdateTopLayers() + self.preferencesChanged.emit() def _getLegendItems(self): if self._legend_items is None: diff --git a/plugins/LayerView/LayerViewProxy.py b/plugins/LayerView/LayerViewProxy.py index d386b53d01..b3a1cca87d 100644 --- a/plugins/LayerView/LayerViewProxy.py +++ b/plugins/LayerView/LayerViewProxy.py @@ -17,6 +17,7 @@ class LayerViewProxy(QObject): maxLayersChanged = pyqtSignal() activityChanged = pyqtSignal() globalStackChanged = pyqtSignal() + preferencesChanged = pyqtSignal() @pyqtProperty(bool, notify = activityChanged) def getLayerActivity(self): @@ -52,7 +53,7 @@ class LayerViewProxy(QObject): return False - @pyqtProperty(bool) + @pyqtProperty(bool, notify = preferencesChanged) def compatibilityMode(self): active_view = self._controller.getActiveView() if type(active_view) == LayerView.LayerView.LayerView: @@ -157,6 +158,9 @@ class LayerViewProxy(QObject): def _onGlobalStackChanged(self): self.globalStackChanged.emit() + def _onPreferencesChanged(self): + self.preferencesChanged.emit() + def _onActiveViewChanged(self): active_view = self._controller.getActiveView() if type(active_view) == LayerView.LayerView.LayerView: @@ -164,3 +168,4 @@ class LayerViewProxy(QObject): active_view.maxLayersChanged.connect(self._onMaxLayersChanged) active_view.busyChanged.connect(self._onBusyChanged) active_view.globalStackChanged.connect(self._onGlobalStackChanged) + active_view.preferencesChanged.connect(self._onPreferencesChanged) From adbcd874a84d831d7c9028e918382d20be95815a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 13 Feb 2017 11:52:46 +0100 Subject: [PATCH 137/156] Add SettingPropertyProvider for machineExtruderCount here too It's not necessary, but this keeps it more localised. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index c10fd03464..ac7297b4ab 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -480,6 +480,14 @@ Column property var resolve: Cura.MachineManager.activeStackId != Cura.MachineManager.activeMachineId ? properties.resolve : "None" } + UM.SettingPropertyProvider + { + id: machineExtruderCount + containerStackId: Cura.MachineManager.activeMachineId + key: "machine_extruder_count" + watchedProperties: ["value"] + } + Loader { sourceComponent: monitorSection From 77f07bbc1d3f921613d99470ffadf3dded5ad622 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 13 Feb 2017 11:54:12 +0100 Subject: [PATCH 138/156] Use Flow for extruder boxes instead of GridLayout Flow makes things a lot more simple with the double-width item at the bottom. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index ac7297b4ab..93cbaafffb 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -67,27 +67,23 @@ Column width: parent.width height: childrenRect.height - GridLayout + Flow { id: extrudersGrid - columns: 2 - columnSpacing: UM.Theme.getSize("sidebar_lining_thin").width - rowSpacing: UM.Theme.getSize("sidebar_lining_thin").height + spacing: UM.Theme.getSize("sidebar_lining_thin").width width: parent.width Repeater { id: extrudersRepeater model: machineExtruderCount.properties.value + delegate: Rectangle { id: extruderRectangle color: UM.Theme.getColor("sidebar") - width: extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2 + width: index == machineExtruderCount.properties.value - 1 && index % 2 == 0 ? extrudersGrid.width : extrudersGrid.width / 2 - UM.Theme.getSize("sidebar_lining_thin").width / 2 height: UM.Theme.getSize("sidebar_extruder_box").height - Layout.fillWidth: index == extrudersRepeater.count - 1 && index % 2 == 0 - anchors.right: (index == extrudersRepeater.count - 1 && index % 2 == 0) ? parent.right : undefined - anchors.left: (index == extrudersRepeater.count - 1 && index % 2 == 0) ? parent.left : undefined Label //Extruder name. { From 34dccfd6a63fba57b872c68891b49a36000e41fc Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 13 Feb 2017 11:57:01 +0100 Subject: [PATCH 139/156] Fix updating extruder names on machine switch The extruder name is asked from the extruder manager, so that the signal from extruder manager properly updates it once the new name is available. Contributes to issue CURA-3161. --- cura/Settings/ExtruderManager.py | 10 ++++++++++ resources/qml/PrintMonitor.qml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/cura/Settings/ExtruderManager.py b/cura/Settings/ExtruderManager.py index 81579f74d0..77e8683e06 100644 --- a/cura/Settings/ExtruderManager.py +++ b/cura/Settings/ExtruderManager.py @@ -103,6 +103,16 @@ class ExtruderManager(QObject): def activeExtruderIndex(self): return self._active_extruder_index + ## Gets the extruder name of an extruder of the currently active machine. + # + # \param index The index of the extruder whose name to get. + @pyqtSlot(int, result = str) + def getExtruderName(self, index): + try: + return list(self.getActiveExtruderStacks())[index].getName() + except IndexError: + return "" + def getActiveExtruderStack(self): global_container_stack = UM.Application.getInstance().getGlobalContainerStack() if global_container_stack: diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 93cbaafffb..7c220ab7a2 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -87,7 +87,7 @@ Column Label //Extruder name. { - text: (extrudersModel.getItem(index) != null && extrudersModel.getItem(index).name != null) ? extrudersModel.getItem(index).name : catalog.i18nc("@label", "Hotend") + text: ExtruderManager.getExtruderName(index) != "" ? ExtruderManager.getExtruderName(index) : catalog.i18nc("@label", "Hotend") color: UM.Theme.getColor("text") font: UM.Theme.getFont("default") anchors.left: parent.left From 2724af7508208a8e5119a1f48b3deaf1e020e54c Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Mon, 13 Feb 2017 12:01:27 +0100 Subject: [PATCH 140/156] Add lining between bottom of extruders and build plate boxes Using margins for this is not applicable since it was the background of the rectangle around the flow that has the correct lining colour. So this is manually adding a line. Contributes to issue CURA-3161. --- resources/qml/PrintMonitor.qml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 7c220ab7a2..7a150a1757 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -139,6 +139,13 @@ Column } } + Rectangle + { + color: UM.Theme.getColor("sidebar_lining") + width: parent.width + height: UM.Theme.getSize("sidebar_lining_thin").width + } + Rectangle { color: UM.Theme.getColor("sidebar") From 106cb6ded9cd4e4fff9c2c19283105ef8cc1ff59 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 13 Feb 2017 12:47:04 +0100 Subject: [PATCH 141/156] Fixed compatibility mode. CURA-3273 --- cura/LayerDataBuilder.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cura/LayerDataBuilder.py b/cura/LayerDataBuilder.py index 1de2302f77..428ad4a210 100644 --- a/cura/LayerDataBuilder.py +++ b/cura/LayerDataBuilder.py @@ -63,8 +63,8 @@ class LayerDataBuilder(MeshBuilder): line_dimensions = numpy.empty((vertex_count, 2), numpy.float32) colors = numpy.empty((vertex_count, 4), numpy.float32) indices = numpy.empty((index_count, 2), numpy.int32) - extruders = numpy.empty((vertex_count), numpy.int32) - line_types = numpy.empty((vertex_count), numpy.int32) + extruders = numpy.empty((vertex_count), numpy.float32) + line_types = numpy.empty((vertex_count), numpy.float32) vertex_offset = 0 index_offset = 0 From 488b952815f9ffe7be861e8e051dc89ead5efaf7 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Mon, 13 Feb 2017 13:21:30 +0100 Subject: [PATCH 142/156] Fix 4.1 shader for line types. CURA-3273 --- plugins/LayerView/layers.shader | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/LayerView/layers.shader b/plugins/LayerView/layers.shader index cc25134216..840c3f25ba 100644 --- a/plugins/LayerView/layers.shader +++ b/plugins/LayerView/layers.shader @@ -78,8 +78,8 @@ vertex41core = uniform lowp float u_shade_factor; uniform highp int u_layer_view_type; - in highp int a_extruder; - in highp int a_line_type; + in highp float a_extruder; + in highp float a_line_type; in highp vec4 a_vertex; in lowp vec4 a_color; in lowp vec4 a_material_color; From 8d7b813318d8a6f552d7c5bfa362ca384c1d50cd Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 13 Feb 2017 13:26:36 +0100 Subject: [PATCH 143/156] All good 20x http replies are now accepted --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 7df3c7bf23..2b2f24e5fd 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -1022,7 +1022,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): self._progress_message.hide() elif reply.operation() == QNetworkAccessManager.PutOperation: - if status_code == 204: + if status_code in [200, 201, 202, 204]: pass # Request was successful! else: Logger.log("d", "Something went wrong when trying to update data of API (%s). Message: %s Statuscode: %s", reply_url, reply.readAll(), status_code) From 6deaf5bd6523b781d523833a41fae581ef7fcaa9 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 13 Feb 2017 13:28:32 +0100 Subject: [PATCH 144/156] Failure logging for network printing is now more explicit (also prints what the operation was) --- .../UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 2b2f24e5fd..1c8426c053 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -1025,7 +1025,17 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): if status_code in [200, 201, 202, 204]: pass # Request was successful! else: - Logger.log("d", "Something went wrong when trying to update data of API (%s). Message: %s Statuscode: %s", reply_url, reply.readAll(), status_code) + operation_type = "Unknown" + if reply.operation() == QNetworkAccessManager.GetOperation: + operation_type = "Get" + elif reply.operation() == QNetworkAccessManager.PutOperation: + operation_type = "Put" + elif reply.operation() == QNetworkAccessManager.PostOperation: + operation_type = "Post" + elif reply.operation() == QNetworkAccessManager.DeleteOperation: + operation_type = "Delete" + + Logger.log("d", "Something went wrong when trying to update data of API (%s). Message: %s Statuscode: %s, operation: %s", reply_url, reply.readAll(), status_code, operation_type) else: Logger.log("d", "NetworkPrinterOutputDevice got an unhandled operation %s", reply.operation()) From f62030dae5e9e30979634b6ed1ae2749d3c8d438 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 13 Feb 2017 13:30:51 +0100 Subject: [PATCH 145/156] setTargetBed temperature now directly sets target temp This is instead of sending /bed/temperature a json which contains target & temp as keyvalue. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 1c8426c053..ea15fc597e 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -276,8 +276,8 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): def _setTargetBedTemperature(self, temperature): if self._target_bed_temperature == temperature: return - url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/temperature") - data = """{"target": "%i"}""" % temperature + url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/temperature/target") + data = str(temperature) put_request = QNetworkRequest(url) put_request.setHeader(QNetworkRequest.ContentTypeHeader, "application/json") self._manager.put(put_request, data.encode()) From cc396d535777b263d441c788113ba2c479251d5c Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Mon, 13 Feb 2017 14:16:22 +0100 Subject: [PATCH 146/156] Fixed target temp never updating --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index ea15fc597e..18229f9d2d 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -276,6 +276,9 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): def _setTargetBedTemperature(self, temperature): if self._target_bed_temperature == temperature: return + self._target_bed_temperature = temperature + self.targetBedTemperatureChanged.emit() + url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/temperature/target") data = str(temperature) put_request = QNetworkRequest(url) From 25fb3fed162e629485048b4384bc3aa997f678bd Mon Sep 17 00:00:00 2001 From: fieldOfView Date: Tue, 14 Feb 2017 10:38:33 +0100 Subject: [PATCH 147/156] Add missing label color One of the labels in the newly redesigned printmonitor is lacking a color, thus making the hotend temperature unstylable. --- resources/qml/PrintMonitor.qml | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/qml/PrintMonitor.qml b/resources/qml/PrintMonitor.qml index 7a150a1757..6fffa0f902 100644 --- a/resources/qml/PrintMonitor.qml +++ b/resources/qml/PrintMonitor.qml @@ -97,6 +97,7 @@ Column Label //Temperature indication. { text: (connectedPrinter != null && connectedPrinter.hotendTemperatures[index] != null) ? Math.round(connectedPrinter.hotendTemperatures[index]) + "°C" : "" + color: UM.Theme.getColor("text") font: UM.Theme.getFont("large") anchors.right: parent.right anchors.top: parent.top From cb400f02573bbe9bacf334decd63db10e03b00fd Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Tue, 14 Feb 2017 13:36:03 +0100 Subject: [PATCH 148/156] Fix for a recent merge problem. --- cura/PrintInformation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cura/PrintInformation.py b/cura/PrintInformation.py index 10e15a5549..b88613b0ac 100644 --- a/cura/PrintInformation.py +++ b/cura/PrintInformation.py @@ -7,7 +7,7 @@ from UM.FlameProfiler import pyqtSlot from UM.Application import Application from UM.Qt.Duration import Duration from UM.Preferences import Preferences -from UM.Settings import ContainerRegistry +from UM.Settings.ContainerRegistry import ContainerRegistry from cura.Settings.ExtruderManager import ExtruderManager From 4928c919428249e9b73e2536d425168c0464cd6f Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Tue, 14 Feb 2017 13:47:37 +0100 Subject: [PATCH 149/156] Make run_mypy.py slightly more cross platform. --- run_mypy.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/run_mypy.py b/run_mypy.py index 24c9d3ae31..25ab54c0bf 100644 --- a/run_mypy.py +++ b/run_mypy.py @@ -21,7 +21,10 @@ def findModules(path): return result def main(): - os.putenv("MYPYPATH", r".;.\plugins;.\plugins\VersionUpgrade;..\Uranium_hint\;..\Uranium_hint\stubs\\" ) + if sys.platform == "win32": + os.putenv("MYPYPATH", r".;.\plugins;.\plugins\VersionUpgrade;..\Uranium\;..\Uranium\stubs\\" ) + else: + os.putenv("MYPYPATH", r".:./plugins:./plugins/VersionUpgrade:../Uranium/:../Uranium\stubs/") # Mypy really needs to be run via its Python script otherwise it can't find its data files. mypyExe = where("mypy.bat" if sys.platform == "win32" else "mypy") From 5055c534c5c31f60ef046cc04c6333cdba21979a Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 14 Feb 2017 16:57:21 +0100 Subject: [PATCH 150/156] Fix links to ContainerRegistry ContainerRegistry is no longer exposed in UM.Settings.__init__, so we must dig the class up from inside the module. Contributes to issue CURA-2917. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 6 +++--- plugins/UltimakerMachineActions/UMOUpgradeSelection.py | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 91b1df0f95..60e1c51ae8 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -8,7 +8,7 @@ from UM.Signal import signalemitter from UM.Message import Message -import UM.Settings +import UM.Settings.ContainerRegistry import UM.Version #To compare firmware version numbers. from cura.PrinterOutputDevice import PrinterOutputDevice, ConnectionState @@ -633,7 +633,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): remote_material_guid, material.getMetaDataEntry("GUID")) - remote_materials = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material", GUID = remote_material_guid, read_only = True) + remote_materials = UM.Settings.ContainerRegistry.ContainerRegistry.getInstance().findInstanceContainers(type = "material", GUID = remote_material_guid, read_only = True) remote_material_name = "Unknown" if remote_materials: remote_material_name = remote_materials[0].getName() @@ -824,7 +824,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): ## Send all material profiles to the printer. def sendMaterialProfiles(self): - for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material"): + for container in UM.Settings.ContainerRegistry.ContainerRegistry.getInstance().findInstanceContainers(type = "material"): try: xml_data = container.serialize() if xml_data == "" or xml_data is None: diff --git a/plugins/UltimakerMachineActions/UMOUpgradeSelection.py b/plugins/UltimakerMachineActions/UMOUpgradeSelection.py index 2b76aa138f..238a13bf61 100644 --- a/plugins/UltimakerMachineActions/UMOUpgradeSelection.py +++ b/plugins/UltimakerMachineActions/UMOUpgradeSelection.py @@ -1,3 +1,6 @@ +# Copyright (c) 2017 Ultimaker B.V. +# Uranium is released under the terms of the AGPLv3 or higher. + from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.InstanceContainer import InstanceContainer from cura.MachineAction import MachineAction @@ -47,7 +50,7 @@ class UMOUpgradeSelection(MachineAction): definition_changes_container.setDefinition(definition) definition_changes_container.addMetaDataEntry("type", "definition_changes") - UM.Settings.ContainerRegistry.getInstance().addContainer(definition_changes_container) + UM.Settings.ContainerRegistry.ContainerRegistry.getInstance().addContainer(definition_changes_container) # Insert definition_changes between the definition and the variant global_container_stack.insertContainer(-1, definition_changes_container) From b488441d81f7ee898982b273877c85f37b51427b Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 14 Feb 2017 17:00:33 +0100 Subject: [PATCH 151/156] Fix link to ContainerRegistry This one was forgotten because it is in a comment. Contributes to issue CURA-2917. --- plugins/XmlMaterialProfile/XmlMaterialProfile.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/XmlMaterialProfile/XmlMaterialProfile.py b/plugins/XmlMaterialProfile/XmlMaterialProfile.py index 24a545bbd3..ccc0dad08e 100644 --- a/plugins/XmlMaterialProfile/XmlMaterialProfile.py +++ b/plugins/XmlMaterialProfile/XmlMaterialProfile.py @@ -1,4 +1,4 @@ -# Copyright (c) 2016 Ultimaker B.V. +# Copyright (c) 2017 Ultimaker B.V. # Cura is released under the terms of the AGPLv3 or higher. import copy @@ -86,7 +86,7 @@ class XmlMaterialProfile(InstanceContainer): # super().setProperty(key, property_name, property_value) # # basefile = self.getMetaDataEntry("base_file", self._id) #if basefile is self.id, this is a basefile. - # for container in UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): + # for container in UM.Settings.ContainerRegistry.ContainerRegistry.getInstance().findInstanceContainers(base_file = basefile): # if not container.isReadOnly(): # container.setDirty(True) From 42982b7a861f2eec2260300e0de935b1bbffb0c8 Mon Sep 17 00:00:00 2001 From: Ghostkeeper Date: Tue, 14 Feb 2017 17:03:37 +0100 Subject: [PATCH 152/156] Fix link to UM.Version.Version The Version object is no longer exposed via UM.__init__, so we have to dig inside the UM.Version module to get it. Contributes to issue CURA-2917. --- plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py index 60e1c51ae8..fbe8eb884d 100644 --- a/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py +++ b/plugins/UM3NetworkPrinting/NetworkPrinterOutputDevice.py @@ -251,7 +251,7 @@ class NetworkPrinterOutputDevice(PrinterOutputDevice): def preheatBed(self, temperature, duration): temperature = round(temperature) #The API doesn't allow floating point. duration = round(duration) - if UM.Version(self.firmwareVersion) < UM.Version("3.5.92"): #Real bed pre-heating support is implemented from 3.5.92 and up. + if UM.Version.Version(self.firmwareVersion) < UM.Version.Version("3.5.92"): #Real bed pre-heating support is implemented from 3.5.92 and up. self.setTargetBedTemperature(temperature = temperature) #No firmware-side duration support then. return url = QUrl("http://" + self._address + self._api_prefix + "printer/bed/pre_heat") From 60d4e6e4fd553dc9cce471d5b78eb8132f7cfc17 Mon Sep 17 00:00:00 2001 From: Simon Edwards Date: Wed, 15 Feb 2017 08:53:18 +0100 Subject: [PATCH 153/156] Make the run_mypy.py script find Uranium via the PYTHONPATH env var. --- run_mypy.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/run_mypy.py b/run_mypy.py index 25ab54c0bf..88adea8db9 100644 --- a/run_mypy.py +++ b/run_mypy.py @@ -4,8 +4,7 @@ import sys import subprocess # A quick Python implementation of unix 'where' command. -def where(exeName): - searchPath = os.getenv("PATH") +def where(exeName, searchPath=os.getenv("PATH")): paths = searchPath.split(";" if sys.platform == "win32" else ":") for path in paths: candidatePath = os.path.join(path, exeName) @@ -21,10 +20,18 @@ def findModules(path): return result def main(): + # Find Uranium via the PYTHONPATH var + uraniumUMPath = where("UM", os.getenv("PYTHONPATH")) + if uraniumUMPath is None: + uraniumUMPath = os.path.join("..", "Uranium") + uraniumPath = os.path.dirname(uraniumUMPath) + + mypyPathParts = [".", os.path.join(".", "plugins"), os.path.join(".", "plugins", "VersionUpgrade"), + uraniumPath, os.path.join(uraniumPath, "stubs")] if sys.platform == "win32": - os.putenv("MYPYPATH", r".;.\plugins;.\plugins\VersionUpgrade;..\Uranium\;..\Uranium\stubs\\" ) + os.putenv("MYPYPATH", ";".join(mypyPathParts)) else: - os.putenv("MYPYPATH", r".:./plugins:./plugins/VersionUpgrade:../Uranium/:../Uranium\stubs/") + os.putenv("MYPYPATH", ":".join(mypyPathParts)) # Mypy really needs to be run via its Python script otherwise it can't find its data files. mypyExe = where("mypy.bat" if sys.platform == "win32" else "mypy") From 9e973732f56678506a9ba9730ce59a52a51d18cb Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 15 Feb 2017 10:50:21 +0100 Subject: [PATCH 154/156] Fixed remember coloring type in Layer View. CURA-3273 --- plugins/LayerView/LayerView.qml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/LayerView/LayerView.qml b/plugins/LayerView/LayerView.qml index ac85d6ccb2..7713b796a9 100644 --- a/plugins/LayerView/LayerView.qml +++ b/plugins/LayerView/LayerView.qml @@ -187,6 +187,9 @@ Item UM.LayerView.disableLegend(); } } + onModelChanged: { + currentIndex = UM.LayerView.getLayerViewType(); + } } Label From ce226ebbeaaebaacb114b4b1e78fd9a3f578d7d6 Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 15 Feb 2017 11:35:49 +0100 Subject: [PATCH 155/156] Fix layerview checkboxes. CURA-3273 --- plugins/LayerView/layers3d.shader | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/LayerView/layers3d.shader b/plugins/LayerView/layers3d.shader index c63bdac7d9..0f0301dbc9 100644 --- a/plugins/LayerView/layers3d.shader +++ b/plugins/LayerView/layers3d.shader @@ -16,8 +16,8 @@ vertex41core = in lowp vec4 a_material_color; in highp vec4 a_normal; in highp vec2 a_line_dim; // line width and thickness - in highp int a_extruder; - in highp int a_line_type; + in highp int a_extruder; // Note: cannot use this in compatibility, int is only available in newer OpenGL. + in highp float a_line_type; out lowp vec4 v_color; @@ -26,7 +26,7 @@ vertex41core = out lowp vec2 v_line_dim; out highp int v_extruder; out highp vec4 v_extruder_opacity; - out int v_line_type; + out float v_line_type; out lowp vec4 f_color; out highp vec3 f_vertex; @@ -82,7 +82,7 @@ geometry41core = in vec2 v_line_dim[]; in int v_extruder[]; in vec4 v_extruder_opacity[]; - in int v_line_type[]; + in float v_line_type[]; out vec4 f_color; out vec3 f_normal; From aab17608ff4cab909ea5cf3f6acd5bd9d6f9b26f Mon Sep 17 00:00:00 2001 From: Jack Ha Date: Wed, 15 Feb 2017 11:53:20 +0100 Subject: [PATCH 156/156] Fixed shader bugs, lines are now nice and smooth again. CURA-3273 --- plugins/LayerView/layers3d.shader | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/LayerView/layers3d.shader b/plugins/LayerView/layers3d.shader index 0f0301dbc9..d968852c71 100644 --- a/plugins/LayerView/layers3d.shader +++ b/plugins/LayerView/layers3d.shader @@ -164,7 +164,7 @@ geometry41core = // left side myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); - myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz)); + myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_vert)); myEmitVertex(v_vertex[0], v_color[0], g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[0].gl_Position + g_vertex_offset_horz_head)); myEmitVertex(v_vertex[0], v_color[0], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[0].gl_Position - g_vertex_offset_horz)); @@ -188,7 +188,7 @@ geometry41core = myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz)); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_vert, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_vert)); myEmitVertex(v_vertex[1], v_color[1], -g_vertex_normal_horz_head, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz_head)); - myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position - g_vertex_offset_horz)); + myEmitVertex(v_vertex[1], v_color[1], g_vertex_normal_horz, u_viewProjectionMatrix * (gl_in[1].gl_Position + g_vertex_offset_horz)); EndPrimitive(); }