예제 #1
0
    def redo(self):
        stack = self._node.callDecoration(
            "getStack"
        )  #Don't try to get the active extruder since it may be None anyway.
        if not stack:
            self._node.addDecorator(SettingOverrideDecorator())

        self._previous_extruder_id = self._node.callDecoration(
            "getActiveExtruder")
        self._node.callDecoration("setActiveExtruder", self._extruder_id)
    def redo(self) -> None:
        stack = self._node.callDecoration(
            "getStack"
        )  #Don't try to get the active extruder since it may be None anyway.
        if not stack:
            self._node.addDecorator(SettingOverrideDecorator())

        self._previous_build_plate_nr = self._node.callDecoration(
            "getBuildPlateNumber")
        self._node.callDecoration("setBuildPlateNumber", self._build_plate_nr)
예제 #3
0
    def _createEraserMesh(self):
        node = CuraSceneNode()

        node.setName("Eraser")
        node.setSelectable(True)
        mesh = MeshBuilder()
        mesh.addCube(10, 10, 10)
        node.setMeshData(mesh.build())
        # Place the cube in the platform. Do it manually so it works if the "automatic drop models" is OFF
        move_vector = Vector(0, 5, 0)
        node.setPosition(move_vector)

        active_build_plate = Application.getInstance().getMultiBuildPlateModel(
        ).activeBuildPlate

        node.addDecorator(SettingOverrideDecorator())
        node.addDecorator(BuildPlateDecorator(active_build_plate))
        node.addDecorator(SliceableObjectDecorator())

        stack = node.callDecoration(
            "getStack"
        )  #Don't try to get the active extruder since it may be None anyway.
        if not stack:
            node.addDecorator(SettingOverrideDecorator())
            stack = node.callDecoration("getStack")

        settings = stack.getTop()

        if not (settings.getInstance("anti_overhang_mesh")
                and settings.getProperty("anti_overhang_mesh", "value")):
            definition = stack.getSettingDefinition("anti_overhang_mesh")
            new_instance = SettingInstance(definition, settings)
            new_instance.setProperty("value", True)
            new_instance.resetState(
            )  # Ensure that the state is not seen as a user state.
            settings.addInstance(new_instance)

        scene = self._controller.getScene()
        op = AddSceneNodeOperation(node, scene.getRoot())
        op.push()
        Application.getInstance().getController().getScene().sceneChanged.emit(
            node)
예제 #4
0
 def __init__(self,
              parent: Optional["SceneNode"] = None,
              visible: bool = True,
              name: str = "",
              no_setting_override: bool = False) -> None:
     super().__init__(parent=parent, visible=visible, name=name)
     if not no_setting_override:
         self.addDecorator(
             SettingOverrideDecorator()
         )  # Now we always have a getActiveExtruderPosition, unless explicitly disabled
     self._outside_buildarea = False
예제 #5
0
    def setSelectedActiveExtruder(self, extruder_stack_id):
        """Changes the active extruder of the currently selected object.

        :param extruder_stack_id: The ID of the extruder to print the currently
        selected object with.
        """

        selected_object = Selection.getSelectedObject(0)
        stack = selected_object.callDecoration(
            "getStack"
        )  #Don't try to get the active extruder since it may be None anyway.
        if not stack:
            selected_object.addDecorator(SettingOverrideDecorator())
        selected_object.callDecoration("setActiveExtruder", extruder_stack_id)
def setting_override_decorator():
    # Ensure that all the call counts and the like are reset.
    container_registry.reset_mock()
    application.reset_mock()
    extruder_manager.reset_mock()

    # Actually create the decorator.
    with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance",
               MagicMock(return_value=container_registry)):
        with patch("UM.Application.Application.getInstance",
                   MagicMock(return_value=application)):
            with patch(
                    "cura.Settings.ExtruderManager.ExtruderManager.getInstance",
                    MagicMock(return_value=extruder_manager)):
                return SettingOverrideDecorator()
    def setMeshType(self, mesh_type: str) -> bool:
        old_mesh_type = self.getMeshType()
        if old_mesh_type == mesh_type:
            return False

        selected_object = Selection.getSelectedObject(0)
        if selected_object is None:
            Logger.log("w", "Tried setting the mesh type of the selected object, but no object was selected")
            return False

        stack = selected_object.callDecoration("getStack") #Don't try to get the active extruder since it may be None anyway.
        if not stack:
            selected_object.addDecorator(SettingOverrideDecorator())
            stack = selected_object.callDecoration("getStack")

        settings_visibility_changed = False
        settings = stack.getTop()
        for property_key in ["infill_mesh", "cutting_mesh", "support_mesh", "anti_overhang_mesh"]:
            if property_key != mesh_type:
                if settings.getInstance(property_key):
                    settings.removeInstance(property_key)
            else:
                if not (settings.getInstance(property_key) and settings.getProperty(property_key, "value")):
                    definition = stack.getSettingDefinition(property_key)
                    new_instance = SettingInstance(definition, settings)
                    new_instance.setProperty("value", True)
                    new_instance.resetState()  # Ensure that the state is not seen as a user state.
                    settings.addInstance(new_instance)

        for property_key in ["top_bottom_thickness", "wall_thickness"]:
            if mesh_type == "infill_mesh":
                if settings.getInstance(property_key) is None:
                    definition = stack.getSettingDefinition(property_key)
                    new_instance = SettingInstance(definition, settings)
                    new_instance.setProperty("value", 0)
                    new_instance.resetState()  # Ensure that the state is not seen as a user state.
                    settings.addInstance(new_instance)
                    settings_visibility_changed = True

            elif old_mesh_type == "infill_mesh" and settings.getInstance(property_key) and settings.getProperty(property_key, "value") == 0:
                settings.removeInstance(property_key)
                settings_visibility_changed = True

        if settings_visibility_changed:
            self.visibility_handler.forceVisibilityChanged()

        self.propertyChanged.emit()
        return True
예제 #8
0
    def setMeshType(self, mesh_type):
        selected_object = Selection.getSelectedObject(0)
        stack = selected_object.callDecoration("getStack") #Don't try to get the active extruder since it may be None anyway.
        if not stack:
            selected_object.addDecorator(SettingOverrideDecorator())
            stack = selected_object.callDecoration("getStack")

        settings = stack.getTop()
        for property_key in ["infill_mesh", "cutting_mesh", "support_mesh", "anti_overhang_mesh"]:
            if property_key != mesh_type:
                if settings.getInstance(property_key):
                    settings.removeInstance(property_key)
            else:
                if not (settings.getInstance(property_key) and settings.getProperty(property_key, "value")):
                    definition = stack.getSettingDefinition(property_key)
                    new_instance = SettingInstance(definition, settings)
                    new_instance.setProperty("value", True)
                    new_instance.resetState()  # Ensure that the state is not seen as a user state.
                    settings.addInstance(new_instance)
예제 #9
0
    def setVisible(self, visible):
        if not self._node:
            return

        if not self._stack:
            self._node.addDecorator(SettingOverrideDecorator())
            self._stack = self._node.callDecoration("getStack")

        settings = self._stack.getTop()
        all_instances = settings.findInstances()
        visibility_changed = False  # Flag to check if at the end the signal needs to be emitted

        # Remove all instances that are not in visibility list
        for instance in all_instances:
            if instance.definition.key not in visible:
                settings.removeInstance(instance.definition.key)
                visibility_changed = True

        # Add all instances that are not added, but are in visibility list
        for item in visible:
            if not settings.getInstance(item):
                definition = self._stack.getSettingDefinition(item)
                if definition:
                    new_instance = SettingInstance(definition, settings)
                    stack_nr = -1
                    if definition.global_inherits_stack and self._stack.getProperty("machine_extruder_count", "value") > 1:
                        #Obtain the value from the correct container stack. Only once, upon adding the setting.
                        stack_nr = str(int(round(float(self._stack.getProperty(item, "global_inherits_stack"))))) #Stack to get the setting from. Round it and remove the fractional part.
                    if stack_nr not in ExtruderManager.getInstance().extruderIds and self._stack.getProperty("extruder_nr", "value"): #Property not defined, but we have an extruder number.
                        stack_nr = str(int(round(float(self._stack.getProperty("extruder_nr", "value")))))
                    if stack_nr in ExtruderManager.getInstance().extruderIds: #We have either a global_inherits_stack or an extruder_nr.
                        stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = ExtruderManager.getInstance().extruderIds[stack_nr])[0]
                    else:
                        stack = UM.Application.getInstance().getGlobalContainerStack()
                    new_instance.setProperty("value", stack.getProperty(item, "value"))
                    new_instance.resetState()  # Ensure that the state is not seen as a user state.
                    settings.addInstance(new_instance)
                    visibility_changed = True
                else:
                    Logger.log("w", "Unable to add instance (%s) to per-object visibility because we couldn't find the matching definition", item)

        if visibility_changed:
            self.visibilityChanged.emit()
예제 #10
0
    def _createEraserMesh(self, parent: CuraSceneNode, position: Vector):
        node = CuraSceneNode()

        node.setName("Eraser")
        node.setSelectable(True)
        mesh = MeshBuilder()
        mesh.addCube(10, 10, 10)
        node.setMeshData(mesh.build())
        node.setPosition(position)

        active_build_plate = Application.getInstance().getMultiBuildPlateModel(
        ).activeBuildPlate

        node.addDecorator(SettingOverrideDecorator())
        node.addDecorator(BuildPlateDecorator(active_build_plate))
        node.addDecorator(SliceableObjectDecorator())

        stack = node.callDecoration(
            "getStack")  # created by SettingOverrideDecorator
        settings = stack.getTop()

        definition = stack.getSettingDefinition("anti_overhang_mesh")
        new_instance = SettingInstance(definition, settings)
        new_instance.setProperty("value", True)
        new_instance.resetState(
        )  # Ensure that the state is not seen as a user state.
        settings.addInstance(new_instance)

        root = self._controller.getScene().getRoot()

        op = GroupedOperation()
        # First add the node to the scene, so it gets the expected transform
        op.addOperation(AddSceneNodeOperation(node, root))
        op.addOperation(SetParentOperation(node, parent))
        op.push()

        Application.getInstance().getController().getScene().sceneChanged.emit(
            node)
예제 #11
0
    def _node(self, mesh, settings):
        node = CuraSceneNode()
        node.setMeshData(mesh)
        node.setSelectable(True)
        node.addDecorator(SliceableObjectDecorator())

        if len(settings) > 0:
            node.addDecorator(SettingOverrideDecorator())
            stack = node.callDecoration('getStack')
            top = stack.getTop()

            for k, v in settings.items():
                if k == 'extruder':
                    node.callDecoration('setActiveExtruder', v)
                else:
                    definition = stack.getSettingDefinition(k)
                    instance = SettingInstance(definition, top)
                    instance.setProperty("value", v)
                    instance.resetState()
                    top.addInstance(instance)

        Logger.log('d', 'node: {0}'.format(node))
        return node
    def setVisible(self, visible):
        if not self._node:
            return

        if not self._stack:
            self._node.addDecorator(SettingOverrideDecorator())
            self._stack = self._node.callDecoration("getStack")

        settings = self._stack.getTop()
        all_instances = settings.findInstances()
        visibility_changed = False  # Flag to check if at the end the signal needs to be emitted

        # Remove all instances that are not in visibility list
        for instance in all_instances:
            if instance.definition.key not in visible:
                settings.removeInstance(instance.definition.key)
                visibility_changed = True

        # Add all instances that are not added, but are in visibility list
        for item in visible:
            if not settings.getInstance(item):
                definition = self._stack.getSettingDefinition(item)
                if definition:
                    new_instance = SettingInstance(definition, settings)
                    if definition.global_inherits_stack and self._stack.getProperty("machine_extruder_count", "value") > 1:
                        #Obtain the value from the correct container stack. Only once, upon adding the setting.
                        stack_nr = self._stack.getProperty(item, "global_inherits_stack") #Stack to get the setting from.
                        if float(stack_nr) >= 0: #Only if it defines an extruder stack.
                            extruder_stack = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = ExtruderManager.getInstance().extruderIds[stack_nr])[0]
                            new_instance.setProperty("value", extruder_stack.getProperty(item, "value"))
                    settings.addInstance(new_instance)
                    visibility_changed = True
                else:
                    Logger.log("w", "Unable to add instance (%s) to per-object visibility because we couldn't find the matching definition", item)

        if visibility_changed:
            self.visibilityChanged.emit()
예제 #13
0
    def _createNodeFromObject(self, object, name=""):
        node = SceneNode()
        node.setName(name)
        mesh_builder = MeshBuilder()
        vertex_list = []

        components = object.find(".//3mf:components", self._namespaces)
        if components:
            for component in components:
                id = component.get("objectid")
                new_object = self._root.find(
                    "./3mf:resources/3mf:object[@id='{0}']".format(id),
                    self._namespaces)
                new_node = self._createNodeFromObject(
                    new_object, self._base_name + "_" + str(id))
                node.addChild(new_node)
                transform = component.get("transform")
                if transform is not None:
                    new_node.setTransformation(
                        self._createMatrixFromTransformationString(transform))

        # for vertex in entry.mesh.vertices.vertex:
        for vertex in object.findall(".//3mf:vertex", self._namespaces):
            vertex_list.append(
                [vertex.get("x"),
                 vertex.get("y"),
                 vertex.get("z")])
            Job.yieldThread()

        xml_settings = list(object.findall(".//cura:setting",
                                           self._namespaces))

        # Add the setting override decorator, so we can add settings to this node.
        if xml_settings:
            node.addDecorator(SettingOverrideDecorator())

            global_container_stack = Application.getInstance(
            ).getGlobalContainerStack()
            # Ensure the correct next container for the SettingOverride decorator is set.
            if global_container_stack:
                multi_extrusion = global_container_stack.getProperty(
                    "machine_extruder_count", "value") > 1
                # Ensure that all extruder data is reset
                if not multi_extrusion:
                    default_stack_id = global_container_stack.getId()
                else:
                    default_stack = ExtruderManager.getInstance(
                    ).getExtruderStack(0)
                    if default_stack:
                        default_stack_id = default_stack.getId()
                    else:
                        default_stack_id = global_container_stack.getId()
                node.callDecoration("setActiveExtruder", default_stack_id)

                # Get the definition & set it
                definition = QualityManager.getInstance(
                ).getParentMachineDefinition(
                    global_container_stack.getBottom())
                node.callDecoration("getStack").getTop().setDefinition(
                    definition)

            setting_container = node.callDecoration("getStack").getTop()
            for setting in xml_settings:
                setting_key = setting.get("key")
                setting_value = setting.text

                # Extruder_nr is a special case.
                if setting_key == "extruder_nr":
                    extruder_stack = ExtruderManager.getInstance(
                    ).getExtruderStack(int(setting_value))
                    if extruder_stack:
                        node.callDecoration("setActiveExtruder",
                                            extruder_stack.getId())
                    else:
                        Logger.log("w",
                                   "Unable to find extruder in position %s",
                                   setting_value)
                    continue
                setting_container.setProperty(setting_key, "value",
                                              setting_value)

        if len(node.getChildren()) > 0:
            group_decorator = GroupDecorator()
            node.addDecorator(group_decorator)

        triangles = object.findall(".//3mf:triangle", self._namespaces)
        mesh_builder.reserveFaceCount(len(triangles))

        for triangle in triangles:
            v1 = int(triangle.get("v1"))
            v2 = int(triangle.get("v2"))
            v3 = int(triangle.get("v3"))

            mesh_builder.addFaceByPoints(
                vertex_list[v1][0], vertex_list[v1][1], vertex_list[v1][2],
                vertex_list[v2][0], vertex_list[v2][1], vertex_list[v2][2],
                vertex_list[v3][0], vertex_list[v3][1], vertex_list[v3][2])

            Job.yieldThread()

        # TODO: We currently do not check for normals and simply recalculate them.
        mesh_builder.calculateNormals(fast=True)
        mesh_builder.setFileName(name)
        mesh_data = mesh_builder.build()

        if len(mesh_data.getVertices()):
            node.setMeshData(mesh_data)

        node.setSelectable(True)
        return node
예제 #14
0
    def setVisible(self, visible):
        if not self._node:
            return

        if not self._stack:
            self._node.addDecorator(SettingOverrideDecorator())
            self._stack = self._node.callDecoration("getStack")

        settings = self._stack.getTop()
        all_instances = settings.findInstances()
        visibility_changed = False  # Flag to check if at the end the signal needs to be emitted

        # Remove all instances that are not in visibility list
        for instance in all_instances:
            # exceptionally skip setting
            if instance.definition.key in self._skip_reset_setting_set:
                continue
            if instance.definition.key not in visible:
                settings.removeInstance(instance.definition.key)
                visibility_changed = True

        # Add all instances that are not added, but are in visibility list
        for item in visible:
            if not settings.getInstance(
                    item):  # Setting was not added already.
                definition = self._stack.getSettingDefinition(item)
                if definition:
                    new_instance = SettingInstance(definition, settings)
                    stack_nr = -1
                    stack = None
                    # Check from what stack we should copy the raw property of the setting from.
                    if self._stack.getProperty("machine_extruder_count",
                                               "value") > 1:
                        if definition.limit_to_extruder != "-1":
                            # A limit to extruder function was set and it's a multi extrusion machine. Check what stack we do need to use.
                            stack_nr = str(
                                int(
                                    round(
                                        float(
                                            self._stack.getProperty(
                                                item, "limit_to_extruder")))))

                        # Check if the found stack_number is in the extruder list of extruders.
                        if stack_nr not in ExtruderManager.getInstance(
                        ).extruderIds and self._stack.getProperty(
                                "extruder_nr", "value") is not None:
                            stack_nr = -1

                        # Use the found stack number to get the right stack to copy the value from.
                        if stack_nr in ExtruderManager.getInstance(
                        ).extruderIds:
                            stack = ContainerRegistry.getInstance(
                            ).findContainerStacks(
                                id=ExtruderManager.getInstance(
                                ).extruderIds[stack_nr])[0]
                    else:
                        stack = self._stack

                    # Use the raw property to set the value (so the inheritance doesn't break)
                    if stack is not None:
                        new_instance.setProperty(
                            "value", stack.getRawProperty(item, "value"))
                    else:
                        new_instance.setProperty("value", None)
                    new_instance.resetState(
                    )  # Ensure that the state is not seen as a user state.
                    settings.addInstance(new_instance)
                    visibility_changed = True
                else:
                    Logger.log(
                        "w",
                        "Unable to add instance (%s) to per-object visibility because we couldn't find the matching definition",
                        item)

        if visibility_changed:
            self.visibilityChanged.emit()
예제 #15
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self._outside_buildarea = True
     self.addDecorator(SettingOverrideDecorator())
예제 #16
0
    def setMeshType(self, mesh_type: str) -> bool:
        """Returns True when the mesh_type was changed, False when current mesh_type == mesh_type"""

        old_mesh_type = self.getMeshType()
        if old_mesh_type == mesh_type:
            return False

        selected_object = Selection.getSelectedObject(0)
        if selected_object is None:
            Logger.log(
                "w",
                "Tried setting the mesh type of the selected object, but no object was selected"
            )
            return False

        stack = selected_object.callDecoration(
            "getStack"
        )  #Don't try to get the active extruder since it may be None anyway.
        if not stack:
            selected_object.addDecorator(SettingOverrideDecorator())
            stack = selected_object.callDecoration("getStack")

        settings_visibility_changed = False
        settings = stack.getTop()
        for property_key in [
                "infill_mesh", "cutting_mesh", "support_mesh",
                "anti_overhang_mesh"
        ]:
            if property_key != mesh_type:
                if settings.getInstance(property_key):
                    settings.removeInstance(property_key)
            else:
                if not (settings.getInstance(property_key)
                        and settings.getProperty(property_key, "value")):
                    definition = stack.getSettingDefinition(property_key)
                    new_instance = SettingInstance(definition, settings)
                    new_instance.setProperty("value", True)
                    new_instance.resetState(
                    )  # Ensure that the state is not seen as a user state.
                    settings.addInstance(new_instance)

        # Override some settings to ensure that the infill mesh by default adds no skin or walls. Or remove them if not an infill mesh.
        specialized_settings = {
            "top_bottom_thickness":
            0,
            "top_thickness":
            "=top_bottom_thickness",
            "bottom_thickness":
            "=top_bottom_thickness",
            "top_layers":
            "=0 if infill_sparse_density == 100 else math.ceil(round(top_thickness / resolveOrValue('layer_height'), 4))",
            "bottom_layers":
            "=0 if infill_sparse_density == 100 else math.ceil(round(bottom_thickness / resolveOrValue('layer_height'), 4))",
            "wall_thickness":
            0,
            "wall_line_count":
            "=max(1, round((wall_thickness - wall_line_width_0) / wall_line_width_x) + 1) if wall_thickness != 0 else 0"
        }
        for property_key in specialized_settings:
            if mesh_type == "infill_mesh":
                if settings.getInstance(property_key) is None:
                    definition = stack.getSettingDefinition(property_key)
                    new_instance = SettingInstance(definition, settings)
                    new_instance.setProperty(
                        "value", specialized_settings[property_key])
                    new_instance.resetState(
                    )  # Ensure that the state is not seen as a user state.
                    settings.addInstance(new_instance)
                    settings_visibility_changed = True

            elif old_mesh_type == "infill_mesh" and settings.getInstance(
                    property_key) and property_key in specialized_settings:
                settings.removeInstance(property_key)
                settings_visibility_changed = True

        if settings_visibility_changed:
            self.visibility_handler.forceVisibilityChanged()

        self.propertyChanged.emit()
        return True
예제 #17
0
    def _convertSavitarNodeToUMNode(self, savitar_node):
        um_node = SceneNode()
        transformation = self._createMatrixFromTransformationString(
            savitar_node.getTransformation())
        um_node.setTransformation(transformation)
        mesh_builder = MeshBuilder()

        data = numpy.fromstring(
            savitar_node.getMeshData().getFlatVerticesAsBytes(),
            dtype=numpy.float32)

        vertices = numpy.resize(data, (int(data.size / 3), 3))
        mesh_builder.setVertices(vertices)
        mesh_builder.calculateNormals(fast=True)
        mesh_data = mesh_builder.build()

        if len(mesh_data.getVertices()):
            um_node.setMeshData(mesh_data)

        for child in savitar_node.getChildren():
            child_node = self._convertSavitarNodeToUMNode(child)
            if child_node:
                um_node.addChild(child_node)

        if um_node.getMeshData() is None and len(um_node.getChildren()) == 0:
            return None

        settings = savitar_node.getSettings()

        # Add the setting override decorator, so we can add settings to this node.
        if settings:
            um_node.addDecorator(SettingOverrideDecorator())

            global_container_stack = Application.getInstance(
            ).getGlobalContainerStack()

            # Ensure the correct next container for the SettingOverride decorator is set.
            if global_container_stack:
                default_stack = ExtruderManager.getInstance().getExtruderStack(
                    0)

                if default_stack:
                    um_node.callDecoration("setActiveExtruder",
                                           default_stack.getId())

                # Get the definition & set it
                definition = QualityManager.getInstance(
                ).getParentMachineDefinition(
                    global_container_stack.getBottom())
                um_node.callDecoration("getStack").getTop().setDefinition(
                    definition.getId())

            setting_container = um_node.callDecoration("getStack").getTop()

            for key in settings:
                setting_value = settings[key]

                # Extruder_nr is a special case.
                if key == "extruder_nr":
                    extruder_stack = ExtruderManager.getInstance(
                    ).getExtruderStack(int(setting_value))
                    if extruder_stack:
                        um_node.callDecoration("setActiveExtruder",
                                               extruder_stack.getId())
                    else:
                        Logger.log("w",
                                   "Unable to find extruder in position %s",
                                   setting_value)
                    continue
                setting_container.setProperty(key, "value", setting_value)

        if len(um_node.getChildren()) > 0:
            group_decorator = GroupDecorator()
            um_node.addDecorator(group_decorator)
        um_node.setSelectable(True)
        if um_node.getMeshData():
            # Assuming that all nodes with mesh data are printable objects
            # affects (auto) slicing
            sliceable_decorator = SliceableObjectDecorator()
            um_node.addDecorator(sliceable_decorator)
        return um_node
예제 #18
0
 def setSelectedActiveExtruder(self, extruder_stack_id):
     selected_object = Selection.getSelectedObject(0)
     stack = selected_object.callDecoration("getStack") #Don't try to get the active extruder since it may be None anyway.
     if not stack:
         selected_object.addDecorator(SettingOverrideDecorator())
     selected_object.callDecoration("setActiveExtruder", extruder_stack_id)
예제 #19
0
 def __init__(self, *args, **kwargs):
     super().__init__(*args, **kwargs)
     if "no_setting_override" not in kwargs:
         self.addDecorator(SettingOverrideDecorator())  # now we always have a getActiveExtruderPosition, unless explicitly disabled
     self._outside_buildarea = False