Exemple #1
0
    def setExtruderForSelection(self, extruder_id: str) -> None:
        operation = GroupedOperation()

        nodes_to_change = []
        for node in Selection.getAllSelectedObjects():
            # Do not change any nodes that already have the right extruder set.
            if node.callDecoration("getActiveExtruder") == extruder_id:
                continue

            # If the node is a group, apply the active extruder to all children of the group.
            if node.callDecoration("isGroup"):
                for grouped_node in BreadthFirstIterator(node):
                    if grouped_node.callDecoration("getActiveExtruder") == extruder_id:
                        continue

                    if grouped_node.callDecoration("isGroup"):
                        continue

                    nodes_to_change.append(grouped_node)
                continue

            nodes_to_change.append(node)

        if not nodes_to_change:
            # If there are no changes to make, we still need to reset the selected extruders.
            # This is a workaround for checked menu items being deselected while still being
            # selected.
            ExtruderManager.getInstance().resetSelectedObjectExtruders()
            return

        for node in nodes_to_change:
            operation.addOperation(SetObjectExtruderOperation(node, extruder_id))
        operation.push()
Exemple #2
0
    def _onStackChanged(self):
        if self._global_container_stack:
            self._global_container_stack.propertyChanged.disconnect(self._onSettingPropertyChanged)
            extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())
            for extruder in extruders:
                extruder.propertyChanged.disconnect(self._onSettingPropertyChanged)

        self._global_container_stack = Application.getInstance().getGlobalContainerStack()

        if self._global_container_stack:
            self._global_container_stack.propertyChanged.connect(self._onSettingPropertyChanged)
            extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())
            for extruder in extruders:
                extruder.propertyChanged.connect(self._onSettingPropertyChanged)

            self._width = self._global_container_stack.getProperty("machine_width", "value")
            machine_height = self._global_container_stack.getProperty("machine_height", "value")
            if self._global_container_stack.getProperty("print_sequence", "value") == "one_at_a_time" and len(self._scene_objects) > 1:
                self._height = min(self._global_container_stack.getProperty("gantry_height", "value"), machine_height)
                if self._height < machine_height:
                    self._build_volume_message.show()
                else:
                    self._build_volume_message.hide()
            else:
                self._height = self._global_container_stack.getProperty("machine_height", "value")
                self._build_volume_message.hide()
            self._depth = self._global_container_stack.getProperty("machine_depth", "value")
            self._shape = self._global_container_stack.getProperty("machine_shape", "value")

            self._updateDisallowedAreas()
            self._updateRaftThickness()

            self.rebuild()
Exemple #3
0
    def __init__(self, parent = None):
        super().__init__(parent)

        self._width = 0
        self._height = 0
        self._depth = 0

        self._shader = None

        self._grid_mesh = None
        self._grid_shader = None

        self._disallowed_areas = []
        self._disallowed_area_mesh = None

        self._prime_tower_area = None
        self._prime_tower_area_mesh = None

        self.setCalculateBoundingBox(False)
        self._volume_aabb = None

        self._raft_thickness = 0.0
        self._adhesion_type = None
        self._platform = Platform(self)

        self._global_container_stack = None
        Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerStackChanged)
        self._onGlobalContainerStackChanged()

        self._active_extruder_stack = None
        ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)
        self._onActiveExtruderStackChanged()

        self._has_errors = False
Exemple #4
0
 def _getSettingFromAllExtruders(self, setting_key, property = "value"):
     all_values = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, property)
     all_types = ExtruderManager.getInstance().getAllExtruderSettings(setting_key, "type")
     for i in range(len(all_values)):
         if not all_values[i] and (all_types[i] == "int" or all_types[i] == "float"):
             all_values[i] = 0
     return all_values
    def _onGlobalContainerChanged(self):
        global_container_stack = Application.getInstance().getGlobalContainerStack()
        if global_container_stack:
            self._multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1

            # Ensure that all extruder data is reset
            if not self._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()

            root_node = Application.getInstance().getController().getScene().getRoot()
            for node in DepthFirstIterator(root_node):
                new_stack_id = default_stack_id
                # Get position of old extruder stack for this node
                old_extruder_pos = node.callDecoration("getActiveExtruderPosition")
                if old_extruder_pos is not None:
                    # Fetch current (new) extruder stack at position
                    new_stack = ExtruderManager.getInstance().getExtruderStack(old_extruder_pos)
                    if new_stack:
                        new_stack_id = new_stack.getId()
                node.callDecoration("setActiveExtruder", new_stack_id)

            self._updateEnabled()
Exemple #6
0
    def _getEdgeDisallowedSize(self):
        if not self._global_container_stack:
            return 0
        container_stack = self._global_container_stack

        # If we are printing one at a time, we need to add the bed adhesion size to the disallowed areas of the objects
        if container_stack.getProperty("print_sequence", "value") == "one_at_a_time":
            return 0.1  # Return a very small value, so we do draw disallowed area's near the edges.

        adhesion_type = container_stack.getProperty("adhesion_type", "value")
        if adhesion_type == "skirt":
            skirt_distance = self._getSettingFromAdhesionExtruder("skirt_gap")
            skirt_line_count = self._getSettingFromAdhesionExtruder("skirt_line_count")
            bed_adhesion_size = skirt_distance + (skirt_line_count * self._getSettingFromAdhesionExtruder("skirt_brim_line_width"))
            if len(ExtruderManager.getInstance().getUsedExtruderStacks()) > 1:
                adhesion_extruder_nr = int(self._global_container_stack.getProperty("adhesion_extruder_nr", "value"))
                extruder_values = ExtruderManager.getInstance().getAllExtruderValues("skirt_brim_line_width")
                del extruder_values[adhesion_extruder_nr]  # Remove the value of the adhesion extruder nr.
                for value in extruder_values:
                    bed_adhesion_size += value
        elif adhesion_type == "brim":
            bed_adhesion_size = self._getSettingFromAdhesionExtruder("brim_line_count") * self._getSettingFromAdhesionExtruder("skirt_brim_line_width")
            if self._global_container_stack.getProperty("machine_extruder_count", "value") > 1:
                adhesion_extruder_nr = int(self._global_container_stack.getProperty("adhesion_extruder_nr", "value"))
                extruder_values = ExtruderManager.getInstance().getAllExtruderValues("skirt_brim_line_width")
                del extruder_values[adhesion_extruder_nr]  # Remove the value of the adhesion extruder nr.
                for value in extruder_values:
                    bed_adhesion_size += value
        elif adhesion_type == "raft":
            bed_adhesion_size = self._getSettingFromAdhesionExtruder("raft_margin")
        elif adhesion_type == "none":
            bed_adhesion_size = 0
        else:
            raise Exception("Unknown bed adhesion type. Did you forget to update the build volume calculations for your new bed adhesion type?")

        support_expansion = 0
        if self._getSettingFromSupportInfillExtruder("support_offset") and self._global_container_stack.getProperty("support_enable", "value"):
            support_expansion += self._getSettingFromSupportInfillExtruder("support_offset")

        farthest_shield_distance = 0
        if container_stack.getProperty("draft_shield_enabled", "value"):
            farthest_shield_distance = max(farthest_shield_distance, container_stack.getProperty("draft_shield_dist", "value"))
        if container_stack.getProperty("ooze_shield_enabled", "value"):
            farthest_shield_distance = max(farthest_shield_distance, container_stack.getProperty("ooze_shield_dist", "value"))

        move_from_wall_radius = 0  # Moves that start from outer wall.
        move_from_wall_radius = max(move_from_wall_radius, max(self._getSettingFromAllExtruders("infill_wipe_dist")))
        used_extruders = ExtruderManager.getInstance().getUsedExtruderStacks()
        avoid_enabled_per_extruder = [stack.getProperty("travel_avoid_other_parts","value") for stack in used_extruders]
        travel_avoid_distance_per_extruder = [stack.getProperty("travel_avoid_distance", "value") for stack in used_extruders]
        for avoid_other_parts_enabled, avoid_distance in zip(avoid_enabled_per_extruder, travel_avoid_distance_per_extruder): #For each extruder (or just global).
            if avoid_other_parts_enabled:
                move_from_wall_radius = max(move_from_wall_radius, avoid_distance)

        # Now combine our different pieces of data to get the final border size.
        # Support expansion is added to the bed adhesion, since the bed adhesion goes around support.
        # Support expansion is added to farthest shield distance, since the shields go around support.
        border_size = max(move_from_wall_radius, support_expansion + farthest_shield_distance, support_expansion + bed_adhesion_size)
        return border_size
    def __init__(self, parent = None):
        super().__init__(parent)
        Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
        self._global_container_stack = None
        self._settings_with_inheritance_warning = []
        self._active_container_stack = None
        self._onGlobalContainerChanged()

        ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
        self._onActiveExtruderChanged()
    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): # 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()
    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.limit_to_extruder 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, "limit_to_extruder"))))
                        )  # 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 limit_to_extruder 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.getRawProperty(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()
Exemple #10
0
    def _onActiveExtruderChanged(self):
        if self._global_container_stack:
            # Connect all extruders of the active machine. This might cause a few connects that have already happend,
            # but that shouldn't cause issues as only new / unique connections are added.
            extruders = list(ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId()))
            if extruders:
                for extruder in extruders:
                    extruder.propertyChanged.connect(self._onSettingChanged)
        if self._active_extruder_stack:
            self._active_extruder_stack.containersChanged.disconnect(self._onChanged)

        self._active_extruder_stack = ExtruderManager.getInstance().getActiveExtruderStack()
        if self._active_extruder_stack:
            self._active_extruder_stack.containersChanged.connect(self._onChanged)
    def __init__(self, parent = None):
        super().__init__("MachineSettingsAction", catalog.i18nc("@action", "Machine Settings"))
        self._qml_url = "MachineSettingsAction.qml"

        self._global_container_stack = None
        self._container_index = 0
        self._extruder_container_index = 0

        self._container_registry = ContainerRegistry.getInstance()
        self._container_registry.containerAdded.connect(self._onContainerAdded)
        self._container_registry.containerRemoved.connect(self._onContainerRemoved)
        Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
        ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderStackChanged)

        self._backend = Application.getInstance().getBackend()
    def __init__(self, parent = None):
        super().__init__(parent)
        Application.getInstance().globalContainerStackChanged.connect(self._onGlobalContainerChanged)
        self._global_container_stack = None
        self._settings_with_inheritance_warning = []
        self._active_container_stack = None
        self._onGlobalContainerChanged()

        ExtruderManager.getInstance().activeExtruderChanged.connect(self._onActiveExtruderChanged)
        self._onActiveExtruderChanged()

        self._update_timer = QTimer()
        self._update_timer.setInterval(500)
        self._update_timer.setSingleShot(True)
        self._update_timer.timeout.connect(self._update)
Exemple #13
0
    def _onGlobalContainerChanged(self) -> None:
        if self._global_stack:
            try:
                self._global_stack.propertyChanged.disconnect(self._onPropertyChanged)
            except TypeError:
                pass
            for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks():
                extruder_stack.propertyChanged.disconnect(self._onPropertyChanged)

        self._global_stack = Application.getInstance().getGlobalContainerStack()
        if self._global_stack:
            self._global_stack.propertyChanged.connect(self._onPropertyChanged)
            for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks():
                extruder_stack.propertyChanged.connect(self._onPropertyChanged)
            self._onPropertyChanged("support_angle", "value")  # Force an re-evaluation
Exemple #14
0
    def _serialiseSettings(self, stack):
        prefix = ";SETTING_" + str(GCodeWriter.version) + " "  # The prefix to put before each line.
        prefix_length = len(prefix)

        container_with_profile = stack.findContainer({"type": "quality"})
        flat_global_container = self._createFlattenedContainerInstance(stack.getTop(),container_with_profile)
        serialized = flat_global_container.serialize()
        data = {"global_quality": serialized}

        for extruder in ExtruderManager.getInstance().getMachineExtruders(stack.getId()):
            extruder_quality = extruder.findContainer({"type": "quality"})
            flat_extruder_quality = self._createFlattenedContainerInstance(extruder.getTop(), extruder_quality)

            extruder_serialized = flat_extruder_quality.serialize()
            data.setdefault("extruder_quality", []).append(extruder_serialized)

        json_string = json.dumps(data)

        # Escape characters that have a special meaning in g-code comments.
        pattern = re.compile("|".join(GCodeWriter.escape_characters.keys()))

        # Perform the replacement with a regular expression.
        escaped_string = pattern.sub(lambda m: GCodeWriter.escape_characters[re.escape(m.group(0))], json_string)

        # Introduce line breaks so that each comment is no longer than 80 characters. Prepend each line with the prefix.
        result = ""

        # Lines have 80 characters, so the payload of each line is 80 - prefix.
        for pos in range(0, len(escaped_string), 80 - prefix_length):
            result += prefix + escaped_string[pos : pos + 80 - prefix_length] + "\n"
        return result
Exemple #15
0
 def _extruderOffsets(self) -> Dict[int, List[float]]:
     result = {}
     for extruder in ExtruderManager.getInstance().getActiveExtruderStacks():
         result[int(extruder.getMetaData().get("position", "0"))] = [
             extruder.getProperty("machine_nozzle_offset_x", "value"),
             extruder.getProperty("machine_nozzle_offset_y", "value")]
     return result
Exemple #16
0
    def _handlePerObjectSettings(self, node: CuraSceneNode, message: Arcus.PythonMessage):
        stack = node.callDecoration("getStack")

        # Check if the node has a stack attached to it and the stack has any settings in the top container.
        if not stack:
            return

        # Check all settings for relations, so we can also calculate the correct values for dependent settings.
        top_of_stack = stack.getTop()  # Cache for efficiency.
        changed_setting_keys = top_of_stack.getAllKeys()

        # Add all relations to changed settings as well.
        for key in top_of_stack.getAllKeys():
            instance = top_of_stack.getInstance(key)
            self._addRelations(changed_setting_keys, instance.definition.relations)
            Job.yieldThread()

        # Ensure that the engine is aware what the build extruder is.
        changed_setting_keys.add("extruder_nr")

        # Get values for all changed settings
        for key in changed_setting_keys:
            setting = message.addRepeatedMessage("settings")
            setting.name = key
            extruder = int(round(float(stack.getProperty(key, "limit_to_extruder"))))

            # Check if limited to a specific extruder, but not overridden by per-object settings.
            if extruder >= 0 and key not in changed_setting_keys:
                limited_stack = ExtruderManager.getInstance().getActiveExtruderStacks()[extruder]
            else:
                limited_stack = stack

            setting.value = str(limited_stack.getProperty(key, "value")).encode("utf-8")

            Job.yieldThread()
Exemple #17
0
    def _computeDisallowedAreasPrinted(self, used_extruders):
        result = {}
        for extruder in used_extruders:
            result[extruder.getId()] = []

        #Currently, the only normally printed object is the prime tower.
        if ExtruderManager.getInstance().getResolveOrValue("prime_tower_enable") == True:
            prime_tower_size = self._global_container_stack.getProperty("prime_tower_size", "value")
            machine_width = self._global_container_stack.getProperty("machine_width", "value")
            machine_depth = self._global_container_stack.getProperty("machine_depth", "value")
            prime_tower_x = self._global_container_stack.getProperty("prime_tower_position_x", "value")
            prime_tower_y = - self._global_container_stack.getProperty("prime_tower_position_y", "value")
            if not self._global_container_stack.getProperty("machine_center_is_zero", "value"):
                prime_tower_x = prime_tower_x - machine_width / 2 #Offset by half machine_width and _depth to put the origin in the front-left.
                prime_tower_y = prime_tower_y + machine_depth / 2

            prime_tower_area = Polygon([
                [prime_tower_x - prime_tower_size, prime_tower_y - prime_tower_size],
                [prime_tower_x, prime_tower_y - prime_tower_size],
                [prime_tower_x, prime_tower_y],
                [prime_tower_x - prime_tower_size, prime_tower_y],
            ])
            prime_tower_area = prime_tower_area.getMinkowskiHull(Polygon.approximatedCircle(0))
            for extruder in used_extruders:
                result[extruder.getId()].append(prime_tower_area) #The prime tower location is the same for each extruder, regardless of offset.

        return result
Exemple #18
0
    def _fetchInstanceContainers(self):
        global_container_stack = Application.getInstance().getGlobalContainerStack()
        if not global_container_stack:
            return {}, {}

        # Fetch the list of quality changes.
        quality_manager = QualityManager.getInstance()
        machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.definition)
        quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition)

        extruder_manager = ExtruderManager.getInstance()
        active_extruder = extruder_manager.getActiveExtruderStack()
        extruder_stacks = self._getOrderedExtruderStacksList()

        # Fetch the list of usable qualities across all extruders.
        # The actual list of quality profiles come from the first extruder in the extruder list.
        quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(global_container_stack, extruder_stacks)

        # Filter the quality_change by the list of available quality_types
        quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list])

        filtered_quality_changes = {qc.getId():qc for qc in quality_changes_list if
                                    qc.getMetaDataEntry("quality_type") in quality_type_set and
                                    qc.getMetaDataEntry("extruder") is not None and
                                    (qc.getMetaDataEntry("extruder") == active_extruder.definition.getMetaDataEntry("quality_definition") or
                                     qc.getMetaDataEntry("extruder") == active_extruder.definition.getId())}

        return filtered_quality_changes, {} #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
    def _fetchInstanceContainers(self):
        global_container_stack = Application.getInstance().getGlobalContainerStack()
        if not global_container_stack:
            return []

        # Fetch the list of quality changes.
        quality_manager = QualityManager.getInstance()
        machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.getBottom())
        quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition)

        # Get the  list of extruders and place the selected extruder at the front of the list.
        extruder_manager = ExtruderManager.getInstance()
        active_extruder = extruder_manager.getActiveExtruderStack()
        extruder_stacks = extruder_manager.getActiveExtruderStacks()
        if active_extruder in extruder_stacks:
            extruder_stacks.remove(active_extruder)
            extruder_stacks = [active_extruder] + extruder_stacks

        # Fetch the list of useable qualities across all extruders.
        # The actual list of quality profiles come from the first extruder in the extruder list.
        quality_list =  QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack,
                                                                                                  extruder_stacks)

        # Filter the quality_change by the list of available quality_types
        quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list])
        filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set]

        return quality_list + filtered_quality_changes
    def _checkForWarnings(self):
        warnings = []
        print_information = CuraApplication.getInstance().getPrintInformation()

        if not print_information.materialLengths:
            Logger.log("w", "There is no material length information. Unable to check for warnings.")
            return warnings

        extruder_manager = ExtruderManager.getInstance()

        for index, extruder in enumerate(self.activePrinter.extruders):
            if index < len(print_information.materialLengths) and print_information.materialLengths[index] != 0:
                # The extruder is by this print.

                # TODO: material length check

                # Check if the right Printcore is active.
                variant = extruder_manager.getExtruderStack(index).findContainer({"type": "variant"})
                if variant:
                    if variant.getName() != extruder.hotendID:
                        warnings.append(i18n_catalog.i18nc("@label", "Different PrintCore (Cura: {cura_printcore_name}, Printer: {remote_printcore_name}) selected for extruder {extruder_id}".format(cura_printcore_name = variant.getName(), remote_printcore_name = extruder.hotendID, extruder_id = index + 1)))
                else:
                    Logger.log("w", "Unable to find variant.")

                # Check if the right material is loaded.
                local_material = extruder_manager.getExtruderStack(index).findContainer({"type": "material"})
                if local_material:
                    if extruder.activeMaterial.guid != local_material.getMetaDataEntry("GUID"):
                        Logger.log("w", "Extruder %s has a different material (%s) as Cura (%s)", index + 1, extruder.activeMaterial.guid, local_material.getMetaDataEntry("GUID"))
                        warnings.append(i18n_catalog.i18nc("@label", "Different material (Cura: {0}, Printer: {1}) selected for extruder {2}").format(local_material.getName(), extruder.activeMaterial.name, index + 1))
                else:
                    Logger.log("w", "Unable to find material.")

        return warnings
Exemple #21
0
def extruder_manager(application, container_registry) -> ExtruderManager:
    if ExtruderManager.getInstance() is not None:
        # Reset the data
        ExtruderManager._ExtruderManager__instance = None

    with patch("cura.CuraApplication.CuraApplication.getInstance", MagicMock(return_value=application)):
        with patch("UM.Settings.ContainerRegistry.ContainerRegistry.getInstance", MagicMock(return_value=container_registry)):
            manager = ExtruderManager()
    return manager
    def __init__(self):
        super().__init__()
        self._stack = PerObjectContainerStack(stack_id = id(self))
        self._stack.setDirty(False)  # This stack does not need to be saved.
        self._stack.addContainer(InstanceContainer(container_id = "SettingOverrideInstanceContainer"))

        if ExtruderManager.getInstance().extruderCount > 1:
            self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId()
        else:
            self._extruder_stack = None

        self._stack.propertyChanged.connect(self._onSettingChanged)

        ContainerRegistry.getInstance().addContainer(self._stack)

        Application.getInstance().globalContainerStackChanged.connect(self._updateNextStack)
        self.activeExtruderChanged.connect(self._updateNextStack)
        self._updateNextStack()
Exemple #23
0
    def _serialiseSettings(self, stack):
        prefix = ";SETTING_" + str(GCodeWriter.version) + " "  # The prefix to put before each line.
        prefix_length = len(prefix)

        container_with_profile = stack.qualityChanges
        if not container_with_profile:
            Logger.log("e", "No valid quality profile found, not writing settings to GCode!")
            return ""

        flat_global_container = self._createFlattenedContainerInstance(stack.getTop(), container_with_profile)
        # If the quality changes is not set, we need to set type manually
        if flat_global_container.getMetaDataEntry("type", None) is None:
            flat_global_container.addMetaDataEntry("type", "quality_changes")

        # Ensure that quality_type is set. (Can happen if we have empty quality changes).
        if flat_global_container.getMetaDataEntry("quality_type", None) is None:
            flat_global_container.addMetaDataEntry("quality_type", stack.quality.getMetaDataEntry("quality_type", "normal"))

        serialized = flat_global_container.serialize()
        data = {"global_quality": serialized}

        for extruder in sorted(ExtruderManager.getInstance().getMachineExtruders(stack.getId()), key = lambda k: k.getMetaDataEntry("position")):
            extruder_quality = extruder.qualityChanges
            if not extruder_quality:
                Logger.log("w", "No extruder quality profile found, not writing quality for extruder %s to file!", extruder.getId())
                continue
            flat_extruder_quality = self._createFlattenedContainerInstance(extruder.getTop(), extruder_quality)
            # If the quality changes is not set, we need to set type manually
            if flat_extruder_quality.getMetaDataEntry("type", None) is None:
                flat_extruder_quality.addMetaDataEntry("type", "quality_changes")

            # Ensure that extruder is set. (Can happen if we have empty quality changes).
            if flat_extruder_quality.getMetaDataEntry("extruder", None) is None:
                flat_extruder_quality.addMetaDataEntry("extruder", extruder.getBottom().getId())

            # Ensure that quality_type is set. (Can happen if we have empty quality changes).
            if flat_extruder_quality.getMetaDataEntry("quality_type", None) is None:
                flat_extruder_quality.addMetaDataEntry("quality_type", extruder.quality.getMetaDataEntry("quality_type", "normal"))
            extruder_serialized = flat_extruder_quality.serialize()
            data.setdefault("extruder_quality", []).append(extruder_serialized)

        json_string = json.dumps(data)

        # Escape characters that have a special meaning in g-code comments.
        pattern = re.compile("|".join(GCodeWriter.escape_characters.keys()))

        # Perform the replacement with a regular expression.
        escaped_string = pattern.sub(lambda m: GCodeWriter.escape_characters[re.escape(m.group(0))], json_string)

        # Introduce line breaks so that each comment is no longer than 80 characters. Prepend each line with the prefix.
        result = ""

        # Lines have 80 characters, so the payload of each line is 80 - prefix.
        for pos in range(0, len(escaped_string), 80 - prefix_length):
            result += prefix + escaped_string[pos : pos + 80 - prefix_length] + "\n"
        return result
Exemple #24
0
    def write(self, stream, nodes, mode=WorkspaceWriter.OutputMode.BinaryMode):
        mesh_writer = Application.getInstance().getMeshFileHandler().getWriter("3MFWriter")

        if not mesh_writer:  # We need to have the 3mf mesh writer, otherwise we can't save the entire workspace
            return False

        # Indicate that the 3mf mesh writer should not close the archive just yet (we still need to add stuff to it).
        mesh_writer.setStoreArchive(True)
        mesh_writer.write(stream, nodes, mode)

        archive = mesh_writer.getArchive()
        if archive is None:  # This happens if there was no mesh data to write.
            archive = zipfile.ZipFile(stream, "w", compression = zipfile.ZIP_DEFLATED)

        global_container_stack = Application.getInstance().getGlobalContainerStack()

        # Add global container stack data to the archive.
        self._writeContainerToArchive(global_container_stack, archive)

        # Also write all containers in the stack to the file
        for container in global_container_stack.getContainers():
            self._writeContainerToArchive(container, archive)

        # Check if the machine has extruders and save all that data as well.
        for extruder_stack in ExtruderManager.getInstance().getMachineExtruders(global_container_stack.getId()):
            self._writeContainerToArchive(extruder_stack, archive)
            for container in extruder_stack.getContainers():
                self._writeContainerToArchive(container, archive)

        # Write preferences to archive
        original_preferences = Preferences.getInstance() #Copy only the preferences that we use to the workspace.
        temp_preferences = Preferences()
        for preference in {"general/visible_settings", "cura/active_mode", "cura/categories_expanded"}:
            temp_preferences.addPreference(preference, None)
            temp_preferences.setValue(preference, original_preferences.getValue(preference))
        preferences_string = StringIO()
        temp_preferences.writeToFile(preferences_string)
        preferences_file = zipfile.ZipInfo("Cura/preferences.cfg")
        archive.writestr(preferences_file, preferences_string.getvalue())

        # Save Cura version
        version_file = zipfile.ZipInfo("Cura/version.ini")
        version_config_parser = configparser.ConfigParser()
        version_config_parser.add_section("versions")
        version_config_parser.set("versions", "cura_version", Application.getInstance().getVersion())
        version_config_parser.set("versions", "build_type", Application.getInstance().getBuildType())
        version_config_parser.set("versions", "is_debug_mode", str(Application.getInstance().getIsDebugMode()))

        version_file_string = StringIO()
        version_config_parser.write(version_file_string)
        archive.writestr(version_file, version_file_string.getvalue())

        # Close the archive & reset states.
        archive.close()
        mesh_writer.setStoreArchive(False)
        return True
Exemple #25
0
    def __init__(self, width, height):
        super().__init__("layerview", width, height)

        self._layer_shader = None
        self._tool_handle_shader = None
        self._gl = OpenGL.getInstance().getBindingsObject()
        self._scene = Application.getInstance().getController().getScene()
        self._extruder_manager = ExtruderManager.getInstance()

        self._layer_view = None
Exemple #26
0
    def _cacheAllExtruderSettings(self):
        global_stack = cast(ContainerStack, CuraApplication.getInstance().getGlobalContainerStack())

        # NB: keys must be strings for the string formatter
        self._all_extruders_settings = {
            "-1": self._buildReplacementTokens(global_stack)
        }
        for extruder_stack in ExtruderManager.getInstance().getActiveExtruderStacks():
            extruder_nr = extruder_stack.getProperty("extruder_nr", "value")
            self._all_extruders_settings[str(extruder_nr)] = self._buildReplacementTokens(extruder_stack)
Exemple #27
0
    def _getOrderedExtruderStacksList() -> List["ExtruderStack"]:
        extruder_manager = ExtruderManager.getInstance()
        extruder_stacks = extruder_manager.getActiveExtruderStacks()
        active_extruder = extruder_manager.getActiveExtruderStack()

        if active_extruder in extruder_stacks:
            extruder_stacks.remove(active_extruder)
            extruder_stacks = [active_extruder] + extruder_stacks

        return extruder_stacks
Exemple #28
0
    def _onActiveExtruderStackChanged(self):
        extruder_container_stack = ExtruderManager.getInstance().getActiveExtruderStack()
        if not self._global_container_stack or not extruder_container_stack:
            return

        # Make sure there is a definition_changes container to store the machine settings
        definition_changes_container = extruder_container_stack.definitionChanges
        if definition_changes_container == self._empty_container:
            definition_changes_container = CuraStackBuilder.createDefinitionChangesContainer(
                extruder_container_stack, extruder_container_stack.getId() + "_settings")
Exemple #29
0
    def _onGlobalStackChanged(self):
        if self._global_stack:
            self._global_stack.propertyChanged.disconnect(self._onSettingValueChanged)
            self._global_stack.containersChanged.disconnect(self._onChanged)
            extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_stack.getId())
            for extruder in extruders:
                extruder.propertyChanged.disconnect(self._onSettingValueChanged)

        self._global_stack = Application.getInstance().getGlobalContainerStack()

        if self._global_stack:
            self._global_stack.propertyChanged.connect(self._onSettingValueChanged)
            self._global_stack.containersChanged.connect(self._onChanged)

            extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_stack.getId())
            for extruder in extruders:
                extruder.propertyChanged.connect(self._onSettingValueChanged)

            self._onChanged()
Exemple #30
0
 def execute(self, data):
     """
     Entry point of the plugin.
     data is the list of original g-code instructions,
     the returned string is the list of modified g-code instructions
     """
     stretcher = Stretcher(
         ExtruderManager.getInstance().getActiveExtruderStack().getProperty("machine_nozzle_size", "value")
         , self.getSettingValueByKey("wc_stretch"), self.getSettingValueByKey("pw_stretch"))
     return stretcher.execute(data)
    def _onGlobalStackChanged(self) -> None:
        if self._global_stack:
            self._global_stack.propertyChanged.disconnect(
                self._onSettingValueChanged)
            self._global_stack.containersChanged.disconnect(self._onChanged)
            extruders = ExtruderManager.getInstance().getActiveExtruderStacks()
            for extruder in extruders:
                extruder.propertyChanged.disconnect(
                    self._onSettingValueChanged)

        self._global_stack = Application.getInstance().getGlobalContainerStack(
        )

        if self._global_stack:
            self._global_stack.propertyChanged.connect(
                self._onSettingValueChanged)
            self._global_stack.containersChanged.connect(self._onChanged)

            extruders = ExtruderManager.getInstance().getActiveExtruderStacks()
            for extruder in extruders:
                extruder.propertyChanged.connect(self._onSettingValueChanged)

            self._onChanged()
Exemple #32
0
    def initialize(self) -> None:
        self._multi_build_plate_model = self._application.getMultiBuildPlateModel()

        self._application.getController().activeViewChanged.connect(self._onActiveViewChanged)

        if self._multi_build_plate_model:
            self._multi_build_plate_model.activeBuildPlateChanged.connect(self._onActiveViewChanged)

        self._application.globalContainerStackChanged.connect(self._onGlobalStackChanged)
        self._onGlobalStackChanged()

        # extruder enable / disable. Actually wanted to use machine manager here, but the initialization order causes it to crash
        ExtruderManager.getInstance().extrudersChanged.connect(self._extruderChanged)

        self.backendQuit.connect(self._onBackendQuit)
        self.backendConnected.connect(self._onBackendConnected)

        # When a tool operation is in progress, don't slice. So we need to listen for tool operations.
        self._application.getController().toolOperationStarted.connect(self._onToolOperationStarted)
        self._application.getController().toolOperationStopped.connect(self._onToolOperationStopped)

        self._machine_error_checker = self._application.getMachineErrorChecker()
        self._machine_error_checker.errorCheckFinished.connect(self._onStackErrorCheckFinished)
Exemple #33
0
    def setExtruderForSelection(self, extruder_id: str) -> None:
        operation = GroupedOperation()

        nodes_to_change = []
        for node in Selection.getAllSelectedObjects():
            # If the node is a group, apply the active extruder to all children of the group.
            if node.callDecoration("isGroup"):
                for grouped_node in BreadthFirstIterator(
                        node
                ):  #type: ignore #Ignore type error because iter() should get called automatically by Python syntax.
                    if grouped_node.callDecoration(
                            "getActiveExtruder") == extruder_id:
                        continue

                    if grouped_node.callDecoration("isGroup"):
                        continue

                    nodes_to_change.append(grouped_node)
                continue

            # Do not change any nodes that already have the right extruder set.
            if node.callDecoration("getActiveExtruder") == extruder_id:
                continue

            nodes_to_change.append(node)

        if not nodes_to_change:
            # If there are no changes to make, we still need to reset the selected extruders.
            # This is a workaround for checked menu items being deselected while still being
            # selected.
            ExtruderManager.getInstance().resetSelectedObjectExtruders()
            return

        for node in nodes_to_change:
            operation.addOperation(
                SetObjectExtruderOperation(node, extruder_id))
        operation.push()
Exemple #34
0
    def createQualityChanges(self, base_name):
        global_stack = Application.getInstance().getGlobalContainerStack()
        if not global_stack:
            return False

        active_quality_name = self._machine_manager.activeQualityName
        if active_quality_name == "":
            Logger.log(
                "w",
                "No quality container found in stack %s, cannot create profile",
                global_stack.getId())
            return False

        self._machine_manager.blurSettings.emit()
        if base_name is None or base_name == "":
            base_name = active_quality_name
        unique_name = self._container_registry.uniqueName(base_name)

        # Go through the active stacks and create quality_changes containers from the user containers.
        for stack in ExtruderManager.getInstance(
        ).getActiveGlobalAndExtruderStacks():
            user_container = stack.getTop()
            quality_container = stack.quality
            quality_changes_container = stack.qualityChanges
            if not quality_container or not quality_changes_container:
                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,
                Application.getInstance().getGlobalContainerStack().getBottom(
                ), extruder_id)
            self._performMerge(new_changes,
                               quality_changes_container,
                               clear_settings=False)
            self._performMerge(new_changes, user_container)

            self._container_registry.addContainer(new_changes)
            stack.replaceContainer(
                stack.getContainerIndex(quality_changes_container),
                new_changes)

        self._machine_manager.activeQualityChanged.emit()
        return True
    def _fetchInstanceContainers(self):
        global_container_stack = Application.getInstance(
        ).getGlobalContainerStack()
        if not global_container_stack:
            return []

        # Fetch the list of quality changes.
        quality_manager = QualityManager.getInstance()
        machine_definition = quality_manager.getParentMachineDefinition(
            global_container_stack.getBottom())
        quality_changes_list = quality_manager.findAllQualityChangesForMachine(
            machine_definition)

        # Detecting if the machine has multiple extrusion
        multiple_extrusion = False
        # Get the  list of extruders and place the selected extruder at the front of the list.
        extruder_manager = ExtruderManager.getInstance()
        active_extruder = extruder_manager.getActiveExtruderStack()
        extruder_stacks = extruder_manager.getActiveExtruderStacks()
        if active_extruder in extruder_stacks:
            multiple_extrusion = True
            extruder_stacks.remove(active_extruder)
            extruder_stacks = [active_extruder] + extruder_stacks

        # Fetch the list of useable qualities across all extruders.
        # The actual list of quality profiles come from the first extruder in the extruder list.
        quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(
            global_container_stack, extruder_stacks)

        # Filter the quality_change by the list of available quality_types
        quality_type_set = set(
            [x.getMetaDataEntry("quality_type") for x in quality_list])

        if multiple_extrusion:
            # If the printer has multiple extruders then quality changes related to the current extruder are kept
            filtered_quality_changes = [
                qc for qc in quality_changes_list
                if qc.getMetaDataEntry("quality_type") in quality_type_set
                and qc.getMetaDataEntry(
                    "extruder") == active_extruder.definition.getId()
            ]
        else:
            # If not, the quality changes of the global stack are selected
            filtered_quality_changes = [
                qc for qc in quality_changes_list
                if qc.getMetaDataEntry("quality_type") in quality_type_set
            ]

        return quality_list + filtered_quality_changes
Exemple #36
0
    def _fetchInstanceContainers(self):
        global_container_stack = Application.getInstance(
        ).getGlobalContainerStack()
        if global_container_stack is None:
            return []
        global_stack_definition = global_container_stack.getBottom()

        # Get the list of extruders and place the selected extruder at the front of the list.
        extruder_manager = ExtruderManager.getInstance()
        active_extruder = extruder_manager.getActiveExtruderStack()
        extruder_stacks = extruder_manager.getActiveExtruderStacks()
        materials = [global_container_stack.material]

        if active_extruder in extruder_stacks:
            extruder_stacks.remove(active_extruder)
            extruder_stacks = [active_extruder] + extruder_stacks
            materials = [extruder.material for extruder in extruder_stacks]

        # Fetch the list of usable qualities across all extruders.
        # The actual list of quality profiles come from the first extruder in the extruder list.
        result = QualityManager.getInstance(
        ).findAllUsableQualitiesForMachineAndExtruders(global_container_stack,
                                                       extruder_stacks)

        # The usable quality types are set
        quality_type_set = set(
            [x.getMetaDataEntry("quality_type") for x in result])

        # Fetch all qualities available for this machine and the materials selected in extruders
        all_qualities = QualityManager.getInstance(
        ).findAllQualitiesForMachineAndMaterials(global_stack_definition,
                                                 materials)

        # If in the all qualities there is some of them that are not available due to incompatibility with materials
        # we also add it so that they will appear in the slide quality bar. However in recomputeItems will be marked as
        # not available so they will be shown in gray
        for quality in all_qualities:
            if quality.getMetaDataEntry(
                    "quality_type") not in quality_type_set:
                result.append(quality)

        # if still profiles are found, add a single empty_quality ("Not supported") instance to the drop down list
        if len(result) == 0:
            # If not qualities are found we dynamically create a not supported container for this machine + material combination
            not_supported_container = ContainerRegistry.getInstance(
            ).findContainers(id="empty_quality")[0]
            result.append(not_supported_container)

        return result
Exemple #37
0
    def _onActiveExtruderChanged(self):
        new_active_stack = ExtruderManager.getInstance().getActiveExtruderStack()
        if not new_active_stack:
            self._active_container_stack = None
            return

        if new_active_stack != self._active_container_stack:  # Check if changed
            if self._active_container_stack:  # Disconnect signal from old container (if any)
                self._active_container_stack.propertyChanged.disconnect(self._onPropertyChanged)
                self._active_container_stack.containersChanged.disconnect(self._onContainersChanged)

            self._active_container_stack = new_active_stack
            self._active_container_stack.propertyChanged.connect(self._onPropertyChanged)
            self._active_container_stack.containersChanged.connect(self._onContainersChanged)
            self._update()  # Ensure that the settings_with_inheritance_warning list is populated.
    def _onActiveExtruderStackChanged(self):
        extruder_container_stack = ExtruderManager.getInstance().getActiveExtruderStack()
        if not self._global_container_stack or not extruder_container_stack:
            return

        # Make sure there is a definition_changes container to store the machine settings
        definition_changes_container = extruder_container_stack.findContainer({"type": "definition_changes"})
        if not definition_changes_container:
            definition_changes_container = self._createDefinitionChangesContainer(extruder_container_stack, extruder_container_stack.getId() + "_settings")

        # Notify the UI in which container to store the machine settings data
        container_index = extruder_container_stack.getContainerIndex(definition_changes_container)
        if container_index != self._extruder_container_index:
            self._extruder_container_index = container_index
            self.extruderContainerIndexChanged.emit()
Exemple #39
0
    def duplicateQualityOrQualityChanges(self, quality_name, base_name):
        global_stack = Application.getInstance().getGlobalContainerStack()
        if not global_stack or not quality_name:
            return ""
        machine_definition = global_stack.getBottom()

        active_stacks = ExtruderManager.getInstance(
        ).getActiveGlobalAndExtruderStacks()
        material_containers = [stack.material for stack in active_stacks]

        result = self._duplicateQualityOrQualityChangesForMachineType(
            quality_name, base_name,
            QualityManager.getInstance().getParentMachineDefinition(
                machine_definition), material_containers)
        return result[0].getName() if result else ""
Exemple #40
0
    def _getFilteredContainersForStack(self, machine_definition: "DefinitionContainerInterface" = None, material_metadata: Optional[List[Dict[str, Any]]] = None, **kwargs):
        # Fill in any default values.
        if machine_definition is None:
            machine_definition = Application.getInstance().getGlobalContainerStack().getBottom()
            quality_definition_id = machine_definition.getMetaDataEntry("quality_definition")
            if quality_definition_id is not None:
                machine_definition = ContainerRegistry.getInstance().findDefinitionContainers(id = quality_definition_id)[0]

        if not material_metadata:
            active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks()
            if active_stacks:
                material_metadata = [stack.material.getMetaData() for stack in active_stacks]

        criteria = kwargs
        filter_by_material = False

        machine_definition = self.getParentMachineDefinition(machine_definition)
        criteria["definition"] = machine_definition.getId()
        found_containers_with_machine_definition = ContainerRegistry.getInstance().findInstanceContainersMetadata(**criteria)
        whole_machine_definition = self.getWholeMachineDefinition(machine_definition)
        if whole_machine_definition.getMetaDataEntry("has_machine_quality"):
            definition_id = machine_definition.getMetaDataEntry("quality_definition", whole_machine_definition.getId())
            criteria["definition"] = definition_id

            filter_by_material = whole_machine_definition.getMetaDataEntry("has_materials")
        # only fall back to "fdmprinter" when there is no container for this machine
        elif not found_containers_with_machine_definition:
            criteria["definition"] = "fdmprinter"

        # Stick the material IDs in a set
        material_ids = set()

        for material_instance in material_metadata:
            if material_instance is not None:
                # Add the parent material too.
                for basic_material in self._getBasicMaterialMetadatas(material_instance):
                    material_ids.add(basic_material["id"])
                material_ids.add(material_instance["id"])
        containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria)

        result = []
        for container in containers:
            # If the machine specifies we should filter by material, exclude containers that do not match any active material.
            if filter_by_material and container.getMetaDataEntry("material") not in material_ids and "global_quality" not in kwargs:
                continue
            result.append(container)

        return result
Exemple #41
0
    def _handlePerObjectSettings(self, node: CuraSceneNode,
                                 message: Arcus.PythonMessage):
        stack = node.callDecoration("getStack")

        # Check if the node has a stack attached to it and the stack has any settings in the top container.
        if not stack:
            return

        # Check all settings for relations, so we can also calculate the correct values for dependent settings.
        top_of_stack = stack.getTop()  # Cache for efficiency.
        changed_setting_keys = top_of_stack.getAllKeys()

        # Remove support_enable for belt-printers
        if self._scene.getRoot().callDecoration("getGantryAngle"):
            for key in ["support_enable", "support_mesh_drop_down"]:
                try:
                    changed_setting_keys.remove(key)
                except KeyError:
                    pass

        # Add all relations to changed settings as well.
        for key in top_of_stack.getAllKeys():
            instance = top_of_stack.getInstance(key)
            self._addRelations(changed_setting_keys,
                               instance.definition.relations)
            Job.yieldThread()

        # Ensure that the engine is aware what the build extruder is.
        changed_setting_keys.add("extruder_nr")

        # Get values for all changed settings
        for key in changed_setting_keys:
            setting = message.addRepeatedMessage("settings")
            setting.name = key
            extruder = int(
                round(float(stack.getProperty(key, "limit_to_extruder"))))

            # Check if limited to a specific extruder, but not overridden by per-object settings.
            if extruder >= 0 and key not in changed_setting_keys:
                limited_stack = ExtruderManager.getInstance(
                ).getActiveExtruderStacks()[extruder]
            else:
                limited_stack = stack

            setting.value = str(limited_stack.getProperty(
                key, "value")).encode("utf-8")

            Job.yieldThread()
Exemple #42
0
 def _updateExtraZClearance(self) -> None:
     extra_z = 0.0
     extruders = ExtruderManager.getInstance().getMachineExtruders(self._global_container_stack.getId())
     use_extruders = False
     for extruder in extruders:
         if extruder.getProperty("retraction_hop_enabled", "value"):
             retraction_hop = extruder.getProperty("retraction_hop", "value")
             if extra_z is None or retraction_hop > extra_z:
                 extra_z = retraction_hop
         use_extruders = True
     if not use_extruders:
         # If no extruders, take global value.
         if self._global_container_stack.getProperty("retraction_hop_enabled", "value"):
             extra_z = self._global_container_stack.getProperty("retraction_hop", "value")
     if extra_z != self._extra_z_clearance:
         self._extra_z_clearance = extra_z
    def __init__(self):
        super().__init__()
        self._stack = PerObjectContainerStack(stack_id = "per_object_stack_" + str(id(self)))
        self._stack.setDirty(False)  # This stack does not need to be saved.
        self._stack.addContainer(InstanceContainer(container_id = "SettingOverrideInstanceContainer"))
        self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId()

        self._is_non_printing_mesh = False

        self._stack.propertyChanged.connect(self._onSettingChanged)

        Application.getInstance().getContainerRegistry().addContainer(self._stack)

        Application.getInstance().globalContainerStackChanged.connect(self._updateNextStack)
        self.activeExtruderChanged.connect(self._updateNextStack)
        self._updateNextStack()
    def _fetchInstanceContainers(self):
        global_container_stack = Application.getInstance(
        ).getGlobalContainerStack()
        if not global_container_stack:
            return {}, {}

        # Fetch the list of quality changes.
        quality_manager = QualityManager.getInstance()
        machine_definition = quality_manager.getParentMachineDefinition(
            global_container_stack.definition)
        quality_changes_list = quality_manager.findAllQualityChangesForMachine(
            machine_definition)

        extruder_manager = ExtruderManager.getInstance()
        active_extruder = extruder_manager.getActiveExtruderStack()
        extruder_stacks = self._getOrderedExtruderStacksList()

        # Fetch the list of usable qualities across all extruders.
        # The actual list of quality profiles come from the first extruder in the extruder list.
        quality_list = quality_manager.findAllUsableQualitiesForMachineAndExtruders(
            global_container_stack, extruder_stacks)

        # Filter the quality_change by the list of available quality_types
        quality_type_set = set(
            [x.getMetaDataEntry("quality_type") for x in quality_list])
        # Also show custom profiles based on "Not Supported" quality profile
        quality_type_set.add(
            self._empty_quality.getMetaDataEntry("quality_type"))
        filtered_quality_changes = {
            qc.getId(): qc
            for qc in quality_changes_list
            if qc.getMetaDataEntry("quality_type") in quality_type_set and ((
                qc.getMetaDataEntry("extruder") == active_extruder.definition.
                getMetaDataEntry("quality_definition") or qc.getMetaDataEntry(
                    "extruder") == active_extruder.definition.getId()
            ) if qc.getMetaDataEntry("extruder") is not None else True) and (
                (qc.getMetaDataEntry("material") == active_extruder.material.id
                 ) if machine_definition.
                getMetaDataEntry("has_machine_materials") else True)
        }

        result = filtered_quality_changes
        for q in quality_list:
            if q.getId() != "empty_quality":
                result[q.getId()] = q
        return result, {
        }  #Only return true profiles for now, no metadata. The quality manager is not able to get only metadata yet.
Exemple #45
0
    def _handlePerObjectSettings(self, node: CuraSceneNode,
                                 message: Arcus.PythonMessage):
        """Check if a node has per object settings and ensure that they are set correctly in the message

        :param node: Node to check.
        :param message: object_lists message to put the per object settings in
        """

        stack = node.callDecoration("getStack")

        # Check if the node has a stack attached to it and the stack has any settings in the top container.
        if not stack:
            return

        # Check all settings for relations, so we can also calculate the correct values for dependent settings.
        top_of_stack = stack.getTop()  # Cache for efficiency.
        changed_setting_keys = top_of_stack.getAllKeys()

        # Add all relations to changed settings as well.
        for key in top_of_stack.getAllKeys():
            instance = top_of_stack.getInstance(key)
            self._addRelations(changed_setting_keys,
                               instance.definition.relations)
            Job.yieldThread()

        # Ensure that the engine is aware what the build extruder is.
        changed_setting_keys.add("extruder_nr")

        # Get values for all changed settings
        for key in changed_setting_keys:
            setting = message.addRepeatedMessage("settings")
            setting.name = key
            extruder = int(
                round(float(stack.getProperty(key, "limit_to_extruder"))))

            # Check if limited to a specific extruder, but not overridden by per-object settings.
            if extruder >= 0 and key not in changed_setting_keys:
                limited_stack = ExtruderManager.getInstance(
                ).getActiveExtruderStacks()[extruder]
            else:
                limited_stack = stack

            setting.value = str(limited_stack.getProperty(
                key, "value")).encode("utf-8")

            Job.yieldThread()
Exemple #46
0
    def __init__(self, width, height):
        super().__init__("simulationview", width, height)

        self._layer_shader = None
        self._layer_shadow_shader = None
        self._current_shader = None  # This shader will be the shadow or the normal depending if the user wants to see the paths or the layers
        self._tool_handle_shader = None
        self._nozzle_shader = None
        self._old_current_layer = 0
        self._old_current_path = 0
        self._switching_layers = True  # It tracks when the user is moving the layers' slider
        self._gl = OpenGL.getInstance().getBindingsObject()
        self._scene = Application.getInstance().getController().getScene()
        self._extruder_manager = ExtruderManager.getInstance()

        self._layer_view = None
        self._compatibility_mode = None
    def _getSettingProperty(self, setting_key, property="value"):
        multi_extrusion = self._global_stack.getProperty(
            "machine_extruder_count", "value") > 1

        if not multi_extrusion:
            return self._global_stack.getProperty(setting_key, property)

        extruder_index = self._global_stack.getProperty(
            setting_key, "limit_to_extruder")
        if extruder_index == "-1":  # If extruder index is -1 use global instead
            return self._global_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]
        return stack.getProperty(setting_key, property)
Exemple #48
0
    def _fetchInstanceContainers(self):
        global_container_stack = Application.getInstance().getGlobalContainerStack()
        if global_container_stack is None:
            return []

        # Get the  list of extruders and place the selected extruder at the front of the list.
        extruder_manager = ExtruderManager.getInstance()
        active_extruder = extruder_manager.getActiveExtruderStack()
        extruder_stacks = extruder_manager.getActiveExtruderStacks()
        if active_extruder in extruder_stacks:
            extruder_stacks.remove(active_extruder)
            extruder_stacks = [active_extruder] + extruder_stacks

        # Fetch the list of useable qualities across all extruders.
        # The actual list of quality profiles come from the first extruder in the extruder list.
        return QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack,
                                                                                         extruder_stacks)
Exemple #49
0
    def _getFilteredContainersForStack(self, machine_definition=None, material_containers=None, **kwargs):
        # Fill in any default values.
        if machine_definition is None:
            machine_definition = Application.getInstance().getGlobalContainerStack().getBottom()
            quality_definition_id = machine_definition.getMetaDataEntry("quality_definition")
            if quality_definition_id is not None:
                machine_definition = ContainerRegistry.getInstance().findDefinitionContainers(id=quality_definition_id)[0]

        if material_containers is None:
            active_stacks = ExtruderManager.getInstance().getActiveGlobalAndExtruderStacks()
            material_containers = [stack.findContainer(type="material") for stack in active_stacks]

        criteria = kwargs
        filter_by_material = False

        machine_definition = self.getParentMachineDefinition(machine_definition)
        whole_machine_definition = self.getWholeMachineDefinition(machine_definition)
        if whole_machine_definition.getMetaDataEntry("has_machine_quality"):
            definition_id = machine_definition.getMetaDataEntry("quality_definition", whole_machine_definition.getId())
            criteria["definition"] = definition_id

            filter_by_material = whole_machine_definition.getMetaDataEntry("has_materials")
        else:
            criteria["definition"] = "fdmprinter"

        # Stick the material IDs in a set
        if material_containers is None or len(material_containers) == 0:
            filter_by_material = False
        else:
            material_ids = set()
            for material_instance in material_containers:
                if material_instance is not None:
                    # Add the parent material too.
                    for basic_material in self._getBasicMaterials(material_instance):
                        material_ids.add(basic_material.getId())
                    material_ids.add(material_instance.getId())

        containers = ContainerRegistry.getInstance().findInstanceContainers(**criteria)

        result = []
        for container in containers:
            # If the machine specifies we should filter by material, exclude containers that do not match any active material.
            if filter_by_material and container.getMetaDataEntry("material") not in material_ids and not "global_quality" in kwargs:
                continue
            result.append(container)
        return result
Exemple #50
0
 def _buildGlobalInheritsStackMessage(self, stack):
     for key in stack.getAllKeys():
         extruder = int(
             round(float(stack.getProperty(key, "limit_to_extruder"))))
         if key == "adhesion_extruder_nr" and int(
                 stack.getProperty(key, "value")) == -1:
             if "Left" in ExtruderManager.getInstance(
             ).getUsedExtruderStacks()[0].getName():
                 extruder = 0
             else:
                 extruder = 1
         if extruder >= 0:  #Set to a specific extruder.
             setting_extruder = self._slice_message.addRepeatedMessage(
                 "limit_to_extruder")
             setting_extruder.name = key
             setting_extruder.extruder = extruder
         Job.yieldThread()
    def _getSettingProperty(self, setting_key, prop = "value"):
        per_mesh_stack = self._node.callDecoration("getStack")
        if per_mesh_stack:
            return per_mesh_stack.getProperty(setting_key, prop)

        extruder_index = self._global_stack.getProperty(setting_key, "limit_to_extruder")
        if extruder_index == "-1":
            # No limit_to_extruder
            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 = ContainerRegistry.getInstance().findContainerStacks(id = extruder_stack_id)[0]
            return extruder_stack.getProperty(setting_key, prop)
        else:
            # Limit_to_extruder is set. The global stack handles this then
            return self._global_stack.getProperty(setting_key, prop)
Exemple #52
0
    def clearUserContainers(self) -> None:
        self._machine_manager.blurSettings.emit()

        send_emits_containers = []

        # Go through global and extruder stacks and clear their topmost container (the user settings).
        for stack in ExtruderManager.getInstance(
        ).getActiveGlobalAndExtruderStacks():
            container = stack.userChanges
            container.clear()
            send_emits_containers.append(container)

        # user changes are possibly added to make the current setup match the current enabled extruders
        Application.getInstance().getMachineManager().correctExtruderSettings()

        for container in send_emits_containers:
            container.sendPostponedEmits()
Exemple #53
0
    def _onActiveExtruderChanged(self):
        if self._global_container_stack:
            # Connect all extruders of the active machine. This might cause a few connects that have already happend,
            # but that shouldn't cause issues as only new / unique connections are added.
            extruders = list(ExtruderManager.getInstance().getMachineExtruders(
                self._global_container_stack.getId()))
            if extruders:
                for extruder in extruders:
                    extruder.propertyChanged.connect(self._onSettingChanged)
        if self._active_extruder_stack:
            self._active_extruder_stack.containersChanged.disconnect(
                self._onChanged)

        self._active_extruder_stack = cura.Settings.ExtruderManager.getInstance(
        ).getActiveExtruderStack()
        if self._active_extruder_stack:
            self._active_extruder_stack.containersChanged.connect(
                self._onChanged)
Exemple #54
0
    def _cacheAllExtruderSettings(self):
        global_stack = cast(
            ContainerStack,
            CuraApplication.getInstance().getGlobalContainerStack())

        # NB: keys must be strings for the string formatter
        self._all_extruders_settings = {
            "-1": self._buildReplacementTokens(global_stack)
        }
        QCoreApplication.processEvents(
        )  # Ensure that the GUI does not freeze.
        for extruder_stack in ExtruderManager.getInstance(
        ).getActiveExtruderStacks():
            extruder_nr = extruder_stack.getProperty("extruder_nr", "value")
            self._all_extruders_settings[str(
                extruder_nr)] = self._buildReplacementTokens(extruder_stack)
            QCoreApplication.processEvents(
            )  # Ensure that the GUI does not freeze.
Exemple #55
0
    def getOverridesForExtruder(self, key, extruder_index):
        result = []

        extruder_stack = ExtruderManager.getInstance().getExtruderStack(extruder_index)
        if not extruder_stack:
            Logger.log("w", "Unable to find extruder for current machine with index %s", extruder_index)
            return result

        definitions = self._global_container_stack.definition.findDefinitions(key = key)
        if not definitions:
            Logger.log("w", "Could not find definition for key [%s] (2)", key)
            return result

        for key in definitions[0].getAllKeys():
            if self._settingIsOverwritingInheritance(key, extruder_stack):
                result.append(key)

        return result
    def write(self, stream, nodes, mode=WorkspaceWriter.OutputMode.BinaryMode):
        mesh_writer = Application.getInstance().getMeshFileHandler().getWriter(
            "3MFWriter")

        if not mesh_writer:  # We need to have the 3mf mesh writer, otherwise we can't save the entire workspace
            return False

        # Indicate that the 3mf mesh writer should not close the archive just yet (we still need to add stuff to it).
        mesh_writer.setStoreArchive(True)
        mesh_writer.write(stream, nodes, mode)

        archive = mesh_writer.getArchive()
        if archive is None:  # This happens if there was no mesh data to write.
            archive = zipfile.ZipFile(stream,
                                      "w",
                                      compression=zipfile.ZIP_DEFLATED)

        global_container_stack = Application.getInstance(
        ).getGlobalContainerStack()

        # Add global container stack data to the archive.
        self._writeContainerToArchive(global_container_stack, archive)

        # Also write all containers in the stack to the file
        for container in global_container_stack.getContainers():
            self._writeContainerToArchive(container, archive)

        # Check if the machine has extruders and save all that data as well.
        for extruder_stack in ExtruderManager.getInstance(
        ).getMachineExtruders(global_container_stack.getId()):
            self._writeContainerToArchive(extruder_stack, archive)
            for container in extruder_stack.getContainers():
                self._writeContainerToArchive(container, archive)

        # Write preferences to archive
        preferences_file = zipfile.ZipInfo("Cura/preferences.cfg")
        preferences_string = StringIO()
        Preferences.getInstance().writeToFile(preferences_string)
        archive.writestr(preferences_file, preferences_string.getvalue())

        # Close the archive & reset states.
        archive.close()
        mesh_writer.setStoreArchive(False)
        return True
    def __init__(self):
        super().__init__()
        self._stack = PerObjectContainerStack(container_id = "per_object_stack_" + str(id(self)))
        self._stack.setDirty(False)  # This stack does not need to be saved.
        user_container = InstanceContainer(container_id = self._generateUniqueName())
        user_container.setMetaDataEntry("type", "user")
        self._stack.userChanges = user_container
        self._extruder_stack = ExtruderManager.getInstance().getExtruderStack(0).getId()

        self._is_non_printing_mesh = False
        self._is_non_thumbnail_visible_mesh = False

        self._stack.propertyChanged.connect(self._onSettingChanged)

        Application.getInstance().getContainerRegistry().addContainer(self._stack)

        Application.getInstance().globalContainerStackChanged.connect(self._updateNextStack)
        self.activeExtruderChanged.connect(self._updateNextStack)
        self._updateNextStack()
    def updateQualityChanges(self):
        global_stack = Application.getInstance().getGlobalContainerStack()
        if not global_stack:
            return False

        self._machine_manager.blurSettings.emit()

        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.qualityChanges
            if not quality_changes or quality_changes.isReadOnly():
                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())

        self._machine_manager.activeQualityChanged.emit()

        return True
    def _onGlobalContainerChanged(self):
        global_container_stack = Application.getInstance().getGlobalContainerStack()
        if global_container_stack:
            self._multi_extrusion = global_container_stack.getProperty("machine_extruder_count", "value") > 1

            # Ensure that all extruder data is reset
            if not self._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()

            root_node = Application.getInstance().getController().getScene().getRoot()
            for node in DepthFirstIterator(root_node):
                node.callDecoration("setActiveExtruder", default_stack_id)

            self._updateEnabled()
Exemple #60
0
    def _fetchInstanceContainers(self):
        global_container_stack = Application.getInstance().getGlobalContainerStack()
        if not global_container_stack:
            return []

        # Fetch the list of quality changes.
        quality_manager = QualityManager.getInstance()
        machine_definition = quality_manager.getParentMachineDefinition(global_container_stack.getBottom())
        quality_changes_list = quality_manager.findAllQualityChangesForMachine(machine_definition)

        # Fetch the list of qualities
        quality_list =  QualityManager.getInstance().findAllUsableQualitiesForMachineAndExtruders(global_container_stack,
                                                              ExtruderManager.getInstance().getActiveExtruderStacks())

        # Filter the quality_change by the list of available quality_types
        quality_type_set = set([x.getMetaDataEntry("quality_type") for x in quality_list])
        filtered_quality_changes = [qc for qc in quality_changes_list if qc.getMetaDataEntry("quality_type") in quality_type_set]

        return filtered_quality_changes