Merge branch 'master' of github.com:Ultimaker/Cura

This commit is contained in:
Tim Kuipers 2016-07-07 15:18:57 +02:00
commit 7fc37e7a74
19 changed files with 205 additions and 108 deletions

View File

@ -53,7 +53,7 @@ class CuraContainerRegistry(ContainerRegistry):
def _containerExists(self, container_type, container_name): def _containerExists(self, container_type, container_name):
container_class = ContainerStack if container_type == "machine" else InstanceContainer container_class = ContainerStack if container_type == "machine" else InstanceContainer
return self.findContainers(container_class, id = container_name, type = container_type) or \ return self.findContainers(container_class, id = container_name, type = container_type, ignore_case = True) or \
self.findContainers(container_class, name = container_name, type = container_type) self.findContainers(container_class, name = container_name, type = container_type)
## Exports an profile to a file ## Exports an profile to a file

View File

@ -22,7 +22,7 @@ class ExtruderManager(QObject):
def __init__(self, parent = None): def __init__(self, parent = None):
super().__init__(parent) super().__init__(parent)
self._extruder_trains = { } #Per machine, a dictionary of extruder container stack IDs. self._extruder_trains = { } #Per machine, a dictionary of extruder container stack IDs.
self._active_extruder_index = 0 self._active_extruder_index = -1
UM.Application.getInstance().globalContainerStackChanged.connect(self._addCurrentMachineExtruders) UM.Application.getInstance().globalContainerStackChanged.connect(self._addCurrentMachineExtruders)
## Gets the unique identifier of the currently active extruder stack. ## Gets the unique identifier of the currently active extruder stack.
@ -66,6 +66,10 @@ class ExtruderManager(QObject):
self._active_extruder_index = index self._active_extruder_index = index
self.activeExtruderChanged.emit() self.activeExtruderChanged.emit()
@pyqtProperty(int, notify = activeExtruderChanged)
def activeExtruderIndex(self):
return self._active_extruder_index
def getActiveExtruderStack(self): def getActiveExtruderStack(self):
global_container_stack = UM.Application.getInstance().getGlobalContainerStack() global_container_stack = UM.Application.getInstance().getGlobalContainerStack()
if global_container_stack: if global_container_stack:

View File

@ -4,6 +4,7 @@
from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal from PyQt5.QtCore import QObject, pyqtSlot, pyqtProperty, pyqtSignal
from UM.Application import Application from UM.Application import Application
from UM.Preferences import Preferences from UM.Preferences import Preferences
from UM.Logger import Logger
import UM.Settings import UM.Settings
from UM.Settings.Validator import ValidatorState from UM.Settings.Validator import ValidatorState
@ -51,6 +52,7 @@ class MachineManagerModel(QObject):
active_machine_id = Preferences.getInstance().getValue("cura/active_machine") active_machine_id = Preferences.getInstance().getValue("cura/active_machine")
self._printer_output_devices = []
Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged) Application.getInstance().getOutputDeviceManager().outputDevicesChanged.connect(self._onOutputDevicesChanged)
if active_machine_id != "": if active_machine_id != "":
@ -72,8 +74,52 @@ class MachineManagerModel(QObject):
outputDevicesChanged = pyqtSignal() outputDevicesChanged = pyqtSignal()
def _onOutputDevicesChanged(self): def _onOutputDevicesChanged(self):
for printer_output_device in self._printer_output_devices:
printer_output_device.hotendIdChanged.disconnect(self._onHotendIdChanged)
printer_output_device.materialIdChanged.disconnect(self._onMaterialIdChanged)
self._printer_output_devices.clear()
for printer_output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices():
if isinstance(printer_output_device, PrinterOutputDevice):
self._printer_output_devices.append(printer_output_device)
printer_output_device.hotendIdChanged.connect(self._onHotendIdChanged)
printer_output_device.materialIdChanged.connect(self._onMaterialIdChanged)
self.outputDevicesChanged.emit() self.outputDevicesChanged.emit()
@pyqtProperty("QVariantList", notify = outputDevicesChanged)
def printerOutputDevices(self):
return self._printer_output_devices
def _onHotendIdChanged(self, index, hotend_id):
if not self._global_container_stack:
return
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "variant", definition = self._global_container_stack.getBottom().getId(), name = hotend_id)
if containers:
Logger.log("d", "Setting hotend variant of hotend %d to %s" % (index, containers[0].getId()))
ExtruderManager.ExtruderManager.getInstance().setActiveExtruderIndex(index)
self.setActiveVariant(containers[0].getId())
def _onMaterialIdChanged(self, index, material_id):
# TODO: fix this
if not self._global_container_stack:
return
definition_id = "fdmprinter"
if self._global_container_stack.getMetaDataEntry("has_machine_materials", False):
definition_id = self._global_container_stack.getBottom().getId()
containers = UM.Settings.ContainerRegistry.getInstance().findInstanceContainers(type = "material", definition = definition_id, GUID = material_id)
if containers:
Logger.log("d", "Setting material of hotend %d to %s" % (index, containers[0].getId()))
ExtruderManager.ExtruderManager.getInstance().setActiveExtruderIndex(index)
self.setActiveMaterial(containers[0].getId())
else:
Logger.log("w", "No material definition found for printer definition %s and GUID %s" % (definition_id, material_id))
def _onGlobalPropertyChanged(self, key, property_name): def _onGlobalPropertyChanged(self, key, property_name):
if property_name == "value": if property_name == "value":
self.globalValueChanged.emit() self.globalValueChanged.emit()
@ -165,9 +211,6 @@ class MachineManagerModel(QObject):
Application.getInstance().setGlobalContainerStack(new_global_stack) Application.getInstance().setGlobalContainerStack(new_global_stack)
@pyqtProperty("QVariantList", notify = outputDevicesChanged)
def printerOutputDevices(self):
return [printer_output_device for printer_output_device in Application.getInstance().getOutputDeviceManager().getOutputDevices() if isinstance(printer_output_device, PrinterOutputDevice)]
## Create a name that is not empty and unique ## Create a name that is not empty and unique
# \param container_type \type{string} Type of the container (machine, quality, ...) # \param container_type \type{string} Type of the container (machine, quality, ...)

View File

@ -6,3 +6,6 @@ class MultiMaterialDecorator(SceneNodeDecorator):
def isMultiMaterial(self): def isMultiMaterial(self):
return True return True
def __deepcopy__(self, memo):
return MultiMaterialDecorator()

View File

@ -24,6 +24,8 @@ class PrinterOutputDevice(QObject, OutputDevice):
self._num_extruders = 1 self._num_extruders = 1
self._hotend_temperatures = [0] * self._num_extruders self._hotend_temperatures = [0] * self._num_extruders
self._target_hotend_temperatures = [0] * self._num_extruders self._target_hotend_temperatures = [0] * self._num_extruders
self._material_ids = [""] * self._num_extruders
self._hotend_ids = [""] * self._num_extruders
self._progress = 0 self._progress = 0
self._head_x = 0 self._head_x = 0
self._head_y = 0 self._head_y = 0
@ -57,6 +59,12 @@ class PrinterOutputDevice(QObject, OutputDevice):
# Signal to be emitted when head position is changed (x,y,z) # Signal to be emitted when head position is changed (x,y,z)
headPositionChanged = pyqtSignal() headPositionChanged = pyqtSignal()
# Signal to be emitted when either of the material ids is changed
materialIdChanged = pyqtSignal(int, str, arguments = ["index", "id"])
# Signal to be emitted when either of the hotend ids is changed
hotendIdChanged = pyqtSignal(int, str, arguments = ["index", "id"])
# Signal that is emitted every time connection state is changed. # Signal that is emitted every time connection state is changed.
# it also sends it's own device_id (for convenience sake) # it also sends it's own device_id (for convenience sake)
connectionStateChanged = pyqtSignal(str) connectionStateChanged = pyqtSignal(str)
@ -212,6 +220,34 @@ class PrinterOutputDevice(QObject, OutputDevice):
self._hotend_temperatures[index] = temperature self._hotend_temperatures[index] = temperature
self.hotendTemperaturesChanged.emit() self.hotendTemperaturesChanged.emit()
@pyqtProperty("QVariantList", notify = materialIdChanged)
def materialIds(self):
return self._material_ids
## Protected setter for the current material id.
# /param index Index of the extruder
# /param material_id id of the material
def _setMaterialId(self, index, material_id):
if material_id and material_id != "" and material_id != self._material_ids[index]:
Logger.log("d", "Setting material id of hotend %d to %s" % (index, material_id))
self._material_ids[index] = material_id
self.materialIdChanged.emit(index, material_id)
@pyqtProperty("QVariantList", notify = hotendIdChanged)
def hotendIds(self):
return self._hotend_ids
## Protected setter for the current hotend id.
# /param index Index of the extruder
# /param hotend_id id of the hotend
def _setHotendId(self, index, hotend_id):
if hotend_id and hotend_id != "" and hotend_id != self._hotend_ids[index]:
Logger.log("d", "Setting hotend id of hotend %d to %s" % (index, hotend_id))
self._hotend_ids[index] = hotend_id
self.hotendIdChanged.emit(index, hotend_id)
## Attempt to establish connection ## Attempt to establish connection
def connect(self): def connect(self):
raise NotImplementedError("connect needs to be implemented") raise NotImplementedError("connect needs to be implemented")

View File

@ -127,13 +127,15 @@ class CuraEngineBackend(Backend):
## Perform a slice of the scene. ## Perform a slice of the scene.
def slice(self): def slice(self):
if not self._enabled or not self._global_container_stack: #We shouldn't be slicing.
# try again in a short time
self._change_timer.start()
return
self.printDurationMessage.emit(0, [0]) self.printDurationMessage.emit(0, [0])
self._stored_layer_data = [] self._stored_layer_data = []
if not self._enabled or not self._global_container_stack: #We shouldn't be slicing.
return
if self._slicing: #We were already slicing. Stop the old job. if self._slicing: #We were already slicing. Stop the old job.
self._terminate() self._terminate()

View File

@ -45,6 +45,7 @@ class SliceInfo(Extension):
Preferences.getInstance().setValue("info/asked_send_slice_info", True) Preferences.getInstance().setValue("info/asked_send_slice_info", True)
def _onWriteStarted(self, output_device): def _onWriteStarted(self, output_device):
try:
if not Preferences.getInstance().getValue("info/send_slice_info"): if not Preferences.getInstance().getValue("info/send_slice_info"):
Logger.log("d", "'info/send_slice_info' is turned off.") Logger.log("d", "'info/send_slice_info' is turned off.")
return # Do nothing, user does not want to send data return # Do nothing, user does not want to send data
@ -115,4 +116,8 @@ class SliceInfo(Extension):
Logger.log("i", "Sent anonymous slice info to %s", self.info_url) Logger.log("i", "Sent anonymous slice info to %s", self.info_url)
f.close() f.close()
except Exception as e: except Exception as e:
Logger.logException("e", e) Logger.logException("e", "An exception occurred while trying to send slice information")
except:
# We really can't afford to have a mistake here, as this would break the sending of g-code to a device
# (Either saving or directly to a printer). The functionality of the slice data is not *that* important.
pass

View File

@ -37,9 +37,8 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
self._connect_thread = threading.Thread(target = self._connect) self._connect_thread = threading.Thread(target = self._connect)
self._connect_thread.daemon = True self._connect_thread.daemon = True
self._end_stop_thread = threading.Thread(target = self._pollEndStop) self._end_stop_thread = None
self._end_stop_thread.daemon = True self._poll_endstop = False
self._poll_endstop = -1
# The baud checking is done by sending a number of m105 commands to the printer and waiting for a readable # The baud checking is done by sending a number of m105 commands to the printer and waiting for a readable
# response. If the baudrate is correct, this should make sense, else we get giberish. # response. If the baudrate is correct, this should make sense, else we get giberish.
@ -221,13 +220,17 @@ class USBPrinterOutputDevice(PrinterOutputDevice):
@pyqtSlot() @pyqtSlot()
def startPollEndstop(self): def startPollEndstop(self):
if self._poll_endstop == -1: if not self._poll_endstop:
self._poll_endstop = True self._poll_endstop = True
if self._end_stop_thread is None:
self._end_stop_thread = threading.Thread(target=self._pollEndStop)
self._end_stop_thread.daemon = True
self._end_stop_thread.start() self._end_stop_thread.start()
@pyqtSlot() @pyqtSlot()
def stopPollEndstop(self): def stopPollEndstop(self):
self._poll_endstop = False self._poll_endstop = False
self._end_stop_thread = None
def _pollEndStop(self): def _pollEndStop(self):
while self._connection_state == ConnectionState.connected and self._poll_endstop: while self._connection_state == ConnectionState.connected and self._poll_endstop:

View File

@ -152,7 +152,7 @@ class USBPrinterOutputDeviceManager(QObject, OutputDevicePlugin, Extension):
"ultimaker_original_plus" : "MarlinUltimaker-UMOP-{baudrate}.hex", "ultimaker_original_plus" : "MarlinUltimaker-UMOP-{baudrate}.hex",
"ultimaker2" : "MarlinUltimaker2.hex", "ultimaker2" : "MarlinUltimaker2.hex",
"ultimaker2_go" : "MarlinUltimaker2go.hex", "ultimaker2_go" : "MarlinUltimaker2go.hex",
"ultimaker2plus" : "MarlinUltimaker2plus.hex", "ultimaker2_plus" : "MarlinUltimaker2plus.hex",
"ultimaker2_extended" : "MarlinUltimaker2extended.hex", "ultimaker2_extended" : "MarlinUltimaker2extended.hex",
"ultimaker2_extended_plus" : "MarlinUltimaker2extended-plus.hex", "ultimaker2_extended_plus" : "MarlinUltimaker2extended-plus.hex",
} }

View File

@ -43,7 +43,6 @@ class UMOCheckupMachineAction(MachineAction):
if self._output_device is None and self._check_started: if self._output_device is None and self._check_started:
self.startCheck() self.startCheck()
def _getPrinterOutputDevices(self): def _getPrinterOutputDevices(self):
return [printer_output_device for printer_output_device in return [printer_output_device for printer_output_device in
Application.getInstance().getOutputDeviceManager().getOutputDevices() if Application.getInstance().getOutputDeviceManager().getOutputDevices() if
@ -63,6 +62,7 @@ class UMOCheckupMachineAction(MachineAction):
self._output_device = None self._output_device = None
self._check_started = False self._check_started = False
self.checkStartedChanged.emit()
# Ensure everything is reset (and right signals are emitted again) # Ensure everything is reset (and right signals are emitted again)
self._bed_test_completed = False self._bed_test_completed = False
@ -137,9 +137,16 @@ class UMOCheckupMachineAction(MachineAction):
self._z_min_endstop_test_completed = True self._z_min_endstop_test_completed = True
self.onZMinEndstopTestCompleted.emit() self.onZMinEndstopTestCompleted.emit()
checkStartedChanged = pyqtSignal()
@pyqtProperty(bool, notify = checkStartedChanged)
def checkStarted(self):
return self._check_started
@pyqtSlot() @pyqtSlot()
def startCheck(self): def startCheck(self):
self._check_started = True self._check_started = True
self.checkStartedChanged.emit()
output_devices = self._getPrinterOutputDevices() output_devices = self._getPrinterOutputDevices()
if output_devices: if output_devices:
self._output_device = output_devices[0] self._output_device = output_devices[0]
@ -150,7 +157,7 @@ class UMOCheckupMachineAction(MachineAction):
self._output_device.bedTemperatureChanged.connect(self._onBedTemperatureChanged) self._output_device.bedTemperatureChanged.connect(self._onBedTemperatureChanged)
self._output_device.hotendTemperaturesChanged.connect(self._onHotendTemperatureChanged) self._output_device.hotendTemperaturesChanged.connect(self._onHotendTemperatureChanged)
self._output_device.endstopStateChanged.connect(self._onEndstopStateChanged) self._output_device.endstopStateChanged.connect(self._onEndstopStateChanged)
except AttributeError: # Connection is probably not a USB connection. Something went pretty wrong if this happens. except AttributeError as e: # Connection is probably not a USB connection. Something went pretty wrong if this happens.
pass pass
@pyqtSlot() @pyqtSlot()

View File

@ -51,7 +51,6 @@ Cura.MachineAction
text: catalog.i18nc("@action:button","Start Printer Check"); text: catalog.i18nc("@action:button","Start Printer Check");
onClicked: onClicked:
{ {
checkupContent.visible = true
manager.startCheck() manager.startCheck()
} }
} }
@ -73,7 +72,7 @@ Cura.MachineAction
id: checkupContent id: checkupContent
anchors.top: startStopButtons.bottom anchors.top: startStopButtons.bottom
anchors.topMargin: UM.Theme.getSize("default_margin").height anchors.topMargin: UM.Theme.getSize("default_margin").height
visible: false visible: manager.checkStarted
width: parent.width width: parent.width
height: 250 height: 250
////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////
@ -157,6 +156,7 @@ Cura.MachineAction
{ {
id: nozzleTempLabel id: nozzleTempLabel
width: checkupMachineAction.leftRow width: checkupMachineAction.leftRow
height: nozzleTempButton.height
anchors.left: parent.left anchors.left: parent.left
anchors.top: endstopZLabel.bottom anchors.top: endstopZLabel.bottom
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
@ -175,20 +175,16 @@ Cura.MachineAction
{ {
id: nozzleTempButton id: nozzleTempButton
width: checkupMachineAction.rightRow * 0.3 width: checkupMachineAction.rightRow * 0.3
height: nozzleTemp.height height: childrenRect.height
anchors.top: nozzleTempLabel.top anchors.top: nozzleTempLabel.top
anchors.left: bedTempStatus.right anchors.left: bedTempStatus.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width/2 anchors.leftMargin: UM.Theme.getSize("default_margin").width/2
Button Button
{ {
height: nozzleTemp.height - 2
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
text: catalog.i18nc("@action:button","Start Heating") text: catalog.i18nc("@action:button","Start Heating")
onClicked: onClicked:
{ {
manager.heatupHotend() manager.heatupHotend()
nozzleTempStatus.text = catalog.i18nc("@info:progress","Checking")
} }
} }
} }
@ -208,10 +204,11 @@ Cura.MachineAction
{ {
id: bedTempLabel id: bedTempLabel
width: checkupMachineAction.leftRow width: checkupMachineAction.leftRow
height: bedTempButton.height
anchors.left: parent.left anchors.left: parent.left
anchors.top: nozzleTempLabel.bottom anchors.top: nozzleTempLabel.bottom
wrapMode: Text.WordWrap wrapMode: Text.WordWrap
text: catalog.i18nc("@label","bed temperature check:") text: catalog.i18nc("@label","Bed temperature check:")
} }
Label Label
@ -227,15 +224,12 @@ Cura.MachineAction
{ {
id: bedTempButton id: bedTempButton
width: checkupMachineAction.rightRow * 0.3 width: checkupMachineAction.rightRow * 0.3
height: bedTemp.height height: childrenRect.height
anchors.top: bedTempLabel.top anchors.top: bedTempLabel.top
anchors.left: bedTempStatus.right anchors.left: bedTempStatus.right
anchors.leftMargin: UM.Theme.getSize("default_margin").width/2 anchors.leftMargin: UM.Theme.getSize("default_margin").width/2
Button Button
{ {
height: bedTemp.height - 2
anchors.verticalCenter: parent.verticalCenter
anchors.horizontalCenter: parent.horizontalCenter
text: catalog.i18nc("@action:button","Start Heating") text: catalog.i18nc("@action:button","Start Heating")
onClicked: onClicked:
{ {

View File

@ -455,7 +455,7 @@
}, },
"skin_line_width": "skin_line_width":
{ {
"label": "Top/bottom Line Width", "label": "Top/Bottom Line Width",
"description": "Width of a single top/bottom line.", "description": "Width of a single top/bottom line.",
"unit": "mm", "unit": "mm",
"minimum_value": "0.0001", "minimum_value": "0.0001",

View File

@ -16,7 +16,7 @@
"overrides": { "overrides": {
"machine_height": { "machine_height": {
"default_value": 315 "default_value": 305
} }
} }
} }

View File

@ -15,7 +15,7 @@
"overrides": { "overrides": {
"machine_height": { "machine_height": {
"default_value": 313 "default_value": 305
}, },
"machine_show_variants": { "machine_show_variants": {
"default_value": true "default_value": true

View File

@ -9,7 +9,7 @@ Generic PLA profile. Serves as an example file, data in this file is not correct
<material>ABS</material> <material>ABS</material>
<color>Generic</color> <color>Generic</color>
</name> </name>
<GUID>506c9f0d-e3aa-4bd4-b2d2-23e2425b1aa9</GUID> <GUID>60636bb4-518f-42e7-8237-fe77b194ebe0</GUID>
<version>0</version> <version>0</version>
<color_code>#FF0000</color_code> <color_code>#FF0000</color_code>
</metadata> </metadata>

View File

@ -9,7 +9,7 @@ Generic PLA profile. Serves as an example file, data in this file is not correct
<material>CPE</material> <material>CPE</material>
<color>Generic</color> <color>Generic</color>
</name> </name>
<GUID>506c9f0d-e3aa-4bd4-b2d2-23e2425b1aa9</GUID> <GUID>12f41353-1a33-415e-8b4f-a775a6c70cc6</GUID>
<version>0</version> <version>0</version>
<color_code>#0000FF</color_code> <color_code>#0000FF</color_code>
</metadata> </metadata>

View File

@ -24,7 +24,7 @@ Rectangle
return UM.Theme.getColor("status_offline") return UM.Theme.getColor("status_offline")
else if(Cura.MachineManager.printerOutputDevices[0].jobState == "printing" || Cura.MachineManager.printerOutputDevices[0].jobState == "pre_print") else if(Cura.MachineManager.printerOutputDevices[0].jobState == "printing" || Cura.MachineManager.printerOutputDevices[0].jobState == "pre_print")
return UM.Theme.getColor("status_busy") return UM.Theme.getColor("status_busy")
else if(Cura.MachineManager.printerOutputDevices[0].jobState == "ready") else if(Cura.MachineManager.printerOutputDevices[0].jobState == "ready" || Cura.MachineManager.printerOutputDevices[0].jobState == "")
return UM.Theme.getColor("status_ready") return UM.Theme.getColor("status_ready")
else if(Cura.MachineManager.printerOutputDevices[0].jobState == "paused") else if(Cura.MachineManager.printerOutputDevices[0].jobState == "paused")
return UM.Theme.getColor("status_paused") return UM.Theme.getColor("status_paused")

View File

@ -103,7 +103,7 @@ Rectangle
return UM.Theme.getIcon("tab_monitor") return UM.Theme.getIcon("tab_monitor")
else if(Cura.MachineManager.printerOutputDevices[0].jobState == "printing" || Cura.MachineManager.printerOutputDevices[0].jobState == "pre_print") else if(Cura.MachineManager.printerOutputDevices[0].jobState == "printing" || Cura.MachineManager.printerOutputDevices[0].jobState == "pre_print")
return UM.Theme.getIcon("tab_monitor_busy") return UM.Theme.getIcon("tab_monitor_busy")
else if(Cura.MachineManager.printerOutputDevices[0].jobState == "ready") else if(Cura.MachineManager.printerOutputDevices[0].jobState == "ready" || Cura.MachineManager.printerOutputDevices[0].jobState == "")
return UM.Theme.getIcon("tab_monitor_connected") return UM.Theme.getIcon("tab_monitor_connected")
else if(Cura.MachineManager.printerOutputDevices[0].jobState == "paused") else if(Cura.MachineManager.printerOutputDevices[0].jobState == "paused")
return UM.Theme.getIcon("tab_monitor_paused") return UM.Theme.getIcon("tab_monitor_paused")

View File

@ -13,7 +13,7 @@ Column
id: base; id: base;
property int totalHeightHeader: childrenRect.height property int totalHeightHeader: childrenRect.height
property int currentExtruderIndex: -1; property int currentExtruderIndex:ExtruderManager.activeExtruderIndex;
spacing: UM.Theme.getSize("default_margin").height spacing: UM.Theme.getSize("default_margin").height
@ -118,7 +118,7 @@ Column
{ {
base.currentExtruderIndex = -1; base.currentExtruderIndex = -1;
forceActiveFocus() forceActiveFocus()
ExtruderManager.setActiveExtruderIndex(0); ExtruderManager.setActiveExtruderIndex(base.currentExtruderIndex);
} }
} }