mirror of
https://github.com/Ultimaker/Cura.git
synced 2025-07-06 22:47:29 -06:00
Merge remote-tracking branch 'origin/master' into doxygen_to_restructuredtext_comments
# Conflicts: # cura/API/__init__.py # cura/Settings/CuraContainerRegistry.py # cura/Settings/ExtruderManager.py # plugins/PostProcessingPlugin/scripts/PauseAtHeight.py # plugins/UM3NetworkPrinting/src/Cloud/CloudApiClient.py # plugins/UM3NetworkPrinting/src/Cloud/ToolPathUploader.py # plugins/UM3NetworkPrinting/src/Network/LocalClusterOutputDeviceManager.py
This commit is contained in:
commit
58ffc9dcae
234 changed files with 3945 additions and 1142 deletions
|
@ -23,6 +23,7 @@ class SyncState:
|
|||
SYNCING = 0
|
||||
SUCCESS = 1
|
||||
ERROR = 2
|
||||
IDLE = 3
|
||||
|
||||
class Account(QObject):
|
||||
"""The account API provides a version-proof bridge to use Ultimaker Accounts
|
||||
|
@ -54,6 +55,7 @@ class Account(QObject):
|
|||
"""
|
||||
lastSyncDateTimeChanged = pyqtSignal()
|
||||
syncStateChanged = pyqtSignal(int) # because SyncState is an int Enum
|
||||
manualSyncEnabledChanged = pyqtSignal(bool)
|
||||
|
||||
def __init__(self, application: "CuraApplication", parent = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
@ -62,7 +64,8 @@ class Account(QObject):
|
|||
|
||||
self._error_message = None # type: Optional[Message]
|
||||
self._logged_in = False
|
||||
self._sync_state = SyncState.SUCCESS
|
||||
self._sync_state = SyncState.IDLE
|
||||
self._manual_sync_enabled = False
|
||||
self._last_sync_str = "-"
|
||||
|
||||
self._callback_port = 32118
|
||||
|
@ -110,16 +113,21 @@ class Account(QObject):
|
|||
:param state: One of SyncState
|
||||
"""
|
||||
|
||||
Logger.info("Service {service} enters sync state {state}", service = service_name, state = state)
|
||||
|
||||
prev_state = self._sync_state
|
||||
|
||||
self._sync_services[service_name] = state
|
||||
|
||||
if any(val == SyncState.SYNCING for val in self._sync_services.values()):
|
||||
self._sync_state = SyncState.SYNCING
|
||||
self._setManualSyncEnabled(False)
|
||||
elif any(val == SyncState.ERROR for val in self._sync_services.values()):
|
||||
self._sync_state = SyncState.ERROR
|
||||
self._setManualSyncEnabled(True)
|
||||
else:
|
||||
self._sync_state = SyncState.SUCCESS
|
||||
self._setManualSyncEnabled(False)
|
||||
|
||||
if self._sync_state != prev_state:
|
||||
self.syncStateChanged.emit(self._sync_state)
|
||||
|
@ -162,11 +170,31 @@ class Account(QObject):
|
|||
self._logged_in = logged_in
|
||||
self.loginStateChanged.emit(logged_in)
|
||||
if logged_in:
|
||||
self.sync()
|
||||
self._setManualSyncEnabled(False)
|
||||
self._sync()
|
||||
else:
|
||||
if self._update_timer.isActive():
|
||||
self._update_timer.stop()
|
||||
|
||||
def _sync(self) -> None:
|
||||
"""Signals all sync services to start syncing
|
||||
|
||||
This can be considered a forced sync: even when a
|
||||
sync is currently running, a sync will be requested.
|
||||
"""
|
||||
|
||||
if self._update_timer.isActive():
|
||||
self._update_timer.stop()
|
||||
elif self._sync_state == SyncState.SYNCING:
|
||||
Logger.warning("Starting a new sync while previous sync was not completed\n{}", str(self._sync_services))
|
||||
|
||||
self.syncRequested.emit()
|
||||
|
||||
def _setManualSyncEnabled(self, enabled: bool) -> None:
|
||||
if self._manual_sync_enabled != enabled:
|
||||
self._manual_sync_enabled = enabled
|
||||
self.manualSyncEnabledChanged.emit(enabled)
|
||||
|
||||
@pyqtSlot()
|
||||
@pyqtSlot(bool)
|
||||
def login(self, force_logout_before_login: bool = False) -> None:
|
||||
|
@ -217,20 +245,23 @@ class Account(QObject):
|
|||
def lastSyncDateTime(self) -> str:
|
||||
return self._last_sync_str
|
||||
|
||||
@pyqtProperty(bool, notify=manualSyncEnabledChanged)
|
||||
def manualSyncEnabled(self) -> bool:
|
||||
return self._manual_sync_enabled
|
||||
|
||||
@pyqtSlot()
|
||||
def sync(self) -> None:
|
||||
"""Signals all sync services to start syncing
|
||||
@pyqtSlot(bool)
|
||||
def sync(self, user_initiated: bool = False) -> None:
|
||||
if user_initiated:
|
||||
self._setManualSyncEnabled(False)
|
||||
|
||||
This can be considered a forced sync: even when a
|
||||
sync is currently running, a sync will be requested.
|
||||
"""
|
||||
self._sync()
|
||||
|
||||
if self._update_timer.isActive():
|
||||
self._update_timer.stop()
|
||||
elif self._sync_state == SyncState.SYNCING:
|
||||
Logger.warning("Starting a new sync while previous sync was not completed\n{}", str(self._sync_services))
|
||||
|
||||
self.syncRequested.emit()
|
||||
@pyqtSlot()
|
||||
def popupOpened(self) -> None:
|
||||
self._setManualSyncEnabled(True)
|
||||
self._sync_state = SyncState.IDLE
|
||||
self.syncStateChanged.emit(self._sync_state)
|
||||
|
||||
@pyqtSlot()
|
||||
def logout(self) -> None:
|
||||
|
|
64
cura/API/ConnectionStatus.py
Normal file
64
cura/API/ConnectionStatus.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
from typing import Optional
|
||||
|
||||
from PyQt5.QtCore import QObject, pyqtSignal, QTimer, pyqtProperty
|
||||
from PyQt5.QtNetwork import QNetworkReply
|
||||
|
||||
from UM.TaskManagement.HttpRequestManager import HttpRequestManager
|
||||
from cura.UltimakerCloud import UltimakerCloudAuthentication
|
||||
|
||||
|
||||
class ConnectionStatus(QObject):
|
||||
"""Status info for some web services"""
|
||||
|
||||
UPDATE_INTERVAL = 10.0 # seconds
|
||||
ULTIMAKER_CLOUD_STATUS_URL = UltimakerCloudAuthentication.CuraCloudAPIRoot + "/connect/v1/"
|
||||
|
||||
__instance = None # type: Optional[ConnectionStatus]
|
||||
|
||||
internetReachableChanged = pyqtSignal()
|
||||
umCloudReachableChanged = pyqtSignal()
|
||||
|
||||
@classmethod
|
||||
def getInstance(cls, *args, **kwargs) -> "ConnectionStatus":
|
||||
if cls.__instance is None:
|
||||
cls.__instance = cls(*args, **kwargs)
|
||||
return cls.__instance
|
||||
|
||||
def __init__(self, parent: Optional["QObject"] = None):
|
||||
super().__init__(parent)
|
||||
|
||||
self._http = HttpRequestManager.getInstance()
|
||||
self._statuses = {
|
||||
self.ULTIMAKER_CLOUD_STATUS_URL: True,
|
||||
"http://example.com": True
|
||||
}
|
||||
|
||||
# Create a timer for automatic updates
|
||||
self._update_timer = QTimer()
|
||||
self._update_timer.setInterval(int(self.UPDATE_INTERVAL * 1000))
|
||||
# The timer is restarted automatically
|
||||
self._update_timer.setSingleShot(False)
|
||||
self._update_timer.timeout.connect(self._update)
|
||||
self._update_timer.start()
|
||||
|
||||
@pyqtProperty(bool, notify=internetReachableChanged)
|
||||
def isInternetReachable(self) -> bool:
|
||||
# Is any of the test urls reachable?
|
||||
return any(self._statuses.values())
|
||||
|
||||
def _update(self):
|
||||
for url in self._statuses.keys():
|
||||
self._http.get(
|
||||
url = url,
|
||||
callback = self._statusCallback,
|
||||
error_callback = self._statusCallback,
|
||||
timeout = 5
|
||||
)
|
||||
|
||||
def _statusCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError = None):
|
||||
url = reply.request().url().toString()
|
||||
prev_statuses = self._statuses.copy()
|
||||
self._statuses[url] = HttpRequestManager.replyIndicatesSuccess(reply, error)
|
||||
|
||||
if any(self._statuses.values()) != any(prev_statuses.values()):
|
||||
self.internetReachableChanged.emit()
|
|
@ -5,6 +5,7 @@ from typing import Optional, TYPE_CHECKING
|
|||
from PyQt5.QtCore import QObject, pyqtProperty
|
||||
|
||||
from cura.API.Backups import Backups
|
||||
from cura.API.ConnectionStatus import ConnectionStatus
|
||||
from cura.API.Interface import Interface
|
||||
from cura.API.Account import Account
|
||||
|
||||
|
@ -44,6 +45,9 @@ class CuraAPI(QObject):
|
|||
|
||||
self._backups = Backups(self._application)
|
||||
|
||||
self._connectionStatus = ConnectionStatus()
|
||||
|
||||
# Interface API
|
||||
self._interface = Interface(self._application)
|
||||
|
||||
def initialize(self) -> None:
|
||||
|
@ -55,6 +59,10 @@ class CuraAPI(QObject):
|
|||
|
||||
return self._account
|
||||
|
||||
@pyqtProperty(QObject, constant = True)
|
||||
def connectionStatus(self) -> "ConnectionStatus":
|
||||
return self._connectionStatus
|
||||
|
||||
@property
|
||||
def backups(self) -> "Backups":
|
||||
"""Backups API"""
|
||||
|
|
|
@ -40,10 +40,10 @@ class CuraPackageManager(PackageManager):
|
|||
machine_with_qualities = []
|
||||
for container_id in ids:
|
||||
for global_stack in global_stacks:
|
||||
for extruder_nr, extruder_stack in global_stack.extruders.items():
|
||||
for extruder_nr, extruder_stack in enumerate(global_stack.extruderList):
|
||||
if container_id in (extruder_stack.material.getId(), extruder_stack.material.getMetaData().get("base_file")):
|
||||
machine_with_materials.append((global_stack, extruder_nr, container_id))
|
||||
machine_with_materials.append((global_stack, str(extruder_nr), container_id))
|
||||
if container_id == extruder_stack.quality.getId():
|
||||
machine_with_qualities.append((global_stack, extruder_nr, container_id))
|
||||
machine_with_qualities.append((global_stack, str(extruder_nr), container_id))
|
||||
|
||||
return machine_with_materials, machine_with_qualities
|
||||
|
|
|
@ -156,9 +156,10 @@ class BaseMaterialsModel(ListModel):
|
|||
global_stack = cura.CuraApplication.CuraApplication.getInstance().getGlobalContainerStack()
|
||||
if not global_stack.hasMaterials:
|
||||
return # There are no materials for this machine, so nothing to do.
|
||||
extruder_stack = global_stack.extruders.get(str(self._extruder_position))
|
||||
if not extruder_stack:
|
||||
extruder_list = global_stack.extruderList
|
||||
if self._extruder_position > len(extruder_list):
|
||||
return
|
||||
extruder_stack = extruder_list[self._extruder_position]
|
||||
nozzle_name = extruder_stack.variant.getName()
|
||||
machine_node = ContainerTree.getInstance().machines[global_stack.definition.getId()]
|
||||
if nozzle_name not in machine_node.variants:
|
||||
|
|
|
@ -128,6 +128,7 @@ class DiscoveredPrintersModel(QObject):
|
|||
self._discovered_printer_by_ip_dict = dict() # type: Dict[str, DiscoveredPrinter]
|
||||
|
||||
self._plugin_for_manual_device = None # type: Optional[OutputDevicePlugin]
|
||||
self._network_plugin_queue = [] # type: List[OutputDevicePlugin]
|
||||
self._manual_device_address = ""
|
||||
|
||||
self._manual_device_request_timeout_in_seconds = 5 # timeout for adding a manual device in seconds
|
||||
|
@ -152,16 +153,21 @@ class DiscoveredPrintersModel(QObject):
|
|||
|
||||
all_plugins_dict = self._application.getOutputDeviceManager().getAllOutputDevicePlugins()
|
||||
|
||||
can_add_manual_plugins = [item for item in filter(
|
||||
self._network_plugin_queue = [item for item in filter(
|
||||
lambda plugin_item: plugin_item.canAddManualDevice(address) in priority_order,
|
||||
all_plugins_dict.values())]
|
||||
|
||||
if not can_add_manual_plugins:
|
||||
if not self._network_plugin_queue:
|
||||
Logger.log("d", "Could not find a plugin to accept adding %s manually via address.", address)
|
||||
return
|
||||
|
||||
plugin = max(can_add_manual_plugins, key = lambda p: priority_order.index(p.canAddManualDevice(address)))
|
||||
self._plugin_for_manual_device = plugin
|
||||
self._attemptToAddManualDevice(address)
|
||||
|
||||
def _attemptToAddManualDevice(self, address: str) -> None:
|
||||
if self._network_plugin_queue:
|
||||
self._plugin_for_manual_device = self._network_plugin_queue.pop()
|
||||
Logger.log("d", "Network plugin %s: attempting to add manual device with address %s.",
|
||||
self._plugin_for_manual_device.getId(), address)
|
||||
self._plugin_for_manual_device.addManualDevice(address, callback=self._onManualDeviceRequestFinished)
|
||||
self._manual_device_address = address
|
||||
self._manual_device_request_timer.start()
|
||||
|
@ -180,8 +186,11 @@ class DiscoveredPrintersModel(QObject):
|
|||
self.manualDeviceRequestFinished.emit(False)
|
||||
|
||||
def _onManualRequestTimeout(self) -> None:
|
||||
Logger.log("w", "Manual printer [%s] request timed out. Cancel the current request.", self._manual_device_address)
|
||||
address = self._manual_device_address
|
||||
Logger.log("w", "Manual printer [%s] request timed out. Cancel the current request.", address)
|
||||
self.cancelCurrentManualDeviceRequest()
|
||||
if self._network_plugin_queue:
|
||||
self._attemptToAddManualDevice(address)
|
||||
|
||||
hasManualDeviceRequestInProgressChanged = pyqtSignal()
|
||||
|
||||
|
@ -197,6 +206,8 @@ class DiscoveredPrintersModel(QObject):
|
|||
self._manual_device_address = ""
|
||||
self.hasManualDeviceRequestInProgressChanged.emit()
|
||||
self.manualDeviceRequestFinished.emit(success)
|
||||
if not success and self._network_plugin_queue:
|
||||
self._attemptToAddManualDevice(address)
|
||||
|
||||
@pyqtProperty("QVariantMap", notify = discoveredPrintersChanged)
|
||||
def discoveredPrintersByAddress(self) -> Dict[str, DiscoveredPrinter]:
|
||||
|
|
|
@ -19,6 +19,7 @@ class GlobalStacksModel(ListModel):
|
|||
ConnectionTypeRole = Qt.UserRole + 4
|
||||
MetaDataRole = Qt.UserRole + 5
|
||||
DiscoverySourceRole = Qt.UserRole + 6 # For separating local and remote printers in the machine management page
|
||||
RemovalWarningRole = Qt.UserRole + 7
|
||||
|
||||
def __init__(self, parent = None) -> None:
|
||||
super().__init__(parent)
|
||||
|
@ -66,13 +67,21 @@ class GlobalStacksModel(ListModel):
|
|||
if parseBool(container_stack.getMetaDataEntry("hidden", False)):
|
||||
continue
|
||||
|
||||
section_name = "Network enabled printers" if has_remote_connection else "Local printers"
|
||||
device_name = container_stack.getMetaDataEntry("group_name", container_stack.getName())
|
||||
section_name = "Connected printers" if has_remote_connection else "Preset printers"
|
||||
section_name = self._catalog.i18nc("@info:title", section_name)
|
||||
|
||||
items.append({"name": container_stack.getMetaDataEntry("group_name", container_stack.getName()),
|
||||
default_removal_warning = self._catalog.i18nc(
|
||||
"@label ({} is object name)",
|
||||
"Are you sure you wish to remove {}? This cannot be undone!", device_name
|
||||
)
|
||||
removal_warning = container_stack.getMetaDataEntry("removal_warning", default_removal_warning)
|
||||
|
||||
items.append({"name": device_name,
|
||||
"id": container_stack.getId(),
|
||||
"hasRemoteConnection": has_remote_connection,
|
||||
"metadata": container_stack.getMetaData().copy(),
|
||||
"discoverySource": section_name})
|
||||
"discoverySource": section_name,
|
||||
"removalWarning": removal_warning})
|
||||
items.sort(key=lambda i: (not i["hasRemoteConnection"], i["name"]))
|
||||
self.setItems(items)
|
||||
|
|
|
@ -151,7 +151,7 @@ class QualitySettingsModel(ListModel):
|
|||
if self._selected_position == self.GLOBAL_STACK_POSITION:
|
||||
user_value = global_container_stack.userChanges.getProperty(definition.key, "value")
|
||||
else:
|
||||
extruder_stack = global_container_stack.extruders[str(self._selected_position)]
|
||||
extruder_stack = global_container_stack.extruderList[self._selected_position]
|
||||
user_value = extruder_stack.userChanges.getProperty(definition.key, "value")
|
||||
|
||||
if profile_value is None and user_value is None:
|
||||
|
|
|
@ -285,7 +285,7 @@ class ConvexHullDecorator(SceneNodeDecorator):
|
|||
# Do not throw away vertices: the convex hull may be too small and objects can collide.
|
||||
# vertex_data = vertex_data[vertex_data[:,1] >= -0.01]
|
||||
|
||||
if len(vertex_data) >= 4: # type: ignore # mypy and numpy don't play along well just yet.
|
||||
if vertex_data is not None and len(vertex_data) >= 4: # type: ignore # mypy and numpy don't play along well just yet.
|
||||
# Round the vertex data to 1/10th of a mm, then remove all duplicate vertices
|
||||
# This is done to greatly speed up further convex hull calculations as the convex hull
|
||||
# becomes much less complex when dealing with highly detailed models.
|
||||
|
|
|
@ -192,9 +192,7 @@ class CuraContainerRegistry(ContainerRegistry):
|
|||
return {"status": "error", "message": catalog.i18nc("@info:status Don't translate the XML tags <filename>!", "Can't import profile from <filename>{0}</filename> before a printer is added.", file_name)}
|
||||
container_tree = ContainerTree.getInstance()
|
||||
|
||||
machine_extruders = []
|
||||
for position in sorted(global_stack.extruders):
|
||||
machine_extruders.append(global_stack.extruders[position])
|
||||
machine_extruders = global_stack.extruderList
|
||||
|
||||
plugin_registry = PluginRegistry.getInstance()
|
||||
extension = file_name.split(".")[-1]
|
||||
|
@ -275,7 +273,7 @@ class CuraContainerRegistry(ContainerRegistry):
|
|||
if len(profile_or_list) == 1:
|
||||
global_profile = profile_or_list[0]
|
||||
extruder_profiles = []
|
||||
for idx, extruder in enumerate(global_stack.extruders.values()):
|
||||
for idx, extruder in enumerate(global_stack.extruderList):
|
||||
profile_id = ContainerRegistry.getInstance().uniqueName(global_stack.getId() + "_extruder_" + str(idx + 1))
|
||||
profile = InstanceContainer(profile_id)
|
||||
profile.setName(quality_name)
|
||||
|
|
|
@ -65,7 +65,7 @@ class CuraStackBuilder:
|
|||
except IndexError:
|
||||
return None
|
||||
|
||||
for new_extruder in new_global_stack.extruders.values(): # Only register the extruders if we're sure that all of them are correct.
|
||||
for new_extruder in new_global_stack.extruderList: # Only register the extruders if we're sure that all of them are correct.
|
||||
registry.addContainer(new_extruder)
|
||||
|
||||
# Register the global stack after the extruder stacks are created. This prevents the registry from adding another
|
||||
|
|
|
@ -154,25 +154,6 @@ class ExtruderManager(QObject):
|
|||
return self._extruder_trains[global_container_stack.getId()][str(index)]
|
||||
return None
|
||||
|
||||
def registerExtruder(self, extruder_train: "ExtruderStack", machine_id: str) -> None:
|
||||
changed = False
|
||||
|
||||
if machine_id not in self._extruder_trains:
|
||||
self._extruder_trains[machine_id] = {}
|
||||
changed = True
|
||||
|
||||
# do not register if an extruder has already been registered at the position on this machine
|
||||
if any(item.getId() == extruder_train.getId() for item in self._extruder_trains[machine_id].values()):
|
||||
Logger.log("w", "Extruder [%s] has already been registered on machine [%s], not doing anything",
|
||||
extruder_train.getId(), machine_id)
|
||||
return
|
||||
|
||||
if extruder_train:
|
||||
self._extruder_trains[machine_id][extruder_train.getMetaDataEntry("position")] = extruder_train
|
||||
changed = True
|
||||
if changed:
|
||||
self.extrudersChanged.emit(machine_id)
|
||||
|
||||
def getAllExtruderSettings(self, setting_key: str, prop: str) -> List[Any]:
|
||||
"""Gets a property of a setting for all extruders.
|
||||
|
||||
|
|
|
@ -45,9 +45,6 @@ class ExtruderStack(CuraContainerStack):
|
|||
stack.addExtruder(self)
|
||||
self.setMetaDataEntry("machine", stack.id)
|
||||
|
||||
# For backward compatibility: Register the extruder with the Extruder Manager
|
||||
ExtruderManager.getInstance().registerExtruder(self, stack.id)
|
||||
|
||||
@override(ContainerStack)
|
||||
def getNextStack(self) -> Optional["GlobalStack"]:
|
||||
return super().getNextStack()
|
||||
|
|
|
@ -500,6 +500,10 @@ class MachineManager(QObject):
|
|||
# A cloud connection is only available if any output device actually is a cloud connected device.
|
||||
return any(d.connectionType == ConnectionType.CloudConnection for d in self._printer_output_devices)
|
||||
|
||||
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
|
||||
def activeMachineHasCloudRegistration(self) -> bool:
|
||||
return self.activeMachine is not None and ConnectionType.CloudConnection in self.activeMachine.configuredConnectionTypes
|
||||
|
||||
@pyqtProperty(bool, notify = printerConnectedStatusChanged)
|
||||
def activeMachineIsUsingCloudConnection(self) -> bool:
|
||||
return self.activeMachineHasCloudConnection and not self.activeMachineHasNetworkConnection
|
||||
|
@ -943,7 +947,7 @@ class MachineManager(QObject):
|
|||
|
||||
@pyqtSlot(int, bool)
|
||||
def setExtruderEnabled(self, position: int, enabled: bool) -> None:
|
||||
if self._global_container_stack is None or str(position) not in self._global_container_stack.extruders:
|
||||
if self._global_container_stack is None or position >= len(self._global_container_stack.extruderList):
|
||||
Logger.log("w", "Could not find extruder on position %s.", position)
|
||||
return
|
||||
extruder = self._global_container_stack.extruderList[position]
|
||||
|
@ -1106,14 +1110,14 @@ class MachineManager(QObject):
|
|||
self._global_container_stack.quality = quality_container
|
||||
self._global_container_stack.qualityChanges = quality_changes_container
|
||||
|
||||
for position, extruder in self._global_container_stack.extruders.items():
|
||||
for position, extruder in enumerate(self._global_container_stack.extruderList):
|
||||
quality_node = None
|
||||
if quality_group is not None:
|
||||
quality_node = quality_group.nodes_for_extruders.get(int(position))
|
||||
quality_node = quality_group.nodes_for_extruders.get(position)
|
||||
|
||||
quality_changes_container = empty_quality_changes_container
|
||||
quality_container = empty_quality_container
|
||||
quality_changes_metadata = quality_changes_group.metadata_per_extruder.get(int(position))
|
||||
quality_changes_metadata = quality_changes_group.metadata_per_extruder.get(position)
|
||||
if quality_changes_metadata:
|
||||
containers = container_registry.findContainers(id = quality_changes_metadata["id"])
|
||||
if containers:
|
||||
|
@ -1132,7 +1136,7 @@ class MachineManager(QObject):
|
|||
def _setVariantNode(self, position: str, variant_node: "VariantNode") -> None:
|
||||
if self._global_container_stack is None:
|
||||
return
|
||||
self._global_container_stack.extruders[position].variant = variant_node.container
|
||||
self._global_container_stack.extruderList[int(position)].variant = variant_node.container
|
||||
self.activeVariantChanged.emit()
|
||||
|
||||
def _setGlobalVariant(self, container_node: "ContainerNode") -> None:
|
||||
|
@ -1147,7 +1151,7 @@ class MachineManager(QObject):
|
|||
return
|
||||
if material_node and material_node.container:
|
||||
material_container = material_node.container
|
||||
self._global_container_stack.extruders[position].material = material_container
|
||||
self._global_container_stack.extruderList[int(position)].material = material_container
|
||||
root_material_id = material_container.getMetaDataEntry("base_file", None)
|
||||
else:
|
||||
self._global_container_stack.extruderList[int(position)].material = empty_material_container
|
||||
|
@ -1251,7 +1255,7 @@ class MachineManager(QObject):
|
|||
if self._global_container_stack is None:
|
||||
return
|
||||
if position is None:
|
||||
position_list = list(self._global_container_stack.extruders.keys())
|
||||
position_list = [str(position) for position in range(len(self._global_container_stack.extruderList))]
|
||||
else:
|
||||
position_list = [position]
|
||||
|
||||
|
@ -1325,17 +1329,15 @@ class MachineManager(QObject):
|
|||
# Keep a temporary copy of the global and per-extruder user changes and transfer them to the user changes
|
||||
# of the new machine after the new_machine becomes active.
|
||||
global_user_changes = self._global_container_stack.userChanges
|
||||
per_extruder_user_changes = {}
|
||||
for extruder_name, extruder_stack in self._global_container_stack.extruders.items():
|
||||
per_extruder_user_changes[extruder_name] = extruder_stack.userChanges
|
||||
per_extruder_user_changes = [extruder_stack.userChanges for extruder_stack in self._global_container_stack.extruderList]
|
||||
|
||||
self.setActiveMachine(new_machine.getId())
|
||||
|
||||
# Apply the global and per-extruder userChanges to the new_machine (which is of different type than the
|
||||
# previous one).
|
||||
self._global_container_stack.setUserChanges(global_user_changes)
|
||||
for extruder_name in self._global_container_stack.extruders.keys():
|
||||
self._global_container_stack.extruders[extruder_name].setUserChanges(per_extruder_user_changes[extruder_name])
|
||||
for i, user_changes in enumerate(per_extruder_user_changes):
|
||||
self._global_container_stack.extruderList[i].setUserChanges(per_extruder_user_changes[i])
|
||||
|
||||
@pyqtSlot(QObject)
|
||||
def applyRemoteConfiguration(self, configuration: PrinterConfigurationModel) -> None:
|
||||
|
@ -1393,7 +1395,7 @@ class MachineManager(QObject):
|
|||
material_container_node = variant_node.materials.get(base_file, material_container_node)
|
||||
|
||||
self._setMaterial(position, material_container_node)
|
||||
self._global_container_stack.extruders[position].setEnabled(True)
|
||||
self._global_container_stack.extruderList[int(position)].setEnabled(True)
|
||||
self.updateMaterialWithVariant(position)
|
||||
|
||||
self.updateDefaultExtruder()
|
||||
|
@ -1446,7 +1448,7 @@ class MachineManager(QObject):
|
|||
if you update an active machine, special measures have to be taken.
|
||||
"""
|
||||
if global_stack is not None and global_stack != self._global_container_stack:
|
||||
global_stack.extruders[position].material = container_node.container
|
||||
global_stack.extruderList[int(position)].material = container_node.container
|
||||
return
|
||||
position = str(position)
|
||||
self.blurSettings.emit()
|
||||
|
@ -1639,7 +1641,7 @@ class MachineManager(QObject):
|
|||
return
|
||||
with postponeSignals(*self._getContainerChangedSignals(), compress = CompressTechnique.CompressPerParameterValue):
|
||||
self._setQualityGroup(self.activeQualityGroup())
|
||||
for stack in [self._global_container_stack] + list(self._global_container_stack.extruders.values()):
|
||||
for stack in [self._global_container_stack] + self._global_container_stack.extruderList:
|
||||
stack.userChanges.clear()
|
||||
|
||||
@pyqtProperty(QObject, fset = setQualityChangesGroup, notify = activeQualityChangesGroupChanged)
|
||||
|
|
|
@ -63,6 +63,7 @@ if with_sentry_sdk:
|
|||
|
||||
# Errors to be ignored by Sentry
|
||||
ignore_errors = [KeyboardInterrupt, MemoryError]
|
||||
try:
|
||||
sentry_sdk.init("https://5034bf0054fb4b889f82896326e79b13@sentry.io/1821564",
|
||||
before_send = CrashHandler.sentryBeforeSend,
|
||||
environment = sentry_env,
|
||||
|
@ -71,6 +72,8 @@ if with_sentry_sdk:
|
|||
max_breadcrumbs = 300,
|
||||
server_name = "cura",
|
||||
ignore_errors = ignore_errors)
|
||||
except Exception:
|
||||
with_sentry_sdk = False
|
||||
|
||||
if not known_args["debug"]:
|
||||
def get_cura_dir_path():
|
||||
|
|
|
@ -598,7 +598,15 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
"""
|
||||
application = CuraApplication.getInstance()
|
||||
|
||||
try:
|
||||
archive = zipfile.ZipFile(file_name, "r")
|
||||
except EnvironmentError as e:
|
||||
message = Message(i18n_catalog.i18nc("@info:error Don't translate the XML tags <filename> or <message>!",
|
||||
"Project file <filename>{0}</filename> is suddenly inaccessible: <message>{1}</message>.", file_name, str(e)),
|
||||
title = i18n_catalog.i18nc("@info:title", "Can't Open Project File"))
|
||||
message.show()
|
||||
self.setWorkspaceName("")
|
||||
return [], {}
|
||||
|
||||
cura_file_names = [name for name in archive.namelist() if name.startswith("Cura/")]
|
||||
|
||||
|
@ -633,7 +641,7 @@ class ThreeMFWorkspaceReader(WorkspaceReader):
|
|||
|
||||
global_stack = CuraStackBuilder.createMachine(machine_name, self._machine_info.definition_id)
|
||||
if global_stack: # Only switch if creating the machine was successful.
|
||||
extruder_stack_dict = global_stack.extruders
|
||||
extruder_stack_dict = {str(position): extruder for position, extruder in enumerate(global_stack.extruderList)}
|
||||
|
||||
self._container_registry.addContainer(global_stack)
|
||||
else:
|
||||
|
|
|
@ -255,7 +255,7 @@ class StartSliceJob(Job):
|
|||
global_stack = CuraApplication.getInstance().getGlobalContainerStack()
|
||||
if not global_stack:
|
||||
return
|
||||
extruders_enabled = {position: stack.isEnabled for position, stack in global_stack.extruders.items()}
|
||||
extruders_enabled = [stack.isEnabled for stack in global_stack.extruderList]
|
||||
filtered_object_groups = []
|
||||
has_model_with_disabled_extruders = False
|
||||
associated_disabled_extruders = set()
|
||||
|
@ -265,7 +265,7 @@ class StartSliceJob(Job):
|
|||
for node in group:
|
||||
# Only check if the printing extruder is enabled for printing meshes
|
||||
is_non_printing_mesh = node.callDecoration("evaluateIsNonPrintingMesh")
|
||||
extruder_position = node.callDecoration("getActiveExtruderPosition")
|
||||
extruder_position = int(node.callDecoration("getActiveExtruderPosition"))
|
||||
if not is_non_printing_mesh and not extruders_enabled[extruder_position]:
|
||||
skip_group = True
|
||||
has_model_with_disabled_extruders = True
|
||||
|
@ -275,8 +275,8 @@ class StartSliceJob(Job):
|
|||
|
||||
if has_model_with_disabled_extruders:
|
||||
self.setResult(StartJobResult.ObjectsWithDisabledExtruder)
|
||||
associated_disabled_extruders = {str(c) for c in sorted([int(p) + 1 for p in associated_disabled_extruders])}
|
||||
self.setMessage(", ".join(associated_disabled_extruders))
|
||||
associated_disabled_extruders = {p + 1 for p in associated_disabled_extruders}
|
||||
self.setMessage(", ".join(map(str, sorted(associated_disabled_extruders))))
|
||||
return
|
||||
|
||||
# There are cases when there is nothing to slice. This can happen due to one at a time slicing not being
|
||||
|
|
|
@ -60,16 +60,12 @@ UM.Dialog
|
|||
CheckBox
|
||||
{
|
||||
id: toggleShowAll
|
||||
|
||||
anchors
|
||||
{
|
||||
top: parent.top
|
||||
right: parent.right
|
||||
}
|
||||
|
||||
text: catalog.i18nc("@label:checkbox", "Show all")
|
||||
checked: listview.model.showAll
|
||||
onClicked: listview.model.showAll = checked
|
||||
}
|
||||
|
||||
ScrollView
|
||||
|
@ -98,6 +94,7 @@ UM.Dialog
|
|||
excluded_settings = excluded_settings.concat(settingPickDialog.additional_excluded_settings)
|
||||
return excluded_settings
|
||||
}
|
||||
showAll: toggleShowAll.checked || filterInput.text !== ""
|
||||
}
|
||||
delegate:Loader
|
||||
{
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
from ..Script import Script
|
||||
class BQ_PauseAtHeight(Script):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def getSettingDataString(self):
|
||||
return """{
|
||||
"name":"Pause at height (BQ Printers)",
|
||||
"key": "BQ_PauseAtHeight",
|
||||
"metadata":{},
|
||||
"version": 2,
|
||||
"settings":
|
||||
{
|
||||
"pause_height":
|
||||
{
|
||||
"label": "Pause height",
|
||||
"description": "At what height should the pause occur",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 5.0
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
def execute(self, data):
|
||||
pause_z = self.getSettingValueByKey("pause_height")
|
||||
for layer in data:
|
||||
lines = layer.split("\n")
|
||||
for line in lines:
|
||||
if self.getValue(line, 'G') == 1 or self.getValue(line, 'G') == 0:
|
||||
current_z = self.getValue(line, 'Z')
|
||||
if current_z is not None:
|
||||
if current_z >= pause_z:
|
||||
prepend_gcode = ";TYPE:CUSTOM\n"
|
||||
prepend_gcode += "; -- Pause at height (%.2f mm) --\n" % pause_z
|
||||
|
||||
# Insert Pause gcode
|
||||
prepend_gcode += "M25 ; Pauses the print and waits for the user to resume it\n"
|
||||
|
||||
index = data.index(layer)
|
||||
layer = prepend_gcode + layer
|
||||
data[index] = layer # Override the data of this layer with the modified data
|
||||
return data
|
||||
break
|
||||
return data
|
|
@ -25,7 +25,7 @@ class PauseAtHeight(Script):
|
|||
"label": "Pause at",
|
||||
"description": "Whether to pause at a certain height or at a certain layer.",
|
||||
"type": "enum",
|
||||
"options": {"height": "Height", "layer_no": "Layer No."},
|
||||
"options": {"height": "Height", "layer_no": "Layer Number"},
|
||||
"default_value": "height"
|
||||
},
|
||||
"pause_height":
|
||||
|
@ -49,6 +49,15 @@ class PauseAtHeight(Script):
|
|||
"minimum_value_warning": "1",
|
||||
"enabled": "pause_at == 'layer_no'"
|
||||
},
|
||||
"pause_method":
|
||||
{
|
||||
"label": "Method",
|
||||
"description": "The method or gcode command to use for pausing.",
|
||||
"type": "enum",
|
||||
"options": {"marlin": "Marlin (M0)", "griffin": "Griffin (M0, firmware retract)", "bq": "BQ (M25)", "reprap": "RepRap (M226)", "repetier": "Repetier (@pause)"},
|
||||
"default_value": "marlin",
|
||||
"value": "\\\"griffin\\\" if machine_gcode_flavor==\\\"Griffin\\\" else \\\"reprap\\\" if machine_gcode_flavor==\\\"RepRap (RepRap)\\\" else \\\"repetier\\\" if machine_gcode_flavor==\\\"Repetier\\\" else \\\"bq\\\" if \\\"BQ\\\" in machine_name else \\\"marlin\\\""
|
||||
},
|
||||
"disarm_timeout":
|
||||
{
|
||||
"label": "Disarm timeout",
|
||||
|
@ -66,7 +75,8 @@ class PauseAtHeight(Script):
|
|||
"description": "What X location does the head move to when pausing.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 190
|
||||
"default_value": 190,
|
||||
"enabled": "pause_method != \\\"griffin\\\""
|
||||
},
|
||||
"head_park_y":
|
||||
{
|
||||
|
@ -74,7 +84,17 @@ class PauseAtHeight(Script):
|
|||
"description": "What Y location does the head move to when pausing.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 190
|
||||
"default_value": 190,
|
||||
"enabled": "pause_method != \\\"griffin\\\""
|
||||
},
|
||||
"head_move_z":
|
||||
{
|
||||
"label": "Head move Z",
|
||||
"description": "The Height of Z-axis retraction before parking.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 15.0,
|
||||
"enabled": "pause_method == \\\"repetier\\\""
|
||||
},
|
||||
"retraction_amount":
|
||||
{
|
||||
|
@ -82,7 +102,8 @@ class PauseAtHeight(Script):
|
|||
"description": "How much filament must be retracted at pause.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0
|
||||
"default_value": 0,
|
||||
"enabled": "pause_method != \\\"griffin\\\""
|
||||
},
|
||||
"retraction_speed":
|
||||
{
|
||||
|
@ -90,7 +111,8 @@ class PauseAtHeight(Script):
|
|||
"description": "How fast to retract the filament.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default_value": 25
|
||||
"default_value": 25,
|
||||
"enabled": "pause_method not in [\\\"griffin\\\", \\\"repetier\\\"]"
|
||||
},
|
||||
"extrude_amount":
|
||||
{
|
||||
|
@ -98,7 +120,8 @@ class PauseAtHeight(Script):
|
|||
"description": "How much filament should be extruded after pause. This is needed when doing a material change on Ultimaker2's to compensate for the retraction after the change. In that case 128+ is recommended.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 0
|
||||
"default_value": 0,
|
||||
"enabled": "pause_method != \\\"griffin\\\""
|
||||
},
|
||||
"extrude_speed":
|
||||
{
|
||||
|
@ -106,7 +129,8 @@ class PauseAtHeight(Script):
|
|||
"description": "How fast to extrude the material after pause.",
|
||||
"unit": "mm/s",
|
||||
"type": "float",
|
||||
"default_value": 3.3333
|
||||
"default_value": 3.3333,
|
||||
"enabled": "pause_method not in [\\\"griffin\\\", \\\"repetier\\\"]"
|
||||
},
|
||||
"redo_layer":
|
||||
{
|
||||
|
@ -121,18 +145,61 @@ class PauseAtHeight(Script):
|
|||
"description": "Change the temperature during the pause.",
|
||||
"unit": "°C",
|
||||
"type": "int",
|
||||
"default_value": 0
|
||||
"default_value": 0,
|
||||
"enabled": "pause_method not in [\\\"griffin\\\", \\\"repetier\\\"]"
|
||||
},
|
||||
"display_text":
|
||||
{
|
||||
"label": "Display Text",
|
||||
"description": "Text that should appear on the display while paused. If left empty, there will not be any message.",
|
||||
"type": "str",
|
||||
"default_value": ""
|
||||
"default_value": "",
|
||||
"enabled": "pause_method != \\\"repetier\\\""
|
||||
},
|
||||
"machine_name":
|
||||
{
|
||||
"label": "Machine Type",
|
||||
"description": "The name of your 3D printer model. This setting is controlled by the script and will not be visible.",
|
||||
"default_value": "Unknown",
|
||||
"type": "str",
|
||||
"enabled": false
|
||||
},
|
||||
"machine_gcode_flavor":
|
||||
{
|
||||
"label": "G-code flavor",
|
||||
"description": "The type of g-code to be generated. This setting is controlled by the script and will not be visible.",
|
||||
"type": "enum",
|
||||
"options":
|
||||
{
|
||||
"RepRap (Marlin/Sprinter)": "Marlin",
|
||||
"RepRap (Volumetric)": "Marlin (Volumetric)",
|
||||
"RepRap (RepRap)": "RepRap",
|
||||
"UltiGCode": "Ultimaker 2",
|
||||
"Griffin": "Griffin",
|
||||
"Makerbot": "Makerbot",
|
||||
"BFB": "Bits from Bytes",
|
||||
"MACH3": "Mach3",
|
||||
"Repetier": "Repetier"
|
||||
},
|
||||
"default_value": "RepRap (Marlin/Sprinter)",
|
||||
"enabled": false
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
## Copy machine name and gcode flavor from global stack so we can use their value in the script stack
|
||||
def initialize(self) -> None:
|
||||
super().initialize()
|
||||
|
||||
global_container_stack = Application.getInstance().getGlobalContainerStack()
|
||||
if global_container_stack is None or self._instance is None:
|
||||
return
|
||||
|
||||
for key in ["machine_name", "machine_gcode_flavor"]:
|
||||
self._instance.setProperty(key, "value", global_container_stack.getProperty(key, "value"))
|
||||
|
||||
## Get the X and Y values for a layer (will be used to get X and Y of the
|
||||
# layer after the pause).
|
||||
def getNextXY(self, layer: str) -> Tuple[float, float]:
|
||||
"""Get the X and Y values for a layer (will be used to get X and Y of the layer after the pause)."""
|
||||
lines = layer.split("\n")
|
||||
|
@ -159,6 +226,7 @@ class PauseAtHeight(Script):
|
|||
extrude_speed = self.getSettingValueByKey("extrude_speed")
|
||||
park_x = self.getSettingValueByKey("head_park_x")
|
||||
park_y = self.getSettingValueByKey("head_park_y")
|
||||
move_z = self.getSettingValueByKey("head_move_z")
|
||||
layers_started = False
|
||||
redo_layer = self.getSettingValueByKey("redo_layer")
|
||||
standby_temperature = self.getSettingValueByKey("standby_temperature")
|
||||
|
@ -167,7 +235,14 @@ class PauseAtHeight(Script):
|
|||
initial_layer_height = Application.getInstance().getGlobalContainerStack().getProperty("layer_height_0", "value")
|
||||
display_text = self.getSettingValueByKey("display_text")
|
||||
|
||||
is_griffin = False
|
||||
pause_method = self.getSettingValueByKey("pause_method")
|
||||
pause_command = {
|
||||
"marlin": self.putValue(M = 0),
|
||||
"griffin": self.putValue(M = 0),
|
||||
"bq": self.putValue(M = 25),
|
||||
"reprap": self.putValue(M = 226),
|
||||
"repetier": self.putValue("@pause now change filament and press continue printing")
|
||||
}[pause_method]
|
||||
|
||||
# T = ExtruderManager.getInstance().getActiveExtruderStack().getProperty("material_print_temperature", "value")
|
||||
|
||||
|
@ -188,8 +263,6 @@ class PauseAtHeight(Script):
|
|||
|
||||
# Scroll each line of instruction for each layer in the G-code
|
||||
for line in lines:
|
||||
if ";FLAVOR:Griffin" in line:
|
||||
is_griffin = True
|
||||
# Fist positive layer reached
|
||||
if ";LAYER:0" in line:
|
||||
layers_started = True
|
||||
|
@ -291,7 +364,22 @@ class PauseAtHeight(Script):
|
|||
else:
|
||||
prepend_gcode += ";current layer: {layer}\n".format(layer = current_layer)
|
||||
|
||||
if not is_griffin:
|
||||
if pause_method == "repetier":
|
||||
#Retraction
|
||||
prepend_gcode += self.putValue(M = 83) + " ; switch to relative E values for any needed retraction\n"
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = 6000) + "\n"
|
||||
|
||||
#Move the head away
|
||||
prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + " ; move up a millimeter to get out of the way\n"
|
||||
prepend_gcode += self.putValue(G = 1, X = park_x, Y = park_y, F = 9000) + "\n"
|
||||
if current_z < move_z:
|
||||
prepend_gcode += self.putValue(G = 1, Z = current_z + move_z, F = 300) + "\n"
|
||||
|
||||
#Disable the E steppers
|
||||
prepend_gcode += self.putValue(M = 84, E = 0) + "\n"
|
||||
|
||||
elif pause_method != "griffin":
|
||||
# Retraction
|
||||
prepend_gcode += self.putValue(M = 83) + " ; switch to relative E values for any needed retraction\n"
|
||||
if retraction_amount != 0:
|
||||
|
@ -323,9 +411,40 @@ class PauseAtHeight(Script):
|
|||
prepend_gcode += self.putValue(M = 18, S = disarm_timeout) + " ; Set the disarm timeout\n"
|
||||
|
||||
# Wait till the user continues printing
|
||||
prepend_gcode += self.putValue(M = 0) + " ; Do the actual pause\n"
|
||||
prepend_gcode += pause_command + " ; Do the actual pause\n"
|
||||
|
||||
if not is_griffin:
|
||||
if pause_method == "repetier":
|
||||
#Push the filament back,
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = 6000) + "\n"
|
||||
|
||||
# Optionally extrude material
|
||||
if extrude_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = extrude_amount, F = 200) + "\n"
|
||||
prepend_gcode += self.putValue("@info wait for cleaning nozzle from previous filament") + "\n"
|
||||
prepend_gcode += self.putValue("@pause remove the waste filament from parking area and press continue printing") + "\n"
|
||||
|
||||
# and retract again, the properly primes the nozzle when changing filament.
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = -retraction_amount, F = 6000) + "\n"
|
||||
|
||||
#Move the head back
|
||||
prepend_gcode += self.putValue(G = 1, Z = current_z + 1, F = 300) + "\n"
|
||||
prepend_gcode += self.putValue(G = 1, X = x, Y = y, F = 9000) + "\n"
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += self.putValue(G = 1, E = retraction_amount, F = 6000) + "\n"
|
||||
|
||||
if current_extrusion_f != 0:
|
||||
prepend_gcode += self.putValue(G = 1, F = current_extrusion_f) + " ; restore extrusion feedrate\n"
|
||||
else:
|
||||
Logger.log("w", "No previous feedrate found in gcode, feedrate for next layer(s) might be incorrect")
|
||||
|
||||
prepend_gcode += self.putValue(M = 82) + "\n"
|
||||
|
||||
# reset extrude value to pre pause value
|
||||
prepend_gcode += self.putValue(G = 92, E = current_e) + "\n"
|
||||
|
||||
elif pause_method != "griffin":
|
||||
if control_temperatures:
|
||||
# Set extruder resume temperature
|
||||
prepend_gcode += self.putValue(M = 109, S = int(target_temperature.get(current_t, 0))) + " ; resume temperature\n"
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
from ..Script import Script
|
||||
|
||||
class PauseAtHeightRepRapFirmwareDuet(Script):
|
||||
|
||||
def getSettingDataString(self):
|
||||
return """{
|
||||
"name": "Pause at height for RepRapFirmware DuetWifi / Duet Ethernet / Duet Maestro",
|
||||
"key": "PauseAtHeightRepRapFirmwareDuet",
|
||||
"metadata": {},
|
||||
"version": 2,
|
||||
"settings":
|
||||
{
|
||||
"pause_height":
|
||||
{
|
||||
"label": "Pause height",
|
||||
"description": "At what height should the pause occur",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 5.0
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
def execute(self, data):
|
||||
current_z = 0.
|
||||
pause_z = self.getSettingValueByKey("pause_height")
|
||||
|
||||
layers_started = False
|
||||
for layer_number, layer in enumerate(data):
|
||||
lines = layer.split("\n")
|
||||
for line in lines:
|
||||
if ";LAYER:0" in line:
|
||||
layers_started = True
|
||||
continue
|
||||
|
||||
if not layers_started:
|
||||
continue
|
||||
|
||||
if self.getValue(line, 'G') == 1 or self.getValue(line, 'G') == 0:
|
||||
current_z = self.getValue(line, 'Z')
|
||||
if current_z != None:
|
||||
if current_z >= pause_z:
|
||||
prepend_gcode = ";TYPE:CUSTOM\n"
|
||||
prepend_gcode += "; -- Pause at height (%.2f mm) --\n" % pause_z
|
||||
prepend_gcode += self.putValue(M = 226) + "\n"
|
||||
layer = prepend_gcode + layer
|
||||
|
||||
data[layer_number] = layer # Override the data of this layer with the modified data
|
||||
return data
|
||||
break
|
||||
return data
|
|
@ -1,178 +0,0 @@
|
|||
from UM.Logger import Logger
|
||||
from ..Script import Script
|
||||
class PauseAtHeightforRepetier(Script):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def getSettingDataString(self):
|
||||
return """{
|
||||
"name":"Pause at height for repetier",
|
||||
"key": "PauseAtHeightforRepetier",
|
||||
"metadata": {},
|
||||
"version": 2,
|
||||
"settings":
|
||||
{
|
||||
"pause_height":
|
||||
{
|
||||
"label": "Pause height",
|
||||
"description": "At what height should the pause occur",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 5.0
|
||||
},
|
||||
"head_park_x":
|
||||
{
|
||||
"label": "Park print head X",
|
||||
"description": "What x location does the head move to when pausing.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 5.0
|
||||
},
|
||||
"head_park_y":
|
||||
{
|
||||
"label": "Park print head Y",
|
||||
"description": "What y location does the head move to when pausing.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 5.0
|
||||
},
|
||||
"head_move_Z":
|
||||
{
|
||||
"label": "Head move Z",
|
||||
"description": "The Hieght of Z-axis retraction before parking.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 15.0
|
||||
},
|
||||
"retraction_amount":
|
||||
{
|
||||
"label": "Retraction",
|
||||
"description": "How much fillament must be retracted at pause.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 5.0
|
||||
},
|
||||
"extrude_amount":
|
||||
{
|
||||
"label": "Extrude amount",
|
||||
"description": "How much filament should be extruded after pause. This is needed when doing a material change on Ultimaker2's to compensate for the retraction after the change. In that case 128+ is recommended.",
|
||||
"unit": "mm",
|
||||
"type": "float",
|
||||
"default_value": 90.0
|
||||
},
|
||||
"redo_layers":
|
||||
{
|
||||
"label": "Redo layers",
|
||||
"description": "Redo a number of previous layers after a pause to increases adhesion.",
|
||||
"unit": "layers",
|
||||
"type": "int",
|
||||
"default_value": 0
|
||||
}
|
||||
}
|
||||
}"""
|
||||
|
||||
def execute(self, data):
|
||||
x = 0.
|
||||
y = 0.
|
||||
current_extrusion_f = 0
|
||||
current_z = 0.
|
||||
pause_z = self.getSettingValueByKey("pause_height")
|
||||
retraction_amount = self.getSettingValueByKey("retraction_amount")
|
||||
extrude_amount = self.getSettingValueByKey("extrude_amount")
|
||||
park_x = self.getSettingValueByKey("head_park_x")
|
||||
park_y = self.getSettingValueByKey("head_park_y")
|
||||
move_Z = self.getSettingValueByKey("head_move_Z")
|
||||
layers_started = False
|
||||
redo_layers = self.getSettingValueByKey("redo_layers")
|
||||
for layer in data:
|
||||
lines = layer.split("\n")
|
||||
for line in lines:
|
||||
if ";LAYER:0" in line:
|
||||
layers_started = True
|
||||
continue
|
||||
|
||||
if not layers_started:
|
||||
continue
|
||||
|
||||
if self.getValue(line, 'G') == 1 or self.getValue(line, 'G') == 0:
|
||||
current_z = self.getValue(line, 'Z')
|
||||
if self.getValue(line, 'F') is not None and self.getValue(line, 'E') is not None:
|
||||
current_extrusion_f = self.getValue(line, 'F', current_extrusion_f)
|
||||
x = self.getValue(line, 'X', x)
|
||||
y = self.getValue(line, 'Y', y)
|
||||
if current_z is not None:
|
||||
if current_z >= pause_z:
|
||||
|
||||
index = data.index(layer)
|
||||
prevLayer = data[index-1]
|
||||
prevLines = prevLayer.split("\n")
|
||||
current_e = 0.
|
||||
for prevLine in reversed(prevLines):
|
||||
current_e = self.getValue(prevLine, 'E', -1)
|
||||
if current_e >= 0:
|
||||
break
|
||||
|
||||
prepend_gcode = ";TYPE:CUSTOM\n"
|
||||
prepend_gcode += ";added code by post processing\n"
|
||||
prepend_gcode += ";script: PauseAtHeightforRepetier.py\n"
|
||||
prepend_gcode += ";current z: %f \n" % (current_z)
|
||||
prepend_gcode += ";current X: %f \n" % (x)
|
||||
prepend_gcode += ";current Y: %f \n" % (y)
|
||||
|
||||
#Retraction
|
||||
prepend_gcode += "M83\n"
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += "G1 E-%f F6000\n" % (retraction_amount)
|
||||
|
||||
#Move the head away
|
||||
prepend_gcode += "G1 Z%f F300\n" % (1 + current_z)
|
||||
prepend_gcode += "G1 X%f Y%f F9000\n" % (park_x, park_y)
|
||||
if current_z < move_Z:
|
||||
prepend_gcode += "G1 Z%f F300\n" % (current_z + move_Z)
|
||||
|
||||
#Disable the E steppers
|
||||
prepend_gcode += "M84 E0\n"
|
||||
#Wait till the user continues printing
|
||||
prepend_gcode += "@pause now change filament and press continue printing ;Do the actual pause\n"
|
||||
|
||||
#Push the filament back,
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += "G1 E%f F6000\n" % (retraction_amount)
|
||||
|
||||
# Optionally extrude material
|
||||
if extrude_amount != 0:
|
||||
prepend_gcode += "G1 E%f F200\n" % (extrude_amount)
|
||||
prepend_gcode += "@info wait for cleaning nozzle from previous filament\n"
|
||||
prepend_gcode += "@pause remove the waste filament from parking area and press continue printing\n"
|
||||
|
||||
# and retract again, the properly primes the nozzle when changing filament.
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode += "G1 E-%f F6000\n" % (retraction_amount)
|
||||
|
||||
#Move the head back
|
||||
prepend_gcode += "G1 Z%f F300\n" % (1 + current_z)
|
||||
prepend_gcode +="G1 X%f Y%f F9000\n" % (x, y)
|
||||
if retraction_amount != 0:
|
||||
prepend_gcode +="G1 E%f F6000\n" % (retraction_amount)
|
||||
|
||||
if current_extrusion_f != 0:
|
||||
prepend_gcode += self.putValue(G=1, F=current_extrusion_f) + " ; restore extrusion feedrate\n"
|
||||
else:
|
||||
Logger.log("w", "No previous feedrate found in gcode, feedrate for next layer(s) might be incorrect")
|
||||
|
||||
prepend_gcode +="M82\n"
|
||||
|
||||
# reset extrude value to pre pause value
|
||||
prepend_gcode +="G92 E%f\n" % (current_e)
|
||||
|
||||
layer = prepend_gcode + layer
|
||||
|
||||
# include a number of previous layers
|
||||
for i in range(1, redo_layers + 1):
|
||||
prevLayer = data[index-i]
|
||||
layer = prevLayer + layer
|
||||
|
||||
data[index] = layer #Override the data of this layer with the modified data
|
||||
return data
|
||||
break
|
||||
return data
|
|
@ -67,6 +67,7 @@ class CloudPackageChecker(QObject):
|
|||
self._application.getHttpRequestManager().get(url,
|
||||
callback = self._onUserPackagesRequestFinished,
|
||||
error_callback = self._onUserPackagesRequestFinished,
|
||||
timeout=10,
|
||||
scope = self._scope)
|
||||
|
||||
def _onUserPackagesRequestFinished(self, reply: "QNetworkReply", error: Optional["QNetworkReply.NetworkError"] = None) -> None:
|
||||
|
|
|
@ -6,11 +6,15 @@ from time import time
|
|||
from typing import Callable, List, Type, TypeVar, Union, Optional, Tuple, Dict, Any, cast
|
||||
|
||||
from PyQt5.QtCore import QUrl
|
||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager
|
||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.TaskManagement.HttpRequestManager import HttpRequestManager
|
||||
from UM.TaskManagement.HttpRequestScope import JsonDecoratorScope
|
||||
from cura.API import Account
|
||||
from cura.CuraApplication import CuraApplication
|
||||
from cura.UltimakerCloud import UltimakerCloudAuthentication
|
||||
from cura.UltimakerCloud.UltimakerCloudScope import UltimakerCloudScope
|
||||
from .ToolPathUploader import ToolPathUploader
|
||||
from ..Models.BaseModel import BaseModel
|
||||
from ..Models.Http.CloudClusterResponse import CloudClusterResponse
|
||||
|
@ -35,18 +39,23 @@ class CloudApiClient:
|
|||
CLUSTER_API_ROOT = "{}/connect/v1".format(ROOT_PATH)
|
||||
CURA_API_ROOT = "{}/cura/v1".format(ROOT_PATH)
|
||||
|
||||
# In order to avoid garbage collection we keep the callbacks in this list.
|
||||
_anti_gc_callbacks = [] # type: List[Callable[[], None]]
|
||||
DEFAULT_REQUEST_TIMEOUT = 10 # seconds
|
||||
|
||||
def __init__(self, account: Account, on_error: Callable[[List[CloudError]], None]) -> None:
|
||||
# In order to avoid garbage collection we keep the callbacks in this list.
|
||||
_anti_gc_callbacks = [] # type: List[Callable[[Any], None]]
|
||||
|
||||
def __init__(self, app: CuraApplication, on_error: Callable[[List[CloudError]], None]) -> None:
|
||||
"""Initializes a new cloud API client.
|
||||
|
||||
:param app:
|
||||
:param account: The user's account object
|
||||
:param on_error: The callback to be called whenever we receive errors from the server.
|
||||
"""
|
||||
super().__init__()
|
||||
self._manager = QNetworkAccessManager()
|
||||
self._account = account
|
||||
self._app = app
|
||||
self._account = app.getCuraAPI().account
|
||||
self._scope = JsonDecoratorScope(UltimakerCloudScope(app))
|
||||
self._http = HttpRequestManager.getInstance()
|
||||
self._on_error = on_error
|
||||
self._upload = None # type: Optional[ToolPathUploader]
|
||||
|
||||
|
@ -63,8 +72,11 @@ class CloudApiClient:
|
|||
"""
|
||||
|
||||
url = "{}/clusters?status=active".format(self.CLUSTER_API_ROOT)
|
||||
reply = self._manager.get(self._createEmptyRequest(url))
|
||||
self._addCallback(reply, on_finished, CloudClusterResponse, failed)
|
||||
self._http.get(url,
|
||||
scope = self._scope,
|
||||
callback = self._parseCallback(on_finished, CloudClusterResponse, failed),
|
||||
error_callback = failed,
|
||||
timeout = self.DEFAULT_REQUEST_TIMEOUT)
|
||||
|
||||
def getClusterStatus(self, cluster_id: str, on_finished: Callable[[CloudClusterStatus], Any]) -> None:
|
||||
"""Retrieves the status of the given cluster.
|
||||
|
@ -74,8 +86,10 @@ class CloudApiClient:
|
|||
"""
|
||||
|
||||
url = "{}/clusters/{}/status".format(self.CLUSTER_API_ROOT, cluster_id)
|
||||
reply = self._manager.get(self._createEmptyRequest(url))
|
||||
self._addCallback(reply, on_finished, CloudClusterStatus)
|
||||
self._http.get(url,
|
||||
scope = self._scope,
|
||||
callback = self._parseCallback(on_finished, CloudClusterStatus),
|
||||
timeout = self.DEFAULT_REQUEST_TIMEOUT)
|
||||
|
||||
def requestUpload(self, request: CloudPrintJobUploadRequest,
|
||||
on_finished: Callable[[CloudPrintJobResponse], Any]) -> None:
|
||||
|
@ -87,9 +101,13 @@ class CloudApiClient:
|
|||
"""
|
||||
|
||||
url = "{}/jobs/upload".format(self.CURA_API_ROOT)
|
||||
body = json.dumps({"data": request.toDict()})
|
||||
reply = self._manager.put(self._createEmptyRequest(url), body.encode())
|
||||
self._addCallback(reply, on_finished, CloudPrintJobResponse)
|
||||
data = json.dumps({"data": request.toDict()}).encode()
|
||||
|
||||
self._http.put(url,
|
||||
scope = self._scope,
|
||||
data = data,
|
||||
callback = self._parseCallback(on_finished, CloudPrintJobResponse),
|
||||
timeout = self.DEFAULT_REQUEST_TIMEOUT)
|
||||
|
||||
def uploadToolPath(self, print_job: CloudPrintJobResponse, mesh: bytes, on_finished: Callable[[], Any],
|
||||
on_progress: Callable[[int], Any], on_error: Callable[[], Any]):
|
||||
|
@ -102,7 +120,7 @@ class CloudApiClient:
|
|||
:param on_error: A function to be called if the upload fails.
|
||||
"""
|
||||
|
||||
self._upload = ToolPathUploader(self._manager, print_job, mesh, on_finished, on_progress, on_error)
|
||||
self._upload = ToolPathUploader(self._http, print_job, mesh, on_finished, on_progress, on_error)
|
||||
self._upload.start()
|
||||
|
||||
# Requests a cluster to print the given print job.
|
||||
|
@ -111,8 +129,11 @@ class CloudApiClient:
|
|||
# \param on_finished: The function to be called after the result is parsed.
|
||||
def requestPrint(self, cluster_id: str, job_id: str, on_finished: Callable[[CloudPrintResponse], Any]) -> None:
|
||||
url = "{}/clusters/{}/print/{}".format(self.CLUSTER_API_ROOT, cluster_id, job_id)
|
||||
reply = self._manager.post(self._createEmptyRequest(url), b"")
|
||||
self._addCallback(reply, on_finished, CloudPrintResponse)
|
||||
self._http.post(url,
|
||||
scope = self._scope,
|
||||
data = b"",
|
||||
callback = self._parseCallback(on_finished, CloudPrintResponse),
|
||||
timeout = self.DEFAULT_REQUEST_TIMEOUT)
|
||||
|
||||
def doPrintJobAction(self, cluster_id: str, cluster_job_id: str, action: str,
|
||||
data: Optional[Dict[str, Any]] = None) -> None:
|
||||
|
@ -126,7 +147,10 @@ class CloudApiClient:
|
|||
|
||||
body = json.dumps({"data": data}).encode() if data else b""
|
||||
url = "{}/clusters/{}/print_jobs/{}/action/{}".format(self.CLUSTER_API_ROOT, cluster_id, cluster_job_id, action)
|
||||
self._manager.post(self._createEmptyRequest(url), body)
|
||||
self._http.post(url,
|
||||
scope = self._scope,
|
||||
data = body,
|
||||
timeout = self.DEFAULT_REQUEST_TIMEOUT)
|
||||
|
||||
def _createEmptyRequest(self, path: str, content_type: Optional[str] = "application/json") -> QNetworkRequest:
|
||||
"""We override _createEmptyRequest in order to add the user credentials.
|
||||
|
@ -185,12 +209,12 @@ class CloudApiClient:
|
|||
else:
|
||||
Logger.log("e", "Cannot find data or errors in the cloud response: %s", response)
|
||||
|
||||
def _addCallback(self,
|
||||
reply: QNetworkReply,
|
||||
def _parseCallback(self,
|
||||
on_finished: Union[Callable[[CloudApiClientModel], Any],
|
||||
Callable[[List[CloudApiClientModel]], Any]],
|
||||
model: Type[CloudApiClientModel],
|
||||
on_error: Optional[Callable] = None) -> None:
|
||||
on_error: Optional[Callable] = None) -> Callable[[QNetworkReply], None]:
|
||||
|
||||
"""Creates a callback function so that it includes the parsing of the response into the correct model.
|
||||
|
||||
The callback is added to the 'finished' signal of the reply.
|
||||
|
@ -200,7 +224,8 @@ class CloudApiClient:
|
|||
:param model: The type of the model to convert the response to.
|
||||
"""
|
||||
|
||||
def parse() -> None:
|
||||
def parse(reply: QNetworkReply) -> None:
|
||||
|
||||
self._anti_gc_callbacks.remove(parse)
|
||||
|
||||
# Don't try to parse the reply if we didn't get one
|
||||
|
@ -216,6 +241,4 @@ class CloudApiClient:
|
|||
self._parseModels(response, on_finished, model)
|
||||
|
||||
self._anti_gc_callbacks.append(parse)
|
||||
reply.finished.connect(parse)
|
||||
if on_error is not None:
|
||||
reply.error.connect(on_error)
|
||||
return parse
|
||||
|
|
|
@ -4,6 +4,7 @@ import os
|
|||
from typing import Dict, List, Optional
|
||||
|
||||
from PyQt5.QtCore import QTimer
|
||||
from PyQt5.QtNetwork import QNetworkReply
|
||||
|
||||
from UM import i18nCatalog
|
||||
from UM.Logger import Logger # To log errors talking to the API.
|
||||
|
@ -40,7 +41,7 @@ class CloudOutputDeviceManager:
|
|||
# Persistent dict containing the remote clusters for the authenticated user.
|
||||
self._remote_clusters = {} # type: Dict[str, CloudOutputDevice]
|
||||
self._account = CuraApplication.getInstance().getCuraAPI().account # type: Account
|
||||
self._api = CloudApiClient(self._account, on_error = lambda error: Logger.log("e", str(error)))
|
||||
self._api = CloudApiClient(CuraApplication.getInstance(), on_error = lambda error: Logger.log("e", str(error)))
|
||||
self._account.loginStateChanged.connect(self._onLoginStateChanged)
|
||||
|
||||
# Ensure we don't start twice.
|
||||
|
@ -118,7 +119,7 @@ class CloudOutputDeviceManager:
|
|||
self._syncing = False
|
||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.SUCCESS)
|
||||
|
||||
def _onGetRemoteClusterFailed(self):
|
||||
def _onGetRemoteClusterFailed(self, reply: QNetworkReply, error: QNetworkReply.NetworkError) -> None:
|
||||
self._syncing = False
|
||||
self._account.setSyncState(self.SYNC_SERVICE_NAME, SyncState.ERROR)
|
||||
|
||||
|
@ -265,6 +266,13 @@ class CloudOutputDeviceManager:
|
|||
machine.setName(device.name)
|
||||
machine.setMetaDataEntry(self.META_CLUSTER_ID, device.key)
|
||||
machine.setMetaDataEntry("group_name", device.name)
|
||||
machine.setMetaDataEntry("removal_warning", self.I18N_CATALOG.i18nc(
|
||||
"@label ({} is printer name)",
|
||||
"{} will be removed until the next account sync. <br> To remove {} permanently, "
|
||||
"visit <a href='https://mycloud.ultimaker.com/'>Ultimaker Digital Factory</a>. "
|
||||
"<br><br>Are you sure you want to remove {} temporarily?",
|
||||
device.name, device.name, device.name
|
||||
))
|
||||
machine.addConfiguredConnectionType(device.connectionType.value)
|
||||
|
||||
def _connectToOutputDevice(self, device: CloudOutputDevice, machine: GlobalStack) -> None:
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# Copyright (c) 2019 Ultimaker B.V.
|
||||
# !/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from PyQt5.QtCore import QUrl
|
||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply, QNetworkAccessManager
|
||||
from typing import Optional, Callable, Any, Tuple, cast
|
||||
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
|
||||
from typing import Callable, Any, Tuple, cast, Dict, Optional
|
||||
|
||||
from UM.Logger import Logger
|
||||
from UM.TaskManagement.HttpRequestManager import HttpRequestManager
|
||||
|
||||
from ..Models.Http.CloudPrintJobResponse import CloudPrintJobResponse
|
||||
|
||||
|
@ -23,7 +23,7 @@ class ToolPathUploader:
|
|||
# The amount of bytes to send per request
|
||||
BYTES_PER_REQUEST = 256 * 1024
|
||||
|
||||
def __init__(self, manager: QNetworkAccessManager, 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]
|
||||
) -> None:
|
||||
"""Creates a mesh upload object.
|
||||
|
@ -36,7 +36,7 @@ class ToolPathUploader:
|
|||
:param on_error: The method to be called when an error occurs.
|
||||
"""
|
||||
|
||||
self._manager = manager
|
||||
self._http = http
|
||||
self._print_job = print_job
|
||||
self._data = data
|
||||
|
||||
|
@ -47,7 +47,6 @@ class ToolPathUploader:
|
|||
self._sent_bytes = 0
|
||||
self._retries = 0
|
||||
self._finished = False
|
||||
self._reply = None # type: Optional[QNetworkReply]
|
||||
|
||||
@property
|
||||
def printJob(self):
|
||||
|
@ -55,19 +54,6 @@ class ToolPathUploader:
|
|||
|
||||
return self._print_job
|
||||
|
||||
def _createRequest(self) -> QNetworkRequest:
|
||||
"""Creates a network request to the print job upload URL, adding the needed content range header."""
|
||||
|
||||
request = QNetworkRequest(QUrl(self._print_job.upload_url))
|
||||
request.setHeader(QNetworkRequest.ContentTypeHeader, self._print_job.content_type)
|
||||
|
||||
first_byte, last_byte = self._chunkRange()
|
||||
content_range = "bytes {}-{}/{}".format(first_byte, last_byte - 1, len(self._data))
|
||||
request.setRawHeader(b"Content-Range", content_range.encode())
|
||||
Logger.log("i", "Uploading %s to %s", content_range, self._print_job.upload_url)
|
||||
|
||||
return request
|
||||
|
||||
def _chunkRange(self) -> Tuple[int, int]:
|
||||
"""Determines the bytes that should be uploaded next.
|
||||
|
||||
|
@ -99,13 +85,23 @@ class ToolPathUploader:
|
|||
raise ValueError("The upload is already finished")
|
||||
|
||||
first_byte, last_byte = self._chunkRange()
|
||||
request = self._createRequest()
|
||||
content_range = "bytes {}-{}/{}".format(first_byte, last_byte - 1, len(self._data))
|
||||
|
||||
# now send the reply and subscribe to the results
|
||||
self._reply = self._manager.put(request, self._data[first_byte:last_byte])
|
||||
self._reply.finished.connect(self._finishedCallback)
|
||||
self._reply.uploadProgress.connect(self._progressCallback)
|
||||
self._reply.error.connect(self._errorCallback)
|
||||
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(
|
||||
url = cast(str, self._print_job.upload_url),
|
||||
headers_dict = headers,
|
||||
data = self._data[first_byte:last_byte],
|
||||
callback = self._finishedCallback,
|
||||
error_callback = self._errorCallback,
|
||||
upload_progress_callback = self._progressCallback
|
||||
)
|
||||
|
||||
def _progressCallback(self, bytes_sent: int, bytes_total: int) -> None:
|
||||
"""Handles an update to the upload progress
|
||||
|
@ -118,7 +114,8 @@ class ToolPathUploader:
|
|||
total_sent = self._sent_bytes + bytes_sent
|
||||
self._on_progress(int(total_sent / len(self._data) * 100))
|
||||
|
||||
def _errorCallback(self) -> None:
|
||||
## Handles an error uploading.
|
||||
def _errorCallback(self, reply: QNetworkReply, error: QNetworkReply.NetworkError) -> None:
|
||||
"""Handles an error uploading."""
|
||||
|
||||
reply = cast(QNetworkReply, self._reply)
|
||||
|
@ -127,7 +124,7 @@ class ToolPathUploader:
|
|||
self.stop()
|
||||
self._on_error()
|
||||
|
||||
def _finishedCallback(self) -> None:
|
||||
def _finishedCallback(self, reply: QNetworkReply) -> None:
|
||||
"""Checks whether a chunk of data was uploaded successfully, starting the next chunk if needed."""
|
||||
|
||||
reply = cast(QNetworkReply, self._reply)
|
||||
|
@ -148,7 +145,7 @@ class ToolPathUploader:
|
|||
|
||||
# Http codes that are not to be retried are assumed to be errors.
|
||||
if status_code > 308:
|
||||
self._errorCallback()
|
||||
self._errorCallback(reply, None)
|
||||
return
|
||||
|
||||
Logger.log("d", "status_code: %s, Headers: %s, body: %s", status_code,
|
||||
|
|
|
@ -286,7 +286,7 @@ class LocalClusterOutputDeviceManager:
|
|||
def _showCloudFlowMessage(device: LocalClusterOutputDevice) -> None:
|
||||
"""Nudge the user to start using Ultimaker Cloud."""
|
||||
|
||||
if CuraApplication.getInstance().getMachineManager().activeMachineIsUsingCloudConnection:
|
||||
if CuraApplication.getInstance().getMachineManager().activeMachineHasCloudRegistration:
|
||||
# This printer is already cloud connected, so we do not bother the user anymore.
|
||||
return
|
||||
if not CuraApplication.getInstance().getCuraAPI().account.isLoggedIn:
|
||||
|
|
|
@ -2,11 +2,44 @@
|
|||
# Cura is released under the terms of the LGPLv3 or higher.
|
||||
|
||||
import configparser
|
||||
import copy # To split up files.
|
||||
from typing import Tuple, List
|
||||
import io
|
||||
from UM.VersionUpgrade import VersionUpgrade
|
||||
|
||||
|
||||
renamed_nozzles = {
|
||||
"deltacomb_025_e3d": "deltacomb_dc20_fbe025",
|
||||
"deltacomb_040_e3d": "deltacomb_dc20_fbe040",
|
||||
"deltacomb_080_e3d": "deltacomb_dc20_vfbe080"
|
||||
}
|
||||
default_qualities_per_nozzle_and_material = {
|
||||
# Can't define defaults for user-defined materials, since we only have the material ID. Those will get reset to empty quality :(
|
||||
"deltacomb_dc20_fbe025": {
|
||||
"generic_pla_175": "deltacomb_FBE0.25_PLA_C",
|
||||
"generic_abs_175": "deltacomb_FBE0.25_ABS_C"
|
||||
},
|
||||
"deltacomb_dc20_fbe040": {
|
||||
"generic_pla_175": "deltacomb_FBE0.40_PLA_C",
|
||||
"generic_abs_175": "deltacomb_FBE0.40_ABS_C",
|
||||
"generic_petg_175": "deltacomb_FBE0.40_PETG_C",
|
||||
"generic_tpu_175": "deltacomb_FBE0.40_TPU_C"
|
||||
},
|
||||
"deltacomb_dc20_vfbe080": {
|
||||
"generic_pla_175": "deltacomb_VFBE0.80_PLA_D",
|
||||
"generic_abs_175": "deltacomb_VFBE0.80_ABS_D"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class VersionUpgrade460to462(VersionUpgrade):
|
||||
def getCfgVersion(self, serialised: str) -> int:
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialised)
|
||||
format_version = int(parser.get("general", "version")) # Explicitly give an exception when this fails. That means that the file format is not recognised.
|
||||
setting_version = int(parser.get("metadata", "setting_version", fallback = "0"))
|
||||
return format_version * 1000000 + setting_version
|
||||
|
||||
def upgradePreferences(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades preferences to have the new version number.
|
||||
|
@ -25,6 +58,66 @@ class VersionUpgrade460to462(VersionUpgrade):
|
|||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
||||
def upgradeExtruderInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades per-extruder instance containers to the new version number.
|
||||
|
||||
This applies all of the changes that are applied in other instance
|
||||
containers as well.
|
||||
|
||||
In the case of Deltacomb printers, it splits the 2 extruders into 4 and
|
||||
changes the definition.
|
||||
:param serialized: The original contents of the instance container.
|
||||
:param filename: The original file name of the instance container.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
those files.
|
||||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None, comment_prefixes = ())
|
||||
parser.read_string(serialized)
|
||||
results = [(parser, filename)]
|
||||
|
||||
if "general" in parser and "definition" in parser["general"]:
|
||||
if parser["general"]["definition"] == "deltacomb_extruder_0":
|
||||
parser["general"]["definition"] = "deltacomb_base_extruder_0"
|
||||
elif parser["general"]["definition"] == "deltacomb_extruder_1": # Split up the second Deltacomb extruder into 3, creating an extra two extruders.
|
||||
parser_e2 = configparser.ConfigParser(interpolation = None)
|
||||
parser_e3 = configparser.ConfigParser(interpolation = None)
|
||||
parser_e2.read_dict(parser)
|
||||
parser_e3.read_dict(parser)
|
||||
|
||||
parser["general"]["definition"] = "deltacomb_base_extruder_1"
|
||||
parser_e2["general"]["definition"] = "deltacomb_base_extruder_2"
|
||||
parser_e3["general"]["definition"] = "deltacomb_base_extruder_3"
|
||||
results.append((parser_e2, filename + "_e2_upgrade")) # Hopefully not already taken.
|
||||
results.append((parser_e3, filename + "_e3_upgrade"))
|
||||
elif parser["general"]["definition"] == "deltacomb": # On the global stack, the per-extruder user container OR the per-extruder quality changes container.
|
||||
parser["general"]["definition"] = "deltacomb_dc20"
|
||||
|
||||
if "metadata" in parser and ("extruder" in parser["metadata"] or "position" in parser["metadata"]): # Per-extruder user container or quality changes container.
|
||||
parser_e2 = configparser.ConfigParser(interpolation = None)
|
||||
parser_e3 = configparser.ConfigParser(interpolation = None)
|
||||
parser_e2.read_dict(parser)
|
||||
parser_e3.read_dict(parser)
|
||||
if "extruder" in parser["metadata"]:
|
||||
parser_e2["metadata"]["extruder"] += "_e2_upgrade"
|
||||
parser_e3["metadata"]["extruder"] += "_e3_upgrade"
|
||||
results.append((parser_e2, filename + "_e2_upgrade"))
|
||||
results.append((parser_e3, filename + "_e3_upgrade"))
|
||||
|
||||
# Now go upgrade with the generic instance container method.
|
||||
final_serialized = [] # type: List[str]
|
||||
final_filenames = [] # type: List[str]
|
||||
for result_parser, result_filename in results:
|
||||
result_ss = io.StringIO()
|
||||
result_parser.write(result_ss)
|
||||
result_serialized = result_ss.getvalue()
|
||||
# The upgrade function itself might also return multiple files, so we need to append all of those into the final list.
|
||||
this_filenames_upgraded, this_serialized_upgraded = self.upgradeInstanceContainer(result_serialized, result_filename)
|
||||
final_serialized += this_serialized_upgraded
|
||||
final_filenames += this_filenames_upgraded
|
||||
|
||||
return final_filenames, final_serialized
|
||||
|
||||
def upgradeInstanceContainer(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades instance containers to have the new version number.
|
||||
|
@ -62,6 +155,9 @@ class VersionUpgrade460to462(VersionUpgrade):
|
|||
def upgradeStack(self, serialized: str, filename: str) -> Tuple[List[str], List[str]]:
|
||||
"""
|
||||
Upgrades stacks to have the new version number.
|
||||
|
||||
This upgrades Deltacomb printers to their new profile structure, and
|
||||
gives them 4 extruders.
|
||||
:param serialized: The original contents of the stack.
|
||||
:param filename: The original file name of the stack.
|
||||
:return: A list of new file names, and a list of the new contents for
|
||||
|
@ -69,12 +165,56 @@ class VersionUpgrade460to462(VersionUpgrade):
|
|||
"""
|
||||
parser = configparser.ConfigParser(interpolation = None)
|
||||
parser.read_string(serialized)
|
||||
results = [(parser, filename)]
|
||||
|
||||
# Update version number.
|
||||
if "metadata" not in parser:
|
||||
parser["metadata"] = {}
|
||||
parser["metadata"]["setting_version"] = "14"
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
if "containers" in parser and "7" in parser["containers"]:
|
||||
if parser["containers"]["7"] == "deltacomb_extruder_0" or parser["containers"]["7"] == "deltacomb_extruder_1": # Extruder stack.
|
||||
if "5" in parser["containers"]:
|
||||
parser["containers"]["5"] = renamed_nozzles.get(parser["containers"]["5"], parser["containers"]["5"])
|
||||
if "3" in parser["containers"] and "4" in parser["containers"] and parser["containers"]["3"] == "empty_quality":
|
||||
parser["containers"]["3"] = default_qualities_per_nozzle_and_material[parser["containers"]["5"]].get(parser["containers"]["4"], "empty_quality")
|
||||
if parser["containers"]["7"] == "deltacomb_extruder_0":
|
||||
parser["containers"]["7"] = "deltacomb_base_extruder_0"
|
||||
else:
|
||||
parser["containers"]["7"] = "deltacomb_base_extruder_1"
|
||||
# Copy this extruder to extruder 3 and 4.
|
||||
extruder3 = configparser.ConfigParser(interpolation=None)
|
||||
extruder4 = configparser.ConfigParser(interpolation=None)
|
||||
extruder3.read_dict(parser)
|
||||
extruder4.read_dict(parser)
|
||||
|
||||
extruder3["general"]["id"] += "_e2_upgrade"
|
||||
extruder3["metadata"]["position"] = "2"
|
||||
extruder3["containers"]["0"] += "_e2_upgrade"
|
||||
if extruder3["containers"]["1"] != "empty_quality_changes":
|
||||
extruder3["containers"]["1"] += "_e2_upgrade"
|
||||
extruder3["containers"]["6"] += "_e2_upgrade"
|
||||
extruder3["containers"]["7"] = "deltacomb_base_extruder_2"
|
||||
results.append((extruder3, filename + "_e2_upgrade"))
|
||||
|
||||
extruder4["general"]["id"] += "_e3_upgrade"
|
||||
extruder4["metadata"]["position"] = "3"
|
||||
extruder4["containers"]["0"] += "_e3_upgrade"
|
||||
if extruder4["containers"]["1"] != "empty_quality_changes":
|
||||
extruder4["containers"]["1"] += "_e3_upgrade"
|
||||
extruder4["containers"]["6"] += "_e3_upgrade"
|
||||
extruder4["containers"]["7"] = "deltacomb_base_extruder_3"
|
||||
results.append((extruder4, filename + "_e3_upgrade"))
|
||||
elif parser["containers"]["7"] == "deltacomb": # Global stack.
|
||||
parser["containers"]["7"] = "deltacomb_dc20"
|
||||
parser["containers"]["3"] = "deltacomb_global_C"
|
||||
|
||||
result_serialized = []
|
||||
result_filenames = []
|
||||
for result_parser, result_filename in results:
|
||||
result_ss = io.StringIO()
|
||||
result_parser.write(result_ss)
|
||||
result_serialized.append(result_ss.getvalue())
|
||||
result_filenames.append(result_filename)
|
||||
|
||||
return result_filenames, result_serialized
|
||||
|
|
|
@ -17,10 +17,10 @@ def getMetaData() -> Dict[str, Any]:
|
|||
("preferences", 6000013): ("preferences", 6000014, upgrade.upgradePreferences),
|
||||
("machine_stack", 4000013): ("machine_stack", 4000014, upgrade.upgradeStack),
|
||||
("extruder_train", 4000013): ("extruder_train", 4000014, upgrade.upgradeStack),
|
||||
("definition_changes", 4000013): ("definition_changes", 4000014, upgrade.upgradeInstanceContainer),
|
||||
("quality_changes", 4000013): ("quality_changes", 4000014, upgrade.upgradeInstanceContainer),
|
||||
("quality", 4000013): ("quality", 4000014, upgrade.upgradeInstanceContainer),
|
||||
("user", 4000013): ("user", 4000014, upgrade.upgradeInstanceContainer),
|
||||
("definition_changes", 4000013): ("definition_changes", 4000014, upgrade.upgradeExtruderInstanceContainer),
|
||||
("quality_changes", 4000013): ("quality_changes", 4000014, upgrade.upgradeExtruderInstanceContainer),
|
||||
("quality", 4000013): ("quality", 4000014, upgrade.upgradeExtruderInstanceContainer),
|
||||
("user", 4000013): ("user", 4000014, upgrade.upgradeExtruderInstanceContainer),
|
||||
},
|
||||
"sources": {
|
||||
"preferences": {
|
||||
|
|
|
@ -58,6 +58,19 @@ class VersionUpgrade462to47(VersionUpgrade):
|
|||
maximum_deviation = "=(" + maximum_deviation + ") / 2"
|
||||
parser["values"]["meshfix_maximum_deviation"] = maximum_deviation
|
||||
|
||||
# Ironing inset is now based on the flow-compensated line width to make the setting have a more logical UX.
|
||||
# Adjust so that the actual print result remains the same.
|
||||
if "ironing_inset" in parser["values"]:
|
||||
ironing_inset = parser["values"]["ironing_inset"]
|
||||
if ironing_inset.startswith("="):
|
||||
ironing_inset = ironing_inset[1:]
|
||||
if "ironing_pattern" in parser["values"] and parser["values"]["ironing_pattern"] == "concentric":
|
||||
correction = " + ironing_line_spacing - skin_line_width * (1.0 + ironing_flow / 100) / 2"
|
||||
else: # If ironing_pattern doesn't exist, it means the default (zigzag) is selected
|
||||
correction = " + skin_line_width * (1.0 - ironing_flow / 100) / 2"
|
||||
ironing_inset = "=(" + ironing_inset + ")" + correction
|
||||
parser["values"]["ironing_inset"] = ironing_inset
|
||||
|
||||
result = io.StringIO()
|
||||
parser.write(result)
|
||||
return [filename], [result.getvalue()]
|
||||
|
@ -88,6 +101,25 @@ class VersionUpgrade462to47(VersionUpgrade):
|
|||
script_parser = configparser.ConfigParser(interpolation=None)
|
||||
script_parser.optionxform = str # type: ignore # Don't transform the setting keys as they are case-sensitive.
|
||||
script_parser.read_string(script_str)
|
||||
|
||||
# Unify all Pause at Height
|
||||
script_id = script_parser.sections()[0]
|
||||
if script_id in ["BQ_PauseAtHeight", "PauseAtHeightRepRapFirmwareDuet", "PauseAtHeightforRepetier"]:
|
||||
script_settings = script_parser.items(script_id)
|
||||
script_settings.append(("pause_method", {
|
||||
"BQ_PauseAtHeight": "bq",
|
||||
"PauseAtHeightforRepetier": "repetier",
|
||||
"PauseAtHeightRepRapFirmwareDuet": "reprap"
|
||||
}[script_id]))
|
||||
|
||||
# Since we cannot rename a section, we remove the original section and create a new section with the new script id.
|
||||
script_parser.remove_section(script_id)
|
||||
script_id = "PauseAtHeight"
|
||||
script_parser.add_section(script_id)
|
||||
for setting_tuple in script_settings:
|
||||
script_parser.set(script_id, setting_tuple[0], setting_tuple[1])
|
||||
|
||||
# Update redo_layers to redo_layer
|
||||
if "PauseAtHeight" in script_parser:
|
||||
if "redo_layers" in script_parser["PauseAtHeight"]:
|
||||
script_parser["PauseAtHeight"]["redo_layer"] = str(int(script_parser["PauseAtHeight"]["redo_layers"]) > 0)
|
||||
|
|
33
resources/definitions/I3MetalMotion.def.json
Normal file
33
resources/definitions/I3MetalMotion.def.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "I3 Metal Motion",
|
||||
"inherits": "fdmprinter",
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "Peter Felecan",
|
||||
"manufacturer": "eMotionTech",
|
||||
"file_formats": "text/x-gcode",
|
||||
"has_materials": true,
|
||||
"preferred_material": "emotiontech_pla",
|
||||
"machine_extruder_trains":
|
||||
{
|
||||
"0": "I3MetalMotion_extruder_0"
|
||||
}
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "I3MetalMotion" },
|
||||
"machine_heated_bed": { "default_value": true },
|
||||
"machine_width": { "default_value": 200 },
|
||||
"machine_height": { "default_value": 200 },
|
||||
"machine_depth": { "default_value": 200 },
|
||||
"machine_center_is_zero": { "default_value": false },
|
||||
"machine_gcode_flavor": { "default_value": "RepRap (RepRap)" },
|
||||
"machine_start_gcode": {
|
||||
"default_value": "G21 ; set units to millimeters\nG90 ; use absolute positioning\nM82 ; absolute extrusion mode\nM104 S{material_print_temperature_layer_0} ; set extruder temp\nM140 S{material_bed_temperature_layer_0} ; set bed temp\nM190 S{material_bed_temperature_layer_0} ; wait for bed temp\nM109 S{material_print_temperature_layer_0} ; wait for extruder temp\nG28 W ; home all\nG92 E0.0 ; reset extruder distance position\nG1 Y-3.0 F1000.0 ; go outside print area\nG1 X60.0 E9.0 F1000.0 ; intro line\nG1 X100.0 E21.5 F1000.0 ; intro line\nG92 E0.0 ; reset extruder distance position"
|
||||
},
|
||||
"machine_end_gcode": {
|
||||
"default_value": "G28 Z\nG28 X\nG28 Y\nM107 ; Turn off the fan\nG91; Relative positioning\nG1 E-1 ; reduce filament pressure\nM104 T0 S0\nG90 ; Absolute positioning\nG92 E0 ; Reset extruder position\nM140 S0 ; Disable heated bed\nM84 ; Turn the steppers off"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb 3D",
|
||||
"inherits": "fdmprinter",
|
||||
|
||||
"metadata": {
|
||||
"author": "Gabriele Rossetti",
|
||||
"visible": true,
|
||||
"manufacturer": "Deltacomb 3D",
|
||||
"file_formats": "text/x-gcode",
|
||||
"icon": "icon_ultimaker2",
|
||||
"platform": "deltacomb.3mf",
|
||||
"has_machine_quality": true,
|
||||
"has_materials": true,
|
||||
"has_variants": true,
|
||||
"variants_name": "Head",
|
||||
"preferred_variant_name": "E3D 0.40mm",
|
||||
"preferred_material": "generic_pla",
|
||||
"preferred_quality_type": "normal",
|
||||
"machine_extruder_trains": { "0": "deltacomb_extruder_0", "1": "deltacomb_extruder_1" }
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_extruder_count": { "default_value": 1 },
|
||||
"machine_heated_bed": { "default_value": true },
|
||||
"machine_width": { "default_value": 190 },
|
||||
"machine_height": { "default_value": 250 },
|
||||
"machine_depth": { "default_value": 190 },
|
||||
"machine_center_is_zero": { "default_value": true },
|
||||
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
|
||||
"machine_start_gcode": { "default_value": "G21 ;metric values\nG90 ;absolute positioning\nM82 ;set extruder to absolute mode\nM107 ;start with the fan off\nG28 ;Home all axes (max endstops)\nG1 Z15.0 F9000 ;move the platform down 15mm\nG92 E0 ;zero the extruded length\nG1 F9000\n;Put printing message on LCD screen\nM117 Printing..."},
|
||||
"machine_end_gcode": { "default_value": "M104 S0 ;extruder heater off\nM140 S0 ;heated bed heater off (if you have it)\nG91 ;relative positioning\nG1 E-1 F300 ;retract the filament a bit before lifting the nozzle, to release some of the pressure\nG28 ;Home all axes (max endstops)\nM84 ;steppers off\nG90 ;absolute positioning" },
|
||||
"machine_shape": { "default_value": "elliptic" },
|
||||
"retraction_hop_enabled": { "default_value": true },
|
||||
"retraction_hop": { "default_value": 1 },
|
||||
"retraction_amount" : { "default_value": 3.5 },
|
||||
"retraction_speed" : { "default_value": 30 },
|
||||
"retraction_combing" : { "default_value": "noskin" },
|
||||
"travel_avoid_distance": { "value": "1" },
|
||||
"speed_print" : { "default_value": 80 },
|
||||
"speed_infill": { "value": "round(speed_print * 1.05, 0)" },
|
||||
"speed_topbottom": { "value": "round(speed_print * 0.95, 0)" },
|
||||
"speed_wall": { "value": "speed_print" },
|
||||
"speed_wall_0": { "value": "30" },
|
||||
"speed_wall_x": { "value": "speed_wall" },
|
||||
"speed_layer_0": { "value": "min(round(speed_print * 0.75, 0), 45.0)" },
|
||||
"speed_travel": { "value": 150 },
|
||||
"speed_travel_layer_0": { "value": "round(speed_travel * 0.7, 0)" },
|
||||
"skirt_brim_speed": { "value": "speed_layer_0" },
|
||||
"skirt_line_count": { "default_value": 3 },
|
||||
"skirt_brim_minimal_length": { "default_value": 150 },
|
||||
"infill_sparse_density": { "default_value": 30 },
|
||||
"infill_pattern": { "value": "'cubic'" },
|
||||
"infill_before_walls" : { "default_value": false },
|
||||
"top_bottom_thickness": { "default_value": 0.8 },
|
||||
"support_z_distance": { "value": "layer_height * 2" },
|
||||
"support_bottom_distance": { "value": "layer_height" },
|
||||
"support_use_towers" : { "default_value": false },
|
||||
"jerk_enabled": { "value": "True" },
|
||||
"jerk_infill" : { "value": "5" },
|
||||
"jerk_support" : { "value": "5" },
|
||||
"acceleration_enabled": { "value": "1" },
|
||||
"acceleration_travel" : { "value": 5000 },
|
||||
"machine_max_feedrate_z" : { "default_value": 300 }
|
||||
}
|
||||
}
|
92
resources/definitions/deltacomb_base.def.json
Executable file
92
resources/definitions/deltacomb_base.def.json
Executable file
|
@ -0,0 +1,92 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb Base Printer",
|
||||
"inherits": "fdmprinter",
|
||||
|
||||
"metadata": {
|
||||
"author": "Gabriele Rossetti",
|
||||
"visible": false,
|
||||
"manufacturer": "Deltacomb 3D Printers",
|
||||
"file_formats": "text/x-gcode",
|
||||
"has_machine_quality": true,
|
||||
"has_materials": true,
|
||||
"has_variants": true,
|
||||
"variants_name": "Head",
|
||||
|
||||
"preferred_quality_type": "d",
|
||||
"preferred_material": "generic_pla",
|
||||
|
||||
"machine_extruder_trains": {
|
||||
"0": "deltacomb_base_extruder_0",
|
||||
"1": "deltacomb_base_extruder_1",
|
||||
"2": "deltacomb_base_extruder_2",
|
||||
"3": "deltacomb_base_extruder_3"
|
||||
}
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_extruder_count": { "default_value": 1, "maximum_value": "4" },
|
||||
"machine_heated_bed": { "default_value": true },
|
||||
"machine_center_is_zero": { "default_value": true },
|
||||
"machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
|
||||
"machine_start_gcode": { "default_value": ";---------------------------------------\n;Deltacomb start script\n;---------------------------------------\nG21 ;metric values\nG90 ;absolute positioning\nM107 ;start with the fan off\nG28 ;Home all axes (max endstops)\nG92 E0 ;zero the extruded length\nG1 Z15.0 F9000 ;move to the platform down 15mm\nG1 F9000\n\n;Put printing message on LCD screen\nM117 Printing...\n;---------------------------------------"},
|
||||
"machine_end_gcode": { "default_value": ";---------------------------------------\n;Deltacomb end script\n;---------------------------------------\nG91 ;relative positioning\nG1 F15000 X8.0 E-4.5 ;Wipe filament+material retraction\nG1 F15000 E4.0 Z1 ;Retraction compensation\nG28 ;Home all axes (max endstops)\nM84 ;steppers off\n" },
|
||||
"machine_shape": { "default_value": "elliptic" },
|
||||
|
||||
"machine_max_feedrate_z" : { "default_value": 300 },
|
||||
|
||||
"speed_print" : { "default_value": 80 },
|
||||
"speed_topbottom": { "value": "speed_print * 0.90" },
|
||||
"speed_wall_0": { "value": "35 if speed_print > 35 else speed_print" },
|
||||
"speed_layer_0": { "value": "speed_print * 0.55" },
|
||||
|
||||
"speed_travel": { "value": "170" },
|
||||
"speed_travel_layer_0": { "value": "speed_travel * 0.70" },
|
||||
"speed_z_hop": { "value": "speed_travel" },
|
||||
|
||||
"acceleration_enabled": { "value": "True" },
|
||||
"acceleration_travel" : { "value": "9000" },
|
||||
"acceleration_print": { "value": "4000" },
|
||||
"acceleration_wall": { "value": "acceleration_print * 0.5" },
|
||||
"acceleration_wall_0": { "value": "acceleration_wall * 0.5" },
|
||||
"acceleration_topbottom": { "value": "acceleration_wall_0" },
|
||||
"acceleration_layer_0": { "value": "acceleration_wall_0" },
|
||||
"acceleration_prime_tower": { "value": "acceleration_wall" },
|
||||
"acceleration_support": { "value": "acceleration_wall" },
|
||||
"acceleration_support_interface": { "value": "acceleration_wall_0" },
|
||||
|
||||
"jerk_enabled": { "value": "True" },
|
||||
"jerk_print": { "value": "25" },
|
||||
"jerk_infill": { "value": "10" },
|
||||
"jerk_travel": { "value": "10" },
|
||||
|
||||
"retraction_hop_enabled": { "default_value": true },
|
||||
"retraction_hop": { "default_value": 0.5 },
|
||||
"retraction_amount" : { "default_value": 3.5 },
|
||||
"retraction_speed" : { "default_value": 70 },
|
||||
"retraction_combing" : { "default_value": "noskin" },
|
||||
"travel_avoid_distance": { "value": "1" },
|
||||
|
||||
"top_bottom_thickness": { "default_value": 0.8 },
|
||||
"roofing_layer_count": { "value": "1" },
|
||||
"roofing_line_width": { "value": "line_width * 0.75" },
|
||||
|
||||
"infill_sparse_density": { "default_value": 30 },
|
||||
"infill_pattern": { "value": "'cubic'" },
|
||||
"infill_before_walls": { "default_value": false },
|
||||
|
||||
"support_z_distance": { "value": "layer_height * 2" },
|
||||
"support_bottom_distance": { "value": "layer_height" },
|
||||
"support_use_towers" : { "default_value": false },
|
||||
"support_bottom_enable" : { "value": "0" },
|
||||
|
||||
"skirt_brim_speed": { "value": "speed_layer_0" },
|
||||
"skirt_line_count": { "default_value": 3 },
|
||||
"skirt_brim_minimal_length": { "default_value": 150 },
|
||||
"brim_width": { "value": "3" },
|
||||
|
||||
"prime_tower_size": { "value": "math.sqrt(extruders_enabled_count * prime_tower_min_volume / layer_height / math.pi) * 2"},
|
||||
"prime_tower_position_x": { "value": "prime_tower_size - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' or (prime_tower_brim_enable and adhesion_type != 'raft') else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0)" },
|
||||
"prime_tower_position_y": { "value": "machine_depth / 2 - prime_tower_size - max(extruderValue(adhesion_extruder_nr, 'brim_width') * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 if adhesion_type == 'brim' or (prime_tower_brim_enable and adhesion_type != 'raft') else (extruderValue(adhesion_extruder_nr, 'raft_margin') if adhesion_type == 'raft' else (extruderValue(adhesion_extruder_nr, 'skirt_gap') if adhesion_type == 'skirt' else 0)), max(extruderValues('travel_avoid_distance'))) - max(extruderValues('support_offset')) - sum(extruderValues('skirt_brim_line_width')) * extruderValue(adhesion_extruder_nr, 'initial_layer_line_width_factor') / 100 - (resolveOrValue('draft_shield_dist') if resolveOrValue('draft_shield_enabled') else 0) - 1" }
|
||||
}
|
||||
}
|
20
resources/definitions/deltacomb_dc20.def.json
Executable file
20
resources/definitions/deltacomb_dc20.def.json
Executable file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb DC-20",
|
||||
"inherits": "deltacomb_base",
|
||||
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"platform": "deltacomb_dc20.stl",
|
||||
"quality_definition": "deltacomb_base",
|
||||
"preferred_variant_name": "FBE 0.40mm"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Deltacomb DC-20" },
|
||||
"machine_width": { "default_value": 190 },
|
||||
"machine_depth": { "default_value": 190 },
|
||||
"machine_height": { "default_value": 250 },
|
||||
"machine_extruder_count": { "default_value": 1, "maximum_value": "4" }
|
||||
}
|
||||
}
|
24
resources/definitions/deltacomb_dc20dual.def.json
Executable file
24
resources/definitions/deltacomb_dc20dual.def.json
Executable file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb DC-20 DUAL",
|
||||
"inherits": "deltacomb_base",
|
||||
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"platform": "deltacomb_dc20.stl",
|
||||
"quality_definition": "deltacomb_base",
|
||||
"preferred_variant_name": "DBE 0.40mm",
|
||||
"machine_extruder_trains": {
|
||||
"0": "deltacomb_dc20dual_extruder_0",
|
||||
"1": "deltacomb_dc20dual_extruder_1"
|
||||
}
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Deltacomb DC-20 DUAL" },
|
||||
"machine_extruder_count": { "default_value": 2, "maximum_value": "2" },
|
||||
"machine_width": { "default_value": 190 },
|
||||
"machine_depth": { "default_value": 190 },
|
||||
"machine_height": { "default_value": 250 }
|
||||
}
|
||||
}
|
29
resources/definitions/deltacomb_dc20flux.def.json
Normal file
29
resources/definitions/deltacomb_dc20flux.def.json
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb DC-20 FLUX",
|
||||
"inherits": "deltacomb_base",
|
||||
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"platform": "deltacomb_dc20.stl",
|
||||
"quality_definition": "deltacomb_base",
|
||||
"preferred_variant_name": "FBE 0.40mm",
|
||||
"machine_extruder_trains": {
|
||||
"0": "deltacomb_dc20flux_extruder_0",
|
||||
"1": "deltacomb_dc20flux_extruder_1",
|
||||
"2": "deltacomb_dc20flux_extruder_2",
|
||||
"3": "deltacomb_dc20flux_extruder_3"
|
||||
}
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Deltacomb DC-20 FLUX" },
|
||||
"machine_width": { "default_value": 190 },
|
||||
"machine_depth": { "default_value": 190 },
|
||||
"machine_height": { "default_value": 250 },
|
||||
"machine_extruder_count": { "default_value": 2, "maximum_value": "4" },
|
||||
"switch_extruder_retraction_amount": { "value": "0" },
|
||||
"prime_tower_min_volume": { "value": "45" },
|
||||
"prime_tower_enable": { "value": "1" }
|
||||
}
|
||||
}
|
20
resources/definitions/deltacomb_dc21.def.json
Executable file
20
resources/definitions/deltacomb_dc21.def.json
Executable file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb DC-21",
|
||||
"inherits": "deltacomb_base",
|
||||
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"platform": "deltacomb_dc20.stl",
|
||||
"quality_definition": "deltacomb_base",
|
||||
"preferred_variant_name": "FBE 0.40mm"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Deltacomb DC-21" },
|
||||
"machine_width": { "default_value": 190 },
|
||||
"machine_depth": { "default_value": 190 },
|
||||
"machine_height": { "default_value": 400 },
|
||||
"machine_extruder_count": { "default_value": 1, "maximum_value": "4" }
|
||||
}
|
||||
}
|
24
resources/definitions/deltacomb_dc21dual.def.json
Executable file
24
resources/definitions/deltacomb_dc21dual.def.json
Executable file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb DC-21 DUAL",
|
||||
"inherits": "deltacomb_base",
|
||||
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"platform": "deltacomb_dc20.stl",
|
||||
"quality_definition": "deltacomb_base",
|
||||
"preferred_variant_name": "DBE 0.40mm",
|
||||
"machine_extruder_trains": {
|
||||
"0": "deltacomb_dc20dual_extruder_0",
|
||||
"1": "deltacomb_dc20dual_extruder_1"
|
||||
}
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Deltacomb DC-20 DUAL" },
|
||||
"machine_extruder_count": { "default_value": 2, "maximum_value": "2" },
|
||||
"machine_width": { "default_value": 190 },
|
||||
"machine_depth": { "default_value": 190 },
|
||||
"machine_height": { "default_value": 400 }
|
||||
}
|
||||
}
|
29
resources/definitions/deltacomb_dc21flux.def.json
Normal file
29
resources/definitions/deltacomb_dc21flux.def.json
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb DC-21 FLUX",
|
||||
"inherits": "deltacomb_base",
|
||||
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"platform": "deltacomb_dc20.stl",
|
||||
"quality_definition": "deltacomb_base",
|
||||
"preferred_variant_name": "FBE 0.40mm",
|
||||
"machine_extruder_trains": {
|
||||
"0": "deltacomb_dc20flux_extruder_0",
|
||||
"1": "deltacomb_dc20flux_extruder_1",
|
||||
"2": "deltacomb_dc20flux_extruder_2",
|
||||
"3": "deltacomb_dc20flux_extruder_3"
|
||||
}
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Deltacomb DC-20 FLUX" },
|
||||
"machine_width": { "default_value": 190 },
|
||||
"machine_depth": { "default_value": 190 },
|
||||
"machine_height": { "default_value": 400 },
|
||||
"machine_extruder_count": { "default_value": 2, "maximum_value": "4" },
|
||||
"switch_extruder_retraction_amount": { "value": "0" },
|
||||
"prime_tower_min_volume": { "value": "45" },
|
||||
"prime_tower_enable": { "value": "1" }
|
||||
}
|
||||
}
|
20
resources/definitions/deltacomb_dc30.def.json
Executable file
20
resources/definitions/deltacomb_dc30.def.json
Executable file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb DC-30",
|
||||
"inherits": "deltacomb_base",
|
||||
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"platform": "deltacomb_dc30.stl",
|
||||
"quality_definition": "deltacomb_base",
|
||||
"preferred_variant_name": "FBE 0.40mm"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Deltacomb DC-30" },
|
||||
"machine_width": { "default_value": 290 },
|
||||
"machine_depth": { "default_value": 290 },
|
||||
"machine_height": { "default_value": 300 },
|
||||
"machine_extruder_count": { "default_value": 1, "maximum_value": "4" }
|
||||
}
|
||||
}
|
24
resources/definitions/deltacomb_dc30dual.def.json
Executable file
24
resources/definitions/deltacomb_dc30dual.def.json
Executable file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb DC-30 DUAL",
|
||||
"inherits": "deltacomb_base",
|
||||
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"platform": "deltacomb_dc30.stl",
|
||||
"quality_definition": "deltacomb_base",
|
||||
"preferred_variant_name": "DBE 0.40mm",
|
||||
"machine_extruder_trains": {
|
||||
"0": "deltacomb_dc30dual_extruder_0",
|
||||
"1": "deltacomb_dc30dual_extruder_1"
|
||||
}
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Deltacomb DC-30 DUAL" },
|
||||
"machine_width": { "default_value": 290 },
|
||||
"machine_depth": { "default_value": 290 },
|
||||
"machine_height": { "default_value": 300 },
|
||||
"machine_extruder_count": { "default_value": 2, "maximum_value": "2" }
|
||||
}
|
||||
}
|
29
resources/definitions/deltacomb_dc30flux.def.json
Normal file
29
resources/definitions/deltacomb_dc30flux.def.json
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Deltacomb DC-30 FLUX",
|
||||
"inherits": "deltacomb_base",
|
||||
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"platform": "deltacomb_dc30.stl",
|
||||
"quality_definition": "deltacomb_base",
|
||||
"preferred_variant_name": "FBE 0.40mm",
|
||||
"machine_extruder_trains": {
|
||||
"0": "deltacomb_dc30flux_extruder_0",
|
||||
"1": "deltacomb_dc30flux_extruder_1",
|
||||
"2": "deltacomb_dc30flux_extruder_2",
|
||||
"3": "deltacomb_dc30flux_extruder_3"
|
||||
}
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Deltacomb DC-30 FLUX" },
|
||||
"machine_width": { "default_value": 290 },
|
||||
"machine_depth": { "default_value": 290 },
|
||||
"machine_height": { "default_value": 300 },
|
||||
"machine_extruder_count": { "default_value": 2, "maximum_value": "4" },
|
||||
"switch_extruder_retraction_amount": { "value": "0" },
|
||||
"prime_tower_min_volume": { "value": "45" },
|
||||
"prime_tower_enable": { "value": "1" }
|
||||
}
|
||||
}
|
|
@ -1575,7 +1575,7 @@
|
|||
"type": "float",
|
||||
"unit": "mm",
|
||||
"default_value": 0.35,
|
||||
"value": "wall_line_width_0 / 2",
|
||||
"value": "wall_line_width_0 / 2 + (ironing_line_spacing - skin_line_width * (1.0 + ironing_flow / 100) / 2 if ironing_pattern == 'concentric' else skin_line_width * (1.0 - ironing_flow / 100) / 2)",
|
||||
"minimum_value_warning": "0",
|
||||
"maximum_value_warning": "wall_line_width_0",
|
||||
"enabled": "ironing_enabled",
|
||||
|
@ -1761,7 +1761,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 traditional default angles (45 and 135 degrees for the lines and zig zag patterns and 45 degrees for all other patterns).",
|
||||
"type": "[int]",
|
||||
"default_value": "[ ]",
|
||||
"enabled": "infill_pattern != 'concentric' and infill_pattern != 'cubicsubdiv' and infill_sparse_density > 0",
|
||||
"enabled": "infill_pattern != 'concentric' and infill_sparse_density > 0",
|
||||
"limit_to_extruder": "infill_extruder_nr",
|
||||
"settable_per_mesh": true
|
||||
},
|
||||
|
|
|
@ -21,11 +21,12 @@
|
|||
"default_value": 220
|
||||
},
|
||||
"machine_height": {
|
||||
"default_value": 220
|
||||
"default_value": 260
|
||||
},
|
||||
"machine_depth": {
|
||||
"default_value": 260
|
||||
}, "machine_center_is_zero": {
|
||||
"default_value": 220
|
||||
},
|
||||
"machine_center_is_zero": {
|
||||
"default_value": false
|
||||
},
|
||||
"layer_height": { "default_value": 0.1 },
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
},
|
||||
"machine_depth": {
|
||||
"default_value": 260
|
||||
}, "machine_center_is_zero": {
|
||||
},
|
||||
"machine_center_is_zero": {
|
||||
"default_value": false
|
||||
},
|
||||
"layer_height": { "default_value": 0.1 },
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
"material_bed_temp_wait": {"default_value": false },
|
||||
"machine_max_feedrate_z": {"default_value": 10 },
|
||||
"machine_acceleration": {"default_value": 180 },
|
||||
"machine_start_gcode": {"default_value": "\n;Neither Hybrid AM Systems nor any of Hybrid AM Systems representatives has any liabilities or gives any warranties on this .gcode file, or on any or all objects made with this .gcode file.\n\nM140 S{material_bed_temperature_layer_0}\n\nM117 Homing Y ......\nG28 Y\nM117 Homing X ......\nG28 X\nM117 Homing Z ......\nG28 Z F100\n\nG1 Z10 F900\nG1 X-25 Y20 F12000\n\nM190 S{material_bed_temperature_layer_0}\nM117 HMS434 Printing ...\n\nM42 P10 S255 ; chamberfans on" },
|
||||
"machine_start_gcode": {"default_value": "\n;Neither Hybrid AM Systems nor any of Hybrid AM Systems representatives has any liabilities or gives any warranties on this .gcode file, or on any or all objects made with this .gcode file.\n\nM114\n\nM140 S{material_bed_temperature_layer_0}\nM118 // action:chamber_fan_on\nM141 S{build_volume_temperature}\n\nM117 Homing Y ......\nG28 Y\nM117 Homing X ......\nG28 X\nM117 Homing Z ......\nG28 Z F100\n\nG1 Z10 F900\nG1 X-25 Y20 F12000\n\nM190 S{material_bed_temperature_layer_0}\n\nM117 HMS434 Printing ..." },
|
||||
"machine_end_gcode": {"default_value": "" },
|
||||
|
||||
"retraction_extra_prime_amount": {"minimum_value_warning": "-2.0" },
|
||||
|
@ -104,7 +104,7 @@
|
|||
"skin_outline_count": {"value": "0"},
|
||||
"ironing_line_spacing": {"value": "line_width / 4 * 3"},
|
||||
"ironing_flow": {"value": "0"},
|
||||
"ironing_inset": {"value": "ironing_line_spacing"},
|
||||
"ironing_inset": {"value": "ironing_line_spacing + (ironing_line_spacing - skin_line_width * (1.0 + ironing_flow / 100) / 2 if ironing_pattern == 'concentric' else skin_line_width * (1.0 - ironing_flow / 100) / 2)"},
|
||||
"speed_ironing": {"value": "150"},
|
||||
|
||||
"infill_sparse_density": {"value": 30},
|
||||
|
|
72
resources/definitions/lotmaxx_sc60.def.json
Normal file
72
resources/definitions/lotmaxx_sc60.def.json
Normal file
|
@ -0,0 +1,72 @@
|
|||
{
|
||||
"name": "Lotmaxx Shark",
|
||||
"version": 2,
|
||||
"inherits": "fdmprinter",
|
||||
"overrides": {
|
||||
"machine_name": { "default_value": "Lotmaxx Shark" },
|
||||
"machine_width": { "default_value": 235 },
|
||||
"machine_depth": { "default_value": 235 },
|
||||
"machine_height": { "default_value": 265 },
|
||||
"machine_head_with_fans_polygon": { "default_value": [
|
||||
[-50.7,16.8],
|
||||
[-50.7,-29.5],
|
||||
[46.9,-29.5],
|
||||
[49.9,16.8]
|
||||
]
|
||||
},
|
||||
"gantry_height": { "value": 29 },
|
||||
"machine_heated_bed": {"value": true},
|
||||
"machine_start_gcode":{
|
||||
"default_value":"G28 ;Home\nG92 E0 ;Reset Extruder\nG1 Z4.0 F3000 ;Move Z Axis up\nG1 X10.1 Y20 Z0.28 F5000.0 ;Move to start position\nG1 X10.1 Y200.0 Z0.28 F1500.0 E15 ;Draw the first line\nG1 X10.4 Y200.0 Z0.28 F5000.0 ;Move to side a little\nG1 X10.4 Y20 Z0.28 F1500.0 E30 ;Draw the second line\nG92 E0 ;Reset Extruder\nG1 Z2.0 F3000 ;Move Z Axis up\n"
|
||||
},
|
||||
"machine_end_gcode":{
|
||||
"default_value":"G91 ;Relative positionning\nG1 E-2 F2700 ;Retract a bit\nG1 E-2 Z0.2 F2400 ;Retract and raise Z\nG1 X5 Y5 F3000 ;Wipe out\nG1 Z10 ;Raise Z more\nG90 ;Absolute positionning\n\nG1 X0 Y{machine_depth} ;Present print\nM106 S0 ;Turn-off fan\nM104 S0 ;Turn-off hotend\nM140 S0 ;Turn-off bed\n\nM84 X Y E ;Disable all steppers but Z\n"
|
||||
},
|
||||
"acceleration_print":{"value":1000},
|
||||
"acceleration_travel":{"value":1000},
|
||||
"acceleration_travel_layer_0":{"value":1000.0},
|
||||
"expand_skins_expand_distance":{"value":0.8},
|
||||
"fill_outline_gaps":{"default_value":false},
|
||||
"infill_sparse_density":{"value":15},
|
||||
"meshfix_maximum_resolution":{"value":0.05},
|
||||
"optimize_wall_printing_order":{"value":true},
|
||||
"retract_at_layer_change":{"value":false},
|
||||
"retraction_amount":{"value":4.5},
|
||||
"roofing_layer_count":{"value":1},
|
||||
"skin_preshrink":{"value":0.8},
|
||||
"speed_layer_0":{"value":30},
|
||||
"speed_print":{"value":45},
|
||||
"speed_roofing":{"value":35},
|
||||
"speed_topbottom":{"value":35},
|
||||
"speed_travel":{"value":80},
|
||||
"speed_wall_0":{"value":32},
|
||||
"speed_wall_x":{"value":32},
|
||||
"support_infill_rate":{"value":5},
|
||||
"support_pattern":{"default_value":"lines"},
|
||||
"support_use_towers":{"value":false},
|
||||
"wall_overhang_speed_factor":{"value":50},
|
||||
"z_seam_corner":{"default_value":"z_seam_corner_any"},
|
||||
"z_seam_relative":{"value":true},
|
||||
"z_seam_type":{"default_value":"sharpest_corner"},
|
||||
"zig_zaggify_infill":{"value":true},
|
||||
"adhesion_type":{"default_value":"skirt"},
|
||||
"prime_tower_enable":{"value":true},
|
||||
"prime_tower_position_x":{"value": 50},
|
||||
"prime_tower_position_y":{"value": 50},
|
||||
"prime_tower_min_volume":{"value": 30},
|
||||
"switch_extruder_retraction_amount": {"value": 100},
|
||||
"switch_extruder_retraction_speeds": {"value": 60}
|
||||
},
|
||||
"metadata": {
|
||||
"visible": true,
|
||||
"author": "lotmaxx.com",
|
||||
"manufacturer": "Lotmaxx",
|
||||
"platform": "lotmaxx_sc_10_20_platform.3mf",
|
||||
"machine_extruder_trains": {
|
||||
"0": "lotmaxx_sc60_extruder_left",
|
||||
"1": "lotmaxx_sc60_extruder_right"
|
||||
},
|
||||
"has_materials": true,
|
||||
"preferred_quality_type": "normal"
|
||||
}
|
||||
}
|
|
@ -345,7 +345,7 @@
|
|||
"value": "0.8"
|
||||
},
|
||||
"ironing_inset": {
|
||||
"value": "0.2"
|
||||
"value": "0.2 + (ironing_line_spacing - skin_line_width * (1.0 + ironing_flow / 100) / 2 if ironing_pattern == 'concentric' else skin_line_width * (1.0 - ironing_flow / 100) / 2)"
|
||||
},
|
||||
"jerk_travel": {
|
||||
"value": "10"
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
"platform": "prusai3_platform.3mf",
|
||||
"machine_extruder_trains":
|
||||
{
|
||||
"0": "tevo_tarantula_extruder_0"
|
||||
"0": "tevo_tarantula_extruder_0",
|
||||
"1": "tevo_tarantula_extruder_1"
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
"has_materials": true,
|
||||
"machine_extruder_trains":
|
||||
{
|
||||
"0": "tevo_tarantula_pro_extruder_0"
|
||||
"0": "tevo_tarantula_pro_extruder_0",
|
||||
"1": "tevo_tarantula_pro_extruder_1"
|
||||
}
|
||||
},
|
||||
|
||||
|
|
17
resources/extruders/I3MetalMotion_extruder_0.def.json
Normal file
17
resources/extruders/I3MetalMotion_extruder_0.def.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
|
||||
"version": 2,
|
||||
"name": "I3MetalMotion extruder",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "I3MetalMotion",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 0 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0 }
|
||||
}
|
||||
}
|
19
resources/extruders/deltacomb_base_extruder_0.def.json
Executable file
19
resources/extruders/deltacomb_base_extruder_0.def.json
Executable file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 1",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_base",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 0, "maximum_value": "3" },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";Deltacomb Extruder 1\n;Put your custom code here"},
|
||||
"machine_extruder_end_code": { "default_value": ";Deltacomb Extruder 1\n;Put your custom code here"}
|
||||
}
|
||||
}
|
19
resources/extruders/deltacomb_base_extruder_1.def.json
Executable file
19
resources/extruders/deltacomb_base_extruder_1.def.json
Executable file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 2",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_base",
|
||||
"position": "1"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 1, "maximum_value": "3" },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";Deltacomb Extruder 2\n;Put your custom code here"},
|
||||
"machine_extruder_end_code": { "default_value": ";Deltacomb Extruder 2\n;Put your custom code here"}
|
||||
}
|
||||
}
|
19
resources/extruders/deltacomb_base_extruder_2.def.json
Executable file
19
resources/extruders/deltacomb_base_extruder_2.def.json
Executable file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 3",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_base",
|
||||
"position": "2"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 2, "maximum_value": "3" },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";Deltacomb Extruder 3\n;Put your custom code here"},
|
||||
"machine_extruder_end_code": { "default_value": ";Deltacomb Extruder 3\n;Put your custom code here"}
|
||||
}
|
||||
}
|
19
resources/extruders/deltacomb_base_extruder_3.def.json
Executable file
19
resources/extruders/deltacomb_base_extruder_3.def.json
Executable file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 4",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_base",
|
||||
"position": "3"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 3, "maximum_value": "3" },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";Deltacomb Extruder 4\n;Put your custom code here"},
|
||||
"machine_extruder_end_code": { "default_value": ";Deltacomb Extruder 4\n;Put your custom code here"}
|
||||
}
|
||||
}
|
19
resources/extruders/deltacomb_dc20dual_extruder_0.def.json
Executable file
19
resources/extruders/deltacomb_dc20dual_extruder_0.def.json
Executable file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 1",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc20dual",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 0 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";DC20 Dual Extruder 1\n;Put your custom code here"},
|
||||
"machine_extruder_end_code": { "default_value": ";DC20 Dual Extruder 1\n;Put your custom code here"}
|
||||
}
|
||||
}
|
19
resources/extruders/deltacomb_dc20dual_extruder_1.def.json
Executable file
19
resources/extruders/deltacomb_dc20dual_extruder_1.def.json
Executable file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 2",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc20dual",
|
||||
"position": "1"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 1 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 19 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0 },
|
||||
"machine_extruder_start_code": { "default_value": ";DC20 Dual Extruder 2\n;Put your custom code here"},
|
||||
"machine_extruder_end_code": { "default_value": ";DC20 Dual Extruder 2\n;Put your custom code here"}
|
||||
}
|
||||
}
|
20
resources/extruders/deltacomb_dc20flux_extruder_0.def.json
Executable file
20
resources/extruders/deltacomb_dc20flux_extruder_0.def.json
Executable file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 1",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc20flux",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 0 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";---------------------------------------\n;DC20 Flux Extruder 1 Start\n;---------------------------------------\nG92 E0 ;zero the extruded length\nG91 ;use relative coordinates\nG1 E68 F10000 ; fast insert\nG92 E0 ;zero the extruded length\nG90 ;absolute positioning\n;---------------------------------------\n;---------------------------------------"},
|
||||
"machine_extruder_end_code": { "default_value": ";---------------------------------------\n;DC20 Flux Extruder 1 End\n;---------------------------------------\nG91 ;use relative coordinates\nG0 E-15 F10000\nG1 Z2 ;lift head\nG4 P3000\nG0 E14.7 F10000\nG1 E-69.7 F10000\nG90 ;absolute positioning\nG92 E0 ;zero the extruded length\n;---------------------------------------\n;---------------------------------------"}
|
||||
}
|
||||
}
|
21
resources/extruders/deltacomb_dc20flux_extruder_1.def.json
Executable file
21
resources/extruders/deltacomb_dc20flux_extruder_1.def.json
Executable file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 2",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc20flux",
|
||||
"position": "1"
|
||||
},
|
||||
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 1 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";---------------------------------------\n;DC20 Flux Extruder 2 Start\n;---------------------------------------\nG92 E0 ;zero the extruded length\nG91 ;use relative coordinates\nG1 E68 F10000 ; fast insert\nG92 E0 ;zero the extruded length\nG90 ;absolute positioning\n;---------------------------------------\n;---------------------------------------"},
|
||||
"machine_extruder_end_code": { "default_value": ";---------------------------------------\n;DC20 Flux Extruder 2 End\n;---------------------------------------\nG91 ;use relative coordinates\nG0 E-15 F10000\nG1 Z2 ;lift head\nG4 P3000\nG0 E14.7 F10000\nG1 E-69.7 F10000\nG90 ;absolute positioning\nG92 E0 ;zero the extruded length\n;---------------------------------------\n;---------------------------------------"},
|
||||
"prime_tower_flow": { "value": "200" }
|
||||
}
|
||||
}
|
21
resources/extruders/deltacomb_dc20flux_extruder_2.def.json
Executable file
21
resources/extruders/deltacomb_dc20flux_extruder_2.def.json
Executable file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 3",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc20flux",
|
||||
"position": "2"
|
||||
},
|
||||
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 2 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";---------------------------------------\n;DC20 Flux Extruder 3 Start\n;---------------------------------------\nG92 E0 ;zero the extruded length\nG91 ;use relative coordinates\nG1 E68 F10000 ; fast insert\nG92 E0 ;zero the extruded length\nG90 ;absolute positioning\n;---------------------------------------\n;---------------------------------------"},
|
||||
"machine_extruder_end_code": { "default_value": ";---------------------------------------\n;DC20 Flux Extruder 3 End\n;---------------------------------------\nG91 ;use relative coordinates\nG0 E-15 F10000\nG1 Z2 ;lift head\nG4 P3000\nG0 E14.7 F10000\nG1 E-69.7 F10000\nG90 ;absolute positioning\nG92 E0 ;zero the extruded length\n;---------------------------------------\n;---------------------------------------"},
|
||||
"prime_tower_flow": { "value": "200" }
|
||||
}
|
||||
}
|
21
resources/extruders/deltacomb_dc20flux_extruder_3.def.json
Executable file
21
resources/extruders/deltacomb_dc20flux_extruder_3.def.json
Executable file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 4",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc20flux",
|
||||
"position": "3"
|
||||
},
|
||||
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 3 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";---------------------------------------\n;DC20 Flux Extruder 4 Start\n;---------------------------------------\nG92 E0 ;zero the extruded length\nG91 ;use relative coordinates\nG1 E68 F10000 ; fast insert\nG92 E0 ;zero the extruded length\nG90 ;absolute positioning\n;---------------------------------------\n;---------------------------------------"},
|
||||
"machine_extruder_end_code": { "default_value": ";---------------------------------------\n;DC20 Flux Extruder 4 End\n;---------------------------------------\nG91 ;use relative coordinates\nG0 E-15 F10000\nG1 Z2 ;lift head\nG4 P3000\nG0 E14.7 F10000\nG1 E-69.7 F10000\nG90 ;absolute positioning\nG92 E0 ;zero the extruded length\n;---------------------------------------\n;---------------------------------------"},
|
||||
"prime_tower_flow": { "value": "200" }
|
||||
}
|
||||
}
|
19
resources/extruders/deltacomb_dc30dual_extruder_0.def.json
Executable file
19
resources/extruders/deltacomb_dc30dual_extruder_0.def.json
Executable file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 1",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc30dual",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 0 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";DC30 Dual Extruder 1\n;Put your custom code here"},
|
||||
"machine_extruder_end_code": { "default_value": ";DC30 Dual Extruder 1\n;Put your custom code here"}
|
||||
}
|
||||
}
|
19
resources/extruders/deltacomb_dc30dual_extruder_1.def.json
Executable file
19
resources/extruders/deltacomb_dc30dual_extruder_1.def.json
Executable file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 2",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc30dual",
|
||||
"position": "1"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 1 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 19 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0 },
|
||||
"machine_extruder_start_code": { "default_value": ";DC30 Dual Extruder 2\n;Put your custom code here"},
|
||||
"machine_extruder_end_code": { "default_value": ";DC30 Dual Extruder 2\n;Put your custom code here"}
|
||||
}
|
||||
}
|
19
resources/extruders/deltacomb_dc30flux_extruder_0.def.json
Executable file
19
resources/extruders/deltacomb_dc30flux_extruder_0.def.json
Executable file
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 1",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc30flux",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 0 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";---------------------------------------\n;DC30 Flux Extruder 1 Start\n;---------------------------------------\nG92 E0 ;zero the extruded length\nG91 ;use relative coordinates\nG1 E68 F10000 ; fast insert\nG92 E0 ;zero the extruded length\nG90 ;absolute positioning\n;---------------------------------------\n;---------------------------------------"},
|
||||
"machine_extruder_end_code": { "default_value": ";---------------------------------------\n;DC30 Flux Extruder 1 End\n;---------------------------------------\nG91 ;use relative coordinates\nG0 E-15 F10000\nG1 Z2 ;lift head\nG4 P3000\nG0 E14.7 F10000\nG1 E-69.7 F10000\nG90 ;absolute positioning\nG92 E0 ;zero the extruded length\n;---------------------------------------\n;---------------------------------------"}
|
||||
}
|
||||
}
|
20
resources/extruders/deltacomb_dc30flux_extruder_1.def.json
Executable file
20
resources/extruders/deltacomb_dc30flux_extruder_1.def.json
Executable file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 2",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc30flux",
|
||||
"position": "1"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 1 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";---------------------------------------\n;DC30 Flux Extruder 2 Start\n;---------------------------------------\nG92 E0 ;zero the extruded length\nG91 ;use relative coordinates\nG1 E68 F10000 ; fast insert\nG92 E0 ;zero the extruded length\nG90 ;absolute positioning\n;---------------------------------------\n;---------------------------------------"},
|
||||
"machine_extruder_end_code": { "default_value": ";---------------------------------------\n;DC30 Flux Extruder 2 End\n;---------------------------------------\nG91 ;use relative coordinates\nG0 E-15 F10000\nG1 Z2 ;lift head\nG4 P3000\nG0 E14.7 F10000\nG1 E-69.7 F10000\nG90 ;absolute positioning\nG92 E0 ;zero the extruded length\n;---------------------------------------\n;---------------------------------------"},
|
||||
"prime_tower_flow": { "value": "200" }
|
||||
}
|
||||
}
|
20
resources/extruders/deltacomb_dc30flux_extruder_2.def.json
Executable file
20
resources/extruders/deltacomb_dc30flux_extruder_2.def.json
Executable file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 3",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc30flux",
|
||||
"position": "2"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 2 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";---------------------------------------\n;DC30 Flux Extruder 3 Start\n;---------------------------------------\nG92 E0 ;zero the extruded length\nG91 ;use relative coordinates\nG1 E68 F10000 ; fast insert\nG92 E0 ;zero the extruded length\nG90 ;absolute positioning\n;---------------------------------------\n;---------------------------------------"},
|
||||
"machine_extruder_end_code": { "default_value": ";---------------------------------------\n;DC30 Flux Extruder 3 End\n;---------------------------------------\nG91 ;use relative coordinates\nG0 E-15 F10000\nG1 Z2 ;lift head\nG4 P3000\nG0 E14.7 F10000\nG1 E-69.7 F10000\nG90 ;absolute positioning\nG92 E0 ;zero the extruded length\n;---------------------------------------\n;---------------------------------------"},
|
||||
"prime_tower_flow": { "value": "200" }
|
||||
}
|
||||
}
|
20
resources/extruders/deltacomb_dc30flux_extruder_3.def.json
Executable file
20
resources/extruders/deltacomb_dc30flux_extruder_3.def.json
Executable file
|
@ -0,0 +1,20 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 4",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb_dc30flux",
|
||||
"position": "3"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 3 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"machine_extruder_start_code": { "default_value": ";---------------------------------------\n;DC30 Flux Extruder 4 Start\n;---------------------------------------\nG92 E0 ;zero the extruded length\nG91 ;use relative coordinates\nG1 E68 F10000 ; fast insert\nG92 E0 ;zero the extruded length\nG90 ;absolute positioning\n;---------------------------------------\n;---------------------------------------"},
|
||||
"machine_extruder_end_code": { "default_value": ";---------------------------------------\n;DC30 Flux Extruder 4 End\n;---------------------------------------\nG91 ;use relative coordinates\nG0 E-15 F10000\nG1 Z2 ;lift head\nG4 P3000\nG0 E14.7 F10000\nG1 E-69.7 F10000\nG90 ;absolute positioning\nG92 E0 ;zero the extruded length\n;---------------------------------------\n;---------------------------------------"},
|
||||
"prime_tower_flow": { "value": "200" }
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 1",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 0 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 }
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 2",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "deltacomb",
|
||||
"position": "1"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 1 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_nozzle_offset_x": { "default_value": 0.0 },
|
||||
"machine_nozzle_offset_y": { "default_value": 0.0 }
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_extruder_start_code": {
|
||||
"default_value": "\n;changing to tool1\nM83\nM109 T0 S{material_print_temperature}\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E-{switch_extruder_retraction_amount} F2400\nG1 Y40 F3000\nG1 X10 F12000\n\n"
|
||||
"default_value": "\n;changing to tool1\nM83\nM109 T0 S{material_print_temperature}\nM114\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E-{switch_extruder_retraction_amount} F2400\nG1 Y40 F3000\nG1 X10 F12000\n\n"
|
||||
},
|
||||
"machine_extruder_end_code": {
|
||||
"default_value": "\nG1 X10 Y40 F12000\nG1 X-25 F12000\nM109 T0 R{material_standby_temperature}\nG1 Y20 F3000\n; ending tool1\n\n"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
"machine_nozzle_offset_y": { "default_value": 0.0 },
|
||||
"material_diameter": { "default_value": 1.75 },
|
||||
"machine_extruder_start_code": {
|
||||
"default_value": "\n;changing to tool2\nM83\nM109 T1 S{material_print_temperature}\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E-{switch_extruder_retraction_amount} F2400\nG1 Y40 F3000\nG1 X10 F12000\n\n"
|
||||
"default_value": "\n;changing to tool2\nM83\nM109 T1 S{material_print_temperature}\nM114\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E{switch_extruder_retraction_amount} F300\nG1 E-{switch_extruder_retraction_amount} F2400\nG1 Y40 F3000\nG1 X10 F12000\n\n"
|
||||
},
|
||||
"machine_extruder_end_code": {
|
||||
"default_value": "\nG1 X10 Y40 F12000\nG1 X-25 F12000\nM109 T1 R{material_standby_temperature}\nG1 Y20 F3000\n; ending tool2\n\n"
|
||||
|
|
15
resources/extruders/lotmaxx_sc60_extruder_left.def.json
Normal file
15
resources/extruders/lotmaxx_sc60_extruder_left.def.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 1",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "lotmaxx_sc60",
|
||||
"position": "0"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 0 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 }
|
||||
}
|
||||
}
|
17
resources/extruders/lotmaxx_sc60_extruder_right.def.json
Normal file
17
resources/extruders/lotmaxx_sc60_extruder_right.def.json
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 2",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "lotmaxx_sc60",
|
||||
"position": "1"
|
||||
},
|
||||
"overrides": {
|
||||
"extruder_nr": {
|
||||
"default_value": 1,
|
||||
"maximum_value": "1"
|
||||
},
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 }
|
||||
}
|
||||
}
|
15
resources/extruders/tevo_tarantula_extruder_1.def.json
Normal file
15
resources/extruders/tevo_tarantula_extruder_1.def.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 2",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "tevo_tarantula",
|
||||
"position": "1"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 1 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 }
|
||||
}
|
||||
}
|
15
resources/extruders/tevo_tarantula_pro_extruder_1.def.json
Normal file
15
resources/extruders/tevo_tarantula_pro_extruder_1.def.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"version": 2,
|
||||
"name": "Extruder 2",
|
||||
"inherits": "fdmextruder",
|
||||
"metadata": {
|
||||
"machine": "tevo_tarantula_pro",
|
||||
"position": "1"
|
||||
},
|
||||
|
||||
"overrides": {
|
||||
"extruder_nr": { "default_value": 1 },
|
||||
"machine_nozzle_size": { "default_value": 0.4 },
|
||||
"material_diameter": { "default_value": 1.75 }
|
||||
}
|
||||
}
|
BIN
resources/meshes/deltacomb_dc20.stl
Normal file
BIN
resources/meshes/deltacomb_dc20.stl
Normal file
Binary file not shown.
BIN
resources/meshes/deltacomb_dc30.stl
Normal file
BIN
resources/meshes/deltacomb_dc30.stl
Normal file
Binary file not shown.
|
@ -108,7 +108,15 @@ Item
|
|||
}
|
||||
}
|
||||
|
||||
onClicked: popup.opened ? popup.close() : popup.open()
|
||||
onClicked: {
|
||||
if (popup.opened)
|
||||
{
|
||||
popup.close()
|
||||
} else {
|
||||
Cura.API.account.popupOpened()
|
||||
popup.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Popup
|
||||
|
@ -119,6 +127,7 @@ Item
|
|||
x: parent.width - width
|
||||
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||
onOpened: Cura.API.account.popupOpened()
|
||||
|
||||
opacity: opened ? 1 : 0
|
||||
Behavior on opacity { NumberAnimation { duration: 100 } }
|
||||
|
|
|
@ -7,11 +7,7 @@ import Cura 1.1 as Cura
|
|||
Row // sync state icon + message
|
||||
{
|
||||
|
||||
property alias iconSource: icon.source
|
||||
property alias labelText: stateLabel.text
|
||||
property alias syncButtonVisible: accountSyncButton.visible
|
||||
property alias animateIconRotation: updateAnimator.running
|
||||
|
||||
id: syncRow
|
||||
width: childrenRect.width
|
||||
height: childrenRect.height
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
@ -23,7 +19,7 @@ Row // sync state icon + message
|
|||
width: 20 * screenScaleFactor
|
||||
height: width
|
||||
|
||||
source: UM.Theme.getIcon("update")
|
||||
source: Cura.API.account.manualSyncEnabled ? UM.Theme.getIcon("update") : UM.Theme.getIcon("checked")
|
||||
color: palette.text
|
||||
|
||||
RotationAnimator
|
||||
|
@ -54,10 +50,11 @@ Row // sync state icon + message
|
|||
Label
|
||||
{
|
||||
id: stateLabel
|
||||
text: catalog.i18nc("@state", "Checking...")
|
||||
text: catalog.i18nc("@state", catalog.i18nc("@label", "You are in sync with your account"))
|
||||
color: UM.Theme.getColor("text")
|
||||
font: UM.Theme.getFont("medium")
|
||||
renderType: Text.NativeRendering
|
||||
visible: !Cura.API.account.manualSyncEnabled
|
||||
}
|
||||
|
||||
Label
|
||||
|
@ -67,11 +64,13 @@ Row // sync state icon + message
|
|||
color: UM.Theme.getColor("secondary_button_text")
|
||||
font: UM.Theme.getFont("medium")
|
||||
renderType: Text.NativeRendering
|
||||
visible: Cura.API.account.manualSyncEnabled
|
||||
height: visible ? accountSyncButton.intrinsicHeight : 0
|
||||
|
||||
MouseArea
|
||||
{
|
||||
anchors.fill: parent
|
||||
onClicked: Cura.API.account.sync()
|
||||
onClicked: Cura.API.account.sync(true)
|
||||
hoverEnabled: true
|
||||
onEntered: accountSyncButton.font.underline = true
|
||||
onExited: accountSyncButton.font.underline = false
|
||||
|
@ -82,25 +81,25 @@ Row // sync state icon + message
|
|||
signal syncStateChanged(string newState)
|
||||
|
||||
onSyncStateChanged: {
|
||||
if(newState == Cura.AccountSyncState.SYNCING){
|
||||
syncRow.iconSource = UM.Theme.getIcon("update")
|
||||
syncRow.labelText = catalog.i18nc("@label", "Checking...")
|
||||
if(newState == Cura.AccountSyncState.IDLE){
|
||||
icon.source = UM.Theme.getIcon("update")
|
||||
} else if(newState == Cura.AccountSyncState.SYNCING){
|
||||
icon.source = UM.Theme.getIcon("update")
|
||||
stateLabel.text = catalog.i18nc("@label", "Checking...")
|
||||
} else if (newState == Cura.AccountSyncState.SUCCESS) {
|
||||
syncRow.iconSource = UM.Theme.getIcon("checked")
|
||||
syncRow.labelText = catalog.i18nc("@label", "You are up to date")
|
||||
icon.source = UM.Theme.getIcon("checked")
|
||||
stateLabel.text = catalog.i18nc("@label", "You are in sync with your account")
|
||||
} else if (newState == Cura.AccountSyncState.ERROR) {
|
||||
syncRow.iconSource = UM.Theme.getIcon("warning_light")
|
||||
syncRow.labelText = catalog.i18nc("@label", "Something went wrong...")
|
||||
icon.source = UM.Theme.getIcon("warning_light")
|
||||
stateLabel.text = catalog.i18nc("@label", "Something went wrong...")
|
||||
} else {
|
||||
print("Error: unexpected sync state: " + newState)
|
||||
}
|
||||
|
||||
if(newState == Cura.AccountSyncState.SYNCING){
|
||||
syncRow.animateIconRotation = true
|
||||
syncRow.syncButtonVisible = false
|
||||
updateAnimator.running = true
|
||||
} else {
|
||||
syncRow.animateIconRotation = false
|
||||
syncRow.syncButtonVisible = true
|
||||
updateAnimator.running = false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,10 @@ import Cura 1.1 as Cura
|
|||
|
||||
Column
|
||||
{
|
||||
width: Math.max(title.width, accountButton.width) + 2 * UM.Theme.getSize("default_margin").width
|
||||
width: Math.max(
|
||||
Math.max(title.width, accountButton.width) + 2 * UM.Theme.getSize("default_margin").width,
|
||||
syncRow.width
|
||||
)
|
||||
|
||||
spacing: UM.Theme.getSize("default_margin").height
|
||||
|
||||
|
@ -29,13 +32,10 @@ Column
|
|||
color: UM.Theme.getColor("text")
|
||||
}
|
||||
|
||||
SyncState
|
||||
{
|
||||
SyncState {
|
||||
id: syncRow
|
||||
}
|
||||
|
||||
|
||||
|
||||
Label
|
||||
{
|
||||
id: lastSyncLabel
|
||||
|
|
|
@ -35,7 +35,8 @@ Item
|
|||
property color headerActiveColor: UM.Theme.getColor("secondary")
|
||||
property color headerHoverColor: UM.Theme.getColor("action_button_hovered")
|
||||
|
||||
property alias enabled: mouseArea.enabled
|
||||
property alias mouseArea: headerMouseArea
|
||||
property alias enabled: headerMouseArea.enabled
|
||||
|
||||
// Text to show when this component is disabled
|
||||
property alias disabledText: disabledLabel.text
|
||||
|
@ -139,6 +140,16 @@ Item
|
|||
anchors.fill: parent
|
||||
visible: base.enabled
|
||||
|
||||
MouseArea
|
||||
{
|
||||
id: headerMouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: toggleContent()
|
||||
hoverEnabled: true
|
||||
onEntered: background.color = headerHoverColor
|
||||
onExited: background.color = base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
|
||||
}
|
||||
|
||||
Loader
|
||||
{
|
||||
id: headerItemLoader
|
||||
|
@ -180,15 +191,6 @@ Item
|
|||
}
|
||||
}
|
||||
|
||||
MouseArea
|
||||
{
|
||||
id: mouseArea
|
||||
anchors.fill: parent
|
||||
onClicked: toggleContent()
|
||||
hoverEnabled: true
|
||||
onEntered: background.color = headerHoverColor
|
||||
onExited: background.color = base.enabled ? headerBackgroundColor : UM.Theme.getColor("disabled")
|
||||
}
|
||||
}
|
||||
|
||||
DropShadow
|
||||
|
|
|
@ -24,7 +24,7 @@ Menu
|
|||
{
|
||||
text:
|
||||
{
|
||||
var path = modelData.toString()
|
||||
var path = decodeURIComponent(modelData.toString())
|
||||
return (index + 1) + ". " + path.slice(path.lastIndexOf("/") + 1);
|
||||
}
|
||||
onTriggered:
|
||||
|
|
|
@ -154,7 +154,7 @@ UM.PreferencesPage
|
|||
|
||||
Component.onCompleted: {
|
||||
append({ text: "English", code: "en_US" })
|
||||
append({ text: "Czech", code: "cs_CZ" })
|
||||
append({ text: "Čeština", code: "cs_CZ" })
|
||||
append({ text: "Deutsch", code: "de_DE" })
|
||||
append({ text: "Español", code: "es_ES" })
|
||||
//Finnish is disabled for being incomplete: append({ text: "Suomi", code: "fi_FI" })
|
||||
|
|
|
@ -136,6 +136,7 @@ UM.ManagementPage
|
|||
{
|
||||
id: confirmDialog
|
||||
object: base.currentItem && base.currentItem.name ? base.currentItem.name : ""
|
||||
text: base.currentItem ? base.currentItem.removalWarning : "";
|
||||
onYes:
|
||||
{
|
||||
Cura.MachineManager.removeMachine(base.currentItem.id)
|
||||
|
|
|
@ -5,16 +5,49 @@ import QtQuick 2.7
|
|||
import QtQuick.Controls 2.3
|
||||
|
||||
import UM 1.2 as UM
|
||||
import Cura 1.0 as Cura
|
||||
import Cura 1.1 as Cura
|
||||
|
||||
Cura.ExpandablePopup
|
||||
{
|
||||
id: machineSelector
|
||||
|
||||
property bool isNetworkPrinter: Cura.MachineManager.activeMachineHasNetworkConnection
|
||||
property bool isCloudPrinter: Cura.MachineManager.activeMachineHasCloudConnection
|
||||
property bool isConnectedCloudPrinter: Cura.MachineManager.activeMachineHasCloudConnection
|
||||
property bool isCloudRegistered: Cura.MachineManager.activeMachineHasCloudRegistration
|
||||
property bool isGroup: Cura.MachineManager.activeMachineIsGroup
|
||||
|
||||
readonly property string connectionStatus: {
|
||||
if (isNetworkPrinter)
|
||||
{
|
||||
return "printer_connected"
|
||||
}
|
||||
else if (isConnectedCloudPrinter && Cura.API.connectionStatus.isInternetReachable)
|
||||
{
|
||||
return "printer_cloud_connected"
|
||||
}
|
||||
else if (isCloudRegistered)
|
||||
{
|
||||
return "printer_cloud_not_available"
|
||||
}
|
||||
else
|
||||
{
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
readonly property string connectionStatusMessage: {
|
||||
if (connectionStatus == "printer_cloud_not_available")
|
||||
{
|
||||
if(Cura.API.connectionStatus.isInternetReachable){
|
||||
return catalog.i18nc("@status", "The cloud connection is currently unavailable. Please check your internet connection and sign in to connect to the cloud printer.")
|
||||
} else {
|
||||
return catalog.i18nc("@status", "The cloud connection is currently unavailable. Please check your internet connection.")
|
||||
}
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
contentPadding: UM.Theme.getSize("default_lining").width
|
||||
contentAlignment: Cura.ExpandablePopup.ContentAlignment.AlignLeft
|
||||
|
||||
|
@ -44,7 +77,7 @@ Cura.ExpandablePopup
|
|||
{
|
||||
return UM.Theme.getIcon("printer_group")
|
||||
}
|
||||
else if (isNetworkPrinter || isCloudPrinter)
|
||||
else if (isNetworkPrinter || isCloudRegistered)
|
||||
{
|
||||
return UM.Theme.getIcon("printer_single")
|
||||
}
|
||||
|
@ -59,6 +92,7 @@ Cura.ExpandablePopup
|
|||
|
||||
UM.RecolorImage
|
||||
{
|
||||
id: connectionStatusImage
|
||||
anchors
|
||||
{
|
||||
bottom: parent.bottom
|
||||
|
@ -66,27 +100,14 @@ Cura.ExpandablePopup
|
|||
leftMargin: UM.Theme.getSize("thick_margin").width
|
||||
}
|
||||
|
||||
source:
|
||||
{
|
||||
if (isNetworkPrinter)
|
||||
{
|
||||
return UM.Theme.getIcon("printer_connected")
|
||||
}
|
||||
else if (isCloudPrinter)
|
||||
{
|
||||
return UM.Theme.getIcon("printer_cloud_connected")
|
||||
}
|
||||
else
|
||||
{
|
||||
return ""
|
||||
}
|
||||
}
|
||||
source: UM.Theme.getIcon(connectionStatus)
|
||||
|
||||
width: UM.Theme.getSize("printer_status_icon").width
|
||||
height: UM.Theme.getSize("printer_status_icon").height
|
||||
|
||||
color: UM.Theme.getColor("primary")
|
||||
visible: isNetworkPrinter || isCloudPrinter
|
||||
color: connectionStatus == "printer_cloud_not_available" ? UM.Theme.getColor("cloud_unavailable") : UM.Theme.getColor("primary")
|
||||
|
||||
visible: isNetworkPrinter || isCloudRegistered
|
||||
|
||||
// Make a themable circle in the background so we can change it in other themes
|
||||
Rectangle
|
||||
|
@ -100,6 +121,38 @@ Cura.ExpandablePopup
|
|||
color: UM.Theme.getColor("main_background")
|
||||
z: parent.z - 1
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
MouseArea // Connection status tooltip hover area
|
||||
{
|
||||
id: connectionStatusTooltipHoverArea
|
||||
anchors.fill: parent
|
||||
hoverEnabled: connectionStatusMessage !== ""
|
||||
acceptedButtons: Qt.NoButton // react to hover only, don't steal clicks
|
||||
|
||||
onEntered:
|
||||
{
|
||||
machineSelector.mouseArea.entered() // we want both this and the outer area to be entered
|
||||
tooltip.show()
|
||||
}
|
||||
onExited: { tooltip.hide() }
|
||||
}
|
||||
|
||||
Cura.ToolTip
|
||||
{
|
||||
id: tooltip
|
||||
|
||||
width: 250 * screenScaleFactor
|
||||
tooltipText: connectionStatusMessage
|
||||
arrowSize: UM.Theme.getSize("button_tooltip_arrow").width
|
||||
x: connectionStatusImage.x - UM.Theme.getSize("narrow_margin").width
|
||||
y: connectionStatusImage.y + connectionStatusImage.height + UM.Theme.getSize("narrow_margin").height
|
||||
z: popup.z + 1
|
||||
targetPoint: Qt.point(
|
||||
connectionStatusImage.x + Math.round(connectionStatusImage.width / 2),
|
||||
connectionStatusImage.y
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,12 +19,20 @@ ToolTip
|
|||
property int contentAlignment: Cura.ToolTip.ContentAlignment.AlignRight
|
||||
|
||||
property alias tooltipText: tooltip.text
|
||||
property alias arrowSize: backgroundRect.arrowSize
|
||||
property var targetPoint: Qt.point(parent.x, y + Math.round(height/2))
|
||||
|
||||
id: tooltip
|
||||
text: ""
|
||||
delay: 500
|
||||
font: UM.Theme.getFont("default")
|
||||
visible: opacity != 0.0
|
||||
opacity: 0.0 // initially hidden
|
||||
|
||||
Behavior on opacity
|
||||
{
|
||||
NumberAnimation { duration: 100; }
|
||||
}
|
||||
|
||||
// If the text is not set, just set the height to 0 to prevent it from showing
|
||||
height: text != "" ? label.contentHeight + 2 * UM.Theme.getSize("thin_margin").width: 0
|
||||
|
@ -60,4 +68,12 @@ ToolTip
|
|||
color: UM.Theme.getColor("tooltip_text")
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
function show() {
|
||||
opacity = 1
|
||||
}
|
||||
|
||||
function hide() {
|
||||
opacity = 0
|
||||
}
|
||||
}
|
22
resources/quality/deltacomb/ABS/deltacomb_DBE0.25_ABS_A.inst.cfg
Executable file
22
resources/quality/deltacomb/ABS/deltacomb_DBE0.25_ABS_A.inst.cfg
Executable file
|
@ -0,0 +1,22 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = A
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = a
|
||||
material = generic_abs
|
||||
variant = DBE 0.25mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 0.5
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
||||
speed_print = 80
|
22
resources/quality/deltacomb/ABS/deltacomb_DBE0.25_ABS_B.inst.cfg
Executable file
22
resources/quality/deltacomb/ABS/deltacomb_DBE0.25_ABS_B.inst.cfg
Executable file
|
@ -0,0 +1,22 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = B
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = b
|
||||
material = generic_abs
|
||||
variant = DBE 0.25mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 0.5
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
||||
speed_print = 55
|
22
resources/quality/deltacomb/ABS/deltacomb_DBE0.25_ABS_C.inst.cfg
Executable file
22
resources/quality/deltacomb/ABS/deltacomb_DBE0.25_ABS_C.inst.cfg
Executable file
|
@ -0,0 +1,22 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = C
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = c
|
||||
material = generic_abs
|
||||
variant = DBE 0.25mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 0.5
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
||||
speed_print = 32
|
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.40_ABS_A.inst.cfg
Executable file
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.40_ABS_A.inst.cfg
Executable file
|
@ -0,0 +1,21 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = A
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = a
|
||||
material = generic_abs
|
||||
variant = DBE 0.40mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 1
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.40_ABS_B.inst.cfg
Executable file
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.40_ABS_B.inst.cfg
Executable file
|
@ -0,0 +1,21 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = B
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = b
|
||||
material = generic_abs
|
||||
variant = DBE 0.40mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 1
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.40_ABS_C.inst.cfg
Executable file
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.40_ABS_C.inst.cfg
Executable file
|
@ -0,0 +1,21 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = C
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = c
|
||||
material = generic_abs
|
||||
variant = DBE 0.40mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 1
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.40_ABS_D.inst.cfg
Executable file
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.40_ABS_D.inst.cfg
Executable file
|
@ -0,0 +1,21 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = D
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = d
|
||||
material = generic_abs
|
||||
variant = FBE 0.40mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 1
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.40_ABS_E.inst.cfg
Executable file
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.40_ABS_E.inst.cfg
Executable file
|
@ -0,0 +1,21 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = E
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = e
|
||||
material = generic_abs
|
||||
variant = DBE 0.40mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 1
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.60_ABS_C.inst.cfg
Executable file
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.60_ABS_C.inst.cfg
Executable file
|
@ -0,0 +1,21 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = C
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = c
|
||||
material = generic_abs
|
||||
variant = DBE 0.60mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 1
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.60_ABS_D.inst.cfg
Executable file
21
resources/quality/deltacomb/ABS/deltacomb_DBE0.60_ABS_D.inst.cfg
Executable file
|
@ -0,0 +1,21 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = D
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = d
|
||||
material = generic_abs
|
||||
variant = FBE 0.60mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 1
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
22
resources/quality/deltacomb/ABS/deltacomb_DBE0.60_ABS_E.inst.cfg
Executable file
22
resources/quality/deltacomb/ABS/deltacomb_DBE0.60_ABS_E.inst.cfg
Executable file
|
@ -0,0 +1,22 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = E
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = e
|
||||
material = generic_abs
|
||||
variant = DBE 0.60mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 1
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
||||
speed_print = 65
|
22
resources/quality/deltacomb/ABS/deltacomb_DBE0.60_ABS_F.inst.cfg
Executable file
22
resources/quality/deltacomb/ABS/deltacomb_DBE0.60_ABS_F.inst.cfg
Executable file
|
@ -0,0 +1,22 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = A
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = f
|
||||
material = generic_abs
|
||||
variant = DBE 0.60mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 1
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
||||
speed_print = 45
|
22
resources/quality/deltacomb/ABS/deltacomb_FBE0.25_ABS_A.inst.cfg
Executable file
22
resources/quality/deltacomb/ABS/deltacomb_FBE0.25_ABS_A.inst.cfg
Executable file
|
@ -0,0 +1,22 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = A
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = a
|
||||
material = generic_abs
|
||||
variant = FBE 0.25mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 0.5
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
||||
speed_print = 80
|
22
resources/quality/deltacomb/ABS/deltacomb_FBE0.25_ABS_B.inst.cfg
Executable file
22
resources/quality/deltacomb/ABS/deltacomb_FBE0.25_ABS_B.inst.cfg
Executable file
|
@ -0,0 +1,22 @@
|
|||
[general]
|
||||
version = 4
|
||||
name = B
|
||||
definition = deltacomb_base
|
||||
|
||||
[metadata]
|
||||
setting_version = 15
|
||||
type = quality
|
||||
quality_type = b
|
||||
material = generic_abs
|
||||
variant = FBE 0.25mm
|
||||
|
||||
[values]
|
||||
adhesion_type = raft
|
||||
cool_fan_full_at_height = 0.5
|
||||
cool_fan_speed = 50
|
||||
cool_fan_speed_max = 50
|
||||
cool_fan_speed_min = 0
|
||||
material_bed_temperature = 100
|
||||
material_bed_temperature_layer_0 = 80
|
||||
material_print_temperature = 240
|
||||
speed_print = 55
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue