From 3b70e5eb6bcbab6da11f6864b85a6a23ae0ccc30 Mon Sep 17 00:00:00 2001 From: Jaime van Kessel Date: Thu, 27 Sep 2018 20:01:55 +0200 Subject: [PATCH] Fix typing For some reason, my MyPy started acting up once I started using the PythonPath while calling it. --- cura/CuraApplication.py | 6 + .../Models/SettingVisibilityPresetsModel.py | 8 +- cura/Machines/QualityManager.py | 6 +- cura/OAuth2/AuthorizationHelpers.py | 4 +- cura/OAuth2/Models.py | 2 +- cura/Scene/ConvexHullDecorator.py | 135 ++++++++++-------- cura/Settings/ContainerManager.py | 7 +- cura/Settings/MachineManager.py | 2 +- plugins/SimulationView/SimulationView.py | 41 +++--- 9 files changed, 120 insertions(+), 91 deletions(-) diff --git a/cura/CuraApplication.py b/cura/CuraApplication.py index 5ff4161fea..04c9ea88db 100755 --- a/cura/CuraApplication.py +++ b/cura/CuraApplication.py @@ -61,6 +61,7 @@ from cura.Scene.CuraSceneController import CuraSceneController from UM.Settings.SettingDefinition import SettingDefinition, DefinitionPropertyType from UM.Settings.ContainerRegistry import ContainerRegistry from UM.Settings.SettingFunction import SettingFunction +from cura.Settings.CuraContainerRegistry import CuraContainerRegistry from cura.Settings.MachineNameValidator import MachineNameValidator from cura.Machines.Models.BuildPlateModel import BuildPlateModel @@ -242,6 +243,8 @@ class CuraApplication(QtApplication): from cura.Settings.CuraContainerRegistry import CuraContainerRegistry self._container_registry_class = CuraContainerRegistry + # Redefined here in order to please the typing. + self._container_registry = None # type: CuraContainerRegistry from cura.CuraPackageManager import CuraPackageManager self._package_manager_class = CuraPackageManager @@ -266,6 +269,9 @@ class CuraApplication(QtApplication): help = "FOR TESTING ONLY. Trigger an early crash to show the crash dialog.") self._cli_parser.add_argument("file", nargs = "*", help = "Files to load after starting the application.") + def getContainerRegistry(self) -> "CuraContainerRegistry": + return self._container_registry + def parseCliOptions(self): super().parseCliOptions() diff --git a/cura/Machines/Models/SettingVisibilityPresetsModel.py b/cura/Machines/Models/SettingVisibilityPresetsModel.py index d5fa51d20a..7e098197a9 100644 --- a/cura/Machines/Models/SettingVisibilityPresetsModel.py +++ b/cura/Machines/Models/SettingVisibilityPresetsModel.py @@ -1,7 +1,7 @@ # Copyright (c) 2018 Ultimaker B.V. # Cura is released under the terms of the LGPLv3 or higher. -from typing import Optional +from typing import Optional, List, Dict, Union import os import urllib.parse from configparser import ConfigParser @@ -60,7 +60,7 @@ class SettingVisibilityPresetsModel(ListModel): def _populate(self) -> None: from cura.CuraApplication import CuraApplication - items = [] + items = [] # type: List[Dict[str, Union[str, int, List[str]]]] for file_path in Resources.getAllResourcesOfType(CuraApplication.ResourceTypes.SettingVisibilityPreset): try: mime_type = MimeTypeDatabase.getMimeTypeForFile(file_path) @@ -79,7 +79,7 @@ class SettingVisibilityPresetsModel(ListModel): if not parser.has_option("general", "name") or not parser.has_option("general", "weight"): continue - settings = [] + settings = [] # type: List[str] for section in parser.sections(): if section == 'general': continue @@ -98,7 +98,7 @@ class SettingVisibilityPresetsModel(ListModel): except Exception: Logger.logException("e", "Failed to load setting preset %s", file_path) - items.sort(key = lambda k: (int(k["weight"]), k["id"])) + items.sort(key = lambda k: (int(k["weight"]), k["id"])) # type: ignore # Put "custom" at the top items.insert(0, {"id": "custom", "name": "Custom selection", diff --git a/cura/Machines/QualityManager.py b/cura/Machines/QualityManager.py index 21abb5a9cc..d924f4c83e 100644 --- a/cura/Machines/QualityManager.py +++ b/cura/Machines/QualityManager.py @@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, Optional, cast, Dict, List from PyQt5.QtCore import QObject, QTimer, pyqtSignal, pyqtSlot from UM.Application import Application + from UM.ConfigurationErrorMessage import ConfigurationErrorMessage from UM.Logger import Logger from UM.Util import parseBool @@ -40,7 +41,8 @@ class QualityManager(QObject): def __init__(self, container_registry: "ContainerRegistry", parent = None) -> None: super().__init__(parent) - self._application = Application.getInstance() # type: CuraApplication + from cura.CuraApplication import CuraApplication + self._application = CuraApplication.getInstance() # type: CuraApplication self._material_manager = self._application.getMaterialManager() self._container_registry = container_registry @@ -458,7 +460,7 @@ class QualityManager(QObject): # stack and clear the user settings. @pyqtSlot(str) def createQualityChanges(self, base_name: str) -> None: - machine_manager = Application.getInstance().getMachineManager() + machine_manager = CuraApplication.getInstance().getMachineManager() global_stack = machine_manager.activeMachine if not global_stack: diff --git a/cura/OAuth2/AuthorizationHelpers.py b/cura/OAuth2/AuthorizationHelpers.py index 4d485b3bda..6cb53d2252 100644 --- a/cura/OAuth2/AuthorizationHelpers.py +++ b/cura/OAuth2/AuthorizationHelpers.py @@ -36,7 +36,7 @@ class AuthorizationHelpers: "code": authorization_code, "code_verifier": verification_code, "scope": self._settings.CLIENT_SCOPES - })) + })) # type: ignore # Request the access token from the authorization server using a refresh token. # \param refresh_token: @@ -48,7 +48,7 @@ class AuthorizationHelpers: "grant_type": "refresh_token", "refresh_token": refresh_token, "scope": self._settings.CLIENT_SCOPES - })) + })) # type: ignore @staticmethod # Parse the token response from the authorization server into an AuthenticationResponse object. diff --git a/cura/OAuth2/Models.py b/cura/OAuth2/Models.py index 796fdf8746..83fc22554f 100644 --- a/cura/OAuth2/Models.py +++ b/cura/OAuth2/Models.py @@ -14,7 +14,7 @@ class OAuth2Settings(BaseModel): CLIENT_ID = None # type: Optional[str] CLIENT_SCOPES = None # type: Optional[str] CALLBACK_URL = None # type: Optional[str] - AUTH_DATA_PREFERENCE_KEY = None # type: Optional[str] + AUTH_DATA_PREFERENCE_KEY = "" # type: str AUTH_SUCCESS_REDIRECT = "https://ultimaker.com" # type: str AUTH_FAILED_REDIRECT = "https://ultimaker.com" # type: str diff --git a/cura/Scene/ConvexHullDecorator.py b/cura/Scene/ConvexHullDecorator.py index 31e21df6bf..8532f40890 100644 --- a/cura/Scene/ConvexHullDecorator.py +++ b/cura/Scene/ConvexHullDecorator.py @@ -5,9 +5,11 @@ from PyQt5.QtCore import QTimer from UM.Application import Application from UM.Math.Polygon import Polygon + from UM.Scene.SceneNodeDecorator import SceneNodeDecorator from UM.Settings.ContainerRegistry import ContainerRegistry + from cura.Settings.ExtruderManager import ExtruderManager from cura.Scene import ConvexHullNode @@ -18,6 +20,8 @@ from typing import TYPE_CHECKING, Any, Optional if TYPE_CHECKING: from UM.Scene.SceneNode import SceneNode from cura.Settings.GlobalStack import GlobalStack + from UM.Mesh.MeshData import MeshData + from UM.Math.Matrix import Matrix ## The convex hull decorator is a scene node decorator that adds the convex hull functionality to a scene node. @@ -33,17 +37,17 @@ class ConvexHullDecorator(SceneNodeDecorator): # Make sure the timer is created on the main thread self._recompute_convex_hull_timer = None # type: Optional[QTimer] - - if Application.getInstance() is not None: - Application.getInstance().callLater(self.createRecomputeConvexHullTimer) + from cura.CuraApplication import CuraApplication + if CuraApplication.getInstance() is not None: + CuraApplication.getInstance().callLater(self.createRecomputeConvexHullTimer) self._raft_thickness = 0.0 - self._build_volume = Application.getInstance().getBuildVolume() + self._build_volume = CuraApplication.getInstance().getBuildVolume() self._build_volume.raftThicknessChanged.connect(self._onChanged) - Application.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged) - Application.getInstance().getController().toolOperationStarted.connect(self._onChanged) - Application.getInstance().getController().toolOperationStopped.connect(self._onChanged) + CuraApplication.getInstance().globalContainerStackChanged.connect(self._onGlobalStackChanged) + CuraApplication.getInstance().getController().toolOperationStarted.connect(self._onChanged) + CuraApplication.getInstance().getController().toolOperationStopped.connect(self._onChanged) self._onGlobalStackChanged() @@ -61,9 +65,9 @@ class ConvexHullDecorator(SceneNodeDecorator): previous_node.parentChanged.disconnect(self._onChanged) super().setNode(node) - - self._node.transformationChanged.connect(self._onChanged) - self._node.parentChanged.connect(self._onChanged) + # Mypy doesn't understand that self._node is no longer optional, so just use the node. + node.transformationChanged.connect(self._onChanged) + node.parentChanged.connect(self._onChanged) self._onChanged() @@ -78,9 +82,9 @@ class ConvexHullDecorator(SceneNodeDecorator): hull = self._compute2DConvexHull() - if self._global_stack and self._node and hull is not None: + if self._global_stack and self._node is not None and hull is not None: # Parent can be None if node is just loaded. - if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and (self._node.getParent() is None or not self._node.getParent().callDecoration("isGroup")): + if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and not self.hasGroupAsParent(self._node): hull = hull.getMinkowskiHull(Polygon(numpy.array(self._global_stack.getProperty("machine_head_polygon", "value"), numpy.float32))) hull = self._add2DAdhesionMargin(hull) return hull @@ -92,6 +96,13 @@ class ConvexHullDecorator(SceneNodeDecorator): return self._compute2DConvexHeadFull() + @staticmethod + def hasGroupAsParent(node: "SceneNode") -> bool: + parent = node.getParent() + if parent is None: + return False + return bool(parent.callDecoration("isGroup")) + ## Get convex hull of the object + head size # In case of printing all at once this is the same as the convex hull. # For one at the time this is area with intersection of mirrored head @@ -100,8 +111,10 @@ class ConvexHullDecorator(SceneNodeDecorator): return None if self._global_stack: - if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and (self._node.getParent() is None or not self._node.getParent().callDecoration("isGroup")): + if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and not self.hasGroupAsParent(self._node): head_with_fans = self._compute2DConvexHeadMin() + if head_with_fans is None: + return None head_with_fans_with_adhesion_margin = self._add2DAdhesionMargin(head_with_fans) return head_with_fans_with_adhesion_margin return None @@ -114,7 +127,7 @@ class ConvexHullDecorator(SceneNodeDecorator): return None if self._global_stack: - if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and (self._node.getParent() is None or not self._node.getParent().callDecoration("isGroup")): + if self._global_stack.getProperty("print_sequence", "value") == "one_at_a_time" and not self.hasGroupAsParent(self._node): # Printing one at a time and it's not an object in a group return self._compute2DConvexHull() return None @@ -153,15 +166,17 @@ class ConvexHullDecorator(SceneNodeDecorator): def _init2DConvexHullCache(self) -> None: # Cache for the group code path in _compute2DConvexHull() - self._2d_convex_hull_group_child_polygon = None - self._2d_convex_hull_group_result = None + self._2d_convex_hull_group_child_polygon = None # type: Optional[Polygon] + self._2d_convex_hull_group_result = None # type: Optional[Polygon] # Cache for the mesh code path in _compute2DConvexHull() - self._2d_convex_hull_mesh = None - self._2d_convex_hull_mesh_world_transform = None - self._2d_convex_hull_mesh_result = None + self._2d_convex_hull_mesh = None # type: Optional[MeshData] + self._2d_convex_hull_mesh_world_transform = None # type: Optional[Matrix] + self._2d_convex_hull_mesh_result = None # type: Optional[Polygon] def _compute2DConvexHull(self) -> Optional[Polygon]: + if self._node is None: + return None if self._node.callDecoration("isGroup"): points = numpy.zeros((0, 2), dtype=numpy.int32) for child in self._node.getChildren(): @@ -187,47 +202,47 @@ class ConvexHullDecorator(SceneNodeDecorator): return offset_hull else: - offset_hull = None - if self._node.getMeshData(): - mesh = self._node.getMeshData() - world_transform = self._node.getWorldTransformation() - - # Check the cache - if mesh is self._2d_convex_hull_mesh and world_transform == self._2d_convex_hull_mesh_world_transform: - return self._2d_convex_hull_mesh_result - - vertex_data = mesh.getConvexHullTransformedVertices(world_transform) - # Don't use data below 0. - # TODO; We need a better check for this as this gives poor results for meshes with long edges. - # Do not throw away vertices: the convex hull may be too small and objects can collide. - # vertex_data = vertex_data[vertex_data[:,1] >= -0.01] - - if len(vertex_data) >= 4: - # Round the vertex data to 1/10th of a mm, then remove all duplicate vertices - # This is done to greatly speed up further convex hull calculations as the convex hull - # becomes much less complex when dealing with highly detailed models. - vertex_data = numpy.round(vertex_data, 1) - - vertex_data = vertex_data[:, [0, 2]] # Drop the Y components to project to 2D. - - # Grab the set of unique points. - # - # This basically finds the unique rows in the array by treating them as opaque groups of bytes - # which are as long as the 2 float64s in each row, and giving this view to numpy.unique() to munch. - # See http://stackoverflow.com/questions/16970982/find-unique-rows-in-numpy-array - vertex_byte_view = numpy.ascontiguousarray(vertex_data).view( - numpy.dtype((numpy.void, vertex_data.dtype.itemsize * vertex_data.shape[1]))) - _, idx = numpy.unique(vertex_byte_view, return_index=True) - vertex_data = vertex_data[idx] # Select the unique rows by index. - - hull = Polygon(vertex_data) - - if len(vertex_data) >= 3: - convex_hull = hull.getConvexHull() - offset_hull = self._offsetHull(convex_hull) - else: + offset_hull = Polygon([]) + mesh = self._node.getMeshData() + if mesh is None: return Polygon([]) # Node has no mesh data, so just return an empty Polygon. + world_transform = self._node.getWorldTransformation() + + # Check the cache + if mesh is self._2d_convex_hull_mesh and world_transform == self._2d_convex_hull_mesh_world_transform: + return self._2d_convex_hull_mesh_result + + vertex_data = mesh.getConvexHullTransformedVertices(world_transform) + # Don't use data below 0. + # TODO; We need a better check for this as this gives poor results for meshes with long edges. + # Do not throw away vertices: the convex hull may be too small and objects can collide. + # vertex_data = vertex_data[vertex_data[:,1] >= -0.01] + + if len(vertex_data) >= 4: # type: ignore # mypy and numpy don't play along well just yet. + # Round the vertex data to 1/10th of a mm, then remove all duplicate vertices + # This is done to greatly speed up further convex hull calculations as the convex hull + # becomes much less complex when dealing with highly detailed models. + vertex_data = numpy.round(vertex_data, 1) + + vertex_data = vertex_data[:, [0, 2]] # Drop the Y components to project to 2D. + + # Grab the set of unique points. + # + # This basically finds the unique rows in the array by treating them as opaque groups of bytes + # which are as long as the 2 float64s in each row, and giving this view to numpy.unique() to munch. + # See http://stackoverflow.com/questions/16970982/find-unique-rows-in-numpy-array + vertex_byte_view = numpy.ascontiguousarray(vertex_data).view( + numpy.dtype((numpy.void, vertex_data.dtype.itemsize * vertex_data.shape[1]))) + _, idx = numpy.unique(vertex_byte_view, return_index=True) + vertex_data = vertex_data[idx] # Select the unique rows by index. + + hull = Polygon(vertex_data) + + if len(vertex_data) >= 3: + convex_hull = hull.getConvexHull() + offset_hull = self._offsetHull(convex_hull) + # Store the result in the cache self._2d_convex_hull_mesh = mesh self._2d_convex_hull_mesh_world_transform = world_transform @@ -338,7 +353,7 @@ class ConvexHullDecorator(SceneNodeDecorator): ## Private convenience function to get a setting from the correct extruder (as defined by limit_to_extruder property). def _getSettingProperty(self, setting_key: str, prop: str = "value") -> Any: - if not self._global_stack: + if self._global_stack is None or self._node is None: return None per_mesh_stack = self._node.callDecoration("getStack") if per_mesh_stack: @@ -358,7 +373,7 @@ class ConvexHullDecorator(SceneNodeDecorator): return self._global_stack.getProperty(setting_key, prop) ## Returns True if node is a descendant or the same as the root node. - def __isDescendant(self, root: "SceneNode", node: "SceneNode") -> bool: + def __isDescendant(self, root: "SceneNode", node: Optional["SceneNode"]) -> bool: if node is None: return False if root is node: diff --git a/cura/Settings/ContainerManager.py b/cura/Settings/ContainerManager.py index e1a1495dac..3cfca1a944 100644 --- a/cura/Settings/ContainerManager.py +++ b/cura/Settings/ContainerManager.py @@ -28,10 +28,10 @@ if TYPE_CHECKING: from cura.Machines.MaterialNode import MaterialNode from cura.Machines.QualityChangesGroup import QualityChangesGroup from UM.PluginRegistry import PluginRegistry - from UM.Settings.ContainerRegistry import ContainerRegistry from cura.Settings.MachineManager import MachineManager from cura.Machines.MaterialManager import MaterialManager from cura.Machines.QualityManager import QualityManager + from cura.Settings.CuraContainerRegistry import CuraContainerRegistry catalog = i18nCatalog("cura") @@ -52,7 +52,7 @@ class ContainerManager(QObject): self._application = application # type: CuraApplication self._plugin_registry = self._application.getPluginRegistry() # type: PluginRegistry - self._container_registry = self._application.getContainerRegistry() # type: ContainerRegistry + self._container_registry = self._application.getContainerRegistry() # type: CuraContainerRegistry self._machine_manager = self._application.getMachineManager() # type: MachineManager self._material_manager = self._application.getMaterialManager() # type: MaterialManager self._quality_manager = self._application.getQualityManager() # type: QualityManager @@ -391,7 +391,8 @@ class ContainerManager(QObject): continue mime_type = self._container_registry.getMimeTypeForContainer(container_type) - + if mime_type is None: + continue entry = { "type": serialize_type, "mime": mime_type, diff --git a/cura/Settings/MachineManager.py b/cura/Settings/MachineManager.py index 0059b7aad2..063f894d23 100755 --- a/cura/Settings/MachineManager.py +++ b/cura/Settings/MachineManager.py @@ -1148,7 +1148,7 @@ class MachineManager(QObject): self._fixQualityChangesGroupToNotSupported(quality_changes_group) quality_changes_container = self._empty_quality_changes_container - quality_container = self._empty_quality_container + quality_container = self._empty_quality_container # type: Optional[InstanceContainer] if quality_changes_group.node_for_global and quality_changes_group.node_for_global.getContainer(): quality_changes_container = cast(InstanceContainer, quality_changes_group.node_for_global.getContainer()) if quality_group is not None and quality_group.node_for_global and quality_group.node_for_global.getContainer(): diff --git a/plugins/SimulationView/SimulationView.py b/plugins/SimulationView/SimulationView.py index 8d739654d4..edf950e55a 100644 --- a/plugins/SimulationView/SimulationView.py +++ b/plugins/SimulationView/SimulationView.py @@ -21,6 +21,7 @@ from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Selection import Selection from UM.Signal import Signal +from UM.View.CompositePass import CompositePass from UM.View.GL.OpenGL import OpenGL from UM.View.GL.OpenGLContext import OpenGLContext @@ -36,7 +37,7 @@ from .SimulationViewProxy import SimulationViewProxy import numpy import os.path -from typing import Optional, TYPE_CHECKING, List +from typing import Optional, TYPE_CHECKING, List, cast if TYPE_CHECKING: from UM.Scene.SceneNode import SceneNode @@ -64,7 +65,7 @@ class SimulationView(View): self._minimum_layer_num = 0 self._current_layer_mesh = None self._current_layer_jumps = None - self._top_layers_job = None + self._top_layers_job = None # type: Optional["_CreateTopLayersJob"] self._activity = False self._old_max_layers = 0 @@ -78,10 +79,10 @@ class SimulationView(View): self._ghost_shader = None # type: Optional["ShaderProgram"] self._layer_pass = None # type: Optional[SimulationPass] - self._composite_pass = None # type: Optional[RenderPass] - self._old_layer_bindings = None + self._composite_pass = None # type: Optional[CompositePass] + self._old_layer_bindings = None # type: Optional[List[str]] self._simulationview_composite_shader = None # type: Optional["ShaderProgram"] - self._old_composite_shader = None + self._old_composite_shader = None # type: Optional["ShaderProgram"] self._global_container_stack = None # type: Optional[ContainerStack] self._proxy = SimulationViewProxy() @@ -204,9 +205,11 @@ class SimulationView(View): if not self._ghost_shader: self._ghost_shader = OpenGL.getInstance().createShaderProgram(Resources.getPath(Resources.Shaders, "color.shader")) - self._ghost_shader.setUniformValue("u_color", Color(*Application.getInstance().getTheme().getColor("layerview_ghost").getRgb())) + theme = CuraApplication.getInstance().getTheme() + if theme is not None: + self._ghost_shader.setUniformValue("u_color", Color(*theme.getColor("layerview_ghost").getRgb())) - for node in DepthFirstIterator(scene.getRoot()): + for node in DepthFirstIterator(scene.getRoot()): # type: ignore # We do not want to render ConvexHullNode as it conflicts with the bottom layers. # However, it is somewhat relevant when the node is selected, so do render it then. if type(node) is ConvexHullNode and not Selection.isSelected(node.getWatchedNode()): @@ -347,7 +350,7 @@ class SimulationView(View): self._old_max_layers = self._max_layers ## Recalculate num max layers new_max_layers = 0 - for node in DepthFirstIterator(scene.getRoot()): + for node in DepthFirstIterator(scene.getRoot()): # type: ignore layer_data = node.callDecoration("getLayerData") if not layer_data: continue @@ -398,7 +401,7 @@ class SimulationView(View): def calculateMaxPathsOnLayer(self, layer_num: int) -> None: # Update the currentPath scene = self.getController().getScene() - for node in DepthFirstIterator(scene.getRoot()): + for node in DepthFirstIterator(scene.getRoot()): # type: ignore layer_data = node.callDecoration("getLayerData") if not layer_data: continue @@ -474,15 +477,17 @@ class SimulationView(View): self._onGlobalStackChanged() if not self._simulationview_composite_shader: - self._simulationview_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(PluginRegistry.getInstance().getPluginPath("SimulationView"), "simulationview_composite.shader")) - theme = Application.getInstance().getTheme() - self._simulationview_composite_shader.setUniformValue("u_background_color", Color(*theme.getColor("viewport_background").getRgb())) - self._simulationview_composite_shader.setUniformValue("u_outline_color", Color(*theme.getColor("model_selection_outline").getRgb())) + plugin_path = cast(str, PluginRegistry.getInstance().getPluginPath("SimulationView")) + self._simulationview_composite_shader = OpenGL.getInstance().createShaderProgram(os.path.join(plugin_path, "simulationview_composite.shader")) + theme = CuraApplication.getInstance().getTheme() + if theme is not None: + self._simulationview_composite_shader.setUniformValue("u_background_color", Color(*theme.getColor("viewport_background").getRgb())) + self._simulationview_composite_shader.setUniformValue("u_outline_color", Color(*theme.getColor("model_selection_outline").getRgb())) if not self._composite_pass: - self._composite_pass = self.getRenderer().getRenderPass("composite") + self._composite_pass = cast(CompositePass, self.getRenderer().getRenderPass("composite")) - self._old_layer_bindings = self._composite_pass.getLayerBindings()[:] # make a copy so we can restore to it later + self._old_layer_bindings = self._composite_pass.getLayerBindings()[:] # make a copy so we can restore to it later self._composite_pass.getLayerBindings().append("simulationview") self._old_composite_shader = self._composite_pass.getCompositeShader() self._composite_pass.setCompositeShader(self._simulationview_composite_shader) @@ -496,8 +501,8 @@ class SimulationView(View): self._nozzle_node.setParent(None) self.getRenderer().removeRenderPass(self._layer_pass) if self._composite_pass: - self._composite_pass.setLayerBindings(self._old_layer_bindings) - self._composite_pass.setCompositeShader(self._old_composite_shader) + self._composite_pass.setLayerBindings(cast(List[str], self._old_layer_bindings)) + self._composite_pass.setCompositeShader(cast(ShaderProgram, self._old_composite_shader)) return False @@ -606,7 +611,7 @@ class _CreateTopLayersJob(Job): def run(self) -> None: layer_data = None - for node in DepthFirstIterator(self._scene.getRoot()): + for node in DepthFirstIterator(self._scene.getRoot()): # type: ignore layer_data = node.callDecoration("getLayerData") if layer_data: break