Merge branch 'master' into CURA-7455_Keep_printer_configurations_when_cloud_printer_removed_from_account

This commit is contained in:
Kostas Karmas 2020-06-10 11:51:50 +02:00
commit fdc555caf3
24 changed files with 278 additions and 218 deletions

View file

@ -886,8 +886,9 @@ class CuraApplication(QtApplication):
# Initialize camera tool # Initialize camera tool
camera_tool = controller.getTool("CameraTool") camera_tool = controller.getTool("CameraTool")
camera_tool.setOrigin(Vector(0, 100, 0)) if camera_tool:
camera_tool.setZoomRange(0.1, 2000) camera_tool.setOrigin(Vector(0, 100, 0))
camera_tool.setZoomRange(0.1, 2000)
# Initialize camera animations # Initialize camera animations
self._camera_animation = CameraAnimation.CameraAnimation() self._camera_animation = CameraAnimation.CameraAnimation()
@ -1909,7 +1910,6 @@ class CuraApplication(QtApplication):
return return
selection_pass = cast(SelectionPass, self.getRenderer().getRenderPass("selection")) selection_pass = cast(SelectionPass, self.getRenderer().getRenderPass("selection"))
if not selection_pass: # If you right-click before the rendering has been initialised there might not be a selection pass yet. if not selection_pass: # If you right-click before the rendering has been initialised there might not be a selection pass yet.
print("--------------ding! Got the crash.")
return return
node = self.getController().getScene().findObject(selection_pass.getIdAtPosition(x, y)) node = self.getController().getScene().findObject(selection_pass.getIdAtPosition(x, y))
if not node: if not node:

View file

@ -100,7 +100,8 @@ class QualitySettingsModel(ListModel):
# the settings in that quality_changes_group. # the settings in that quality_changes_group.
if quality_changes_group is not None: if quality_changes_group is not None:
container_registry = ContainerRegistry.getInstance() container_registry = ContainerRegistry.getInstance()
global_containers = container_registry.findContainers(id = quality_changes_group.metadata_for_global["id"]) metadata_for_global = quality_changes_group.metadata_for_global
global_containers = container_registry.findContainers(id = metadata_for_global["id"])
global_container = None if len(global_containers) == 0 else global_containers[0] global_container = None if len(global_containers) == 0 else global_containers[0]
extruders_containers = {pos: container_registry.findContainers(id = quality_changes_group.metadata_per_extruder[pos]["id"]) for pos in quality_changes_group.metadata_per_extruder} extruders_containers = {pos: container_registry.findContainers(id = quality_changes_group.metadata_per_extruder[pos]["id"]) for pos in quality_changes_group.metadata_per_extruder}
extruders_container = {pos: None if not containers else containers[0] for pos, containers in extruders_containers.items()} extruders_container = {pos: None if not containers else containers[0] for pos, containers in extruders_containers.items()}

View file

@ -2,6 +2,7 @@
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from http.server import HTTPServer from http.server import HTTPServer
from socketserver import ThreadingMixIn
from typing import Callable, Any, TYPE_CHECKING from typing import Callable, Any, TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
@ -9,7 +10,7 @@ if TYPE_CHECKING:
from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers from cura.OAuth2.AuthorizationHelpers import AuthorizationHelpers
class AuthorizationRequestServer(HTTPServer): class AuthorizationRequestServer(ThreadingMixIn, HTTPServer):
"""The authorization request callback handler server. """The authorization request callback handler server.
This subclass is needed to be able to pass some data to the request handler. This cannot be done on the request This subclass is needed to be able to pass some data to the request handler. This cannot be done on the request

View file

@ -1,6 +1,6 @@
# Copyright (c) 2020 Ultimaker B.V. # Copyright (c) 2020 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
import sys
import threading import threading
from typing import Any, Callable, Optional, TYPE_CHECKING from typing import Any, Callable, Optional, TYPE_CHECKING
@ -71,7 +71,7 @@ class LocalAuthorizationServer:
self._web_server.setState(state) self._web_server.setState(state)
# Start the server on a new thread. # Start the server on a new thread.
self._web_server_thread = threading.Thread(None, self._web_server.serve_forever, daemon = self._daemon) self._web_server_thread = threading.Thread(None, self._serve_forever, daemon = self._daemon)
self._web_server_thread.start() self._web_server_thread.start()
def stop(self) -> None: def stop(self) -> None:
@ -81,9 +81,28 @@ class LocalAuthorizationServer:
if self._web_server: if self._web_server:
try: try:
self._web_server.shutdown()
self._web_server.server_close() self._web_server.server_close()
except OSError: except OSError:
# OS error can happen if the socket was already closed. We really don't care about that case. # OS error can happen if the socket was already closed. We really don't care about that case.
pass pass
self._web_server = None self._web_server = None
self._web_server_thread = None self._web_server_thread = None
def _serve_forever(self) -> None:
"""
If the platform is windows, this function calls the serve_forever function of the _web_server, catching any
OSErrors that may occur in the thread, thus making the reported message more log-friendly.
If it is any other platform, it just calls the serve_forever function immediately.
:return: None
"""
if self._web_server:
if sys.platform == "win32":
try:
self._web_server.serve_forever()
except OSError as e:
Logger.warning(str(e))
else:
# Leave the default behavior in non-windows platforms
self._web_server.serve_forever()

View file

@ -6,6 +6,7 @@ from PyQt5.QtWidgets import QApplication
from UM.Scene.Camera import Camera from UM.Scene.Camera import Camera
from cura.UI.ObjectsModel import ObjectsModel from cura.UI.ObjectsModel import ObjectsModel
from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel from cura.Machines.Models.MultiBuildPlateModel import MultiBuildPlateModel
from cura.Scene.CuraSceneNode import CuraSceneNode
from UM.Application import Application from UM.Application import Application
from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator from UM.Scene.Iterator.DepthFirstIterator import DepthFirstIterator
@ -43,6 +44,26 @@ class CuraSceneController(QObject):
self._change_timer.start() self._change_timer.start()
def updateMaxBuildPlate(self, *args): def updateMaxBuildPlate(self, *args):
global_stack = Application.getInstance().getGlobalContainerStack()
if global_stack:
scene_has_support_meshes = self._sceneHasSupportMeshes() # TODO: see if this can be cached
if scene_has_support_meshes != global_stack.getProperty("support_meshes_present", "value"):
# Adjust the setting without having the setting value in an InstanceContainer
setting_definitions = global_stack.definition.findDefinitions(key="support_meshes_present")
if setting_definitions:
# Recreate the setting definition because the default_value is readonly
definition_dict = setting_definitions[0].serialize_to_dict()
definition_dict["enabled"] = False # The enabled property has a value that would need to be evaluated
definition_dict["default_value"] = scene_has_support_meshes
relations = setting_definitions[0].relations # Relations are wiped when deserializing from a dict
setting_definitions[0].deserialize(definition_dict)
# Restore relations and notify them that the setting has changed
for relation in relations:
setting_definitions[0].relations.append(relation)
global_stack.propertyChanged.emit(relation.target.key, "enabled")
max_build_plate = self._calcMaxBuildPlate() max_build_plate = self._calcMaxBuildPlate()
changed = False changed = False
if max_build_plate != self._max_build_plate: if max_build_plate != self._max_build_plate:
@ -72,6 +93,15 @@ class CuraSceneController(QObject):
max_build_plate = max(build_plate_number, max_build_plate) max_build_plate = max(build_plate_number, max_build_plate)
return max_build_plate return max_build_plate
def _sceneHasSupportMeshes(self):
root = Application.getInstance().getController().getScene().getRoot()
for node in root.getAllChildren():
if isinstance(node, CuraSceneNode):
per_mesh_stack = node.callDecoration("getStack")
if per_mesh_stack and per_mesh_stack.getProperty("support_mesh", "value"):
return True
return False
@pyqtSlot(int) @pyqtSlot(int)
def changeSelection(self, index): def changeSelection(self, index):
"""Either select or deselect an item""" """Either select or deselect an item"""

View file

@ -38,6 +38,12 @@ class CuraSceneNode(SceneNode):
def isSelectable(self) -> bool: def isSelectable(self) -> bool:
return super().isSelectable() and self.callDecoration("getBuildPlateNumber") == cura.CuraApplication.CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate return super().isSelectable() and self.callDecoration("getBuildPlateNumber") == cura.CuraApplication.CuraApplication.getInstance().getMultiBuildPlateModel().activeBuildPlate
def isSupportMesh(self) -> bool:
per_mesh_stack = self.callDecoration("getStack")
if not per_mesh_stack:
return False
return per_mesh_stack.getProperty("support_mesh", "value")
def getPrintingExtruder(self) -> Optional[ExtruderStack]: def getPrintingExtruder(self) -> Optional[ExtruderStack]:
"""Get the extruder used to print this node. If there is no active node, then the extruder in position zero is returned """Get the extruder used to print this node. If there is no active node, then the extruder in position zero is returned

View file

@ -302,6 +302,7 @@ class ExtruderManager(QObject):
for extruder in self.getMachineExtruders(machine_id): for extruder in self.getMachineExtruders(machine_id):
ContainerRegistry.getInstance().removeContainer(extruder.userChanges.getId()) ContainerRegistry.getInstance().removeContainer(extruder.userChanges.getId())
ContainerRegistry.getInstance().removeContainer(extruder.definitionChanges.getId())
ContainerRegistry.getInstance().removeContainer(extruder.getId()) ContainerRegistry.getInstance().removeContainer(extruder.getId())
if machine_id in self._extruder_trains: if machine_id in self._extruder_trains:
del self._extruder_trains[machine_id] del self._extruder_trains[machine_id]

View file

@ -490,7 +490,11 @@ class MachineManager(QObject):
@pyqtProperty(bool, notify = printerConnectedStatusChanged) @pyqtProperty(bool, notify = printerConnectedStatusChanged)
def activeMachineIsGroup(self) -> bool: def activeMachineIsGroup(self) -> bool:
return bool(self._printer_output_devices) and len(self._printer_output_devices[0].printers) > 1 if self.activeMachine is None:
return False
group_size = int(self.activeMachine.getMetaDataEntry("group_size", "-1"))
return group_size > 1
@pyqtProperty(bool, notify = printerConnectedStatusChanged) @pyqtProperty(bool, notify = printerConnectedStatusChanged)
def activeMachineIsLinkedToCurrentAccount(self) -> bool: def activeMachineIsLinkedToCurrentAccount(self) -> bool:
@ -726,6 +730,8 @@ class MachineManager(QObject):
containers = CuraContainerRegistry.getInstance().findInstanceContainersMetadata(type = "user", machine = machine_id) containers = CuraContainerRegistry.getInstance().findInstanceContainersMetadata(type = "user", machine = machine_id)
for container in containers: for container in containers:
CuraContainerRegistry.getInstance().removeContainer(container["id"]) CuraContainerRegistry.getInstance().removeContainer(container["id"])
machine_stack = CuraContainerRegistry.getInstance().findContainerStacks(type = "machine", name = machine_id)[0]
CuraContainerRegistry.getInstance().removeContainer(machine_stack.definitionChanges.getId())
CuraContainerRegistry.getInstance().removeContainer(machine_id) CuraContainerRegistry.getInstance().removeContainer(machine_id)
# If the printer that is being removed is a network printer, the hidden printers have to be also removed # If the printer that is being removed is a network printer, the hidden printers have to be also removed

View file

@ -466,10 +466,10 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
extruder_info.intent_info = instance_container_info_dict[intent_id] extruder_info.intent_info = instance_container_info_dict[intent_id]
if not machine_conflict and containers_found_dict["machine"]: if not machine_conflict and containers_found_dict["machine"]:
if position not in global_stack.extruders: if int(position) >= len(global_stack.extrurderList):
continue continue
existing_extruder_stack = global_stack.extruders[position] existing_extruder_stack = global_stack.extruderList[int(position)]
# check if there are any changes at all in any of the container stacks. # check if there are any changes at all in any of the container stacks.
id_list = self._getContainerIdListFromSerialized(serialized) id_list = self._getContainerIdListFromSerialized(serialized)
for index, container_id in enumerate(id_list): for index, container_id in enumerate(id_list):

View file

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2020 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from UM.Application import Application from UM.Application import Application
@ -114,7 +114,7 @@ class FirmwareUpdateCheckerJob(Job):
# notify the user when no new firmware version is available. # notify the user when no new firmware version is available.
if (checked_version != "") and (checked_version != current_version): if (checked_version != "") and (checked_version != current_version):
Logger.log("i", "Showing firmware update message for new version: {version}".format(version = current_version)) Logger.log("i", "Showing firmware update message for new version: {version}".format(version = current_version))
message = FirmwareUpdateCheckerMessage(machine_id, self._machine_name, message = FirmwareUpdateCheckerMessage(machine_id, self._machine_name, current_version,
self._lookups.getRedirectUserUrl()) self._lookups.getRedirectUserUrl())
message.actionTriggered.connect(self._callback) message.actionTriggered.connect(self._callback)
message.show() message.show()

View file

@ -1,4 +1,4 @@
# Copyright (c) 2018 Ultimaker B.V. # Copyright (c) 2020 Ultimaker B.V.
# Cura is released under the terms of the LGPLv3 or higher. # Cura is released under the terms of the LGPLv3 or higher.
from UM.i18n import i18nCatalog from UM.i18n import i18nCatalog
@ -11,11 +11,12 @@ i18n_catalog = i18nCatalog("cura")
class FirmwareUpdateCheckerMessage(Message): class FirmwareUpdateCheckerMessage(Message):
STR_ACTION_DOWNLOAD = "download" STR_ACTION_DOWNLOAD = "download"
def __init__(self, machine_id: int, machine_name: str, download_url: str) -> None: def __init__(self, machine_id: int, machine_name: str, latest_version: str, download_url: str) -> None:
super().__init__(i18n_catalog.i18nc( super().__init__(i18n_catalog.i18nc(
"@info Don't translate {machine_name}, since it gets replaced by a printer name!", "@info Don't translate {machine_name}, since it gets replaced by a printer name!",
"New features are available for your {machine_name}! It is recommended to update the firmware on your printer.").format( "New features or bug-fixes may be available for your {machine_name}! If not already at the latest version, "
machine_name = machine_name), "it is recommended to update the firmware on your printer to version {latest_version}.").format(
machine_name = machine_name, latest_version = latest_version),
title = i18n_catalog.i18nc( title = i18n_catalog.i18nc(
"@info:title The %s gets replaced with the printer name.", "@info:title The %s gets replaced with the printer name.",
"New %s firmware available") % machine_name) "New %s firmware available") % machine_name)

View file

@ -32,10 +32,7 @@ Item
var type = currentMeshType var type = currentMeshType
// set checked state of mesh type buttons // set checked state of mesh type buttons
normalButton.checked = type === normalMeshType updateMeshTypeCheckedState(type)
supportMeshButton.checked = type === supportMeshType
overhangMeshButton.checked = type === infillMeshType || type === cuttingMeshType
antiOverhangMeshButton.checked = type === antiOverhangMeshType
// update active type label // update active type label
for (var button in meshTypeButtons.children) for (var button in meshTypeButtons.children)
@ -49,9 +46,19 @@ Item
visibility_handler.addSkipResetSetting(currentMeshType) visibility_handler.addSkipResetSetting(currentMeshType)
} }
function updateMeshTypeCheckedState(type)
{
// set checked state of mesh type buttons
normalButton.checked = type === normalMeshType
supportMeshButton.checked = type === supportMeshType
overlapMeshButton.checked = type === infillMeshType || type === cuttingMeshType
antiOverhangMeshButton.checked = type === antiOverhangMeshType
}
function setMeshType(type) function setMeshType(type)
{ {
UM.ActiveTool.setProperty("MeshType", type) UM.ActiveTool.setProperty("MeshType", type)
updateMeshTypeCheckedState(type)
} }
UM.I18nCatalog { id: catalog; name: "cura"} UM.I18nCatalog { id: catalog; name: "cura"}
@ -95,7 +102,7 @@ Item
Button Button
{ {
id: overhangMeshButton id: overlapMeshButton
text: catalog.i18nc("@label", "Modify settings for overlaps") text: catalog.i18nc("@label", "Modify settings for overlaps")
iconSource: UM.Theme.getIcon("pos_modify_overlaps"); iconSource: UM.Theme.getIcon("pos_modify_overlaps");
property bool needBorder: true property bool needBorder: true

View file

@ -289,6 +289,13 @@ class Stretcher:
self.layergcode = self.layergcode + sout + "\n" self.layergcode = self.layergcode + sout + "\n"
ipos = ipos + 1 ipos = ipos + 1
else: else:
# The command is intended to be passed through unmodified via
# the comment field. In the case of an extruder only move, though,
# the extruder and potentially the feed rate are modified.
# We need to update self.outpos accordingly so that subsequent calls
# to stepToGcode() knows about the extruder and feed rate change.
self.outpos.step_e = layer_steps[i].step_e
self.outpos.step_f = layer_steps[i].step_f
self.layergcode = self.layergcode + layer_steps[i].comment + "\n" self.layergcode = self.layergcode + layer_steps[i].comment + "\n"
def workOnSequence(self, orig_seq, modif_seq): def workOnSequence(self, orig_seq, modif_seq):

View file

@ -101,7 +101,7 @@ class SliceInfo(QObject, Extension):
user_modified_setting_keys = set() # type: Set[str] user_modified_setting_keys = set() # type: Set[str]
for stack in [global_stack] + list(global_stack.extruders.values()): for stack in [global_stack] + global_stack.extruderList:
# Get all settings in user_changes and quality_changes # Get all settings in user_changes and quality_changes
all_keys = stack.userChanges.getAllKeys() | stack.qualityChanges.getAllKeys() all_keys = stack.userChanges.getAllKeys() | stack.qualityChanges.getAllKeys()
user_modified_setting_keys |= all_keys user_modified_setting_keys |= all_keys
@ -152,7 +152,7 @@ class SliceInfo(QObject, Extension):
# add extruder specific data to slice info # add extruder specific data to slice info
data["extruders"] = [] data["extruders"] = []
extruders = list(global_stack.extruders.values()) extruders = global_stack.extruderList
extruders = sorted(extruders, key = lambda extruder: extruder.getMetaDataEntry("position")) extruders = sorted(extruders, key = lambda extruder: extruder.getMetaDataEntry("position"))
for extruder in extruders: for extruder in extruders:

View file

@ -97,7 +97,7 @@ class UFPWriter(MeshWriter):
Logger.log("w", "The material extension: %s was already added", material_extension) Logger.log("w", "The material extension: %s was already added", material_extension)
added_materials = [] added_materials = []
for extruder_stack in global_stack.extruders.values(): for extruder_stack in global_stack.extruderList:
material = extruder_stack.material material = extruder_stack.material
try: try:
material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material" material_file_name = material.getMetaData()["base_file"] + ".xml.fdm_material"

View file

@ -74,7 +74,7 @@ class CloudOutputDevice(UltimakerNetworkedPrinterOutputDevice):
b"name": cluster.friendly_name.encode() if cluster.friendly_name else b"", b"name": cluster.friendly_name.encode() if cluster.friendly_name else b"",
b"firmware_version": cluster.host_version.encode() if cluster.host_version else b"", b"firmware_version": cluster.host_version.encode() if cluster.host_version else b"",
b"printer_type": cluster.printer_type.encode() if cluster.printer_type else b"", b"printer_type": cluster.printer_type.encode() if cluster.printer_type else b"",
b"cluster_size": b"1" # cloud devices are always clusters of at least one b"cluster_size": str(cluster.printer_count).encode() if cluster.printer_count else b"1"
} }
super().__init__( super().__init__(

View file

@ -97,8 +97,6 @@ class CloudOutputDeviceManager:
if self._syncing: if self._syncing:
return return
Logger.info("Syncing cloud printer clusters")
self._syncing = True self._syncing = True
self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.SYNCING) self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.SYNCING)
self._api.getClusters(self._onGetRemoteClustersFinished, self._onGetRemoteClusterFailed) self._api.getClusters(self._onGetRemoteClustersFinished, self._onGetRemoteClusterFailed)
@ -187,7 +185,11 @@ class CloudOutputDeviceManager:
self._connectToActiveMachine() self._connectToActiveMachine()
return return
new_devices.sort(key = lambda x: x.name.lower()) # Sort new_devices on online status first, alphabetical second.
# Since the first device might be activated in case there is no active printer yet,
# it would be nice to prioritize online devices
online_cluster_names = {c.friendly_name.lower() for c in clusters if c.is_online and not c.friendly_name is None}
new_devices.sort(key = lambda x: ("a{}" if x.name.lower() in online_cluster_names else "b{}").format(x.name.lower()))
image_path = os.path.join( image_path = os.path.join(
CuraApplication.getInstance().getPluginRegistry().getPluginPath("UM3NetworkPrinting") or "", CuraApplication.getInstance().getPluginRegistry().getPluginPath("UM3NetworkPrinting") or "",
@ -365,6 +367,7 @@ class CloudOutputDeviceManager:
machine.setName(device.name) machine.setName(device.name)
machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key) machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
machine.setMetaDataEntry("group_name", device.name) machine.setMetaDataEntry("group_name", device.name)
machine.setMetaDataEntry("group_size", device.clusterSize)
machine.setMetaDataEntry("removal_warning", self.I18N_CATALOG.i18nc( machine.setMetaDataEntry("removal_warning", self.I18N_CATALOG.i18nc(
"@label ({} is printer name)", "@label ({} is printer name)",
"{} will be removed until the next account sync. <br> To remove {} permanently, " "{} will be removed until the next account sync. <br> To remove {} permanently, "

View file

@ -20,9 +20,6 @@ class ToolPathUploader:
# The HTTP codes that should trigger a retry. # The HTTP codes that should trigger a retry.
RETRY_HTTP_CODES = {500, 502, 503, 504} RETRY_HTTP_CODES = {500, 502, 503, 504}
# The amount of bytes to send per request
BYTES_PER_REQUEST = 256 * 1024
def __init__(self, http: HttpRequestManager, print_job: CloudPrintJobResponse, data: bytes, def __init__(self, http: HttpRequestManager, print_job: CloudPrintJobResponse, data: bytes,
on_finished: Callable[[], Any], on_progress: Callable[[int], Any], on_error: Callable[[], Any] on_finished: Callable[[], Any], on_progress: Callable[[int], Any], on_error: Callable[[], Any]
) -> None: ) -> None:
@ -44,7 +41,6 @@ class ToolPathUploader:
self._on_progress = on_progress self._on_progress = on_progress
self._on_error = on_error self._on_error = on_error
self._sent_bytes = 0
self._retries = 0 self._retries = 0
self._finished = False self._finished = False
@ -54,50 +50,34 @@ class ToolPathUploader:
return self._print_job return self._print_job
def _chunkRange(self) -> Tuple[int, int]:
"""Determines the bytes that should be uploaded next.
:return: A tuple with the first and the last byte to upload.
"""
last_byte = min(len(self._data), self._sent_bytes + self.BYTES_PER_REQUEST)
return self._sent_bytes, last_byte
def start(self) -> None: def start(self) -> None:
"""Starts uploading the mesh.""" """Starts uploading the mesh."""
if self._finished: if self._finished:
# reset state. # reset state.
self._sent_bytes = 0
self._retries = 0 self._retries = 0
self._finished = False self._finished = False
self._uploadChunk() self._upload()
def stop(self): def stop(self):
"""Stops uploading the mesh, marking it as finished.""" """Stops uploading the mesh, marking it as finished."""
Logger.log("i", "Stopped uploading") Logger.log("i", "Finished uploading")
self._finished = True self._finished = True # Signal to any ongoing retries that we should stop retrying.
self._on_finished()
def _uploadChunk(self) -> None:
"""Uploads a chunk of the mesh to the cloud."""
def _upload(self) -> None:
"""
Uploads the print job to the cloud printer.
"""
if self._finished: if self._finished:
raise ValueError("The upload is already finished") raise ValueError("The upload is already finished")
first_byte, last_byte = self._chunkRange() Logger.log("i", "Uploading print to {upload_url}".format(upload_url = self._print_job.upload_url))
content_range = "bytes {}-{}/{}".format(first_byte, last_byte - 1, len(self._data))
headers = {
"Content-Type": cast(str, self._print_job.content_type),
"Content-Range": content_range
} # type: Dict[str, str]
Logger.log("i", "Uploading %s to %s", content_range, self._print_job.upload_url)
self._http.put( self._http.put(
url = cast(str, self._print_job.upload_url), url = cast(str, self._print_job.upload_url),
headers_dict = headers, headers_dict = {"Content-Type": cast(str, self._print_job.content_type)},
data = self._data[first_byte:last_byte], data = self._data,
callback = self._finishedCallback, callback = self._finishedCallback,
error_callback = self._errorCallback, error_callback = self._errorCallback,
upload_progress_callback = self._progressCallback upload_progress_callback = self._progressCallback
@ -109,10 +89,9 @@ class ToolPathUploader:
:param bytes_sent: The amount of bytes sent in the current request. :param bytes_sent: The amount of bytes sent in the current request.
:param bytes_total: The amount of bytes to send in the current request. :param bytes_total: The amount of bytes to send in the current request.
""" """
Logger.log("i", "Progress callback %s / %s", bytes_sent, bytes_total) Logger.debug("Cloud upload progress %s / %s", bytes_sent, bytes_total)
if bytes_total: if bytes_total:
total_sent = self._sent_bytes + bytes_sent self._on_progress(int(bytes_sent / len(self._data) * 100))
self._on_progress(int(total_sent / len(self._data) * 100))
## Handles an error uploading. ## Handles an error uploading.
def _errorCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError) -> None: def _errorCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError) -> None:
@ -136,7 +115,7 @@ class ToolPathUploader:
self._retries += 1 self._retries += 1
Logger.log("i", "Retrying %s/%s request %s", self._retries, self.MAX_RETRIES, reply.url().toString()) Logger.log("i", "Retrying %s/%s request %s", self._retries, self.MAX_RETRIES, reply.url().toString())
try: try:
self._uploadChunk() self._upload()
except ValueError: # Asynchronously it could have completed in the meanwhile. except ValueError: # Asynchronously it could have completed in the meanwhile.
pass pass
return return
@ -148,16 +127,5 @@ class ToolPathUploader:
Logger.log("d", "status_code: %s, Headers: %s, body: %s", status_code, Logger.log("d", "status_code: %s, Headers: %s, body: %s", status_code,
[bytes(header).decode() for header in reply.rawHeaderList()], bytes(reply.readAll()).decode()) [bytes(header).decode() for header in reply.rawHeaderList()], bytes(reply.readAll()).decode())
self._chunkUploaded()
def _chunkUploaded(self) -> None: self.stop()
"""Handles a chunk of data being uploaded, starting the next chunk if needed."""
# We got a successful response. Let's start the next chunk or report the upload is finished.
first_byte, last_byte = self._chunkRange()
self._sent_bytes += last_byte - first_byte
if self._sent_bytes >= len(self._data):
self.stop()
self._on_finished()
else:
self._uploadChunk()

View file

@ -11,7 +11,7 @@ class CloudClusterResponse(BaseModel):
def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str, def __init__(self, cluster_id: str, host_guid: str, host_name: str, is_online: bool, status: str,
host_internal_ip: Optional[str] = None, host_version: Optional[str] = None, host_internal_ip: Optional[str] = None, host_version: Optional[str] = None,
friendly_name: Optional[str] = None, printer_type: str = "ultimaker3", **kwargs) -> None: friendly_name: Optional[str] = None, printer_type: str = "ultimaker3", printer_count: int = 1, **kwargs) -> None:
"""Creates a new cluster response object. """Creates a new cluster response object.
:param cluster_id: The secret unique ID, e.g. 'kBEeZWEifXbrXviO8mRYLx45P8k5lHVGs43XKvRniPg='. :param cluster_id: The secret unique ID, e.g. 'kBEeZWEifXbrXviO8mRYLx45P8k5lHVGs43XKvRniPg='.
@ -23,6 +23,7 @@ class CloudClusterResponse(BaseModel):
:param host_internal_ip: The internal IP address of the host printer. :param host_internal_ip: The internal IP address of the host printer.
:param friendly_name: The human readable name of the host printer. :param friendly_name: The human readable name of the host printer.
:param printer_type: The machine type of the host printer. :param printer_type: The machine type of the host printer.
:param printer_count: The amount of printers in the print cluster. 1 for a single printer
""" """
self.cluster_id = cluster_id self.cluster_id = cluster_id
@ -34,6 +35,7 @@ class CloudClusterResponse(BaseModel):
self.host_internal_ip = host_internal_ip self.host_internal_ip = host_internal_ip
self.friendly_name = friendly_name self.friendly_name = friendly_name
self.printer_type = printer_type self.printer_type = printer_type
self.printer_count = printer_count
super().__init__(**kwargs) super().__init__(**kwargs)
# Validates the model, raising an exception if the model is invalid. # Validates the model, raising an exception if the model is invalid.

View file

@ -887,7 +887,7 @@
"maximum_value_warning": "3 * machine_nozzle_size", "maximum_value_warning": "3 * machine_nozzle_size",
"default_value": 0.4, "default_value": 0.4,
"type": "float", "type": "float",
"enabled": "(support_enable or support_tree_enable)", "enabled": "(support_enable or support_tree_enable or support_meshes_present)",
"value": "line_width", "value": "line_width",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -903,7 +903,7 @@
"minimum_value_warning": "0.1 + 0.4 * machine_nozzle_size", "minimum_value_warning": "0.1 + 0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size", "maximum_value_warning": "2 * machine_nozzle_size",
"type": "float", "type": "float",
"enabled": "(support_enable or support_tree_enable) and support_interface_enable", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_interface_enable",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"value": "line_width", "value": "line_width",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -920,7 +920,7 @@
"minimum_value_warning": "0.4 * machine_nozzle_size", "minimum_value_warning": "0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size", "maximum_value_warning": "2 * machine_nozzle_size",
"type": "float", "type": "float",
"enabled": "(support_enable or support_tree_enable) and support_roof_enable", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_roof_enable",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_line_width')", "value": "extruderValue(support_roof_extruder_nr, 'support_interface_line_width')",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -936,7 +936,7 @@
"minimum_value_warning": "0.4 * machine_nozzle_size", "minimum_value_warning": "0.4 * machine_nozzle_size",
"maximum_value_warning": "2 * machine_nozzle_size", "maximum_value_warning": "2 * machine_nozzle_size",
"type": "float", "type": "float",
"enabled": "(support_enable or support_tree_enable) and support_bottom_enable", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_bottom_enable",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"value": "extruderValue(support_bottom_extruder_nr, 'support_interface_line_width')", "value": "extruderValue(support_bottom_extruder_nr, 'support_interface_line_width')",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -2846,7 +2846,7 @@
"maximum_value_warning": "150", "maximum_value_warning": "150",
"default_value": 60, "default_value": 60,
"value": "speed_print", "value": "speed_print",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"settable_per_mesh": false, "settable_per_mesh": false,
"limit_to_extruder": "support_extruder_nr", "limit_to_extruder": "support_extruder_nr",
"settable_per_extruder": true, "settable_per_extruder": true,
@ -2863,7 +2863,7 @@
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)", "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150", "maximum_value_warning": "150",
"value": "speed_support", "value": "speed_support",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -2878,7 +2878,7 @@
"minimum_value": "0.1", "minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)", "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150", "maximum_value_warning": "150",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)", "enabled": "support_interface_enable and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"value": "speed_support / 1.5", "value": "speed_support / 1.5",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -2895,7 +2895,7 @@
"minimum_value": "0.1", "minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)", "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150", "maximum_value_warning": "150",
"enabled": "support_roof_enable and (support_enable or support_tree_enable)", "enabled": "support_roof_enable and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"value": "extruderValue(support_roof_extruder_nr, 'speed_support_interface')", "value": "extruderValue(support_roof_extruder_nr, 'speed_support_interface')",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -2911,7 +2911,7 @@
"minimum_value": "0.1", "minimum_value": "0.1",
"maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)", "maximum_value": "math.sqrt(machine_max_feedrate_x ** 2 + machine_max_feedrate_y ** 2)",
"maximum_value_warning": "150", "maximum_value_warning": "150",
"enabled": "support_bottom_enable and (support_enable or support_tree_enable)", "enabled": "support_bottom_enable and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"value": "extruderValue(support_bottom_extruder_nr, 'speed_support_interface')", "value": "extruderValue(support_bottom_extruder_nr, 'speed_support_interface')",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -3186,7 +3186,7 @@
"maximum_value_warning": "10000", "maximum_value_warning": "10000",
"default_value": 3000, "default_value": 3000,
"value": "acceleration_print", "value": "acceleration_print",
"enabled": "resolveOrValue('acceleration_enabled') and (support_enable or support_tree_enable)", "enabled": "resolveOrValue('acceleration_enabled') and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"limit_to_extruder": "support_extruder_nr", "limit_to_extruder": "support_extruder_nr",
"settable_per_extruder": true, "settable_per_extruder": true,
@ -3203,7 +3203,7 @@
"minimum_value": "0.1", "minimum_value": "0.1",
"minimum_value_warning": "100", "minimum_value_warning": "100",
"maximum_value_warning": "10000", "maximum_value_warning": "10000",
"enabled": "resolveOrValue('acceleration_enabled') and (support_enable or support_tree_enable)", "enabled": "resolveOrValue('acceleration_enabled') and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -3219,7 +3219,7 @@
"minimum_value": "0.1", "minimum_value": "0.1",
"minimum_value_warning": "100", "minimum_value_warning": "100",
"maximum_value_warning": "10000", "maximum_value_warning": "10000",
"enabled": "resolveOrValue('acceleration_enabled') and support_interface_enable and (support_enable or support_tree_enable)", "enabled": "resolveOrValue('acceleration_enabled') and support_interface_enable and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
@ -3236,7 +3236,7 @@
"minimum_value": "0.1", "minimum_value": "0.1",
"minimum_value_warning": "100", "minimum_value_warning": "100",
"maximum_value_warning": "10000", "maximum_value_warning": "10000",
"enabled": "acceleration_enabled and support_roof_enable and (support_enable or support_tree_enable)", "enabled": "acceleration_enabled and support_roof_enable and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -3252,7 +3252,7 @@
"minimum_value": "0.1", "minimum_value": "0.1",
"minimum_value_warning": "100", "minimum_value_warning": "100",
"maximum_value_warning": "10000", "maximum_value_warning": "10000",
"enabled": "acceleration_enabled and support_bottom_enable and (support_enable or support_tree_enable)", "enabled": "acceleration_enabled and support_bottom_enable and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -3471,7 +3471,7 @@
"maximum_value_warning": "50", "maximum_value_warning": "50",
"default_value": 20, "default_value": 20,
"value": "jerk_print", "value": "jerk_print",
"enabled": "resolveOrValue('jerk_enabled') and (support_enable or support_tree_enable)", "enabled": "resolveOrValue('jerk_enabled') and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
"limit_to_extruder": "support_extruder_nr", "limit_to_extruder": "support_extruder_nr",
@ -3487,7 +3487,7 @@
"value": "jerk_support", "value": "jerk_support",
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "50", "maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and (support_enable or support_tree_enable)", "enabled": "resolveOrValue('jerk_enabled') and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -3502,7 +3502,7 @@
"value": "jerk_support", "value": "jerk_support",
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "50", "maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and support_interface_enable and (support_enable or support_tree_enable)", "enabled": "resolveOrValue('jerk_enabled') and support_interface_enable and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
@ -3518,7 +3518,7 @@
"value": "extruderValue(support_roof_extruder_nr, 'jerk_support_interface')", "value": "extruderValue(support_roof_extruder_nr, 'jerk_support_interface')",
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "50", "maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and support_roof_enable and (support_enable or support_tree_enable)", "enabled": "resolveOrValue('jerk_enabled') and support_roof_enable and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -3533,7 +3533,7 @@
"value": "extruderValue(support_roof_extruder_nr, 'jerk_support_interface')", "value": "extruderValue(support_roof_extruder_nr, 'jerk_support_interface')",
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "50", "maximum_value_warning": "50",
"enabled": "resolveOrValue('jerk_enabled') and support_bottom_enable and (support_enable or support_tree_enable)", "enabled": "resolveOrValue('jerk_enabled') and support_bottom_enable and (support_enable or support_tree_enable or support_meshes_present)",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -3777,7 +3777,7 @@
"description": "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excessive stringing within the support structure.", "description": "Omit retraction when moving from support to support in a straight line. Enabling this setting saves print time, but can lead to excessive stringing within the support structure.",
"type": "bool", "type": "bool",
"default_value": true, "default_value": true,
"enabled": "retraction_enable and (support_enable or support_tree_enable)", "enabled": "retraction_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
}, },
@ -4107,7 +4107,7 @@
"type": "extruder", "type": "extruder",
"default_value": "0", "default_value": "0",
"value": "int(defaultExtruderPosition())", "value": "int(defaultExtruderPosition())",
"enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and extruders_enabled_count > 1",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": false, "settable_per_extruder": false,
"children": { "children": {
@ -4118,7 +4118,7 @@
"type": "extruder", "type": "extruder",
"default_value": "0", "default_value": "0",
"value": "support_extruder_nr", "value": "support_extruder_nr",
"enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and extruders_enabled_count > 1",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": false "settable_per_extruder": false
}, },
@ -4129,7 +4129,7 @@
"type": "extruder", "type": "extruder",
"default_value": "0", "default_value": "0",
"value": "support_extruder_nr", "value": "support_extruder_nr",
"enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and extruders_enabled_count > 1",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": false "settable_per_extruder": false
}, },
@ -4140,7 +4140,7 @@
"type": "extruder", "type": "extruder",
"default_value": "0", "default_value": "0",
"value": "support_extruder_nr", "value": "support_extruder_nr",
"enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and extruders_enabled_count > 1",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": false, "settable_per_extruder": false,
"children": "children":
@ -4152,7 +4152,7 @@
"type": "extruder", "type": "extruder",
"default_value": "0", "default_value": "0",
"value": "support_interface_extruder_nr", "value": "support_interface_extruder_nr",
"enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and extruders_enabled_count > 1",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": false "settable_per_extruder": false
}, },
@ -4163,7 +4163,7 @@
"type": "extruder", "type": "extruder",
"default_value": "0", "default_value": "0",
"value": "support_interface_extruder_nr", "value": "support_interface_extruder_nr",
"enabled": "(support_enable or support_tree_enable) and extruders_enabled_count > 1", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and extruders_enabled_count > 1",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": false "settable_per_extruder": false
} }
@ -4217,7 +4217,7 @@
"gyroid": "Gyroid" "gyroid": "Gyroid"
}, },
"default_value": "zigzag", "default_value": "zigzag",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -4232,7 +4232,7 @@
"maximum_value_warning": "0 if (support_skip_some_zags and support_pattern == 'zigzag') else 3", "maximum_value_warning": "0 if (support_skip_some_zags and support_pattern == 'zigzag') else 3",
"type": "int", "type": "int",
"value": "1 if support_tree_enable else (1 if (support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'concentric') else 0)", "value": "1 if support_tree_enable else (1 if (support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'concentric') else 0)",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -4244,7 +4244,7 @@
"type": "bool", "type": "bool",
"default_value": false, "default_value": false,
"value": "support_pattern == 'cross' or support_pattern == 'gyroid'", "value": "support_pattern == 'cross' or support_pattern == 'gyroid'",
"enabled": "(support_enable or support_tree_enable) and (support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'cross' or support_pattern == 'gyroid')", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and (support_pattern == 'grid' or support_pattern == 'triangles' or support_pattern == 'cross' or support_pattern == 'gyroid')",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -4255,7 +4255,7 @@
"description": "Connect the ZigZags. This will increase the strength of the zig zag support structure.", "description": "Connect the ZigZags. This will increase the strength of the zig zag support structure.",
"type": "bool", "type": "bool",
"default_value": true, "default_value": true,
"enabled": "(support_enable or support_tree_enable) and support_pattern == 'zigzag'", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_pattern == 'zigzag'",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -4270,7 +4270,7 @@
"maximum_value_warning": "100", "maximum_value_warning": "100",
"default_value": 15, "default_value": 15,
"value": "15 if support_enable else 0 if support_tree_enable else 15", "value": "15 if support_enable else 0 if support_tree_enable else 15",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
@ -4285,7 +4285,7 @@
"minimum_value": "0", "minimum_value": "0",
"minimum_value_warning": "support_line_width", "minimum_value_warning": "support_line_width",
"default_value": 2.66, "default_value": 2.66,
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"value": "0 if support_infill_rate == 0 else (support_line_width * 100) / support_infill_rate * (2 if support_pattern == 'grid' else (3 if support_pattern == 'triangles' else 1))", "value": "0 if support_infill_rate == 0 else (support_line_width * 100) / support_infill_rate * (2 if support_pattern == 'grid' else (3 if support_pattern == 'triangles' else 1))",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -4300,7 +4300,7 @@
"minimum_value": "0", "minimum_value": "0",
"minimum_value_warning": "support_line_width", "minimum_value_warning": "support_line_width",
"default_value": 2.66, "default_value": 2.66,
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"value": "support_line_distance", "value": "support_line_distance",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
@ -4314,7 +4314,7 @@
"description": "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angle 0 degrees.", "description": "A list of integer line directions to use. Elements from the list are used sequentially as the layers progress and when the end of the list is reached, it starts at the beginning again. The list items are separated by commas and the whole list is contained in square brackets. Default is an empty list which means use the default angle 0 degrees.",
"type": "[int]", "type": "[int]",
"default_value": "[ ]", "default_value": "[ ]",
"enabled": "(support_enable or support_tree_enable) and support_pattern != 'concentric' and support_infill_rate > 0", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_pattern != 'concentric' and support_infill_rate > 0",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -4325,7 +4325,7 @@
"description": "Generate a brim within the support infill regions of the first layer. This brim is printed underneath the support, not around it. Enabling this setting increases the adhesion of support to the build plate.", "description": "Generate a brim within the support infill regions of the first layer. This brim is printed underneath the support, not around it. Enabling this setting increases the adhesion of support to the build plate.",
"type": "bool", "type": "bool",
"default_value": false, "default_value": false,
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -4339,7 +4339,7 @@
"default_value": 8.0, "default_value": 8.0,
"minimum_value": "0.0", "minimum_value": "0.0",
"maximum_value_warning": "50.0", "maximum_value_warning": "50.0",
"enabled": "(support_enable or support_tree_enable) and support_brim_enable", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_brim_enable",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
@ -4354,7 +4354,7 @@
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "50 / skirt_brim_line_width", "maximum_value_warning": "50 / skirt_brim_line_width",
"value": "math.ceil(support_brim_width / (skirt_brim_line_width * initial_layer_line_width_factor / 100.0))", "value": "math.ceil(support_brim_width / (skirt_brim_line_width * initial_layer_line_width_factor / 100.0))",
"enabled": "(support_enable or support_tree_enable) and support_brim_enable", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_brim_enable",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
"limit_to_extruder": "support_infill_extruder_nr" "limit_to_extruder": "support_infill_extruder_nr"
@ -4371,7 +4371,7 @@
"maximum_value_warning": "machine_nozzle_size", "maximum_value_warning": "machine_nozzle_size",
"default_value": 0.1, "default_value": 0.1,
"limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"settable_per_mesh": true, "settable_per_mesh": true,
"children": "children":
{ {
@ -4384,7 +4384,7 @@
"maximum_value_warning": "machine_nozzle_size", "maximum_value_warning": "machine_nozzle_size",
"default_value": 0.1, "default_value": 0.1,
"type": "float", "type": "float",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"value": "extruderValue(support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr, 'support_z_distance')", "value": "extruderValue(support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr, 'support_z_distance')",
"limit_to_extruder": "support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr if support_roof_enable else support_infill_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
@ -4400,7 +4400,7 @@
"value": "extruderValue(support_bottom_extruder_nr if support_bottom_enable else support_infill_extruder_nr, 'support_z_distance') if support_type == 'everywhere' else 0", "value": "extruderValue(support_bottom_extruder_nr if support_bottom_enable else support_infill_extruder_nr, 'support_z_distance') if support_type == 'everywhere' else 0",
"limit_to_extruder": "support_bottom_extruder_nr if support_bottom_enable else support_infill_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr if support_bottom_enable else support_infill_extruder_nr",
"type": "float", "type": "float",
"enabled": "(support_enable or support_tree_enable) and resolveOrValue('support_type') == 'everywhere'", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and resolveOrValue('support_type') == 'everywhere'",
"settable_per_mesh": true "settable_per_mesh": true
} }
} }
@ -4415,7 +4415,7 @@
"maximum_value_warning": "1.5 * machine_nozzle_tip_outer_diameter", "maximum_value_warning": "1.5 * machine_nozzle_tip_outer_diameter",
"default_value": 0.7, "default_value": 0.7,
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_xy_overrides_z": "support_xy_overrides_z":
@ -4430,7 +4430,7 @@
}, },
"default_value": "z_overrides_xy", "default_value": "z_overrides_xy",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"enabled": "support_enable", "enabled": "support_enable or support_meshes_present",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_xy_distance_overhang": "support_xy_distance_overhang":
@ -4445,7 +4445,7 @@
"default_value": 0.2, "default_value": 0.2,
"value": "machine_nozzle_size / 2", "value": "machine_nozzle_size / 2",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"enabled": "support_enable and support_xy_overrides_z == 'z_overrides_xy'", "enabled": "(support_enable or support_meshes_present) and support_xy_overrides_z == 'z_overrides_xy'",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_bottom_stair_step_height": "support_bottom_stair_step_height":
@ -4458,7 +4458,7 @@
"limit_to_extruder": "support_bottom_extruder_nr if support_bottom_enable else support_infill_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr if support_bottom_enable else support_infill_extruder_nr",
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "1.0", "maximum_value_warning": "1.0",
"enabled": "support_enable", "enabled": "support_enable or support_meshes_present",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_bottom_stair_step_width": "support_bottom_stair_step_width":
@ -4471,7 +4471,7 @@
"limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr if support_interface_enable else support_infill_extruder_nr",
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "10.0", "maximum_value_warning": "10.0",
"enabled": "support_enable", "enabled": "support_enable or support_meshes_present",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_join_distance": "support_join_distance":
@ -4484,7 +4484,7 @@
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"minimum_value_warning": "0", "minimum_value_warning": "0",
"maximum_value_warning": "10", "maximum_value_warning": "10",
"enabled": "support_enable", "enabled": "support_enable or support_meshes_present",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_offset": "support_offset":
@ -4497,7 +4497,7 @@
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"minimum_value_warning": "-1 * machine_nozzle_size", "minimum_value_warning": "-1 * machine_nozzle_size",
"maximum_value_warning": "10 * machine_nozzle_size", "maximum_value_warning": "10 * machine_nozzle_size",
"enabled": "support_enable", "enabled": "support_enable or support_meshes_present",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_infill_sparse_thickness": "support_infill_sparse_thickness":
@ -4511,7 +4511,7 @@
"maximum_value_warning": "0.75 * machine_nozzle_size", "maximum_value_warning": "0.75 * machine_nozzle_size",
"maximum_value": "resolveOrValue('layer_height') * 8", "maximum_value": "resolveOrValue('layer_height') * 8",
"value": "resolveOrValue('layer_height')", "value": "resolveOrValue('layer_height')",
"enabled": "(support_enable or support_tree_enable) and support_infill_rate > 0", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_infill_rate > 0",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false "settable_per_mesh": false
}, },
@ -4524,7 +4524,7 @@
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "1 if (support_pattern == 'cross' or support_pattern == 'lines' or support_pattern == 'zigzag' or support_pattern == 'concentric') else 5", "maximum_value_warning": "1 if (support_pattern == 'cross' or support_pattern == 'lines' or support_pattern == 'zigzag' or support_pattern == 'concentric') else 5",
"maximum_value": "999999 if support_line_distance == 0 else (20 - math.log(support_line_distance) / math.log(2))", "maximum_value": "999999 if support_line_distance == 0 else (20 - math.log(support_line_distance) / math.log(2))",
"enabled": "(support_enable or support_tree_enable) and support_infill_rate > 0", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_infill_rate > 0",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false "settable_per_mesh": false
}, },
@ -4537,7 +4537,7 @@
"default_value": 1, "default_value": 1,
"minimum_value": "0.0001", "minimum_value": "0.0001",
"minimum_value_warning": "3 * resolveOrValue('layer_height')", "minimum_value_warning": "3 * resolveOrValue('layer_height')",
"enabled": "(support_enable or support_tree_enable) and support_infill_rate > 0 and gradual_support_infill_steps > 0", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_infill_rate > 0 and gradual_support_infill_steps > 0",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false "settable_per_mesh": false
}, },
@ -4550,7 +4550,7 @@
"default_value": 0.0, "default_value": 0.0,
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "5", "maximum_value_warning": "5",
"enabled": "support_enable", "enabled": "support_enable or support_meshes_present",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": true "settable_per_mesh": true
}, },
@ -4561,7 +4561,7 @@
"type": "bool", "type": "bool",
"default_value": false, "default_value": false,
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"settable_per_mesh": true, "settable_per_mesh": true,
"children": "children":
{ {
@ -4573,7 +4573,7 @@
"default_value": false, "default_value": false,
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_enable')", "value": "extruderValue(support_roof_extruder_nr, 'support_interface_enable')",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_bottom_enable": "support_bottom_enable":
@ -4584,7 +4584,7 @@
"default_value": false, "default_value": false,
"value": "extruderValue(support_bottom_extruder_nr, 'support_interface_enable')", "value": "extruderValue(support_bottom_extruder_nr, 'support_interface_enable')",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"settable_per_mesh": true "settable_per_mesh": true
} }
} }
@ -4600,7 +4600,7 @@
"minimum_value_warning": "0.2 + layer_height", "minimum_value_warning": "0.2 + layer_height",
"maximum_value_warning": "10", "maximum_value_warning": "10",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)", "enabled": "support_interface_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": true, "settable_per_mesh": true,
"children": "children":
{ {
@ -4616,7 +4616,7 @@
"maximum_value_warning": "10", "maximum_value_warning": "10",
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_height')", "value": "extruderValue(support_roof_extruder_nr, 'support_interface_height')",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_roof_enable and (support_enable or support_tree_enable)", "enabled": "support_roof_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_bottom_height": "support_bottom_height":
@ -4631,7 +4631,7 @@
"minimum_value_warning": "min(support_bottom_distance + layer_height, support_bottom_stair_step_height)", "minimum_value_warning": "min(support_bottom_distance + layer_height, support_bottom_stair_step_height)",
"maximum_value_warning": "10", "maximum_value_warning": "10",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_bottom_enable and (support_enable or support_tree_enable)", "enabled": "support_bottom_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": true "settable_per_mesh": true
} }
} }
@ -4645,7 +4645,7 @@
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "support_interface_height", "maximum_value_warning": "support_interface_height",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)", "enabled": "support_interface_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"support_interface_density": "support_interface_density":
@ -4658,7 +4658,7 @@
"minimum_value": "0", "minimum_value": "0",
"maximum_value_warning": "100", "maximum_value_warning": "100",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)", "enabled": "support_interface_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
"children": "children":
@ -4673,7 +4673,7 @@
"minimum_value": "0", "minimum_value": "0",
"maximum_value": "100", "maximum_value": "100",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_roof_enable and (support_enable or support_tree_enable)", "enabled": "support_roof_enable and (support_enable or support_tree_enable or support_meshes_present)",
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_density')", "value": "extruderValue(support_roof_extruder_nr, 'support_interface_density')",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
@ -4690,7 +4690,7 @@
"minimum_value_warning": "support_roof_line_width - 0.0001", "minimum_value_warning": "support_roof_line_width - 0.0001",
"value": "0 if support_roof_density == 0 else (support_roof_line_width * 100) / support_roof_density * (2 if support_roof_pattern == 'grid' else (3 if support_roof_pattern == 'triangles' else 1))", "value": "0 if support_roof_density == 0 else (support_roof_line_width * 100) / support_roof_density * (2 if support_roof_pattern == 'grid' else (3 if support_roof_pattern == 'triangles' else 1))",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_roof_enable and (support_enable or support_tree_enable)", "enabled": "support_roof_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
} }
@ -4706,7 +4706,7 @@
"minimum_value": "0", "minimum_value": "0",
"maximum_value": "100", "maximum_value": "100",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_bottom_enable and (support_enable or support_tree_enable)", "enabled": "support_bottom_enable and (support_enable or support_tree_enable or support_meshes_present)",
"value": "extruderValue(support_bottom_extruder_nr, 'support_interface_density')", "value": "extruderValue(support_bottom_extruder_nr, 'support_interface_density')",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
@ -4723,7 +4723,7 @@
"minimum_value_warning": "support_bottom_line_width - 0.0001", "minimum_value_warning": "support_bottom_line_width - 0.0001",
"value": "0 if support_bottom_density == 0 else (support_bottom_line_width * 100) / support_bottom_density * (2 if support_bottom_pattern == 'grid' else (3 if support_bottom_pattern == 'triangles' else 1))", "value": "0 if support_bottom_density == 0 else (support_bottom_line_width * 100) / support_bottom_density * (2 if support_bottom_pattern == 'grid' else (3 if support_bottom_pattern == 'triangles' else 1))",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_bottom_enable and (support_enable or support_tree_enable)", "enabled": "support_bottom_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
} }
@ -4746,7 +4746,7 @@
}, },
"default_value": "concentric", "default_value": "concentric",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)", "enabled": "support_interface_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
"children": "children":
@ -4767,7 +4767,7 @@
"default_value": "concentric", "default_value": "concentric",
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_pattern')", "value": "extruderValue(support_roof_extruder_nr, 'support_interface_pattern')",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_roof_enable and (support_enable or support_tree_enable)", "enabled": "support_roof_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
}, },
@ -4787,7 +4787,7 @@
"default_value": "concentric", "default_value": "concentric",
"value": "extruderValue(support_bottom_extruder_nr, 'support_interface_pattern')", "value": "extruderValue(support_bottom_extruder_nr, 'support_interface_pattern')",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_bottom_enable and (support_enable or support_tree_enable)", "enabled": "support_bottom_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
} }
@ -4803,7 +4803,7 @@
"minimum_value": "0", "minimum_value": "0",
"minimum_value_warning": "minimum_support_area", "minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)", "enabled": "support_interface_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": true, "settable_per_mesh": true,
"children": "children":
{ {
@ -4818,7 +4818,7 @@
"minimum_value": "0", "minimum_value": "0",
"minimum_value_warning": "minimum_support_area", "minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_roof_enable and (support_enable or support_tree_enable)", "enabled": "support_roof_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": true "settable_per_mesh": true
}, },
"minimum_bottom_area": "minimum_bottom_area":
@ -4832,7 +4832,7 @@
"minimum_value": "0", "minimum_value": "0",
"minimum_value_warning": "minimum_support_area", "minimum_value_warning": "minimum_support_area",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_bottom_enable and (support_enable or support_tree_enable)", "enabled": "support_bottom_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": true "settable_per_mesh": true
} }
} }
@ -4846,7 +4846,7 @@
"default_value": 0.0, "default_value": 0.0,
"maximum_value": "extruderValue(support_extruder_nr, 'support_offset')", "maximum_value": "extruderValue(support_extruder_nr, 'support_offset')",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"enabled": "support_interface_enable and (support_enable or support_tree_enable)", "enabled": "support_interface_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
"children": "children":
@ -4861,7 +4861,7 @@
"value": "extruderValue(support_roof_extruder_nr, 'support_interface_offset')", "value": "extruderValue(support_roof_extruder_nr, 'support_interface_offset')",
"maximum_value": "extruderValue(support_extruder_nr, 'support_offset')", "maximum_value": "extruderValue(support_extruder_nr, 'support_offset')",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"enabled": "support_roof_enable and (support_enable or support_tree_enable)", "enabled": "support_roof_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
}, },
@ -4875,7 +4875,7 @@
"value": "extruderValue(support_bottom_extruder_nr, 'support_interface_offset')", "value": "extruderValue(support_bottom_extruder_nr, 'support_interface_offset')",
"maximum_value": "extruderValue(support_extruder_nr, 'support_offset')", "maximum_value": "extruderValue(support_extruder_nr, 'support_offset')",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "support_bottom_enable and (support_enable or support_tree_enable)", "enabled": "support_bottom_enable and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
} }
@ -4888,7 +4888,7 @@
"type": "[int]", "type": "[int]",
"default_value": "[ ]", "default_value": "[ ]",
"limit_to_extruder": "support_interface_extruder_nr", "limit_to_extruder": "support_interface_extruder_nr",
"enabled": "(support_enable or support_tree_enable) and support_interface_enable and support_interface_pattern != 'concentric'", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_interface_enable and support_interface_pattern != 'concentric'",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
"children": "children":
@ -4901,7 +4901,7 @@
"default_value": "[ ]", "default_value": "[ ]",
"value": "support_interface_angles", "value": "support_interface_angles",
"limit_to_extruder": "support_roof_extruder_nr", "limit_to_extruder": "support_roof_extruder_nr",
"enabled": "(support_enable or support_tree_enable) and support_roof_enable and support_roof_pattern != 'concentric'", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_roof_enable and support_roof_pattern != 'concentric'",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
}, },
@ -4913,7 +4913,7 @@
"default_value": "[ ]", "default_value": "[ ]",
"value": "support_interface_angles", "value": "support_interface_angles",
"limit_to_extruder": "support_bottom_extruder_nr", "limit_to_extruder": "support_bottom_extruder_nr",
"enabled": "(support_enable or support_tree_enable) and support_bottom_enable and support_bottom_pattern != 'concentric'", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_bottom_enable and support_bottom_pattern != 'concentric'",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
} }
@ -4925,7 +4925,7 @@
"description": "When enabled, the print cooling fan speed is altered for the skin regions immediately above the support.", "description": "When enabled, the print cooling fan speed is altered for the skin regions immediately above the support.",
"type": "bool", "type": "bool",
"default_value": false, "default_value": false,
"enabled": "support_enable or support_tree_enable", "enabled": "support_enable or support_tree_enable or support_meshes_present",
"settable_per_mesh": false "settable_per_mesh": false
}, },
"support_supported_skin_fan_speed": "support_supported_skin_fan_speed":
@ -4937,7 +4937,7 @@
"maximum_value": "100", "maximum_value": "100",
"default_value": 100, "default_value": 100,
"type": "float", "type": "float",
"enabled": "(support_enable or support_tree_enable) and support_fan_enable", "enabled": "(support_enable or support_tree_enable or support_meshes_present) and support_fan_enable",
"settable_per_mesh": false "settable_per_mesh": false
}, },
"support_use_towers": "support_use_towers":
@ -5003,6 +5003,17 @@
"settable_per_extruder": false, "settable_per_extruder": false,
"settable_per_meshgroup": false, "settable_per_meshgroup": false,
"settable_globally": false "settable_globally": false
},
"support_meshes_present":
{
"label": "Scene Has Support Meshes",
"description": "There are support meshes present in the scene. This setting is controlled by Cura.",
"type": "bool",
"default_value": false,
"enabled": false,
"settable_per_mesh": false,
"settable_per_extruder": false,
"settable_per_meshgroup": false
} }
} }
}, },
@ -5173,7 +5184,7 @@
"description": "Enforce brim to be printed around the model even if that space would otherwise be occupied by support. This replaces some regions of the first layer of support by brim regions.", "description": "Enforce brim to be printed around the model even if that space would otherwise be occupied by support. This replaces some regions of the first layer of support by brim regions.",
"type": "bool", "type": "bool",
"default_value": true, "default_value": true,
"enabled": "resolveOrValue('adhesion_type') == 'brim' and (support_enable or support_tree_enable)", "enabled": "resolveOrValue('adhesion_type') == 'brim' and (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
"limit_to_extruder": "support_infill_extruder_nr" "limit_to_extruder": "support_infill_extruder_nr"
@ -5957,7 +5968,7 @@
"description": "Remove empty layers beneath the first printed layer if they are present. Disabling this setting can cause empty first layers if the Slicing Tolerance setting is set to Exclusive or Middle.", "description": "Remove empty layers beneath the first printed layer if they are present. Disabling this setting can cause empty first layers if the Slicing Tolerance setting is set to Exclusive or Middle.",
"type": "bool", "type": "bool",
"default_value": true, "default_value": true,
"enabled": "not (support_enable or support_tree_enable)", "enabled": "not (support_enable or support_tree_enable or support_meshes_present)",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": false "settable_per_extruder": false
}, },
@ -6369,7 +6380,7 @@
"description": "Skip some support line connections to make the support structure easier to break away. This setting is applicable to the Zig Zag support infill pattern.", "description": "Skip some support line connections to make the support structure easier to break away. This setting is applicable to the Zig Zag support infill pattern.",
"type": "bool", "type": "bool",
"default_value": false, "default_value": false,
"enabled": "support_enable and (support_pattern == 'zigzag')", "enabled": "(support_enable or support_meshes_present) and support_pattern == 'zigzag'",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true
@ -6383,7 +6394,7 @@
"default_value": 20, "default_value": 20,
"minimum_value": "0", "minimum_value": "0",
"minimum_value_warning": "support_line_distance", "minimum_value_warning": "support_line_distance",
"enabled": "support_enable and (support_pattern == 'zigzag') and support_skip_some_zags", "enabled": "(support_enable or support_meshes_present) and support_pattern == 'zigzag' and support_skip_some_zags",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true, "settable_per_extruder": true,
@ -6398,7 +6409,7 @@
"value": "0 if support_line_distance == 0 else round(support_skip_zag_per_mm / support_line_distance)", "value": "0 if support_line_distance == 0 else round(support_skip_zag_per_mm / support_line_distance)",
"minimum_value": "1", "minimum_value": "1",
"minimum_value_warning": "3", "minimum_value_warning": "3",
"enabled": "support_enable and (support_pattern == 'zigzag') and support_skip_some_zags", "enabled": "(support_enable or support_meshes_present) and support_pattern == 'zigzag' and support_skip_some_zags",
"limit_to_extruder": "support_infill_extruder_nr", "limit_to_extruder": "support_infill_extruder_nr",
"settable_per_mesh": false, "settable_per_mesh": false,
"settable_per_extruder": true "settable_per_extruder": true

View file

@ -1,4 +1,4 @@
// Copyright (c) 2018 Ultimaker B.V. // Copyright (c) 2020 Ultimaker B.V.
// Cura is released under the terms of the LGPLv3 or higher. // Cura is released under the terms of the LGPLv3 or higher.
import QtQuick 2.7 import QtQuick 2.7
@ -98,7 +98,7 @@ Button
target: buttonText target: buttonText
property: "width" property: "width"
value: button.fixedWidthMode ? button.width - button.leftPadding - button.rightPadding value: button.fixedWidthMode ? button.width - button.leftPadding - button.rightPadding
: ((maximumWidth != 0 && contentWidth > maximumWidth) ? maximumWidth : undefined) : ((maximumWidth != 0 && button.contentWidth > maximumWidth) ? maximumWidth : undefined)
} }
} }

View file

@ -96,7 +96,7 @@ Item
id: configurationList id: configurationList
spacing: UM.Theme.getSize("narrow_margin").height spacing: UM.Theme.getSize("narrow_margin").height
width: container.width - ((height > container.maximumHeight) ? container.ScrollBar.vertical.background.width : 0) //Make room for scroll bar if there is any. width: container.width - ((height > container.maximumHeight) ? container.ScrollBar.vertical.background.width : 0) //Make room for scroll bar if there is any.
height: childrenRect.height height: contentHeight
interactive: false // let the ScrollView process scroll events. interactive: false // let the ScrollView process scroll events.
section.property: "modelData.printerType" section.property: "modelData.printerType"

View file

@ -4,6 +4,7 @@
import QtQuick 2.10 import QtQuick 2.10
import QtQuick.Controls 2.3 import QtQuick.Controls 2.3
import QtQuick.Controls.Styles 1.4 import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.3
import UM 1.2 as UM import UM 1.2 as UM
import Cura 1.0 as Cura import Cura 1.0 as Cura
@ -37,70 +38,68 @@ Cura.ExpandablePopup
headerItem: Item headerItem: Item
{ {
// Horizontal list that shows the extruders and their materials // Horizontal list that shows the extruders and their materials
ListView RowLayout
{ {
id: extrudersList
orientation: ListView.Horizontal
anchors.fill: parent anchors.fill: parent
model: extrudersModel Repeater
visible: Cura.MachineManager.activeMachine.hasMaterials
delegate: Item
{ {
height: parent.height model: extrudersModel
width: Math.round(ListView.view.width / extrudersModel.count) delegate: Item
// Extruder icon. Shows extruder index and has the same color as the active material.
Cura.ExtruderIcon
{ {
id: extruderIcon Layout.fillWidth: true
materialColor: model.color Layout.fillHeight: true
extruderEnabled: model.enabled
height: parent.height
width: height
}
// Label for the brand of the material // Extruder icon. Shows extruder index and has the same color as the active material.
Label Cura.ExtruderIcon
{
id: typeAndBrandNameLabel
text: model.material_brand + " " + model.material
elide: Text.ElideRight
font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
anchors
{ {
top: extruderIcon.top id: extruderIcon
left: extruderIcon.right materialColor: model.color
leftMargin: UM.Theme.getSize("default_margin").width extruderEnabled: model.enabled
right: parent.right height: parent.height
rightMargin: UM.Theme.getSize("default_margin").width width: height
} }
}
// Label that shows the name of the variant
Label
{
id: variantLabel
visible: Cura.MachineManager.activeMachine.hasVariants // Label for the brand of the material
Label
text: model.variant
elide: Text.ElideRight
font: UM.Theme.getFont("default_bold")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
anchors
{ {
left: extruderIcon.right id: typeAndBrandNameLabel
leftMargin: UM.Theme.getSize("default_margin").width
top: typeAndBrandNameLabel.bottom text: model.material_brand + " " + model.material
right: parent.right elide: Text.ElideRight
rightMargin: UM.Theme.getSize("default_margin").width font: UM.Theme.getFont("default")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
anchors
{
top: extruderIcon.top
left: extruderIcon.right
leftMargin: UM.Theme.getSize("default_margin").width
right: parent.right
rightMargin: UM.Theme.getSize("default_margin").width
}
}
// Label that shows the name of the variant
Label
{
id: variantLabel
visible: Cura.MachineManager.activeMachine.hasVariants
text: model.variant
elide: Text.ElideRight
font: UM.Theme.getFont("default_bold")
color: UM.Theme.getColor("text")
renderType: Text.NativeRendering
anchors
{
left: extruderIcon.right
leftMargin: UM.Theme.getSize("default_margin").width
top: typeAndBrandNameLabel.bottom
right: parent.right
rightMargin: UM.Theme.getSize("default_margin").width
}
} }
} }
} }

View file

@ -73,8 +73,6 @@ Item
height: textLabel.contentHeight + 2 * UM.Theme.getSize("narrow_margin").height height: textLabel.contentHeight + 2 * UM.Theme.getSize("narrow_margin").height
hoverEnabled: true hoverEnabled: true
baselineOffset: null // If we don't do this, there is a binding loop. WHich is a bit weird, since we override the contentItem anyway...
contentItem: RowLayout contentItem: RowLayout
{ {
spacing: 0 spacing: 0